STM32F1 HAL库笔记0

2024-09-05 17:20
文章标签 笔记 hal stm32f1

本文主要是介绍STM32F1 HAL库笔记0,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考UM1850  Description of STM32F1 HAL and low-layer drivers

1、STM32Cube 包括:

        • STM32CubeMX,图形软件配置工具,使用图形向导生成 C 初始化代码。

        • 嵌入式软件平台,按系列提供(例如用于STM32F1的STM32CubeF1),包括:

        ——STM32Cube HAL,STM32抽象层嵌入式软件,确保在STM32产品组合中实现最大的可移植性。HAL API 可用于所有外围设备。

        ——低层 API (LL) 提供快速、轻量级、面向专家的层,比 HAL 更接近硬件。LL API 仅适用于一组外围设备。

        —— 一组一致的中间件组件,例如 RTOS、USB、TCP/IP 和图形。

        ——所有嵌入式软件实用程序,随附全套示例。

!!!以上的意思,写STM32的程序的方法是,通过使用STM32CubeMX生产初始代码,调用HAL APIs、LL APIs或者搭配RTOS来完成开发工作。有示例程序可参考的。

2、HAL的特征

        HAL针对功能模块,不是外设器件。啥意思?例如,一个USART 外设会存在这么几个模块:UART 驱动程序模块、USART 驱动程序模块、SMARTCARD 驱动程序模块和 IRDA 驱动程序模块。模块,在程序里理解为C语言数据结构struct,或者C++的类,使用时实例化为实例instance。

        API分为通用API和扩展API(也就是当初没设计,后来又设计了一些特殊功能)。

        三种 API 编程模型:轮询、中断和 DMA。(API里有不同的后缀区分)

        API 符合 RTOS 标准:完全可重入的 API (RTOS不同线程调用同一API,不会死锁);在轮询模式下系统地使用超时(阻塞延时,RTOS可以重新调度运行其它线程)。

        支持外设多实例,允许对给定外设的多个实例(USART1、USART2...)进行并发 API 调用。

        三种用户回调函数(写程序只用启动,然后写好回调函数就行):

                ——初始化外设 Init/DeInit回调函数,执行外设系统级初始化/取消初始化(一般操作这些:时钟、GPIO、中断、DMA)

                ——外设中断事件回调,中断处理函数里已经清除中断标志,直接写业务逻辑

                —— 错误事件回调

        对象锁定机制:安全的硬件访问,防止对共享资源的多次虚假访问。

        用于所有阻塞进程的超时:超时可以是简单的计数器或时基。超时和延时在HAL里很重要,一般默认为systick为时基。

3、HAL数据结构

        有三种,外设句柄结构、初始化和配置结构、处理流程结构。

        ——外设句柄结构:PPP_HandleTypeDef  *handle;每个外设/模块实例都有自己的句柄,实例资源是独立的。外设进程通信:句柄结构有通信资源,全局指针、DMA 句柄、状态机。存储:句柄可以有全局变量,存储数据。

        例子:usart句柄,可以实例化为USART1、USART2......结构体有发送接收过程的buffer,有DMA的句柄,状态机,出错控制等。还有初始化句柄。

typedef struct
{
USART_TypeDef *Instance; /* USART registers base address */
USART_InitTypeDef Init; /* Usart communication parameters */
uint8_t *pTxBuffPtr;/* Pointer to Usart Tx transfer Buffer */
uint16_t TxXferSize; /* Usart Tx Transfer size */
__IO uint16_t TxXferCount;/* Usart Tx Transfer Counter */
uint8_t *pRxBuffPtr;/* Pointer to Usart Rx transfer Buffer */
uint16_t RxXferSize; /* Usart Rx Transfer size */
__IO uint16_t RxXferCount; /* Usart Rx Transfer Counter */
DMA_HandleTypeDef *hdmatx; /* Usart Tx DMA Handle parameters */
DMA_HandleTypeDef *hdmarx; /* Usart Rx DMA Handle parameters */
HAL_LockTypeDef Lock; /* Locking object */
__IO HAL_USART_StateTypeDef State; /* Usart communication state */
__IO HAL_USART_ErrorTypeDef ErrorCode;/* USART Error code */
}USART_HandleTypeDef;

        多实例特性意味着应用程序中使用的所有 API 都是可重入的,例子???

        GPIO、SYSTICK、NVIC、PWR、RCC、FLASH这些共享外设,不适用句柄结构来描述,直接使用HAL函数。

        ——初始化和配置结构,这个好理解,例如UART_InitTypeDef、HAL_ADC_ConfigChannel (ADC_HandleTypeDef* hadc, ADC_ChannelConfTypeDef* sConfig)。

        ——处理流程结构,例如:HAL_PPP_Process (PPP_HandleTypeDef* hadc,PPP_ProcessConfig* sConfig)。

4、API分类

        通用APIs

HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef* hadc); 
HAL_StatusTypeDef HAL_ADC_DeInit(ADC_HandleTypeDef *hadc); 
HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc); 
HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc); 
HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc); 
HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc); 
void HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc);

        扩展APIs

系列特定API
HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef* hadc, uint32_t Sing
leDiff); uint32_t HAL_ADCEx_Calibration_GetValue(ADC_HandleTypeDef* hadc, uint32_t S
ingleDiff);
指定型号API
HAL_ADCEx_MultiModeStart_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint32_tLengt
h);
HAL_StatusTypeDef HAL_ADCEx_MultiModeStop_DMA(ADC_HandleTypeDef *hadc);

5、HAL 驱动程序规则

5.1、HAL API 命名规则

        File names                     stm32f1xx_hal_ppp.c/stm32f1xx_hal_ppp.h

        Module name                 HAL_PPP_ MODULE

        Function name               HAL_PPP_Function、HAL_PPP_FeatureFunction_MODE

        Handle name                 PPP_HandleTypedef 

        Init structure name         PPP_InitTypeDef 

        Enum name                   HAL_PPP_StructnameTypeDef

        PPP 前缀是指外设功能模式,而不是外设本身。例如,如果 USART,PPP 可以是 USART、IRDA、UART 或 SMARTCARD,具体取决于外设模式。

        一个文件中使用的常量在此文件中定义。在多个文件中使用的常量在头文件中定义。所有常量都以大写形式写入,但外设驱动程序函数参数除外。

        typedef 变量名称应以 _TypeDef 为后缀。

        寄存器被视为常量。在大多数情况下,它们的名称为大写,并使用与 STM32F1 参考手册中相同的首字母缩略词。

        外设寄存器在 CMSIS 标头的 PPP_TypeDef 结构(例如 ADC_TypeDef)中声明:stm32f1xxx.h 对应于 stm32f100xb.h、stm32f100xe.h、stm32f101x6.h等

        外设函数名称以 HAL_ 为前缀,然后是相应的外设首字母缩略词(大写),后跟下划线。每个单词的首字母为大写(例如 HAL_UART_Transmit())。函数名称中只允许使用一个下划线,以将外设首字母缩略词与函数名称的其余部分分隔开。

        包含 PPP 外设初始化参数的结构命名为 PPP_InitTypeDef (例如 ADC_InitTypeDef)。

        包含 PPP 外设设备的特定配置参数的结构命名为 PPP_xxxxConfTypeDef (例如 ADC_ChannelConfTypeDef)。        

        外设句柄结构命名为 PPP_HandleTypedef (例如 DMA_HandleTypeDef)

        用于根据 PPP_InitTypeDef 中指定的参数初始化 PPP 外设的函数命名为 HAL_PPP_Init (例如 HAL_TIM_Init())。

        用于将 PPP 外设寄存器重置为默认值的函数命名为 HAL_PPP_DeInit (例如 HAL_TIM_DeInit())。

        MODE 后缀是指进程模式,可以是轮询、中断或 DMA。例如,当除了原生资源之外还使用 DMA 时,应该调用该函数:HAL_PPP_Function_DMA () 。

        Feature 前缀应引用新功能。示例:HAL_ADC_Start()是指注入模式。

5.2、HAL 一般命名规则

        对于共享外设和系统外设,不使用句柄或实例对象。此规则适用于以下外围设备:GPIO、 SYSTICK、NVIC、RCC、FLASH。

        GPIO示例:HAL_GPIO_Init() 只需要 GPIO 地址及其配置参数。

HAL_StatusTypeDef HAL_GPIO_Init (GPIO_TypeDef* GPIOx, GPIO_InitTypeDef *Init)
{
/*GPIO Initialization body */
}

        中断示例:在每个 peripheral/module driver中,定义了处理中断和特定时钟配置的宏。这些宏将导出到外设驱动程序头文件中使用它们。这些宏的列表定义如下:

__HAL_PPP_ENABLE_IT(__HANDLE__, __INTERRUPT__)         //中断使能
__HAL_PPP_DISABLE_IT(__HANDLE__,__INTERRUPT__)         //中断失能
__HAL_PPP_GET_IT (__HANDLE__, __ INTERRUPT __)         //获取中断IT标志
__HAL_PPP_CLEAR_IT (__HANDLE__, __ INTERRUPT __)       //清除中断IT标志
__HAL_PPP_GET_FLAG (__HANDLE__, __FLAG__)              //获取中断flag
__HAL_PPP_CLEAR_FLAG (__HANDLE__, __FLAG__)            //清除中断flag
__HAL_PPP_ENABLE(__HANDLE__)                           //使能外设
__HAL_PPP_DISABLE(__HANDLE__)                          //失能外设
__HAL_PPP_XXXX (__HANDLE__, __PARAM__)                 //特定的PPP HAL driver宏
__HAL_PPP_GET_ IT_SOURCE (__HANDLE__, __INTERRUPT __)  //获取中断源

        NVIC 和 SYSTICK 是 Arm® Cortex® 的两个核心功能。与这些功能相关的 API 位于 stm32f1xx_hal_cortex.c 文件中。

        (原书应该写错了)PPP_InitTypeDef句柄在使用 HAL_PPP_Init() API之前有效。init 函数在修改 handle 字段之前执行检查。如下形式:

hppp = HAL_PPP_Init(PPP_InitTypeDef) 
if(hppp == NULL){ return HAL_ERROR;}

        宏包括,条件宏:使用?:运算符而已。

#define ABS(x) (((x) > 0) ? (x) : -(x))

                      伪代码宏 (多指令宏):使用do{}while(0)包含多个指令而已。

#define __HAL_LINKDMA(__HANDLE__, __PPP_DMA_FIELD_, __DMA_HANDLE_) \ 
do{ \ 
(__HANDLE__)->__PPP_DMA_FIELD_ = &(__DMA_HANDLE_); \ 
(__DMA_HANDLE_).Parent = (__HANDLE__); \ 
} while(0)

5.3、HAL 中断处理程序和回调函数

        HAL 外设驱动程序还包括 中断处理程序HAL_PPP_IRQHandler()(在stm32f1xx_it.c),用户回调函数(具有 “weak” 属性的空函数,必须在用户代码中定义)。

        有三种类型的用户回调函数:外设初始化/去初始化回调:HAL_PPP_MspInit() 和 HAL_PPP_MspDeInit();处理完成回调:HAL_PPP_ProcessCpltCallback(); 错误回调:HAL_PPP_ErrorCallback()。

        回调函数 示例 

HAL_PPP_MspInit() / _DeInit()    
例如:HAL_USART_MspInit():HAL_PPP_Init() API 函数调用此函数,以执行外设系统级初始化(即初始化GPIO、时钟、DMA、中断)。 
HAL_PPP_ProcessCpltCallback()      
例如:HAL_USART_TxCpltCallback():当USART TX完成时由外设或DMA的中断处理程序调用 
HAL_PPP_ErrorCallback()
例如:HAL_USART_ErrorCallback(): 发生错误时由外设或DMA的中断处理程序调用

6、HAL 通用 API

        有4组通用API:

初始化/去初始化:HAL_PPP_Init()、HAL_PPP_DeInit()
IO 操作:HAL_PPP_Read()、HAL_PPP_Write()、HAL_PPP_Transmit()、HAL_PPP_Receive() 
控制功能:HAL_PPP_Set()、HAL_PPP_Get()。 
State 和 Errors 函数:HAL_PPP_GetState()、HAL_PPP_GetError()

        初始化和去初始化功能允许初始化外设和配置硬件资源,主要是时钟、GPIO、替代功能 (AF) 以及可能的 DMA 和中断。HAL_DeInit() 函数恢复 外设默认状态,释放硬件资源并删除与硬件的任何直接依赖关系。

        IO 操作函数对外设有效数据执行基本的写入和读取访问。

        控制功能用于动态更改外设设备配置,并设置另一种操作模式。

        外设状态和错误功能允许在运行时检索外设和数据流状态,并识别发生的错误类型。

下面的示例基于 ADC 外设。泛型 API 的列表并不详尽。它仅作为示例给出。

初始化组 
HAL_ADC_Init()   			//此函数初始化外设并配置相关资源(时钟、GPIO、AF 等)
HAL_ADC_DeInit() 			//此函数恢复外设默认状态,释放相关资源并消除与硬件的任何直接依赖关系。IO 操作组 
HAL_ADC_Start () 			//此函数在使用轮询方法时启动 ADC 转换 
HAL_ADC_Stop () 			//此函数在使用轮询方法时停止 ADC 转换 
HAL_ADC_PollForConversion() //此函数允许在使用轮询方法时等待转换结束。在这种情况下,超时值由用户根据应用程序指定。
HAL_ADC_Start_IT() 			//此函数在使用中断方法时启动 ADC 转换 
HAL_ADC_Stop_IT() 			//此函数在使用中断方法时停止 ADC 转换 
HAL_ADC_IRQHandler() 		//此函数处理 ADC 中断请求 
HAL_ADC_ConvCpltCallback() 	//在 IT 子例程中调用的回调函数,以指示当前进程的结束或当 DMA 传输完成时 
HAL_ADC_ErrorCallback() 	//在 IT 子例程中调用的回调函数,如果发生外设错误或 DMA 传输错误 控制组 
HAL_ADC_ConfigChannel() 	//此功能配置选定的 ADC 常规通道、定序器中的相应列和采样时间 
HAL_ADC_AnalogWDGConfig 	//此功能为选定的 ADC 配置模拟看门狗状态和错误组 
HAL_ADC_GetState() 			//此功能允许在运行时获取外设和数据流状态。
HAL_ADC_GetError() 			//此功能允许在运行时获取 IT 例程中发生的错误

7、HAL 扩展 API

        扩展 API 为特定系列或同一系列中的特定型号提供特定功能或覆盖修改后的 API。扩展API位于 stm32f1xx_hal_ppp_ex.c、stm32f1xx_hal_ppp_ex.h。

        基于 ADC 外设的示例:HAL_ADCEx_CalibrationStart()  //此功能用于启动自动 ADC 校准

        添加新功能的扩展API怎么扩展:5种方式如下:

        (1)在文件stm32f1xx_hal_ppp_ex.c(h)里增加API HAL_PPPEx_Function()

例如stm32f1xx_hal_adc_ex.c/h里

#if defined(STM32F101xG) || defined (STM32F103x6) || defined (STM32F103xB) || defined (STM32F
105xC) ||
defined (STM32F107xC) || defined (STM32F103xE) || defined(STM32F103xG)
/* ADC multimode */
HAL_StatusTypeDef HAL_ADCEx_MultiModeStart_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint
32_t Length);
HAL_StatusTypeDef HAL_ADCEx_MultiModeStop_DMA(ADC_HandleTypeDef *hadc);
#endif 

        (2)新增一个.c文件stm32f1xx_hal_newppp.c,并在stm32f1xx_hal_conf.h使用宏开启:#define HAL_NEWPPP_MODULE_ENABLED

        (3)将stm32f1xx_hal_ppp.c的API加__weak修饰,在文件stm32f1xx_hal_ppp_ex.c里覆写此API

           (4)  加入数据结构中,使用#if defined来控制开启

#if defined(STM32F100xB)
typedef struct
{
(...)
}PPP_InitTypeDef;
#endif /* STM32F100xB */

8、include头文件

        stm32f1xx_hal_conf.h:PPP 驱动程序是项目中使用的独立模块。用户必须在配置文件stm32f1xx_hal_conf.h中使用相应的 USE_HAL_PPP_MODULE define 语句来使能某个PPP驱动程序。例如:#define USE_HAL_USART_MODULE、 #define USE_HAL_IRDA_MODULE

        stm32f1xx_hal.h:stm32f1xx_hal.h包含了整个 HAL 库的通用配置。用户程序和 HAL C源文件中只需包含包含此头文件调用HAL资源。stm32f1xx_hal.h包含了stm32f1xx_hal_conf.h。

9、HAL 通用的定义

        在 stm32f1xx_hal_def.h 中定义了常见的枚举、结构和宏。 

待续,要去练车,科目三

这篇关于STM32F1 HAL库笔记0的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1139591

相关文章

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

数学建模笔记—— 非线性规划

数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学的一个重要分支。2

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个

查看提交历史 —— Git 学习笔记 11

查看提交历史 查看提交历史 不带任何选项的git log-p选项--stat 选项--pretty=oneline选项--pretty=format选项git log常用选项列表参考资料 在提交了若干更新,又或者克隆了某个项目之后,你也许想回顾下提交历史。 完成这个任务最简单而又有效的 工具是 git log 命令。 接下来的例子会用一个用于演示的 simplegit

记录每次更新到仓库 —— Git 学习笔记 10

记录每次更新到仓库 文章目录 文件的状态三个区域检查当前文件状态跟踪新文件取消跟踪(un-tracking)文件重新跟踪(re-tracking)文件暂存已修改文件忽略某些文件查看已暂存和未暂存的修改提交更新跳过暂存区删除文件移动文件参考资料 咱们接着很多天以前的 取得Git仓库 这篇文章继续说。 文件的状态 不管是通过哪种方法,现在我们已经有了一个仓库,并从这个仓

忽略某些文件 —— Git 学习笔记 05

忽略某些文件 忽略某些文件 通过.gitignore文件其他规则源如何选择规则源参考资料 对于某些文件,我们不希望把它们纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。通常它们都是些自动生成的文件,比如日志文件、编译过程中创建的临时文件等。 通过.gitignore文件 假设我们要忽略 lib.a 文件,那我们可以在 lib.a 所在目录下创建一个名为 .gi

取得 Git 仓库 —— Git 学习笔记 04

取得 Git 仓库 —— Git 学习笔记 04 我认为, Git 的学习分为两大块:一是工作区、索引、本地版本库之间的交互;二是本地版本库和远程版本库之间的交互。第一块是基础,第二块是难点。 下面,我们就围绕着第一部分内容来学习,先不考虑远程仓库,只考虑本地仓库。 怎样取得项目的 Git 仓库? 有两种取得 Git 项目仓库的方法。第一种是在本地创建一个新的仓库,第二种是把其他地方的某个

Git 的特点—— Git 学习笔记 02

文章目录 Git 简史Git 的特点直接记录快照,而非差异比较近乎所有操作都是本地执行保证完整性一般只添加数据 参考资料 Git 简史 众所周知,Linux 内核开源项目有着为数众多的参与者。这么多人在世界各地为 Linux 编写代码,那Linux 的代码是如何管理的呢?事实是在 2002 年以前,世界各地的开发者把源代码通过 diff 的方式发给 Linus,然后由 Linus