我正在使用与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);
}
}
}
答案 0 :(得分: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
用于什么?对我而言,它看起来弊大于利。
答案 1 :(得分:3)
回调函数和程序其余部分之间共享的变量必须声明为volatile,以防止编译器错误地优化代码。
您还必须确保对这些变量的写入和读取是原子的,或者用信号量保护它们。否则你可能会遇到竞争条件错误。
这两个经典错误中的任何一个或两个都可能导致您描述的问题:两者都会导致难以重新产生的间歇性,意外行为。
此外,如果您的CPU允许,请设置一个断点,该断点在对中断使能寄存器进行写访问时触发并检查跟踪。