在线时间2231 小时
UID3253523
注册时间2016-3-21
NXP金币3750
该用户从未签到
超级版主
 
- 积分
- 25545
- 最后登录
- 2025-9-11
|
概述
在串口通信应用中,我们经常会遇到 不定长数据接收 的需求,例如上位机发送一条 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) 等场景,能够显著提高系统的实时性与可靠性。
|
|