查看: 164|回复: 0

基于 MCXA156 的 UART 不定长接收实现

[复制链接]

该用户从未签到

723

主题

6382

帖子

0

超级版主

Rank: 8Rank: 8

积分
25545
最后登录
2025-9-11
发表于 2025-9-3 17:28:02 | 显示全部楼层 |阅读模式
概述
在串口通信应用中,我们经常会遇到 不定长数据接收 的需求,例如上位机发送一条 AT 命令,或者传感器输出一帧可变长度的数据。传统的定长接收方式(如接收固定 16 字节)显然无法满足需求,因此需要一种机制来自动识别一帧数据的结束位置。
目前SDK中的例子都为lpuart 定长接收。
本文基于 NXP MCXA156 MCU,介绍一种常用的 不定长接收实现方法:

硬件环境:
        开发板:FRDM-MCXA156

软件环境:
        IDE:MCUXpresso IDE v11.9.0
        SDK:SDK Builder | MCUXpresso SDKBuilder (nxp.com)
        基础工程: frdmmcxa156_lpuart_edma_transfer

1. 设计思路
本方案的设计目标是:支持 UART 不定长接收,同时尽量减少 CPU 负担。整体思路如下:
a. DMA 自动接收
使用 eDMA 将 UART 接收数据直接搬运到内存缓冲区,避免逐字节触发中断,提高效率。
b. 空闲中断识别帧结束
当一帧数据接收完成后,UART 硬件会检测到总线空闲并触发 Idle Line 中断。该信号可作为数据帧结束的标志。
c. 计算接收长度
在中断中查询 eDMA 的剩余传输字节数,从而计算实际接收的数据长度。
d. 数据交付处理
将接收到的数据交给应用层进行解析、存储或回显。
e. 重新启动接收
在处理完成后,重新启动 eDMA 接收,为下一帧数据做好准备。


2. 实现方法
2.1 数据处理函数
  1. void ProcessReceivedData(uint8_t *data, size_t length)
  2. {
  3.     // 回显数据
  4.     LPUART_WriteBlocking(DEMO_LPUART, data, length);
  5.     PRINTF("length=%d.\r\n", length);
  6. }
复制代码
2.2 UART 中断回调函数

  1. void DEMO_LPUART_IRQHandler(void)
  2. {
  3.     uint32_t flags = LPUART_GetStatusFlags(DEMO_LPUART);

  4.     if (flags & kLPUART_IdleLineFlag)
  5.     {
  6. // 清除空闲中断标志
  7.         LPUART_ClearStatusFlags(DEMO_LPUART, kLPUART_IdleLineFlag);

  8.         if (g_lpuartEdmaHandle.rxState == kLPUART_RxBusy)
  9.         {
  10.               // 计算已接收的数据长度
  11.             size_t remaining = EDMA_GetRemainingMajorLoopCount(
  12.                 g_lpuartEdmaHandle.rxEdmaHandle->base,
  13.                 g_lpuartEdmaHandle.rxEdmaHandle->channel);
  14.          
  15.             LPUART_TransferAbortReceiveEDMA(DEMO_LPUART, &g_lpuartEdmaHandle);
  16.             size_t receivedLength = RX_DMA_BUFFER_SIZE - remaining;
  17. // 数据交给上层处理
  18.             ProcessReceivedData(g_rxBuffer, receivedLength);

  19.             // 重启 DMA 接收
  20.             lpuart_transfer_t receiveXfer;
  21.             receiveXfer.data = g_rxBuffer;
  22.             receiveXfer.dataSize = RX_DMA_BUFFER_SIZE;
  23.             LPUART_ReceiveEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &receiveXfer);
  24.         }
  25.     }
  26. }/
复制代码
2.3 主函数初始化
  1. int main(void)
  2. {
  3.     BOARD_InitHardware();

  4.     // UART 初始化
  5.     // eDMA 初始化和绑定
  6.     // ... 省略配置 ...
  7.     // 开启空闲中断
  8.     LPUART_EnableInterrupts(DEMO_LPUART, kLPUART_IdleLineInterruptEnable);
  9.     EnableIRQ(DEMO_LPUART_IRQn);

  10.     // 启动首次接收
  11.     lpuart_transfer_t receiveXfer;
  12.     receiveXfer.data = g_rxBuffer;
  13.     receiveXfer.dataSize = RX_DMA_BUFFER_SIZE;
  14.     LPUART_ReceiveEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &receiveXfer);

  15.     while (1)
  16.     {
  17.         // 主循环空转
  18.     }
  19. }
复制代码

3. 系统流程图
图片1.png

4. 测试结果
在实验中,MCXA156 LPUART 被配置为 115200bps,接收来自上位机的变长数据。测试结果如下:
当上位机发送 14 字节数据时,系统正确接收到长度为 14 的数据,并回显。
图片2.png

5. 结语
本文基于 MCXA156 MCU,利用 UART Idle Line 中断 + eDMA 实现了 不定长串口接收。该方案具有以下优点:
灵活性:支持任意长度数据帧,无需固定长度缓冲区;
高效性:DMA 自动搬运数据,CPU 仅在帧结束时介入;
可靠性:利用 UART 硬件的 Idle Line 信号,避免了基于定时器的软件超时判定。
该方法特别适用于 变长协议通信、AT 命令解析、传感器数据采集、工业协议(如 Modbus) 等场景,能够显著提高系统的实时性与可靠性。






回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|恩智浦技术社区

GMT+8, 2025-9-17 03:39 , Processed in 0.086817 second(s), 20 queries , MemCache On.

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

快速回复 返回顶部 返回列表