标准库占绝大多数,自己买的板子跟的资料也一般是标准库,HAL库很少,不过要是使用STM32CubeMx配置,那么就是使用的HAL库了,而参考资料是标准库的,就没有办法用。
注意:
1. 标准库与HAL库不兼容,不要想着直接拿来用了,比如标准库使用#include "stm32f10x.h",HAL库使用#include "stm32f1xx_hal.h"
要让标准库程序使用HAL库时也可以正常运行得到想要的结果,有以下几种方法:
一、 将标准库程序中的每个函数内的代码修改为使用HAL库且同样效果的代码,
比如标准库中配置GPIO的代码直接就可以用STM32CubeMx配置为相同效果
二、根据标准库程序整个程序运行的原理使用HAL库中提供的函数实现,
比如使用IIC写入内存的代码可以使用HAL库中提供的函数HAL_I2C_Mem_Write
实现
先举例介绍第一种方法:
1. 外部中断
标准库:中断入口函数在stm32f10x_it.c中,修改void EXTI&_IRQHandler()
使用if(EXTI_GetITStatus(EXTI_Line2)==SET)判断是否产生中断
处理中断时,要清除中断线路挂起位(EXTI_ClearITPendingBit),以便下次使用
HAL库:在stm32f1xx_it.c中依然有中断入口函数void EXTI2_IRQHandler(void)
该函数调用了HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);,当该引脚产生中断事件时会调用该函数
最后会由HAL_GPIO_EXTI_Callback(GPIO_Pin);回调函数执行中断,该函数是可以被重定义的,复制该函数添加到main.c中就可以进行特定引脚的中断事件处理
在HAL库的回调函数和标准库的中断入口函数中的中断事件执行是差不多的
2. 引脚操作
51、STM32的标准库和HAL库对引脚都有基本的读取引脚状态和设置引脚的操作
51:P0 = 0x00; //置P0口为低电平,P08个IO口全为低电平
P0 = 0xff; //置P0口为高电平
注意P0有8个IO口,即从P0.0到P0.7,而0x00二进制就是0000 0000,效果就是P0.0到P0.7都是0,即低电平。
P0 = 0xC8;
51可以实现直接将八位二进制直接传递给8个IO口,只需一次传值;也可以单独对某个IO口设置,但HAL库只能一次对一个引脚操作
标准库:GPIO_SetBits(GPIOC,GPIO_Pin_All);将引脚置1,可以将多个引脚一起设置使用GPIOx->BSRR = GPIO_Pin;
GPIO_ResetBits(GPIOC,GPIO_Pin_All);将引脚置0,使用GPIOx->BRR = GPIO_Pin;
GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)读取引脚状态
HAL库:所有GPIO的操作函数在stm32f1xx_hal_gpio.h中,也定义了一些GPIO设置用到的参数
具体函数见stm32f1xx_hal_gpio.h,功能和标准库大致相同,有一个引脚反转函数HAL_GPIO_TogglePin
问题:如何使用HAL库实现向多个引脚写入八位十六进制数据?
51:cmd = 0xc8;
PC = cmd;
HAL库:cmd = 0xc8;
if(cmd&0x01)
{
HAL_GPIO_WritePin(GPIOC,D0_Pin,GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOC,D0_Pin,GPIO_PIN_RESET);
}
if(cmd&0x02)
{
HAL_GPIO_WritePin(GPIOC,D1_Pin,GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOC,D1_Pin,GPIO_PIN_RESET);
}
if(cmd&0x04)
{
HAL_GPIO_WritePin(GPIOC,D2_Pin,GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOC,D2_Pin,GPIO_PIN_RESET);
}
if(cmd&0x08)
{
HAL_GPIO_WritePin(GPIOC,D3_Pin,GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOC,D3_Pin,GPIO_PIN_RESET);
}
if(cmd&0x10)
{
HAL_GPIO_WritePin(GPIOC,D4_Pin,GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOC,D4_Pin,GPIO_PIN_RESET);
}
if(cmd&0x20)
{
HAL_GPIO_WritePin(GPIOC,D5_Pin,GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOC,D5_Pin,GPIO_PIN_RESET);
}
if(cmd&0x40)
{
HAL_GPIO_WritePin(GPIOC,D6_Pin,GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOC,D6_Pin,GPIO_PIN_RESET);
}
if(cmd&0x80)
{
HAL_GPIO_WritePin(GPIOC,D7_Pin,GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOC,D7_Pin,GPIO_PIN_RESET);
}
这个方法比较笨,是使用与运算直接判断八位二进制数据的各位是0还是1,然后设置相应引脚即可。
3. 直接操作寄存器
这个在标准库和HAL库中的使用是一样的,
标准库:例如 #define IIC_SDA_IN() {GPIOB->CRH &= 0XFFFF0FFF;GPIOB->CRH |= 8 << 12;GPIOB->BSRR = 1 << 11;}
其中GPIOB是在stm32f10x.h中定义的,其中BSRR、CRH等是GPIO结构体中的属性,结构体为:
typedef struct
{
__IO uint32_t CRL;
__IO uint32_t CRH;
__IO uint32_t IDR;
__IO uint32_t ODR;
__IO uint32_t BSRR;
__IO uint32_t BRR;
__IO uint32_t LCKR;
} GPIO_TypeDef;
HAL库:例如 #define LCD_RST_CLR GPIOC->BRR=1<<5
其中GPIOC是在stm32f103xe.h中定义的,BSRR,BRR等GPIO结构体的属性也是在该文件中定义的,具体结构体为:
typedef struct
{
__IO uint32_t CRL;
__IO uint32_t CRH;
__IO uint32_t IDR;
__IO uint32_t ODR;
__IO uint32_t BSRR;
__IO uint32_t BRR;
__IO uint32_t LCKR;
} GPIO_TypeDef;
与标准库的GPIO结构体定义相同。