通信设计中考虑协议的灵活性,经常把协议设计成“不定长度”。
一个实例如下图:锐米LoRa终端的通信协议帧。

如果一个系统接收上述“不定长度”的协议帧,将会有一个挑战--如何高效接收与解析。
为简化系统设计,我们强烈建议您采用“状态机”来解析UART数据帧,并且把解析工作放在ISR(中断服务程序)完成,仅当接收到最后一个字节(0x0D)时,再将整个数据帧提交给进程处理。
该解析状态机的原理如下图所示:

那么ISR处理这个状态机来得及吗?答案是:so easy!因为它只有3个动作,运算量十分小:
比较接收数据 -> 更新状态变量 -> 存储接收数据,C语言仅3条语句,翻译成机器指令也不超过10条。
代码清单如下:
/*** @brief Status of received communication frame*/typedef enum{STATUS_IDLE = (uint8_t)0,STATUS_HEAD, /* Rx Head=0x3C */STATUS_TYPE, /* Rx Type */STATUS_DATA, /* Data filed */STATUS_TAIL, /* Tail=0x0D */STATUS_END, /* End of this frame */} COMM_TRM_STATUS_TypeDef;/*** @brief Data object for received communication frame*/typedef struct{uint8_t byCnt; /* Count of 1 field */uint8_t byDataLen; /* Length of data field */uint8_t byFrameLen; /* Length of frame */COMM_TRM_STATUS_TypeDef eRxStatus;uint8_t a_byRxBuf[MAX_LEN_COMM_TRM_DATA];} COMM_TRM_DATA;/*** @brief Data object for received communication frame.* @note Prevent race condition that accessed by both ISR and process.*/static COMM_TRM_DATA s_stComm2TrmData;/*** @brief Put a data that received by UART into buffer.* @note Prevent race condition this called by ISR.* @param uint8_t byData: the data received by UART.* @retval None*/void comm2trm_RxUartData(uint8_t byData){/* Update status according to the received data */switch (s_stComm2TrmData.eRxStatus){case STATUS_IDLE:if (COMM_TRM_HEAD == byData) /* Is Head */{s_stComm2TrmData.eRxStatus = STATUS_HEAD;}else{goto rx_exception;}break;case STATUS_HEAD:if (TYPE_INVALID_MIN < byData && byData < TYPE_INVALID_MAX) /* Valid type */{s_stComm2TrmData.eRxStatus = STATUS_TYPE;}else{goto rx_exception;}break;case STATUS_TYPE:if (byData <= MAX_LEN_UART_FRAME_DATA) /* Valid data size */{s_stComm2TrmData.eRxStatus = STATUS_DATA;s_stComm2TrmData.byDataLen = byData;}else{goto rx_exception;}break;case STATUS_DATA:if (s_stComm2TrmData.byCnt < s_stComm2TrmData.byDataLen){++s_stComm2TrmData.byCnt;}else{s_stComm2TrmData.eRxStatus = STATUS_TAIL;}break;case STATUS_TAIL:if (COMM_TRM_TAIL == byData){/* We received a frame of data, now tell process to deal with it! */process_poll(&Comm2TrmProcess);}else{goto rx_exception;}break;default:ASSERT(!"Error: Bad status of comm2trm_RxUartData(). ");break;}/* Save the received data */s_stComm2TrmData.a_byRxBuf[s_stComm2TrmData.byFrameLen++] = byData;return;rx_exception:ClearCommFrame();return;}
原文:
https://blog.csdn.net/jiangjunjie_2005/article/details/50619884
审核编辑:符乾江
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。
举报投诉
-
单片机
+关注
关注
6074文章
45341浏览量
663700 -
通信协议
+关注
关注
28文章
1073浏览量
41869
发布评论请先 登录
相关推荐
热点推荐
Xilinx FPGA串行通信协议介绍
Xilinx FPGA因其高性能和低延迟,常用于串行通信接口设计。本文深入分析了Aurora、PCI Express和Serial RapidIO这三种在Xilinx系统设计中关键的串行通信协议。介绍了它们的特性、优势和应用场景,以及如何在不同需求下选择合适的
分布式能源并网的通信协议有哪些?
在分布式能源(如光伏、储能、微电网)并网场景中,通信协议需满足 设备互联、数据传输、远程控制、调度协同 等核心需求,不同协议因设计目标不同,适用于从设备层到调度层的不同层级。以下按 “国际标准协议
Modbus 转 Profinet:工业通信协议的桥梁
1. 引言 在工业自动化领域,Modbus 和 Profinet 是两种广泛使用的通信协议。Modbus 是一种串行通信协议,常用于连接工业电子设备,而 Profinet 是一种基于以太网的工业
Dali通信的工作原理 如何使用Dali通信协议
一、引言 Dali(Digital Addressable Lighting Interface,数字可寻址照明接口)是一种用于照明控制产品之间双向通信的协议。通过Dali通信协议,可以实现对照
labview串口通信丢数问题(非终止符问题)
通信协议是参考32960的,和串口助手测试过程正常,和labview通信过程会出现丢数的问题,体现在Bytes at port属性节点返回的字节数上,单片机目前测试的功能是固定每组数据发送127个字节,上位
发表于 01-20 09:13
I2C总线与单片机的连接
在现代电子系统中,单片机(MCU)是核心控制单元,而I2C总线作为一种多主机、多从机的串行通信协议,因其简单、高效和节省引脚的特性而被广泛应用于各种电子设备中。 I2C总线概述 I2C总线由两条线
详解REST API通信协议
的一环。 为了实现这一目标,我们采用了多种通信协议,包括MQTT、OPC UA、AMQP和REST API,它们共同构成了智能通信的坚实基础。本期内容,让我们聚焦REST API通信协议,探索它如何在IIoT领域中发挥关键作用。
搞懂TTL、RS232、485通信协议!
本文介绍了TTL、RS232和RS485这三种常见的通信协议的传输距离、应用场景以及影响通信距离的各种因素。TTL是一种短距离通信标准,通常用于同一电路板内的通信;RS232是一种传统
总线通信协议解析及应用
在现代计算机系统中,总线通信协议扮演着至关重要的角色。它们定义了数据如何在处理器、内存、输入/输出设备等组件之间传输。 总线通信协议的基本概念 总线通信协议是一组规则,它规定了数据在系统总线上的传输
常见串口通信协议 如何设置串口参数
串口通信是一种常见的通信方式,广泛应用于计算机、嵌入式系统和各种电子设备之间。串口通信协议主要是指在串行通信中,数据传输的格式和规则。 常见串口通信
AUTOSAR通信协议解析 如何实现AUTOSAR通信
通信协议栈是一个复杂的系统,它涵盖了多种通信方式和模块,以实现车内ECU之间的高效、可靠的数据交换。以下是对AUTOSAR通信协议的解析及实现AUTOSAR通信的方法: 一、AUTOS

单片机的通信协议该如何设计
评论