🧩 1. CubeMX 中配置(如果你已经配置可以跳过):
-
USART1:
-
Mode: Asynchronous
-
Baudrate: 如
115200 -
Enable Global Interrupt (勾上 NVIC 的 USART1 interrupt)
-
-
FreeRTOS:
-
新建一个任务:名字为
Uart_rec -
优先级设为 Normal 或 Low
-
🧩 2. 在 freertos.c 中完善任务 Uart_rec()
打开 freertos.c,找到自动生成的任务函数:
// 外部 UART 句柄(要加在文件顶部)
extern UART_HandleTypeDef huart1;
// 接收缓冲区
uint8_t uart1_rx_buf[3];
volatile uint8_t uart1_rx_flag = 0;
void Uart_rec(void const * argument)
{
// 启动第一次接收中断
HAL_UART_Receive_IT(&huart1, uart1_rx_buf, 3);
for(;;)
{
// 检查是否收到数据
if (uart1_rx_flag)
{
HAL_UART_Transmit(&huart1, uart1_rx_buf, 3, 10);
// 这句话一定不要放在这里,给删掉
//HAL_UART_Receive_IT(&huart1, uart1_rx_buf, 3);
}
osDelay(10); // 合理延时,避免空转
}
}
🧩 3. 添加接收完成回调函数
这个函数放在 stm32f4xx_it.c 或 usart.c 的尾部都可以,也可以你新建个 uart_user.c 来维护更好。
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
extern volatile uint8_t uart1_rx_flag;
extern uint8_t uart1_rx_buf[3];
HAL_UART_Receive_IT(&huart1, uart1_rx_buf, 3);
uart1_rx_flag = 1; // 通知任务数据已接收
//HAL_UART_Transmit(&huart2, (uint8_t *)"IN INT\r\n", 8, 10);
}
}
🧩 4. 变量声明:在 freertos.c 顶部加上
// 放在 freertos.c 顶部区域(或建立 uart_user.h)
uint8_t uart1_rx_buf[3];
volatile uint8_t uart1_rx_flag = 0;
或者你也可以放到 main.c 并用 extern 声明。
🧩 5. 中断函数不要被注释掉!
确保在 stm32f4xx_it.c 中 保留 USART1 IRQHandler:
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart1);
}
✅ 整体流程说明
-
初始化时调用
HAL_UART_Receive_IT()启动中断接收 -
数据到来后进入
HAL_UART_RxCpltCallback() -
设置标志
uart_rx_flag,并再次启动接收 -
Uart_rec()任务中轮询uart_rx_flag来处理数据(不会阻塞)
✅ 可选优化:使用队列/消息通知
如果你不想任务中不停轮询 uart_rx_flag,可以用:
-
xTaskNotifyFromISR() -
xQueueSendFromISR()
这样回调中通知任务处理数据就更“实时”了。需要我可以继续帮你改写成通知方式。
✅ 结语
你现在的结构是:
| 组件 | 用法 |
|---|---|
freertos.c | Uart_rec() 中做数据处理 |
HAL_UART_RxCpltCallback() | 接收完成后触发,设置标志再接收下一次 |
HAL_UART_Receive_IT() | 启动中断接收 |
这套是CubeIDE + STM32 + FreeRTOS里最常见、最稳定的做法之一。
3853

被折叠的 条评论
为什么被折叠?



