基于标准库函数与基于HAL函数库STM32编程方式的差异

摘要:

本文将基于串口通信的例程,分析基于标准库函数与基于HAL库函数的stm32编程方式的差异

一、简谈标准库函数和HAL库函数的区别

通过对正点原子的产品手册的学习渐渐对这两个库有了更加清晰地认识,下面就谈谈两者的差别

🔥 标准库

这个就是ST以前推出的,哈哈,是不是有种感觉是随着时间推移,这个库函数会退出历史舞台?它的优势在于针对解决了寄存器版本的劣势,方便我们的使用。但是!它的劣势,也就是HAL的优势了!每次修改MCU功能,都要手动修改,自己修改也不能。在不同的MCU间移植性就不是很好了

🔥 HAL库

HAL库,HAL是Hardware Abstraction Layer的缩写,中文名称是:硬件抽象层,HAL库工程一般使用Cube软件来生成工程。HAL库是ST公司为STM32的MCU最新推出的抽象层嵌入式软件,更方便的实现跨STM32产品的最大可移植性。优势就是不需要开发工程师再关注所用MCU型号,只需要专注所以要的功能软件开发工作。而且是未来主推的方向,正在不断的推出更新。

所以 ,我们还是应该与时俱进,多多掌握HAL库


二、具体例子说明差异(串口通信)

下面代码均参考正点原子的代码

标准库

int main(void)
 {		
 	u16 t;  
	u16 len;	
	u16 times=0;
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 //串口初始化为115200
 	LED_Init();			     //LED端口初始化
	KEY_Init();          //初始化与按键连接的硬件接口
 	while(1)
	{
		if(USART_RX_STA&0x8000)
		{					   
			len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
			printf("\r\n您发送的消息为:\r\n\r\n");
			for(t=0;t<len;t++)
			{
				USART_SendData(USART1, USART_RX_BUF[t]);//向串口1发送数据
				while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
			}
			printf("\r\n\r\n");//插入换行
			USART_RX_STA=0;
		}else
		{
			times++;
			if(times%5000==0)
			{
				printf("\r\n精英STM32开发板 串口实验\r\n");
				printf("正点原子@ALIENTEK\r\n\r\n");
			}
			if(times%200==0)printf("请输入数据,以回车键结束\r\n"); 
			if(times%30==0){LED0=!LED0; LED1=!LED1;}//闪烁LED,提示系统正在运行.
			delay_ms(10);   
		}
	}	 
 }

HAL

int main(void)
{
	u8 len;	
	u16 times=0;
	
    HAL_Init();                    	 	//初始化HAL库    
    Stm32_Clock_Init(RCC_PLL_MUL9);   	//设置时钟,72M
	delay_init(72);               		//初始化延时函数
	uart_init(115200);					//初始化串口
	LED_Init();							//初始化LED	
	KEY_Init();							//初始化按键
	
    while(1)
    {
			
       if(USART_RX_STA&0x8000)
		{					   
			len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
			printf("\r\n您发送的消息为:\r\n");
			HAL_UART_Transmit(&UART1_Handler,(uint8_t*)USART_RX_BUF,len,1000);	//发送接收到的数据
			while(__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_TC)!=SET);		//等待发送结束
			printf("\r\n\r\n");//插入换行
			USART_RX_STA=0;
		}else
		{
			times++;
			if(times%5000==0)
			{
				printf("\r\nALIENTEK 精英STM32开发板 串口实验\r\n");
				printf("正点原子@ALIENTEK\r\n\r\n\r\n");
			}
			if(times%200==0)printf("请输入数据,以回车键结束\r\n");  
			if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行.
			delay_ms(10);   
		} 
    }
}

是不是乍一看主函数并没有什么不同

但是对比初始化函数

还是有很大不一样的,左图HAL,右图标准库

体现在非常重要的一点:

函数句柄

  • 在STM32的标准库中,假设我们要初始化一个外设(这里以 USART为例)我们首先要初始化他们的各个寄存器。在标准库中,这些操作都是利用固件库结构体变量+固件库lnit函数实现的;可以看到,要初始化一个串口,需要对六个位置进行赋值,然后引用Init函数,并且 USART Initstructure并不是一个全局结构体变量,而是只在函数内部的局部变量。USART_InitTypeDef USART_InitStructure;函数内定义
  • 而在HAL库中,同样是 USARTA初始化结构体变量,我们要定义为全局变量。UART_HandleTypeDef UART1_Handler;函数外定义。看其结构体定义,与标准库不同的是,该成员不仅包含了之前标准库就有的六个成员(波特率,数据、格式等),还包含过采样、(发送或接收的)数据存、数据指针、串口DMA相关的变量、各种标志位等等要在整个项目流程中都要设置的各个成员。回调函数只需要用函数句柄就好

三、总结

正如上面所谈到的,标准库函数的优点就是寄存器的缺点,而标准库函数的缺点就是HAL库的优点。这一块相比大家仔细看看代码也能发现这个道理。更好的移植性是HAL的特点而凭借这个特点在未来,HAL库将会越走越远。

参考
[1]https://blog.csdn.net/weixin_34417183/article/details/91683056?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control
[2]http://www.360doc.com/content/19/1225/17/38894361_882147885.shtml

  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值