以下代码供你参考:
// 定义通信状态
typedef enum {
STATE_IDLE = 0, // 空闲状态
STATE_TX_WAIT, // 等待发送完成
STATE_RX_WAIT, // 等待接收应答
STATE_PROCESS_DATA // 处理数据
} CommState_t;
volatile CommState_t comm_state = STATE_IDLE;
volatile uint8_t rx_data[2] = {0};
volatile uint8_t tx_data[2] = {0};
volatile uint32_t rx_tick = 0; // 记录接收时间,用于超时判断
// 1. 触发发送的函数(在主循环或定时器中调用)
void Trigger_Send(uint8_t d0, uint8_t d1) {
if (comm_state == STATE_IDLE) { // 只有空闲时才允许发起新通信
tx_data[0] = d0;
tx_data[1] = d1;
// 使用非阻塞发送
if (HAL_UART_Transmit_IT(&huart1, (uint8_t*)tx_data, 2) == HAL_OK) {
comm_state = STATE_TX_WAIT;
}
}
}
// 2. 串口发送完成回调
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == USART1) {
// 发送完成后,立刻开启接收,并记录当前系统时间
HAL_UART_Receive_IT(&huart1, (uint8_t*)rx_data, 2);
rx_tick = HAL_GetTick();
comm_state = STATE_RX_WAIT;
}
}
// 3. 串口接收完成回调
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == USART1) {
// 收到数据,切换到处理状态
comm_state = STATE_PROCESS_DATA;
}
}
// 4. 主循环处理
int main(void) {
// ... 初始化代码 ...
comm_state = STATE_IDLE;
while (1) {
switch (comm_state) {
case STATE_IDLE:
// 在这里判断是否需要发送新数据
// 例如:if(need_send) Trigger_Send(0x12, 0x45);
break;
case STATE_TX_WAIT:
// 等待发送完成(由中断回调自动切换状态)
break;
case STATE_RX_WAIT:
// 【关键】超时防死机制:如果等待超过100ms还没收到,视为超时
if ((HAL_GetTick() - rx_tick) > 100) {
comm_state = STATE_IDLE; // 超时,回到空闲,准备下一次
}
break;
case STATE_PROCESS_DATA:
// 在这里处理接收到的 rx_data
// 处理完毕后,回到空闲状态
comm_state = STATE_IDLE;
break;
}
}
} |