FREERTOS 串口

🧩 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.cusart.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.cUart_rec() 中做数据处理
HAL_UART_RxCpltCallback()接收完成后触发,设置标志再接收下一次
HAL_UART_Receive_IT()启动中断接收

这套是CubeIDE + STM32 + FreeRTOS里最常见、最稳定的做法之一。

### FreeRTOS 中与串口通信的实现及配置 #### 1. 基于 STM32 的 FreeRTOS 串口通信基础 FreeRTOS 是一种轻量级的操作系统,广泛应用于嵌入式设备中。在 STM32 微控制器上使用 FreeRTOS 进行串口通信时,通常会结合硬件外设(如 UART 或 USART)以及软件机制(如队列、信号量等)。这种组合可以有效提升系统的实时性和可靠性。 在一个典型的 STM32 和 FreeRTOS 结合的应用场景中,可以通过 HAL 库或 LL 库初始化串口模块,并将其与 FreeRTOS 的任务调度相结合[^1]。例如,在中断模式下接收数据并存储到 FreeRTOS 队列中,随后由其他任务读取这些数据进行进一步处理。 --- #### 2. 使用队列实现高效的串口通信 为了确保多任务环境下的数据一致性,推荐采用 FreeRTOS 提供的消息队列来传递串口中断捕获的数据。这种方式能够显著减少因任务切换而导致的数据丢失风险。具体来说: - 当串口接收到新字符时触发中断服务程序 (ISR),在此 ISR 内部调用 `xQueueSendFromISR` 将数据写入指定队列。 - 创建一个独立的任务负责从该队列中取出数据并完成后续逻辑操作,比如解析协议帧或将数据转发给其他组件。 这种方法不仅提高了代码可维护性还增强了整个应用架构灵活性[^2]。 --- #### 3. DMA 方式的不定长数据接收优化方案 对于某些特殊需求场合可能需要支持不确定长度消息流输入情况,则可以考虑引入直接内存存取(DMA)技术辅助完成这项工作。相比单纯依靠轮询或者简单中断方法而言,DMA能带来更低CPU占用率同时也具备更高吞吐能力. 以下是关于如何设置这样一个基于DMA驱动的异步收发过程的一些要点说明: - 利用CubeMX工具快速生成基本框架结构,包括使能相应通道及其回调函数定义. - 自定义缓冲区管理策略适应不同应用场景特点;例如动态分配较大连续空间作为临时储存区域等待最终确认后再释放多余部分. - 调整优先级关系保证关键事件得到及时响应而不被阻塞太久影响整体性能表现.[^4] 下面给出一段简化版伪代码展示上述概念的实际运用情形: ```c // 定义全局变量保存当前状态信息 volatile uint8_t RxBuffer[BUFFER_SIZE]; uint16_t ReceivedLength = 0; void MX_USART_Init(void){ // 初始化串口参数... } __weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ if(huart->Instance == USARTx){ BaseType_t xHigherPriorityTaskWoken; // 向队列发送已接收字节数目通知主线程更新界面等内容 xQueueSendFromISR(queueHandle,&ReceivedLength,&xHigherPriorityTaskWoken); // 继续启动新一轮DMA传输直到满足特定条件停止为止 HAL_UART_Receive_DMA(&huartX,RxBuffer,BUFFER_SIZE); } } ``` --- #### 4. CRTP 协议移植实例中的注意事项 当涉及到复杂通讯协议如CRTP(Control Real-Time Protocol),除了常规流程之外还需要额外关注几个方面以确保持久稳定连接质量良好: - 正确调整堆内存大小避免频繁申请失败现象发生从而导致崩溃异常等问题出现;可通过编辑`FreeRTOSConfig.h`文件内的宏定义项达成目标效果[^5]. - 如果发现终端没有任何输出显示则可能是波特率设定错误或者是电平转换电路存在问题所致需逐一排查解决. --- ### 总结 综上所述,借助FreeRTOS强大的同步原语特性配合恰当外围器件选型搭配合理算法设计思路完全可以构建起一套既强大又灵活可控性强弱分明层次清晰易于扩展升级完善的解决方案体系服务于各类实际工程项目当中去创造更大价值回报社会贡献力量!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值