一般工况是类似MODBUS主从通讯,上位机发下位机收,如果通信负载不大,极少出现发送数据时候出现接收中断,不过这种BUG经不起通讯测试。如:
测试用例:
测试冗余数据发送,使用自动测试脚本,在通信帧的校验码后字节添加1-8字节随机数,每种字节长度测试10000次。
以上测试初串口就会崩溃,只能发不能收,调试结果是,串口接收中断不再响应。
源码中使用HAL_UART_Receive_IT 中断接收数据,HAL_UART_Transmit非中断方式发送,两个函数内部均有这样的宏函数:
#define __HAL_LOCK(__HANDLE__)\
do{\
if((__HANDLE__)->Lock == HAL_LOCKED)\
{\
return HAL_BUSY;
\
}\
else\
{\
(__HANDLE__)->Lock = HAL_LOCKED;
\
}\
}while (0U)#define __HAL_UNLOCK(__HANDLE__)\
do{\
(__HANDLE__)->Lock = HAL_UNLOCKED;
\
}while (0U)
原因在于进入接收中断后__HAL_LOCK(huart)发现UART资源已经被锁,随即返回HAL_BUSY,不再执行HAL_UART_Receive_IT中的打开接收中断代码,所以uart再无法接收数据。锁住该UART的是发送函数中的__HAL_LOCK(huart)。
此BUG多次在论坛提及,只是ST官方一直没有处理,着实坑过不少人……参见:
https://community.st.com/s/question/0D50X00009XkeOGSAZ/questions-surrounding-hallock
他们的临时处理方式是将库函数中发送功能代码拷贝到自己的函数中,去掉上锁解锁操作。
解决方式:
注释掉__HAL_LOCK、__HAL_UNLOCK即可。
话说为什么要加锁呢?看起来只是为了保护一些串口操作变量,不过乍一看唯一有冲突的是这个:
【huart->ErrorCode = HAL_UART_ERROR_NONE; 】
因为发送与接收操作变量是分开的,只有ErrorCode有可能被异常地修改,所以注释掉这种保护并不会影响正常使用。
【STM32 HAL库 串口收发崩溃原因 ( __HAL_LOCK)】同样的问题,可以参考这个:https://www.jianshu.com/p/6995fb60364f
最后,CAN, USB, UART等出现类似问题也不足为奇了。
推荐阅读
- C语言学习|第十一届蓝桥杯省赛 大学B组 C/C++ 第一场
- 【C】题目|【C语言】题集 of ⑥
- 单片机|自学单片机好找工作吗(会单片机能找什么工作?)
- 单片机|keil把源代码生成lib的方法
- c语言|一文搞懂栈(stack)、堆(heap)、单片机裸机内存管理malloc
- c语言|C语言初期学习遇到的特殊点 【三子棋详解】【初学者福音,详细总结,复习能手】
- 笔记|C语言数据结构——二叉树的顺序存储和二叉树的遍历
- 个人理解|【C语言基础之类型转换】
- c语言|【C语言】自定义类型 结构体 枚举 联合
- 学习分享|【C语言函数基础】