找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1682|回复: 11
收起左侧

关于单片机串口数据解析

[复制链接]
ID:1041056 发表于 2022-8-1 20:34 | 显示全部楼层 |阅读模式
50黑币
由串口接收回的数据存储在u8 USART2_RX_BUF[];下面是串口接收中断函数
void  USART2_IRQHandler(void)
{
      
        u8 Res;
        if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
                        {
                        Res =USART_ReceiveData(USART2);        //读取接收到的数据
                  Res&=0x7F;
                       
                        if((USART2_RX_STA&0x8000)==0)//接收未完成
                                {
                                if(USART2_RX_STA&0x4000)//接收到了0x0d
                                        {
                                        if(Res!=0x0a)USART2_RX_STA=0;//接收错误,重新开始
                                        else USART2_RX_STA|=0x8000;        //接收完成了
                                        }
                                else //还没收到0X0D
                                        {      
                                        if(Res==0x0d)USART2_RX_STA|=0x4000;
                                        else
                                                {
                                                USART2_RX_BUF[USART2_RX_STA&0X3FFF]=Res ;
                                                USART2_RX_STA++;
                                                if(USART2_RX_STA>(USART2_REC_LEN-1))USART2_RX_STA=0;//接收数据错误,重新开始接收         
                                                }                 
                                        }
                                }                    
                         }
}

USART2_RX_BUF[]的数据格式如图所示,红框标注为有效数据,红框内数据前8位是压力值,后8位是浓度值,数据类型为浮点型
2022-08-01_203346.png
我想1、将有效数据截取出来
2、将浮点数据转为正常的数值
3、可从串口输出

回复

使用道具 举报

ID:301191 发表于 2022-8-3 03:52 | 显示全部楼层
顶一下
回复

使用道具 举报

ID:94031 发表于 2022-8-3 06:24 | 显示全部楼层
数据内容里是3个数:
42 c8 5c 29 对应压力值:   100.18  (浮点数);
00 10         对应模块状态:0x0010 (16进制数);
41 44 cc cd 对应浓度值:   12.3     (浮点数);
回复

使用道具 举报

ID:123289 发表于 2022-8-3 09:25 | 显示全部楼层
1、研读、了解通讯协议,按协议分解数据。
2、弄通浮点数的组数方式。
这样你就会象板櫈一样明白了。
回复

使用道具 举报

ID:1041056 发表于 2022-8-3 10:37 | 显示全部楼层
yzwzfyz 发表于 2022-8-3 09:25
1、研读、了解通讯协议,按协议分解数据。
2、弄通浮点数的组数方式。
这样你就会象板櫈一样明白了。

转浮点是先将8位16进制转成32位的二进制数,再对二进制进行计算,我现在完成了转二进制,但是二进制数在单片机里也是十六进制表示的,又不会算了
回复

使用道具 举报

ID:195496 发表于 2022-8-3 10:50 | 显示全部楼层
这个不难,要自已把接收数据程序改一下,中断接收采用超时方法进行,接收到有效数据后,置位一个标志位,在主程序中查询,进行数据解析,不要所有工作都在串口中断程序中进行。
回复

使用道具 举报

ID:1034262 发表于 2022-8-3 11:45 | 显示全部楼层
协议不完善吧?没有转义字符?如果数据域中出现冒号或回车换行相同的数据,怎么办?
这是字符同步通讯,我会设置3个特殊字符:命令开始字符、结束字符、转义字符。数据域中出现等于这3个控制字符的数据时,使用转义字符转换一下。
回复

使用道具 举报

ID:883242 发表于 2022-8-3 13:06 | 显示全部楼层
coody_sz 发表于 2022-8-3 11:45
协议不完善吧?没有转义字符?如果数据域中出现冒号或回车换行相同的数据,怎么办?
这是字符同步通讯,我 ...

扯淡,这种协议从0x0~0xff任何字符都可能出现,如果设冒号回车换行这些转义字符就乱套了。

很简单,用超时,比如MODBUS/RTU规定超过3.5个字节的总线空闲就是帧头标志。
回复

使用道具 举报

ID:161164 发表于 2022-8-3 13:14 | 显示全部楼层
首先你要确保USART2_RX_BUF[0]是':'
然后就简单了

float *YaLi;
float *LongDu;

YaLi = (float*)&USART2_RX_BUF[4]);
LongDu = (float*)&USART2_RX_BUF[10]);

printf("YaLi = %0.2f, LongDu = %0.2f\r\n",*YaLi,*LongDu);
回复

使用道具 举报

ID:401564 发表于 2022-8-3 17:41 | 显示全部楼层
这个像是Modbus通讯
1,当串口接收到第1个数据时,启动定时器,并把数据保存到缓冲池中
2,接收到结束符,并且一定时间之后,如果再没接收到新的数据,就认为这是一个完整的数据帧
3,把缓冲池的数据复制到另一个缓冲池中,在主程序对另一个缓冲池的数据进行处理,因为有可能你在处理的时候,来了新的数据,缓冲池的数据结构就不一样了,读取出来的就不一定是原始的数据了

我一般用的是结构struct                                           //串口Buffer结构
{
unsigned char buf_uart[32];                //留32个地址来存放串口的数据
unsigned char cnt_Byte;        //接收到的字节数量
}Buffer0,Buffer1;        //两个结构变量,让串口接收和保存不相互影响

接收到一个完整的数据帧之后,就直接

Buffer1=Buffer0;//把串口缓存的数据复制过来
memset(&Buffer0,0,sizeof(Buffer0));//清除串口接收缓冲
STM32有足够的能力处理串口这点小数据的

读取数据出来不就是很简单的事情吗?就是直接读取数组的数据而已,9#已经给出方法了
回复

使用道具 举报

ID:401564 发表于 2022-8-3 17:51 | 显示全部楼层
coody_sz 发表于 2022-8-3 11:45
协议不完善吧?没有转义字符?如果数据域中出现冒号或回车换行相同的数据,怎么办?
这是字符同步通讯,我 ...

这个数据看着像modbus
两个简单的起始符和结束符意义并不大,接收到的数据中随时有可能就出现了,搞不好数据还没有接收完就结束了
回复

使用道具 举报

ID:883242 发表于 2022-8-3 17:53 | 显示全部楼层
Y_G_G 发表于 2022-8-3 17:41
这个像是Modbus通讯
1,当串口接收到第1个数据时,启动定时器,并把数据保存到缓冲池中
2,接收到结束符,并且 ...

根本就不是什么MODBUS,要么用超时来做帧头标记,中间可以是0x0~0xff任意数字,这是MODBUS/RTU的实现方法。要么用特殊字符比如:做帧头,\r\n做帧尾标记,中间只能出现'0'~'9'、‘A’~‘Z’这类可打印的ASCII字符,绝对不可以在数据帧中间出现: \r \n这几个帧标志,这是MODBUS/ASC的做法。

这个协议的制定者显然是个不懂装懂的半瓶醋,才会搞出这种有逻辑漏洞的东西。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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