赞
踩
一、配置寄存器
不少先学了51的朋友可能会知道,会有一小部分人或是教程是通过汇编语言直接操作寄存器实现功能的,这种方法到了STM32就变得不太容易行得通了,因为STM32的寄存器数量是51单片机的十数倍,如此多的寄存器根本无法全部记忆,开发时需要经常的翻查芯片的数据手册,此时直接操作寄存器就变得非常的费力了。但还是会有很小一部分人,喜欢去直接操作寄存器,因为这样更接近原理,知其然也知其所以然。(不是特别推荐,除非是特别感兴趣的小伙伴)
二、标准库
标准外设库(Standard Peripherals Library)是对STM32芯片的一个完整的封装,包括所有标准器件外设的器件驱动器。因为STM32有非常多的寄存器,而导致了开发困难,所以为此ST公司就为每款芯片都编写了一份库文件,也就是工程文件里stm32F1xx.....之类的。有很多的c文件,h文件,包括一些常用量的宏定义,把一些外设也通过结构体变量封装起来,如GPIO口时钟等。因此在使用中我们只需要配置结构体变量成员就可以修改外设的配置寄存器,从而选择不同的功能。但是,标准外设库也是针对某一系列芯片而言的,没有可移植性。
三、HAL库
HAL库是ST公司目前主力推的开发方式,全称就是Hardware Abstraction Layer(抽象印象层)。库如其名,很抽象,一眼看上去不太容易知道他的作用是什么。它的出现比标准库要晚,但其实和标准库一样,都是为了节省程序开发的时期,而且HAL库尤其的有效,如果说标准库把实现功能需要配置的寄存器集成了,那么HAL库的一些函数甚至可以做到某些特定功能的集成。举个例子,标准库就像是你在农村做饭需要大锅烧火,而HAL库就是那个电饭煲你不需要烧火了,并且HAL库也很好的解决了程序移植的问题,不同型号的stm32芯片它的标准库是不一样的,例如在F4上开发的程序移植到F3上是不能通用的,而使用HAL库,只要使用的是相通的外设,程序基本可以完全复制粘贴,注意是相通外设,意思也就是不能无中生有,例如F7比F3要多几个定时器,不能明明没有这个定时器却非要配置,但其实这种情况不多,绝大多数都可以直接复制粘贴。是而且使用ST公司研发的STMcube软件,可以通过图形化的配置功能,直接生成整个使用HAL库的工程文件,可以说是方便至极,但是方便的同时也造成了它执行效率的低下,在各种论坛帖子真的是被吐槽的数不胜数。
STM32CubeMX 是 ST 意法半导体近几年来大力推荐的STM32 芯片图形化配置工具,目的就是为了方便开发者, 允许用户使用图形化向导生成C 初始化代码,可以大大减轻开发工作,时间和费用,提高开发效率。STM32CubeMX几乎覆盖了STM32 全系列芯片。
在CubeMX上,通过傻瓜化的操作便能实现相关配置,最终能够生成C语言代码,支持多种工具链,比如MDK、IAR For ARM、TrueStudio等 省去了我们配置各种外设的时间,大大的节省了时间。
四、配置寄存器与标准库的区别
这里我就用单总线的18B20温湿度传感器的总线转向的代码来表示区别:
这是寄存器:
- #define DS18B20_IO_IN() {GPIOB->CRL&=0XFFFFFFF0;GPIOB->CRL|=8<<0;}
-
- #define DS18B20_IO_OUT() {GPIOB->CRL&=0XFFFFFFF0;GPIOB->CRL|=3<<0;}
这是标准库:
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
寄存器需要查大量手册,太麻烦了,而标准库就是固定的结构,各位多学一些STM32的知识就能记住。
五、STM32 HAL库与标准库的区别
在STM32的标准库中,假设我们要初始化一个外设(这里以USART为例) 我们首先要初始化他们的各个寄存器。在标准库中,这些操作都是利用固件库结构体变量+固件库Init函数实现的:
- USART_InitTypeDef USART_InitStructure;
-
- USART_InitStructure.USART_BaudRate = bound;//串口波特率
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
- USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
- USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
-
- USART_Init(USART1, &USART_InitStructure); //初始化串口1
-
可以看到,要初始化一个串口,需要对六个位置进行赋值,然后引用Init函数,并且USART_InitStructure并不是一个全局结构体变量,而是只在函数内部的局部变量,初始化完成之后,USART_InitStructure就失去了作用。
而在HAL库中,同样是USART初始化结构体变量,我们要定义为全局变量。
UART_HandleTypeDef UART1_Handler;
右键查看结构体成员
- typedef struct
- {
- USART_TypeDef *Instance; /*!< UART registers base address */
- UART_InitTypeDef Init; /*!< UART communication parameters */
- uint8_t *pTxBuffPtr; /*!< Pointer to UART Tx transfer Buffer */
- uint16_t TxXferSize; /*!< UART Tx Transfer size */
- uint16_t TxXferCount; /*!< UART Tx Transfer Counter */
- uint8_t *pRxBuffPtr; /*!< Pointer to UART Rx transfer Buffer */
- uint16_t RxXferSize; /*!< UART Rx Transfer size */
- uint16_t RxXferCount; /*!< UART Rx Transfer Counter */
- DMA_HandleTypeDef *hdmatx; /*!< UART Tx DMA Handle parameters */
- DMA_HandleTypeDef *hdmarx; /*!< UART Rx DMA Handle parameters */
- HAL_LockTypeDef Lock; /*!< Locking object */
- __IO HAL_UART_StateTypeDef State; /*!< UART communication state */
- __IO uint32_t ErrorCode; /*!< UART Error code */
- }UART_HandleTypeDef;
我们发现,与标准库不同的是,该成员不仅包含了之前标准库就有的六个成员(波特率,数据格式等),还包含过采样、(发送或接收的)数据缓存、数据指针、串口 DMA 相关的变量、各种标志位等等要在整个项目流程中都要设置的各个成员。
该UART1_Handler就被称为串口的句柄 它被贯穿整个USART收发的流程,比如开启中断:
HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);
本人也了解的不深,见解有限,我不能理解的不敢写了,大家还想有更深的了解可参考其它厉害的博主,比如博客里的:z小旋,某乎里的:嵌入式er,等等
六、总结
总结一下,配置寄存器太麻烦了,用标准库需要用很多的结构体,而且标准库有很多东西是没有的,需要自己去下载相应的文件到项目,令人头疼的是加入项目后编译不过也不知道是哪里有问题;HAL库功能齐全,并归纳到了一起,使用很简单,只需要使用图像软件简单配置就可以正常使用。但是HAL库模糊了底层逻辑,所以要想明白底层逻辑,更自由的去编程,还是需要学习标准库。
最后,学标准库,推荐大家去看B站的:江协科技,这个UP非常强大,解说非常详细,一手一手的教你,只要你在认真听课,你是一定能学会的。
学HAL库,推荐大家去看B站的:正点原子,不用多说都是很好的UP。
也可以看博客里的:z小旋,配备了STM32CubeMX的下载地址,以及系统的HAL库的学习教程
学配置寄存器的话,这个我并不是很了解,就不误导大家了。
希望文章对大家有用!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。