Y_G_G 发表于 2022-8-3 17:41 根本就不是什么MODBUS,要么用超时来做帧头标记,中间可以是0x0~0xff任意数字,这是MODBUS/RTU的实现方法。要么用特殊字符比如:做帧头,\r\n做帧尾标记,中间只能出现'0'~'9'、‘A’~‘Z’这类可打印的ASCII字符,绝对不可以在数据帧中间出现: \r \n这几个帧标志,这是MODBUS/ASC的做法。 这个协议的制定者显然是个不懂装懂的半瓶醋,才会搞出这种有逻辑漏洞的东西。 |
coody_sz 发表于 2022-8-3 11:45 这个数据看着像modbus 两个简单的起始符和结束符意义并不大,接收到的数据中随时有可能就出现了,搞不好数据还没有接收完就结束了 |
这个像是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#已经给出方法了 |
首先你要确保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); |
coody_sz 发表于 2022-8-3 11:45 扯淡,这种协议从0x0~0xff任何字符都可能出现,如果设冒号回车换行这些转义字符就乱套了。 很简单,用超时,比如MODBUS/RTU规定超过3.5个字节的总线空闲就是帧头标志。 |
协议不完善吧?没有转义字符?如果数据域中出现冒号或回车换行相同的数据,怎么办? 这是字符同步通讯,我会设置3个特殊字符:命令开始字符、结束字符、转义字符。数据域中出现等于这3个控制字符的数据时,使用转义字符转换一下。 |
这个不难,要自已把接收数据程序改一下,中断接收采用超时方法进行,接收到有效数据后,置位一个标志位,在主程序中查询,进行数据解析,不要所有工作都在串口中断程序中进行。 |
yzwzfyz 发表于 2022-8-3 09:25 转浮点是先将8位16进制转成32位的二进制数,再对二进制进行计算,我现在完成了转二进制,但是二进制数在单片机里也是十六进制表示的,又不会算了 |
1、研读、了解通讯协议,按协议分解数据。 2、弄通浮点数的组数方式。 这样你就会象板櫈一样明白了。 |
数据内容里是3个数: 42 c8 5c 29 对应压力值: 100.18 (浮点数); 00 10 对应模块状态:0x0010 (16进制数); 41 44 cc cd 对应浓度值: 12.3 (浮点数); |
顶一下 |