[STM32] 串口数据帧处理(第一弹)
文章目录
- 1 串口使用的常用场景
- 2 字节帧处理
- 总结
1 串口使用的常用场景
使用串口的主要目的是实现数据的交互,数据的交互的方法脱身于常用的场景。这里描述一个比较典型的场景:
MCU作为主控制器通过串口和外部的设备或者人进行交互。对于单片机端的设备往往存在一系列的指令。对于控制一个电机而言,他可以具备如下的行为,停止、转动、速度设置、位置设置等等。进而,对于多个微控制器存在的系统而言,各个控制器间也需要进行一定的信息交互,比如,从机向主机定时的发送心跳包来告知主机我的工作状态良好等。因此,一套遵从统一规则的串口帧协议十分重要,可以较好对命令集合进行处理,同时,可以对常见的问题进行合理的调整。
2 字节帧处理
制定串口协议的方式有很多,这里说一下我处理字节帧的一点经验。
以做过的一个项目为例,具体的帧结构如下图所示:
- 数据帧头:AA 55
- ID编号为固定的 0x10
- CH: 输入 1 – 4 选通指定通道, 5:失能所有通道 6:使能所有通道
- NULL: 空字节 可填入任意值
- SUM: SUM = ID + CH + NULL + NULL + NULL + NULL + NULL + NULL + NULL + NULL + NULL + NULL + NULL + NULL + NULL + NULL + NULL + NULL + NULL + NULL
帧定义了帧头、数据、帧尾。这里使用的帧属于定长帧,定长帧的优势在于处理的方式较为简便。缺点也显而易见,对于数据位较少的帧,是一种时间上的浪费(问题不大)。
解帧思路:同时获取到两个帧头,获取ID,通过ID来判断数据的长度,进而获取完整数据,再者检查校验码。校验码正确则消费数据,否则丢弃。
好了,直接上代码(有优化的可以评论留言):
#define FRAME_HEAD1 0xAA
#define FRAME_HEAD2 0x55
#define FRAME_DATA_LEN 20/*
***********************************************************************************************
* 函 数 名: CheckSum
* 功能说明: 校验和判断
* 形 参:无
* 返 回 值: true :校验正确 false:校验失败
***********************************************************************************************
*/
static uint8_t CheckSum(uint8_t *pValueBuff, uint8_t u8BuffLen, uint8_t u8CheckNum)
{uint8_t u8Sum = 0;if (u8BuffLen > FRAME_DATA_LEN){return FALSE;}for (uint8_t i = 0; i < u8BuffLen; i++){u8Sum += *pValueBuff;pValueBuff++;}return u8CheckNum == u8Sum ? TRUE : FALSE;
}/*
***********************************************************************************************
* 函 数 名: DealCmd
* 功能说明: 命令处理函数
* 形 参:数据帧
* 返 回 值: 无
***********************************************************************************************
*/
void DealCmd(uint8_t *pFrame)
{switch (*pFrame){case EM_CYCLIC_ID:{DealCvFrame(pFrame);}break; case EM_PULSE_ID:{ DealDpvFrame(pFrame);}break;case EM_TEST_ID:{ DealTestFrame(pFrame);}break; default:{print(PERROR, " 无效ID\n ");}break;}
}/*
***********************************************************************************************
* 函 数 名: GetConfigCmd
* 功能说明: 数据帧处理
* 形 参:无
* 返 回 值: 无
***********************************************************************************************
*/
void GetConfigCmd(void)
{uint8_t u8Temp = 0;static uint8_t u8index = 0;static uint8_t u8HeadFlag = 0;static uint8_t u8BuffTemp[FRAME_DATA_LEN + 1] = {0};while (comGetChar(CONNECT_COM, &u8Temp)){if (FRAME_HEAD1 == u8Temp && FALSE == u8HeadFlag){u8HeadFlag = 1;}if (FRAME_HEAD2 == u8Temp && 1 == u8HeadFlag){u8HeadFlag = 2;continue;}if (2 == u8HeadFlag){u8BuffTemp[u8index++] = u8Temp;if (u8index > FRAME_DATA_LEN){if (CheckSum(u8BuffTemp, FRAME_DATA_LEN, u8BuffTemp[FRAME_DATA_LEN])){DealCmd(u8BuffTemp); //消费数据 }u8HeadFlag = FALSE;u8index = 0;u8BuffTemp[0] = EM_MAX_ID;}}}
}
这个实际上不是重点,下面来看看如何提取数据。
我们知道我们很大概率需要传送的数据有,(有无符号)整形,浮点型(往往更具精度乘一定倍数处理成整形)。那如何将这两种类型较好的处理呢。
这里我们用到了C种的结构体,我们知道结构体存在字节对齐的问题,但我们的数据是单字节对齐的,不存在空位的,因此需要使用如下命令告知编译器不适用默认的字节对齐规则,而是单字节对齐。
第二个问题是对于ARM而言,数据的存储方式是小端模式,但是我们的串口数据在接收后存在FIFO种是大端的模式,因此我们需要进行转换。
解决第一个问题:
#pragma pack(1) 中 1 代表单字节对齐。
#pragma pack(1)
typedef struct CV_DATA_FRAME
{uint8_t Id;int16_t InitE;int16_t HighE;int16_t LowE;uint8_t InitPN;uint16_t ScanRate;uint32_t SweepSeg;uint8_t SampleInt;uint32_t QuietTime;
}stCvFrame;
#pragma pack()
解决第二个问题:
#define REVERSE_16(X) ((X & 0x00FFU) << 8 | (X & 0xFF00U) >> 8)#define REVERSE_32(X) ((X & 0x000000FFU) << 24 | (X & 0x0000FF00U) << 8 | (X & 0x00FF0000U) >> 8 | (X & 0xFF000000U) >> 24)
OK, 到此为止一切解决。现在看一下提取数据:
/*
***********************************************************************************************
* 函 数 名: DealCvFrame
* 功能说明: 命令处理函数
* 形 参:数据帧
* 返 回 值: 无
***********************************************************************************************
*/
void DealCvFrame(uint8_t *pFrame)
{stCvFrame *p_stCvDataFrame;stCvFrame stCvDataTemp;p_stCvDataFrame = (stCvFrame *)pFrame;{stCvDataTemp.InitE = REVERSE_16(p_stCvDataFrame->InitE);stCvDataTemp.HighE = REVERSE_16(p_stCvDataFrame->HighE);stCvDataTemp.LowE = REVERSE_16(p_stCvDataFrame->LowE);stCvDataTemp.InitPN = p_stCvDataFrame->InitPN;stCvDataTemp.ScanRate = REVERSE_16(p_stCvDataFrame->ScanRate);stCvDataTemp.SweepSeg = REVERSE_32(p_stCvDataFrame->SweepSeg);stCvDataTemp.SampleInt = p_stCvDataFrame->SampleInt; }{stCvDataTemp.QuietTime = REVERSE_32(p_stCvDataFrame->QuietTime);stCvDataTemp.Id = p_stCvDataFrame->Id;}
}
总结
具体的实现都写在了正文中,同时如果你有好的建议欢迎留言交流,共同学习。
[STM32] 串口数据帧处理(第一弹)相关推荐
- STM32串口第一个字节丢失问题的分析过程
STM32串口发送必须先检测状态,否则第一个字节无法发出,发送完毕,必须检测发送状态是否完成,否则,发送不成功,使用stm32f10x调试串口通讯时,发现一个出错的现象,硬件复位重启之后,发送测试数据 ...
- stm32串口传输数据第一个数据被吞_stm32串口发送数据复位 第一个数据丢失
http://blog.csdn.net/kevinhg/article/details/40991655 STM32串口发送必须先检测状态,否则第一个字节无法发出,发送完毕,必须检测发送状态是否完成 ...
- stm32串口传输数据第一个数据被吞_STM32串口第一个字节丢失问题的分析过程
STM32串口发送必须先检测状态,否则第一个字节无法发出,发送完毕,必须检测发送状态是否完成,否则,发送不成功,使用stm32f10x调试串口通讯时,发现一个出错的现象,硬件复位重启之后,发送测试数据 ...
- STM32串口第一字节消失或者误码的原因和解决方案
现象:stm32复位之后串口打印的第一个字节误码或者消失. 误码原因:误码多是由于端口初始化有问题.使用ST官方v3.5的标准库时,对串口输出端口进行了重复初始化. 如下代码: /* PA[15:0] ...
- proteus如何添加stm32_新手入门轻松掌握 STM32 串口应用
stm32 USART串口在我们的实际开发中是经常会用到的一个一项技术,所以对于stm32串口的学习还是要细致些的,所以今天我们就来看一下stm32 USART串口的应用,先通过一些文字和简单的代码来 ...
- STM32串口通信详解以及通信异常或者卡死常见问题分析
STM32串口通信详解以及通信异常或者卡死常见问题分析 目录 STM32串口通信详解以及通信异常或者卡死常见问题分析 一.常见的异常问题 二.STM32的串口简介 1.串口的通讯方式 ①按数据传输方向 ...
- STM32 —— 串口通讯
STM32 -- 串口通讯 什么是串口通讯 串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此大部分电子设备都支持该通讯方式,其通讯协议可分层 ...
- dma接收双缓存 stm32_容易被大多数人忽视的STM32串口DMA问题
讨论三个问题: 1.什么叫串口DMA 请求: 2.串口简要复习: 3.串口DMA发送流程. 第一 什么叫串口DMA 请求(战舰STM32开发板) 说这个问题之前先简单回顾DMA的基本特性.先导出原子哥 ...
- STM32串口接收数据
参考串口接收中断处理函数: //------------------------------------------------------------------ //函数名:void USART1 ...
最新文章
- 自画菜单中如何触发MeasureItem事件的问题及解决办法
- php一个英文几个字符,PHP指定截取字符串中的中英文或数字字符的实例分享
- sap系统操作流程财务软件_金蝶财务软件的操作流程汇总
- 淘宝top平台调用接口响应时间优化
- 使用halcon将一个圆上的点拟合成圆形并且求出圆心
- 如何在Linux上使用netstat命令查证DDOS***
- 如何成为合格的数据分析师
- mindoc mysql_MinDoc文档管理系统搭建
- BOSS直聘下载自己的简历要钱!而且是PDF格式 - 解决方法
- 计算机科学技术对教育的影响,计算机科学技术在计算机教育中的应用分析(原稿)...
- 艾尔塔7号/Elta7
- (Emitted value instead of an instance of Error)
- 支持苹果18W-60W PD快充协议芯片JD6606S
- JavaWeb学习(第一天)-1-HTML部分
- 为什么要学Markdown?有什么用?
- 11.18C语言练习题
- 市场调研-全球与中国FPGA和CPLD开发套件市场现状及未来发展趋势
- 虚拟服务器安装ibm mq,IBM MQ 客户端查看服务端消息的工具 WMQTool
- 【转】Blogcn(中国博客网)宣布终止免费服务
- 维修普源DS1102E示波器 24位脉冲编码器
热门文章
- 亚马逊登陆显示服务器出错,亚马逊登录不上去为什么?是因为被封号了吗?
- imagenet 数据整理
- 朗读评价语言集锦_转载‖语文课堂评价语集锦
- 如何从Mac轻松清理其他存储文件?
- 2017年下一个百亿美金级创业机会的6个特征
- 三角形有限元matlab,3结点三角形单元有限元程序MATLAB语言
- jQuery怎么把html转义,JS及JQuery对Html内容编码,Html转义
- Typora收费后我换了个Markdown编辑器(Marktext)
- RR和RC的MVCC实现
- couple和double的区别_Double Trouble Couple