
🎬 渡水无言 :个人主页渡水无言
❄专栏传送门 : 《linux专栏》《嵌入式linux驱动开发》《linux系统移植专栏》
❄专栏传送门 : 《freertos专栏》 《STM32 HAL库专栏》《linux裸机开发专栏》
⭐️流水不争先,争的是滔滔不绝
📚博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生
| 省级优秀毕业生获得者 | csdn新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生
在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连
目录
[一、UplinkTask 任务定位](#一、UplinkTask 任务定位)
[三、UplinkTask 完整代码](#三、UplinkTask 完整代码)
前言
在前面的系列文章中,我们已经搭建起机器人下位机的三大核心任务:
CommTask 实现上位机指令解析。
ControlTask 完成底盘运动控制闭环。
SensorTask 构建整机状态感知体系。
SensorTask 通过系统状态快照机制,统一采集并缓存了电池电压、轮速、IMU 姿态等关键数据,但这些数据只有上传到上位机,才能实现可视化监控、远程调试、状态诊断等功能。
因此本篇我们实现 UplinkTask 上行数据上报任务 ,它专门负责:定时读取状态快照 → 协议组帧 → DMA 串口发送 → 上传至上位机。
一、UplinkTask 任务定位
UplinkTask 是纯数据输出任务,不操作任何硬件传感器,只做三件事:
固定周期从 系统状态快照 安全读取系统状态。
按通信协议打包状态帧。
通过 USART1 + DMA 异步发送到上位机。
二、全局时序交互图
下面是整个系统 采集 → 快照 → 上报 → 发送 的完整时序流程,是整篇文章的核心图:

SensorTask 周期采集传感器数据,并原子写入全局快照。
UplinkTask 周期读取快照,不影响采集任务。
协议层组帧后,通过 DMA 异步发送。
发送完成 / 失败由 HAL 回调通知,释放发送标志。
发送繁忙时自动丢弃,不阻塞、不堆积。
全程无任务阻塞,架构干净、稳定、高效。
三、UplinkTask 完整代码
总体流程:

代码如下:
cpp
/**
****************************************************************************************************
* @file uplink_task.c
* @brief 上行状态上报任务(Uplink Task)
* 本任务用于周期性向上位机发送系统状态信息,典型流程为:
*
* SensorTask / ControlTask
* ↓
* SensorSnap_Get()(获取一次完整快照)
* ↓
* UplinkProto_SendStatus()
* ↓
* UART 发送(协议帧)
*
****************************************************************************************************
*/
#include "uplink_task.h"
#include "FreeRTOS.h"
#include "task.h"
#include <stdint.h>
#include "log_task.h"
#include "control_task.h"
#include "uplink_proto.h"
#include "sensor_task.h"
#include "usart.h"
#include "protocol.h"
#include "monitor_task.h"
/* 上行周期(ms):1s 上报一次状态 */
#define UPLINK_PERIOD_MS (1000u)
/**
* @brief 上行状态上报任务入口
* @details 周期性读取快照 → 协议组帧 → 串口DMA发送
*/
void KaoYaApp_UplinkTask(void *argument)
{
(void)argument;
/* 帧序号(用于上位机检测丢包/乱序) */
uint8_t seq = 0;
/* 初始化上行协议模块 */
UplinkProto_Init();
/* 上行协议帧缓存 */
proto_uplink_t tx;
/* 系统状态快照 */
proto_status_t st;
/* 周期调度基准 */
TickType_t last_wake = xTaskGetTickCount();
for (;;)
{
/* 1. 任务心跳:监控任务是否正常运行 */
MON_HB_UPLINK();
/* 2. 线程安全读取全局状态快照 */
SensorSnap_Get(&st);
/* 3. 协议打包并发送状态帧 */
UplinkProto_SendStatus(&tx, seq++,
st.battery_mv, st.temp,
st.vx, st.vy, st.vz,
st.gx, st.gy, st.gz,
st.ax, st.ay, st.az);
#if UPLINK_KAOYATEACH_ENABLE
/* 调试打印:上报内容输出 */
uint32_t seq_sent = (uint32_t)(seq - 1u);
LOGKAOYA_T("UPLINK", "==================UPLINK==================");
LOGKAOYA_T("UPLINK", "【上报】STATUS 已发送:seq=%lu", (unsigned long)seq_sent);
LOGKAOYA_T("UPLINK", "【电池】BAT=%u mV", (unsigned int)st.battery_mv);
LOGKAOYA_T("UPLINK", "【温度】TEMP=%d C", (int)st.temp);
LOGKAOYA_T("UPLINK", "【速度】v(mm/s)=(%d,%d,%d)", (int)st.vx, (int)st.vy, (int)st.vz);
LOGKAOYA_T("UPLINK", "【角速度】g(0.01deg/s)=(%d,%d,%d)", (int)st.gx, (int)st.gy, (int)st.gz);
LOGKAOYA_T("UPLINK", "【加速度】a(mg)=(%d,%d,%d)", (int)st.ax, (int)st.ay, (int)st.az);
#endif
/* 4. 固定周期延时:1秒上报一次 */
vTaskDelayUntil(&last_wake, pdMS_TO_TICKS(UPLINK_PERIOD_MS));
}
}
总结
本篇实现的 UplinkTask 上行上报任务,与前面的 SensorTask 完美配合,实现数据上报功能。