STM32的CubeMX关于串口中断接收

C语言

作为刚工作不久的小白,刚接触STM32的HAL库,工作中使用到了,就记录下自己遇到的问题,希望看到的大佬多多指教。

1、关于串口的初始化函数:

    MX_USART2_UART_Init()---波特率、奇偶校验等配置

            HAL_UART_Init()---会将 huart->RxState = HAL_UART_STATE_READY;

    HAL_UART_MspInit()---GPIO,中断优先级等配置

2、当需要使用中断接收时需要调用

    HAL_UART_Receive_IT()---配置接收的缓冲区指针,数量,huart->RxState = HAL_UART_STATE_BUSY_RX;,最后使能相应中断

3、当中断发生时,执行

    HAL_UART_IRQHandler()--判断中断的类型,在此处我用到的是非空中断,那么会继续调用UART_Receive_IT(huart);

    这个函数会首先判断串口的接收状态huart->RxState == HAL_UART_STATE_BUSY_RX,若果为真就进行数据的保存,进 如     果达到规定的传输数量就会关闭中断,改变huart->RxState = HAL_UART_STATE_READY;然后执行HAL_UART_RxCpltCallback();如果不为真,就清除接收中断标志。

4、HAL_UART_RxCpltCallback()这个函数里尽可能的少些代码否则影响效率,如果想再次开启中断,可以在这里调用       HAL_UART_Receive_IT(),进行再次接收

下面说说我遇到的问题:

初始化串口完毕后,调用一次HAL_UART_Receive_IT(&huart2,uxComDMA.ucRxBuf,ONE_BYTE),进行一个字节的中断接收,然后在HAL_UART_RxCpltCallback()函数里,进行帧头的校验和传输数量的计算,然后继续开启。代码如下

           //如果计算的数量大于规定的数量,说明传输出错。丢弃,判定上位机发送是否错误
            if(usRecLength > DMA_BUF_MAX)
            {
                uxComDMA.ucRxBuf[eMsg_DTH] = APP_NULL;
                uxComDMA.ucRxBuf[eMsg_DTL] = APP_NULL;
                uxComDMA.usRxLen = APP_NULL;
                PTCL_Dbg("计算数量大于规定数量");
            }
            //接收的数量大于等于计算的数量
            if(uxComDMA.usRxLen >= usRecLength)
            {
                uxComDMA.uxReceiveFlag = eAppTrue;//标记接收完成。---此时不再调用HAL_UART_Receive_IT()
            }
            else//继续接受下一个数据
            {
                HAL_UART_Receive_IT(&huart2, uxComDMA.ucRxBuf+uxComDMA.usRxLen,ONE_BYTE);

            }

当正确接收一帧数据后,便不再开启,直到这一阵数据处理完,主程序再次调用HAL_UART_Receive_IT()进行下一轮的接收。

那么问题来了:规定的协议是8个字节,在正确接收到8个字节后便不再开启中断接收,主函数执行数据帧的处理完毕后才会开启。但是如果上位机一次一共发送了10个字节,前8个字节是正确的一帧,后面2个无用。当下位机接收到8个字节便关闭了中断,处理完后再次开启。然后上位机再发来数据,发现下位机再也不能执行HAL_UART_RxCpltCallback(),协议就报废了。

调试后发现,后来接收数据时虽然可以进入中断并且执行了UART_Receive_IT();但是huart->RxState 的值不是HAL_UART_STATE_BUSY_RX导致不能继续执行传输完成回调。疑问是,最后一次开启中断接收时调用HAL_UART_Receive_IT()函数确实将 huart->RxState = HAL_UART_STATE_BUSY_RX;

PTCL_Dbg("初始化接收的状态%d",HAL_UART_Receive_IT(&huart2,uxComDMA.ucRxBuf,ONE_BYTE));//串口2的接收中断

                                                                                                                                                       函数返回值为HAL_OK

PTCL_Dbg("串口的接收状态%#x\r\n",huart2.RxState);----确实不等于HAL_UART_STATE_BUSY_RX,而是等于                                                                                                                                                   HAL_UART_STATE_READY

//    huart2.RxState = HAL_UART_STATE_BUSY_RX; ----加上这句话,可以解决问题


这是为什呢?

解决上述问题:

关于上述问题的总结:后两个字节传输时,已经关闭了中断,但是硬件将ORE位(溢出标志,看数据手册)置一和RXNE位置一。当调用HAL_UART_Receive_IT()函数时,会同时使能EIE、PEIE、RXNEIE三个中断。第一次我手动将RXNE位清除,但是没有清除ORE位,造成调用就会立即产生中断(溢出中断)。当执行HAL_UART_IRQHandler()函数时:      

   



关于HAL库,更多的是考虑到安全性和兼容性所以代码量比较大,一开始使用不会像我们使用寄存器那么随意,所以必须深入看源码,才能更好的使用。


猜你喜欢

转载自blog.csdn.net/qq_41092963/article/details/81053499