【STM32C5教程】(10)LPUART DMA 通信实验

发布时间:2026/10/21 2:30:02
【STM32C5教程】(10)LPUART DMA 通信实验
欢迎关注 youcansxidian【嵌入式软件AI编程】专栏【STM32C5教程】1STM32C5系列介绍【STM32C5教程】2STM32CubeMX2 安装与STM32C5闪灯【STM32C5教程】3GPIO 按键输入实验【STM32C5教程】4GPIO 外部中断实验【STM32C5教程】5定时器周期中断实验【STM32C5教程】6定时器 PWM 输出实验【STM32C5教程】7TIM1 互补 PWM 输出实验【STM32C5教程】8ADC 模拟量数据采集实验【STM32C5教程】9DAC 模拟量信号输出实验【STM32C5教程】10LPUART DMA 通信实验1. 项目简介1.1 实验目标本实验在 NUCLEO-C542RC 开发板上使用 LPUART1 通过板载虚拟串口以 DMA 方式连续发送 JustFloat 格式的锯齿波数据并在 VOFA 中显示波形。数据格式以 vofa_justfloat.md 为准。功能需求使用 LPUART1115200 波特率、8 数据位、1 停止位、无校验通过板载 ST-LINK 虚拟串口发送数据使用 DMA 发送每帧包含 1 个浮点采样值和固定帧尾共 8 字节锯齿波数据每 10 ms 提交一帧周期约 1 秒串口数据流只包含 JustFloat 数据帧不插入文本、换行或图片数据在发送过程中不得改写 DMA 正在读取的缓冲区。开发板和 MCU 型号NUCLEO-C542RC 开发板搭载 STM32C542RCT6 MCU。1.2 实验条件硬件NUCLEO-C542RC 开发板支持数据传输的 USB Type-C 线用于连接 ST-LINK 接口同时提供下载、调试和虚拟串口软件STM32CubeMX2用于引脚、时钟、LPUART1 和 DMA 配置与代码生成VS Code STM32Cube 插件用于编译、烧录、调试VOFA用于串口数据接收与波形显示1.3 VOFA JustFloat 协议说明VOFA 支持多种数据引擎JustFloat 是面向波形显示的二进制协议。其帧结构为N 个 32 位小端浮点数 4 字节固定帧尾 0x00 0x00 0x80 0x7F。VOFA 依靠帧尾识别一帧结束按帧长解析后绘制各通道波形。JustFloat 的数据帧由两部分组成struct Frame{float ch_data[CH_COUNT];// 浮点通道数据小端 unsigned char tail[4];// 固定帧尾};ch_data 为浮点型通道数据采用小端字节序。STM32 默认即为小端可直接通过内存拷贝写入。CH_COUNT 为每帧的通道数量。tail 为固定帧尾内容为 0x00 0x00 0x80 0x7F对应 Infinity 的小端表示。VOFA 依靠帧尾识别一帧的结束因此帧尾必须完整、不能缺失。本实验每帧发送 1 路锯齿波数据CH_COUNT 1每帧共 8 字节前 4 字节为当前采样值的 float 小端表示后 4 字节为固定帧尾。串口数据流中只包含 JustFloat 数据帧不插入文本、换行或调试打印。VOFA 侧串口参数需与 MCU 一致115200、8N1、无流控数据引擎选择 JustFloat。2. 硬件说明2.1 NUCLEO-C542RC 开发板NUCLEO-C542RC 是 ST 基于 STM32C542RCT6 推出的 Nucleo-64 开发板。主要特性MCUSTM32C542RCT6Arm Cortex-M33 内核最高主频 144 MHz256 KB Flash64 KB RAM调试器板载 STLINK-V3EC支持大容量存储、虚拟串口和调试端口三种功能用户 LEDLD1连接 PA5用户按键B1连接 PC13扩展接口Arduino Uno V3 和 ST morpho 连接器本实验通过板载 ST-LINK 的虚拟串口VCP将 LPUART1 的数据传输到 PC无需额外外接 USB 转串口模块。一根 USB 线同时完成供电、下载、调试和串口通信。2.2 引脚说明引脚复用功能Swap 后实际功能说明PA2LPUART1_RXAF3LPUART1_TX连接 ST-LINK VCP 的 RXPA3LPUART1_TXAF3LPUART1_RX连接 ST-LINK VCP 的 TXPA2、PA3配置为 LPUART1 复用功能AF3并启用 Tx/Rx Pins swapping。引脚复用配置本身不变通过外设内部交换完成信号路由。STM32C542RCT6 的 LPUART1 默认复用功能AF3映射为 PA2RX、PA3TX。而 NUCLEO-C542RC 板载 ST-LINK 的虚拟串口要求 MCU 侧的 TX 引脚连接到 PA2。默认映射与板载 VCP 连线不匹配因此必须启用 LPUART1 的 Tx and Rx Pins swapping 功能。交换后PA2 实际输出 LPUART1_TXPA3 实际接收 LPUART1_RX与板载 VCP 正确对接。生成代码中的引脚注释仍显示原始复用名称这是正常现象。2.3 DMA 资源分配资源配置说明LPDMA1_CH0LPUART1_TX DMA内存到外设源地址递增目标地址固定字节宽度LPDMA1_CH1LPUART1_RX DMA已配置本实验未启动接收3. STM32CubeMX2 工程配置3.1 新建工程本实验采用 MCU 方式创建工程即以芯片型号 STM32C542RC 为起点而非开发板方式。进入 MCU 选择界面启动 STM32CubeMX2在首页点击 MCU进入芯片型号选择列表。搜索并选中芯片在 MCU name 输入框中输入 STM32C542RC或完整型号 STM32C542RCT6从筛选出的列表中选择对应型号。填写项目信息输入项目名称 LPUART_DMA 和项目保存路径。项目名称避免使用特殊字符路径建议使用纯英文目录。3.2 基础配置工程创建后软件自动进入 Pinout 视图。时钟配置本工程系统时钟配置为 144 MHzLPUART1 时钟源为 APB3频率 144 MHz串口预分频系数为 1。3.3 LPUART1 配置1启用 LPUART1在左侧外设列表中找到Connectivity→LPUART1激活ActiveLPUART1。在Main features中将Mode设置为Asynchronous异步模式。设置完成后Pinout 视图中PA2自动分配为LPUART1_RXPA3自动分配为LPUART1_TX均为 AF3 复用功能。2LPUART1 参数设置在Main features中设置参数值Baud Rate115200 Bits/sWord Length8 Bits (including Parity)ParityNoneStop Bits1Data DirectionReceive and TransmitHardware Flow ControlNoneOver Sampling163启用 TX/RX 引脚交换在Advanced Features中将Tx and Rx Pins swapping设置为Enabled。STM32C542RCT6 的 LPUART1 默认 AF3 映射为 PA2RX、PA3TX而 NUCLEO-C542RC 板载 ST-LINK 的虚拟串口要求 MCU 侧的 TX 连接到 PA2。启用 Swap 后外设内部交换 TX/RX 信号路由使 PA2 实际输出 TX、PA3 实际接收 RX与板载 VCP 正确对接。引脚复用配置AF3本身不变。4配置 DMA Settings在DMA Settings中点击DMA Tx后的 “Enable” 开关 激活 TX DMA 请求CubeMX2 会自动将该请求分配到LPDMA1_CH0。参数值Request TxLPUART1_CH0ModeDirect transferPeripheral RequestLPUART1_Tx_dmaDirectionMemory To PeripheralSource Data WidthByteDestination Data WidthBytePriorityLow如需接收功能可选择LPUART1_Rx方向设为Peripheral To Memory。5使能中断设置如下中断使能LPUART1 global interruptLPDMA1_CH0 interruptTX DMA 完成中断TX DMA 完成中断是 HAL_UART_TxCpltCallback 被调用的前提。3.4 项目配置点击Project Settings进入工程设置页面。在IDE Format下拉选项中选择CMake。在CMake Toolchain下拉选项中选择GCC。确认配置无误后点击Generate Code。CubeMX2 会执行配置检查如果没有错误开始在指定路径下生成 CMake 工程文件。4. 编程实现4.1 实现思路采用“主循环定时调度 DMA 单次发送 静态帧缓冲区”的方案mx_system_init() // CubeMX2 生成时钟、GPIO、LPUART1、DMA 初始化 │ ▼ 主循环 wave_process() │ ├─ 检查是否有发送错误待恢复 │ └─ 是 → HAL_UART_AbortTransmit()等待下一个周期 │ ├─ 距上次提交 10 ms或 UART TX 状态非空闲 │ └─ 是 → 直接返回 │ ├─ 将当前采样值写入帧缓冲区前 4 字节memcpy小端 │ ├─ HAL_UART_Transmit_DMA() 提交一帧8 字节 │ ├─ HAL_OK → 采样序号加一超过 99 归零 │ ├─ HAL_BUSY → 本次跳过不计错误 │ └─ 其他 → 记录错误置恢复标志 │ └─ 更新上次提交时刻DMA 与阻塞发送的对比HAL_UART_Transmit()会逐字节等待发送寄存器空115200 波特率下一帧 8 字节约需 0.7 ms期间 CPU 无法执行其他任务。DMA 由硬件搬运数据CPU 只需调用一次启动函数即可返回。单帧提交与 DMA 循环模式DMA 设为Direct transfer即 Normal 模式每次传输完成后停止。主循环按 10 ms 周期重复提交每帧的采样值都可以更新。循环模式下 DMA 会反复发送同一个缓冲区波形无法变化。提交前检查 TX 状态HAL_UART_Transmit_DMA()在上一帧尚未发完时调用会返回HAL_BUSY。通过HAL_UART_GetTxState()判断为空闲再提交避免无意义的忙状态返回调度逻辑更清晰。静态帧缓冲区DMA 在后台读取内存。缓冲区如果定义为栈上的局部变量函数返回后内存可能被覆盖导致发送数据错乱。静态存储区在整个程序生命周期内有效DMA 读取期间不会被回收。时间调度使用HAL_GetTick()差值(now - last) 10的写法在毫秒计数器回绕时仍然正确且是非阻塞的主循环不会被延时卡住。关键 HAL 函数步骤HAL 函数作用获取 LPUART1 句柄mx_lpuart1_uart_gethandle()返回 CubeMX2 生成的 LPUART1 句柄查询 TX 状态HAL_UART_GetTxState()判断上一帧是否发送完成启动 DMA 发送HAL_UART_Transmit_DMA()提交一帧数据立即返回中止发送HAL_UART_AbortTransmit()出错时停止 DMA 并清理状态获取毫秒时基HAL_GetTick()10 ms 周期调度4.2 关键代码在 VS Code 中打开生成的 CMake 工程找到Core/Src/main.c添加以下代码。1文件头部添加头文件与宏定义#includemain.h#includemx_lpuart1.h#includestring.h/* Private define ------------------------------------------------------------*/#defineWAVE_SAMPLE_INTERVAL_MS10U#defineWAVE_SAMPLES_PER_PERIOD100U#defineJUSTFLOAT_FRAME_SIZE8U_Static_assert(sizeof(float)4U,JustFloat requires a 32-bit float);2静态帧缓冲区与统计变量/* Private variables ---------------------------------------------------------*/staticuint8_twave_tx_frame[JUSTFLOAT_FRAME_SIZE]{0U,0U,0U,0U,0x00U,0x00U,0x80U,0x7FU};staticvolatileuint32_twave_tx_error_pending;staticvolatileuint32_twave_tx_completed_count;staticvolatileuint32_twave_tx_error_count;/* Private functions prototype -----------------------------------------------*/staticvoidwave_process(void);3主函数intmain(void){if(mx_system_init()!SYSTEM_OK){return(-1);}else{while(1){wave_process();}}}4波形发送调度函数staticvoidwave_process(void){staticuint32_tlast_sample_tick;staticuint32_tsample_index;hal_uart_handle_t*huartmx_lpuart1_uart_gethandle();constuint32_tnowHAL_GetTick();if(wave_tx_error_pending!0U){/* 出错后在中断外恢复先停止 DMA再等待下一个周期 */wave_tx_error_pending0U;if(HAL_UART_AbortTransmit(huart)!HAL_OK){wave_tx_error_pending1U;}last_sample_ticknow;return;}if(((uint32_t)(now-last_sample_tick)WAVE_SAMPLE_INTERVAL_MS)||(HAL_UART_GetTxState(huart)!HAL_UART_TX_STATE_IDLE)){return;}/* STM32 为小端float 直接拷贝到前 4 字节后 4 字节帧尾保持不变 */constfloatsample(float)sample_index;memcpy(wave_tx_frame,sample,sizeof(sample));consthal_status_tstatusHAL_UART_Transmit_DMA(huart,wave_tx_frame,sizeof(wave_tx_frame));last_sample_ticknow;if(statusHAL_OK){sample_index;if(sample_indexWAVE_SAMPLES_PER_PERIOD){sample_index0U;}}elseif(status!HAL_BUSY){wave_tx_error_count;wave_tx_error_pending1U;}}5UART 发送完成与错误回调voidHAL_UART_TxCpltCallback(hal_uart_handle_t*huart){if(huartmx_lpuart1_uart_gethandle()){wave_tx_completed_count;}}voidHAL_UART_ErrorCallback(hal_uart_handle_t*huart){if(huartmx_lpuart1_uart_gethandle()){wave_tx_error_count;wave_tx_error_pending1U;}}代码说明wave_tx_frame为静态数组DMA 读取期间始终有效。前 4 字节每次发送前更新后 4 字节0x00 0x00 0x80 0x7F为 JustFloat 固定帧尾。memcpy将float写入字节数组避免指针强制转换的别名问题也避免结构体填充影响帧长。HAL_UART_GetTxState()返回HAL_UART_TX_STATE_IDLE表示上一帧已发送完成可以提交下一帧。HAL_UART_Transmit_DMA()返回HAL_OK只表示启动成功不表示数据已发完真正完成由 TX DMA 中断触发HAL_UART_TxCpltCallback。HAL_UART_ErrorCallback在串口出错时被调用置位wave_tx_error_pending主循环在下一轮调用HAL_UART_AbortTransmit()恢复。采样序号从 0 递增到 99 后归零配合 10 ms 周期锯齿波周期约为 1 秒。5. 编译烧录与运行测试5.1 编译与烧录打开工程用 VS Code 打开 CubeMX2 生成的 CMake 工程文件夹如LPUART_DMA_cmake。编译点击 VS Code 底部状态栏的Build按钮或使用命令面板执行 CMake 构建。编译完成后终端应输出Build finished with exit code 0无 error。连接开发板用支持数据传输的 USB Type-C 线连接 NUCLEO-C542RC 的 ST-LINK USB 口CN1。确认设备识别打开设备管理器在“端口 (COM 和 LPT)”下应能看到STLink COMx。烧录点击 VS Code 中的Flash按钮将固件下载到开发板。5.2 运行与测试烧录完成后点击 VS Code 中的Run按钮程序开始运行。1VOFA 连接设置打开 VOFA在串口连接区域选择与开发板对应的STLink COMx。串口参数设置为115200、8 数据位、1 停止位、无校验、无流控数据引擎选择JustFloat。2波形显示烧录完成后点击 VS Code 中的 Run 按钮程序开始运行。打开 VOFA选择对应的 STLink COM 端口串口参数设为 115200、8 数据位、1 停止位、无校验、无流控数据引擎选择 JustFloat打开串口连接并添加 1 个波形通道。观察波形应显示连续、无断裂的锯齿波数值从 0 递增到 99 后回落周期约 1 秒。编译、烧录、运行及 VOFA 波形显示均正常符合预期。6. 小结本实验通过 LPUART1 和 DMA 实现了 JustFloat 格式锯齿波数据的连续发送并在 VOFA 中成功显示波形掌握了 STM32C5 系列 LPUART1 的 DMA 发送配置与使用方法。核心逻辑可以概括为“主循环定时调度 → 封装 JustFloat 帧 → DMA 单次发送 → 中断通知完成”。需要注意的是TX/RX 引脚交换。 STM32C542RCT6 的 LPUART1 默认 AF3 映射为 PA2RX、PA3TX而板载 ST-LINK 虚拟串口要求 MCU 侧的 TX 连接到 PA2。必须在 CubeMX2 中启用 Tx and Rx Pins swapping否则数据无法通过虚拟串口发送到 PC。DMA 模式与缓冲区。 DMA 设为 Direct transferNormal 模式每帧发送完成后停止由主循环按 10 ms 周期重复提交。帧缓冲区使用静态存储保证 DMA 读取期间始终有效。版权声明欢迎关注 youcansxidian【嵌入式软件AI编程】专栏转发必须注明原文链接【STM32C5教程】10LPUART DMA 通信实验Copyright by ai4mcuqq.com 2026Crated2026-10