4

我正在使用与 xbee 连接的 STM32f4 发现板来接收来自远程温度传感器的温度数据。使用的代码是 CMIS UART 示例代码。我将接收数据包数据,一次 1 个字节。换句话说,只要接收到每个字节,就会调用 UART 接收中断。一旦我得到完整的数据包,我将复制温度数据。我的 UART 回调函数可以正常工作。但是几个小时后,UART接收中断停止工作,UART无法接收任何东西。但是 UART 传输仍然有效。我正在使用波特率为 115200 的 UART1。我已将 UART 中断优先级设置为 0,并且没有其他中断共享此优先级。所有其他中断优先级均低于 UART。谁能告诉我为什么UART中断停止触发?

#define PACKET_DELIMETER 0x7E

uint8_t g_frame_ok=0; //flag to indicate complete packet received
uint8_t g_index_of_aoBuf=0; //Index of receive buffer
uint8_t g_aoBuf_of_xbee[100]={0};//Receive Buffer
uint8_t r_byte=0; //Receiving byte 

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *allUartHandle)
{
 __HAL_UART_FLUSH_DRREGISTER(allUartHandle); 

 if(HAL_UART_Receive_IT(allUartHandle, (uint8_t *)&r_byte, 1) == HAL_OK) //Interrupt occurs when each byte arrives
 {
    if(r_byte==PACKET_DELIMETER)
    {
        //start receiving packet
    }
    if( g_index_of_aoBuf>=g_aoBuf_of_xbee[2]+4)
    {
        g_frame_ok=1;
        BSP_LED_On(LED4);
    }           
   }
 }
4

2 回答 2

4

我从未使用过您提到的 API,所以我可能是错的,但以下是我在查看后注意到的一些事情:

HAL_UART_RxCpltCallback不是UART中断。它是来自 HAL 子系统的回调,当您发出的接收请求完成时将调用该回调。这意味着它只会在您发出接收请求后的一段时间内被调用。你无权访问 UART 中断,如果你使用 HAL 层,你不应该尝试弄乱它。

关于这个,HAL_UART_Receive_IT实际上是一个会发出接收请求的函数。它总是会立即返回,并且永远不会收到任何东西。这意味着调用后接收缓冲区中的数据无效。一旦您发出请求,HAL_UART_RxCpltCallback将在接收完成后随时调用。只有此时缓冲区中的数据才有效。要检索数据,您可以使用 中的相同变量HAL_UART_Receive_IT,但也可以通过(UART_HandleTypeDef*)->pRxBuffPtr回调参数使用数据缓冲区。

我认为HAL_UART_Receive_IT在回调中再次调用是可以的,但最后可能会更好。

还有,是干什么__HAL_UART_FLUSH_DRREGISTER用的?在我看来,它弊大于利。

于 2015-07-01T12:25:33.860 回答
3

在回调函数和程序其余部分之间共享的变量必须声明为 volatile,以防止编译器错误地优化代码。

您还必须确保对此类变量的写入和读取是原子的,或者使用信号量保护它们。否则你可能会遇到竞争条件错误。

这两个经典错误中的一个或两个都可能导致您描述的问题:两者都倾向于导致难以重现的间歇性、意外行为。

此外,如果您的 CPU 允许,请设置一个断点,该断点在对中断启用寄存器的写访问时触发并检查跟踪。

于 2015-07-01T11:25:39.173 回答