? ? ? ? 又遇到了一个问题,就是usart做压力测试,usart1和usart2透传(usart1接收usart2发/usart2接收usart1发),收一个数据回调中发一个数据,快速传输大量数据的情况下会发生卡死,无法继续传输,只能reset解决的办法,并且我开了usart1和2这个问题只出现在了usart2上,胡乱猜测可能是因为usart2是挂载总线时钟apb2上才导致这个问题或者是中断执行是先写usart1的判断导致时间长了几us。但是有了上次的教训这次一下就找到了问题所在,还是坑比hal库。
? ? ? ? 句柄有个很有用的成员是errorcode,基本上只要出错他就会忠实的记录出错的地方,一翻发现是出现溢出错误了,这个溢出错误我现在还是没搞懂是什么意思,因为好像我就算不理他我的数据好像也没错,btw先给出参考手册的定义
我看其他帖子说这里其实有一个文字错误是清除中断的方法是读sr和dr而不是读sr和cr
????????但是hal库最逗的地方在于他给你报完错直接给你卡死了,读代码可以发现是中断处理函数的逻辑有问题,在中断处理函数HAL_UART_IRQHandler中,是先判断错误标志位再进行读取操作的,也就是说当ore置位,不进入hal库的中断处理UART_Receive_IT而是直接报错就结束了。
????????这就导致一个问题,因为清除接收中断标志位是通过读取里面的数据以后自动完成的,所以如果没进入UART_Receive_IT,那么就不会清除标志位,下次中断无法触发,即使加入语句清了ORE和RXNE也会出些很迷惑的错误,一直中断或者丢数据一类的。
/* If no error occurs */
errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
//在这里判断了ore的值,如果ore置位,errorflags不为0,无法进入uart_receive_it
if (errorflags == RESET)
{
/* UART in mode Receiver -------------------------------------------------*/
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
{
UART_Receive_IT(huart);
return;
}
}
????????解决办法我看了好几个,有关闭ore检测的(好像现在的cubemx没有这个功能了),有写错误回调的,还有其他的一些办法,但是我不太敢动库函数怕忘记,还是采用了最简单的std库思想来写,把源码中涉及读写的两给语句拉出来。
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
if((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE)||__HAL_UART_GET_FLAG(&huart1, UART_FLAG_ORE))==SET)
{
*SendBuff = (uint8_t)(huart1.Instance->DR & (uint8_t)0x00FF);
huart2.Instance->DR = (uint8_t)(*SendBuff & 0xFFU);
简单的读标志位,然后对数据读完再写,检测了一下发多少字节收的到多少字节,快速循环发送也不出错。
? ? ? ? 还有一个办法就是置一个标志变量在主循环发完再清零,但是如果是主循环有长时间延时的对于频繁的数据收发可能不好用
? ? ? ? 只能说hal库对于系统的封装过于死板和冗余了,冗余的错误判断和死板的回调真的会导致当需求不在他提供的接口里面时,整个hal库的逻辑都会是你完成需求的障碍
|