中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。
中断优先级,如图2所示。
图2 中断优先级
处理器根据不同中断的重要程序设置不同的优先等级。不同优先级中断的处理原则是:高级中断可以打断低级中断;低级中断不能打断高级中断。
NVIC中有一个8位中断优先级寄存器NVIC_IPR,理论上可以配置0~255共256级中断。
STM32只使用了其中的高4位,并分成抢占优先级和子优先级两组。多个中断同时提出中断申请时:先比较抢占优先级,抢占优先级高的中断先执行,如果抢占优先级相同,则比较子优先级。而二者都相同时,比较中断编号。编号越小,优先级越高。
图3 中断优先分组
HAL库初始化函数HAL_lnit将优先级分组设置为第4组,即有0~15,共16级抢占优先级,没有子优先级。编号越小的优先级越高:0号为最高,15号为最低。
速度匹配:可以解决快速的CPU与慢速的外部设备之间传送数据的矛盾。
分时操作:CPU可以分时为多个外部设备服务,提高计算机的利用率。
实时响应:CPU能够及时处理应用系统的随机事件,增强系统的实时性。
可靠性高:CPU可以处理设备故障及掉电等突发事件,提高可靠性。
本实验主要采用下降沿触发的方式。
(1)、引脚分配
将PA6设置为GPIO_Output
模式,将PB13作为按键的引脚设置为外部中断模式GPIO_EXTI
,如图5所示。
图5 引脚分配
引脚分组:①尾号相同的引脚一组,接入1个外部中断线
②同组引脚只能有一个设置为外部中断功能
中断功能:①EXTI0~EXTI4分别具有独立的中断通道
②EXTI5~EXTI9共享同一个中断通道
③EXTI10~EXTI15共享同一个中断通道
如图6所示
图6 中断通道
(2)、外设配置
本实验主要是上升沿触发,PB13的引脚设置为下拉电阻,选择上升沿触发,如图7、8所示。
使能对应的外部中断线
如图9所示
点击NVIC
选择Enabled
图9 使能对应的外部中断线
(3)、中断优先级配置
点击NVIC
,如图10所示。
图10 配置中断优先级
注:大多数情况不必设置中断优先级,而直接使用由中断编号设置的默认中断优先级。抢占优先级为15。
在/* USER CODE BEGIN 4 */
和/* USER CODE END 4 */
中添加代码:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if( GPIO_Pin ==B1_EXTI_Pin)
{
HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);
}
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
是外部中断回调函数
功能描述:外部中断回调函数,用于处理具体的中断任务。
入口参数:GPIO_Pin
:连接对应外部中断线的引脚,范围是GPIO_PIN_0~GPIO_PIN_15
。
HAL_GPIO_TogglePin
实现LED灯引脚翻转,异或操作,0 ^ 1 =1,1 ^ 1 =0。
(1)、HAL库中断处理过程
如图11所示
图11 中断处理过程
(2)、在在stm32f4xx_it.c
中的中断服务程序,如图12、13所示。
图12 服务程序
HAL_GPIO_EXTI_IRQHandler
外部中断通用处理函数
函数原型:void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
功能描述:作为所有外部中断发生后的通用处理函数
图13 调用外部中断回调函数
(3)回调函数
如图14所示。
图14 默认的回调函数
_weak标记,表明这是一个弱函数,用户需要编写同名的回调函数。__weak在回调函数的时候经常用到。这样的好处是,系统默认定义了一个空的回调函数,保证编译器不会报错。同时,如果用户自己要定义用户回调函数,那么只需要重新定义即可,不需要考虑函数重复定义的问题。
在main.c
文件中我们已经编译了我们需要的回调函数。
(4)查看中断工作模式,如图15所示。
图15 触发模式
由图可得,外部中断触发方式为上升沿触发。
1、接线过程和之前作业中的流水灯接线过程相同。本实验采用杜邦线代替按键。因为是上升沿,当PB13从低电平变为高电平,LED灯翻转。
RCC设置为外部时钟源
(1)串口设置参数
如图17所示。
图17 串口设置
设置为异步通信,NVIC Settings
接收中断。
然后创建工程,使用HAL库。
(1)在atm32f1xx_hal.c
中添加
#include "stm32f1xx_hal.h"
#include
extern UART_HandleTypeDef huart1; //声明串口
UART_HandleTypeDef huart1;
UART结构体定义
/**
* 函数功能: 重定向c库函数printf到DEBUG_USARTx
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
/**
* 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
int fgetc(FILE *f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
return ch;
}
发送函数
函数原型:
HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
功能描述:在轮询方式下发送一定数量的数据。4
参数1huart
:串口句柄的地址
参数2pData
:待发送数据的首地址
参数3Size
:待发送数据的个数
参数4Timeout
:超时等待时间,以ms为单位,HAL_MAX_DELAY
表示无限等待。
接收函数
函数原型HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
功能描述:在轮询方式下接收一定数量的数据
参数定义与发送函数相同。
(2)在main.c
中添加
添加定义函数:
#include "stdio.h"
#include
#define RXBUFFERSIZE 256 //最大接收字节数
char RxBuffer[RXBUFFERSIZE]; //接收数据
uint8_t aRxBuffer; //接收中断缓冲
uint8_t Uart1_Rx_Cnt = 0; //接收缓冲计数
在main()
主函数中,调用接收中断函数
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);//使能接收中断
/* USER CODE END 2 */
在main.c
中添加中断回调函数
/* USER CODE BEGIN 4 */
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;
memset(RxBuffer,0x00,sizeof(RxBuffer));
HAL_UART_Transmit(&huart1, (uint8_t *)"数据溢出", 10,0xFFFF);
}
else
{
RxBuffer[Uart1_Rx_Cnt++] = aRxBuffer; //接收数据转存
if((RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
{
HAL_UART_Transmit(&huart1, (uint8_t *)&RxBuffer, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);//检测UART发送结束
Uart1_Rx_Cnt = 0;
memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组
}
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1); //再开启接收中断
}
/* USER CODE END 4 */
串口接收中断回调函数
函数原型:void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
功能描述:回调函数,用于处理所有串口的接收中断,用户在该函数内编写实际的任务
处理程序
串口中断通用处理函数:
函数原型:void HAL_UART_IRQHandler(UART_HandleTypeDef *huart
功能描述:作为所有串口发生后的通用处理函数
1、烧录,可参考我以前的博客
使用野火的串口调式助手,查看结果,如图18所示。
图18串口结构
当每发送一次数据,进行中断输出发送数据stop,然后继续输出hello windows!
注:在烧录的时候可能存在烧录不成功的现象或是其他如工程有误现象可能出现串口调试接收窗口无显示的情况,可以先进性仿真,查看结果是否有输出,串口的仿真可参考我上一篇博客STM32串口描述。
本次实验主要完成中断的两个例题实验,LED灯按键闪亮、串口通信。STM32中断的功能非常强大,中断系统可以实时控制、故障自动处理,中断系统的应用大大提高了计算机效率 。关于中断的描写和例题网上有很多,在实验过程中我也参考了很多资料,所以全程也都没有遇到什么麻烦,关于对中断的学习我还没有弄得太明白,还需要继续学习。如有错误,请指正。
【1】第七章—中断系统
【2】https://blog.csdn.net/as480133937/article/details/99073783
【3】https://blog.csdn.net/u010632165/article/details/104544622