在线时间2240 小时
UID3253523
注册时间2016-3-21
NXP金币4514 
 
 
 
该用户从未签到 
超级版主 
   
	- 积分
 - 26096
 
 
- 最后登录
 - 2025-11-3
  
 
 | 
 
概述 
在串口通信应用中,我们经常会遇到 不定长数据接收 的需求,例如上位机发送一条 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 数据处理函数 
- void ProcessReceivedData(uint8_t *data, size_t length)
 
 - {
 
 -     // 回显数据
 
 -     LPUART_WriteBlocking(DEMO_LPUART, data, length);
 
 -     PRINTF("length=%d.\r\n", length);
 
 - }
 
  复制代码 2.2 UART 中断回调函数 
- void DEMO_LPUART_IRQHandler(void)
 
 - {
 
 -     uint32_t flags = LPUART_GetStatusFlags(DEMO_LPUART);
 
  
-     if (flags & kLPUART_IdleLineFlag)
 
 -     {
 
 - // 清除空闲中断标志
 
 -         LPUART_ClearStatusFlags(DEMO_LPUART, kLPUART_IdleLineFlag);
 
  
-         if (g_lpuartEdmaHandle.rxState == kLPUART_RxBusy)
 
 -         {
 
 -               // 计算已接收的数据长度
 
 -             size_t remaining = EDMA_GetRemainingMajorLoopCount(
 
 -                 g_lpuartEdmaHandle.rxEdmaHandle->base,
 
 -                 g_lpuartEdmaHandle.rxEdmaHandle->channel);
 
 -           
 
 -             LPUART_TransferAbortReceiveEDMA(DEMO_LPUART, &g_lpuartEdmaHandle);
 
 -             size_t receivedLength = RX_DMA_BUFFER_SIZE - remaining;
 
 -  // 数据交给上层处理
 
 -             ProcessReceivedData(g_rxBuffer, receivedLength);
 
  
-             // 重启 DMA 接收
 
 -             lpuart_transfer_t receiveXfer;
 
 -             receiveXfer.data = g_rxBuffer;
 
 -             receiveXfer.dataSize = RX_DMA_BUFFER_SIZE;
 
 -             LPUART_ReceiveEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &receiveXfer);
 
 -         }
 
 -     }
 
 - }/
 
 
  复制代码 2.3 主函数初始化 
- int main(void)
 
 - {
 
 -     BOARD_InitHardware();
 
  
-     // UART 初始化
 
 -     // eDMA 初始化和绑定
 
 -     // ... 省略配置 ...
 
 -     // 开启空闲中断
 
 -     LPUART_EnableInterrupts(DEMO_LPUART, kLPUART_IdleLineInterruptEnable);
 
 -     EnableIRQ(DEMO_LPUART_IRQn);
 
  
-     // 启动首次接收
 
 -     lpuart_transfer_t receiveXfer;
 
 -     receiveXfer.data = g_rxBuffer;
 
 -     receiveXfer.dataSize = RX_DMA_BUFFER_SIZE;
 
 -     LPUART_ReceiveEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &receiveXfer);
 
  
-     while (1)
 
 -     {
 
 -         // 主循环空转
 
 -     }
 
 - }
 
 
  复制代码 
3. 系统流程图 
 
 
 
4. 测试结果 
在实验中,MCXA156 LPUART 被配置为 115200bps,接收来自上位机的变长数据。测试结果如下: 
当上位机发送 14 字节数据时,系统正确接收到长度为 14 的数据,并回显。 
 
 
 
5. 结语 
本文基于 MCXA156 MCU,利用 UART Idle Line 中断 + eDMA 实现了 不定长串口接收。该方案具有以下优点: 
灵活性:支持任意长度数据帧,无需固定长度缓冲区; 
高效性:DMA 自动搬运数据,CPU 仅在帧结束时介入; 
可靠性:利用 UART 硬件的 Idle Line 信号,避免了基于定时器的软件超时判定。 
该方法特别适用于 变长协议通信、AT 命令解析、传感器数据采集、工业协议(如 Modbus) 等场景,能够显著提高系统的实时性与可靠性。 
 
 
 
 
 
        
        
        
         |   
 
 
 
 |