历史上的今天
今天是:2025年07月09日(星期三)
2019年07月09日 | 使用STM32hal库usart的接收中断分析及出现部分问题的解决
2019-07-09 来源:eefocus
最近开始使用ST的hal库,这个库相较于之前的标准库,优缺点兼具吧,hal库封装了更多底层的细节,我们可以很轻易的实现我们需要的功能,但是由于封装了太多的细节,导致一旦出问题,你就很难发现问题,内部调用的复杂让你觉得懵逼。
(一)hal库接收中断的分析
这几天在使用hal库的USART,其中用到的是接收中断,官方推荐的使用接收中断的方式是:在初始化函数上面先开启接收中断(这里就不介绍串口的配置,网上一大推,我就不给世界增加无谓的存储量了),开启的函数如下:
HAL_UART_Receive_IT(&huart2,(uint8_t*)aRxBuffer, 1);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量
接着直接调用总的回调函数就可以了(这个函数的名称是定义好的),的:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART2)//判断,如果是串口2
{
//在这里写入自己要实现的代码
}
}
其实使用回调函数的原理大概是这样的:MCU接收到数据产生中断,进入中断函数:
//串口中断服务程序
void USART1_IRQHandler(void)
{
u32 timeout=0;
HAL_UART_IRQHandler(&UART1_Handler); //调用HAL库中断处理公用函数
//省略部分代码
/*
代码
*/
}
也就是中断进入了HAL_UART_IRQHandler(&UART1_Handler);这个函数,这个函数是一个总的中断处理函数,也就是很多串口的中断处理最后都汇集到这个地方来处理。其实体如下:
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
/*
省略一部分代码
*/
UART_Receive_IT(huart);
/*
省略一部分代码
*/
}
而UART_Receive_IT(huart);的实现如下:
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
/*
省略一部分代码
*/
HAL_UART_RxCpltCallback(huart);
/*
省略一部分代码
*/
}
也就是说最后会调用到 HAL_UART_RxCpltCallback(huart);,我们在这个函数内部做自己的需求就好了。
(二) 为了效率出了问题
由上面的分析,我们可以知道,hal库的中断接收虽然很方便,但是是非常没有效率的,兜兜转转绕了一个大弯才能处理中断接收的数据。尤其是我使用的是STM32F0的芯片,频率只有48M,不比那些动不动就上百兆的芯片,这样的中断处理显然不能接受。
所以,借鉴于标准库,我想直接在串口中断函数(void USART2_IRQHandler(void))上直接处理函数,而不用在转一个圈跑到回调函数( HAL_UART_RxCpltCallback(huart))上处理。
然而,一改,问题就来了,一共遇到过两个问题。
(1)一进中断就出不来
由于不知道之前hal库在中断处理做了什么手脚,所以自己也忘了判断和清除中断标志,加上下面几句话就好了。
void USART2_IRQHandler(void)
{
/* UART in mode Receiver ---------------------------------------------------*/
if((__HAL_UART_GET_IT(&huart2, UART_IT_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_RXNE) != RESET))
{
/*
处理代码
*/
/* Clear RXNE interrupt flag */
__HAL_UART_SEND_REQ(&huart2, UART_RXDATA_FLUSH_REQUEST); //清除接收数据非空中断标志
}
}
(2)一进入中断MCU就死机
这个问题是由于我在中断处理了大量的任务导致的死机,虽然我之前同样在别的芯片上这样处理而没有出现问题,不过以前用的芯片比我现在用的这款强大太多了,还是那句老话:不要在中断干太多的任务。你可以在中断完成一些标志,或者处理一下接收的数据(可以转存到别的数据,但记住不要用hal库的函数,卡死不负责)然后在回到主函数处理。比如:
void USART2_IRQHandler(void)
{
/* UART in mode Receiver ---------------------------------------------------*/
if((__HAL_UART_GET_IT(&huart2, UART_IT_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_RXNE) != RESET))
{
flag_text=1; //中断标志
/* Clear RXNE interrupt flag */
__HAL_UART_SEND_REQ(&huart2, UART_RXDATA_FLUSH_REQUEST); //清除接收数据非空中断标志
}
}
最后,祝自己和各位少遇bug
史海拾趣
|
CE下普通应用开发是选择C还是高级的.NET(Java)合适? 公司有一定数量的普通应用开发,涉及到Socket或其它网络通信,而不是开发驱动程序,这种情况下的常见方案是否选择C/C++?… 查看全部问答> |
|
举个例子来引出我的问题 MX27 处理器以MX21 为基础进行设计,基于ARM926EJ-S s3c2410的处理器是ARM920T 请问各位 首先,之间有什么区别,是不是:1、处理器型号?2、寄存器地址不同?等等 大家能不能帮我说个大概? 其次,编程的时候是不是每 ...… 查看全部问答> |
|
闲的无事,来测试一下LED的一致性怎么样,用应急灯的变压器输出18V,串联470欧电阻,5只LED串联,测量得5只LED压降分别为 3V 2.92V 2.92V 2.91V 2.87V 电流为6mA。以上参数供大家参考。… 查看全部问答> |
|
(CoreCon) Failed to connect debug message service! Please check the transport settings.(CoreCon) Transport service failed to connect(CoreCon) Error: A service has failed to connect. Make sure that all services are correctly config ...… 查看全部问答> |
|
向tiankai001求助winavr+avrstudio C语言编译要求makefile问题 tiankai001你好,我正想学用avr,刚一上手就遇到编译问题,在avrstudio4环境下借助winavr用C编写程序, 要求makefile,不知怎么解决。在论坛里看到你在用winavr,希望能得到你的帮助,如何在avrstudio中用C 编译一个程序,如点亮一个LED,多谢!… 查看全部问答> |
|
我在连接上internet之后,隔了大概2分钟,服务器发来的数据我的GPRS就收不到了数据了。而在这2分钟之内发数据是可以收到的。谁能帮我解答下这是什么原因啊? 还有就是,确认MC52i跟Internet还是连接的,没有断开,因为在这期间一直可以发送数据到 ...… 查看全部问答> |




