我有一个使用 STM32L010F4 的项目,它通过 UART 接收六个字节的数据。收到后,它应该将 ACK 发送到不同的设备。 RX 数据有一个已知的 SOF 和 EOF 字节。我正在使用 DMA 接收数据。重新启动项目后,我第一次获取数据的顺序是正确的:第一个字节是 SOF,然后是四个字节的数据,然后是 EOF 字节。然而,随后的接收首先是 EOF 字节,然后是 SOF 字节,然后是四个数据字节。我正在清除读取之间的 RX 缓冲区,所以我不认为这可能是剩余数据的情况。
/* Private user code -------------------------------------------*/
uint8_t RX_Data[6] = {0};
uint8_t ACK_Data[3] = {0x01, 0x30, 0x0D};
uint8_t RX_Data_Rdy = 0;
uint8_t TX_Data_Pending = 0;
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* MCU Configuration-----------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART2_UART_Init();
MX_LPUART1_UART_Init();
/* Infinite loop */
while (1)
{
if(RX_Data_Rdy != 1)
{
uint8_t Result = HAL_UART_Receive_DMA (&huart2, RX_Data, 6);
}
if(TX_Data_Pending)
{
HAL_UART_Transmit_DMA(&hlpuart1, ACK_Data, 3);
}
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
RX_Data_Rdy = 1;
TX_Data_Pending = 1;
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
TX_Data_Pending = 0;
RX_Data_Rdy = 0;
memset(RX_Data, 0, 6);
}
您的代码已损坏,因为它实际上只有两种状态:接收,在这种情况下,您在循环中重复调用
HAL_UART_Receive_DMA()
,以及传输,在这种情况下,您在循环中重复调用 HAL_UART_Transmit_DMA()
。
到目前为止,最简单的解决方案是忘记 DMA 和中断,只使用常规轮询例程,例如:
while (1)
{
HAL_StatusTypeDef result;
result = HAL_UART_Receive(&huart2, RX_Data, 6, 1000); // 1000ms timeout
if (result != HAL_OK)
{
// Handle error or timeout
}
result = HAL_UART_Transmit(&hlpuart1, ACK_Data, 3, 1000);
if (result != HAL_OK)
{
// Handle error or timeout
}
}
如果你绝对确定你必须使用DMA和中断,你真的需要两个以上的状态来告诉你你当前在做什么。它可能是这样的:
enum state_e {
STATE_READY_TO_RECEIVE,
STATE_RECEIVING,
STATE_READY_TO_SEND,
STATE_SENDING
};
volatile enum state_e state = STATE_READY_TO_RECEIVE;
int main(void)
{
// Other initialisation stuff here
while (1)
{
HAL_StatusTypedef result;
switch(state)
{
case STATE_READY_TO_RECEIVE:
result = HAL_UART_Receive_DMA (&huart2, RX_Data, 6);
// check result for errors
state = STATE_RECEIVING;
break;
case STATE_READY_TO_SEND:
result = HAL_UART_Transmit_DMA(&hlpuart1, ACK_Data, 3);
// check result for errors
state = STATE_SENDING;
break;
case STATE_RECEIVING:
case STATE_SENDING:
// Nothing to do, waiting for the hardware
break;
default:
// handle bad state error
break;
}
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (state == STATE_RECEIVING)
{
state = STATE_READY_TO_SEND;
}
else
{
// error - state machine broken
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if (state == STATE_SENDING)
{
state = STATE_READY_TO_RECEIVE;
}
else
{
// error - state machine broken
}
}