本文开发环境:
- MCU型号:STM32F051R8T6
- IDE环境: MDK 5.25
- 代码生成工具:STM32CubeMx 5.0.1
- HAL库版本:v1.9.0(STM32Cube MCU Package for STM32F0 Series)
本文内容:
- STM32CubeMx 配置异步串口中断配置
- 串口数据的中断收发
所需工具:
硬件:USB转串口模块
软件:串口助手
STM32CubeMx 初始化串口中断的配置
在上一节中,我们已经初始化了串口的最基本功能,由于没有开启中断,只能使用轮询方式收发数据。但是我们经常需要中断来实现程序功能。
所以这里我们打开上一节的CubeMx文件(目录下 .ioc 格式文件),进一步的配置串口的中断。配置中断主要是使能NVIC中断,并设置好中断优先组。以下是具体的配置:
我们在NVIC设置中,使能串口的全局中断,这样工程就会生成串口中断函数的定义。但是我们还需要让工程生成串口中断初始化函数,这部分在NVIC中配置,具体如下图所示:
M0的中断优先级别没有M3,M4那样可以设置分组,它只有4个等级可以选,我们这里可以保持默认的0,和其它模式一致,也可以改为其他数值。这个根据具体程序需求来确定,具体设置方法如下(以等级为1为例):
这点击GENERATE CODE生成代码后,就可以编写用户程序了。
中断回调函数的使用
当我们配置使能中断以后,一旦MCU对应的串口收到数据,就会触发串口中断,串口中断函数会判断一些错误信息标志位等,如果串口状态正常,则失能该串口中断,然后执行回调函数,所以当我们运行回调函数后,结束前需要再次开启中断,否则中断处于失能状态。接着,工程默认函数串口的中断处于失能状态,我们可以通过HAL_USART_Receive_IT()函数来使能,同时它也是配置函数,关于中断的使用,示例程序如下:
... ...
uint8_t recv_data[512]; //定义接受数据的数组
uint8_t send_data[512]; //定义发送数据的数组
... ...
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
send_data[0] = recv_data[0] + 1;
HAL_UART_Transmit(&huart1,(unsigned char *)&send_data,1,0x200);//发送数据+1后的值
HAL_UART_Receive_IT(&huart1, recv_data,1); //再次使能接受中断
}
... ...
void main(void)
{
... ...
HAL_UART_Receive_IT(&huart1, recv_data,1); //使能接收中断,并配置为每次1个字节,即收到1个字节即调用回调函数
... ...
while(1)
{
}
}
特别的,这个函数是串口中断函数,并非某一串口特有,既是,任何一个串口中断的发生,最后都会调用这个函数中,当我们的工程有多个串口中断的时候,我们就需要区分本次中断的来源,我们可以通过huart->Instance变量来判断,示例代码如下:
... ...
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
HAL_UART_Transmit(&huart1,"串口1中断\r\n",strlen("串口1中断\r\n"),0x200);
HAL_UART_Receive_IT(&huart1, recv_data,1); //再次使能接受中断
}
if(huart->Instance == USART2)
{
HAL_UART_Transmit(&huart1,"串口2中断\r\n",strlen("串口2中断\r\n"),0x200);
HAL_UART_Receive_IT(&huart2, recv_data,1);
}
}
当然本代码只是示例了判断的方法,在实际应用中,需要在CubeMx中初始化串口2等相关操作。
常见问题
关于CubeMx串口中断最常见的问题是已经生成串口中断相关的初始化代码了,但中断函数并不运行,这可能是因为默认没有开启串口中断的原因,只在软件配置使能使能了NIVC中断。
还有可能发现程序只运行一次串口中断,这是因为每次串口中断函数都会关闭自身中断,然后再调用回调函数,如果回调函数中不重新开启中断,则串口将处于中断失能状态。
最后,虽然本文的MCU型号是STM32F051,但是在STM32F103,STM32F205的MCU上,配置流程和代码使用并无不同,这也体现了CubeMx工具的便利性和HAL库的兼容性。