基于HAL库的STM32外部中断模式
板子:STM32F103C8
编译工具:Keil&STM32CubeMX
烧录工具:FlyMcu
串口调试工具:XCOM
文章目录
〇、什么是中断
指处理机处理程序运行中出现的紧急事件的整个过程.程序运行过程中,系统外部、系统内部或者现行程序本身若出现紧急事件,处理机立即中止现行程序的运行,自动转入相应的处理程序(中断服务程序),待处理完后,再返回原来的程序运行,这整个过程称为程序中断;当处理机接受中断时,只需暂停一个或几个周期而不执行处理程序的中断,称为简单中断.
中断又可分为屏蔽中断和非屏蔽中断两类.可由程序控制其屏蔽的中断称为屏蔽中断或可屏蔽中断.屏蔽时,处理机将不接受中断.反之,不能由程序控制其屏蔽,处理机一定要立即处理的中断称为非屏蔽中断或不可屏蔽中断.非屏蔽中断主要用于断电、电源故障等必须立即处理的情况.处理机响应中断时,不需执行查询程序.由被响应中断源向CPU发向量地址的中断称为向量中断,反之为非向量中断.向量中断可以提高中断响应速度。
------中断控制LED灯亮灭------
一、STMCubeMX配置项目
1. 引脚配置
- A6输出控制LED灯的亮灭,所以为
GPIO_Output
- A4持续输出高电平,同上
- B0持续输出低电平,同上
- B5模拟按钮,设置为
GPIO_Exit5
2. GPIO与NVIC设置
-
B5
引脚的GPIO mode设置为Rising/Falling -
A4
设置为高电平输出,A6
,B0
不管,因为CubeMX默认设置是低电平 -
设置用户标签,方便写代码。这一步看自己,我不推荐,因为不是每一个人的CubeMX都可以成功生成对应代码
笔者在这里使用了用户标签来写函数但报错了,原因是未声明,但是按理来说CubeMX应该在生成代码时用#define声明了这几个标签,可是没有,所以我也不建议非要用用户标签来写代码。
- NVIC中勾选EXTI line[9:5] interrupts
3. 生成项目
因为本次使用到的是Keil,所以我们在IDE这一栏要选择MDK-ARM,Version选择V5及以上。其他的不再多说
这里记得勾选,用于创造一些必要的头文件
二、Keil配置代码
生成Keil代码后点击Open project来到keil界面:
-
点击
stm32f1xx_hal_gpio.c
文件可以找到中断服务函数
右键点击stm32f1xx_hal_gpio.c
,选择F12,进入该函数声明部分,往下划,找到HAL_GPIO_EXTI_Callback
这个函数是回调函数,前面__weak表示此函数为虚函数,需要用户重写。 -
在里面重写下列代码
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
if(GPIO_Pin == GPIO_PIN_5){
//获取B5的电位
GPIO_PinState pinState = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_5);
//低电位
if(pinState==GPIO_PIN_RESET)
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_RESET);//把A6变为低电位
//高电位
else
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_SET);//把A6变为高电位
}
}
- 编译生成.hex文件,烧录
在此之前记得配置一下魔法棒!
三、实际效果
--------中断串口通信--------
四、STMCubeMX配置项目
1. 设置引脚
根据F103C8原理图,得知PA9,PA10分别负责串口1的发送和接收
所以将PA9,PA10引脚的TXD,RXD激活
2. 使能USERT1中断
3. 生成项目
步骤和配置LED一致,不再叙述。
五、Keil配置代码
- 在
main.c
中添加以下声明
uint8_t aRxBuffer; //接收中断缓冲
uint8_t Uart1_RxBuff[256]; //接收缓冲
uint8_t Uart1_Rx_Cnt = 0; //接收缓冲计数
uint8_t cAlmStr[] = "数据溢出(大于256)\r\n";
- 在int main(void){}之后找到如下位置修改代码
/* USER CODE BEGIN 4 */
/**
* @brief Rx Transfer completed callbacks.
* @param huart pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_UART_TxCpltCallback could be implemented in the user file
*/
if(Uart1_Rx_Cnt >= 255) //溢出判断
{
Uart1_Rx_Cnt = 0;
for(int i=0;i<255;i++)
{
Uart1_RxBuff[i]=0;
}
HAL_UART_Transmit(&huart1, (uint8_t *)&cAlmStr, sizeof(cAlmStr),0xFFFF);
}
else
{
Uart1_RxBuff[Uart1_Rx_Cnt++] = aRxBuffer; //接收数据转存
if((Uart1_RxBuff[Uart1_Rx_Cnt-1] == 0x0A)&&(Uart1_RxBuff[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
{
HAL_UART_Transmit(&huart1, (uint8_t *)&Uart1_RxBuff, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
Uart1_Rx_Cnt = 0;
for(int i=0;i<255;i++)
{
Uart1_RxBuff[i]=0;
} //清空数组
}
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1); //再开启接收中断
}
/* USER CODE END 4 */
- 编译烧录
六、实际效果
七、总结
通过中断操作可以更加灵活地使用程序,如果有必要还能够设置优先级使程序能够优先处理紧急任务。
八、参考文章
https://blog.csdn.net/ChenJ_1012/article/details/120962950
https://blog.csdn.net/qq_45659777/article/details/121110712