相关文章推荐
犯傻的绿茶  ·  clickhouse ...·  1 月前    · 
善良的鞭炮  ·  connection aborted.' ...·  1 年前    · 

一、Modbus协议0x10功能码

0x10功能码:写多个寄存器
在这里插入图片描述
例: 请求在从机设备 17 中的 2 个寄存器中放入预置值, 起始寄存器为 40002 , 预置值为 00 0AH 和 01 02H。

  • Modbus主机查询
    在这里插入图片描述
  • Modbus从机回复
    在这里插入图片描述

二、数据在内存中存储方式

要想把字节正确组合成浮点数,首先要了解数据在内存中是怎么存储的。存储方式有两种:

  • 大端模式
    大端模式是指数据的高字节保存在内存的低地址单元中,而数据的低字节保存在内存的高地址单元中,这样的存储模式有点类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。

  • 小端模式
    小端模式是指数据的高字节保存在内存的高地址单元中,而数据的低字节保存在内存的低地址单元中。

我使用的是STM32F4芯片,STM32的存储方式是小端模式,数据的低字节存在内存的低地址单元中,高字节存在内存的高地址单元中。如下图所示:

三、从机处理接收到的数据

我的Modbus主站是触摸屏,Modbus从站是STM32。主机输入浮点数之后,我的从机收到如下数据:

01 10 00 15 00 02 04 41 BC 00 00 CRC-L CRC-H

41 BC 00 00 这四个字节就是我想提取的浮点数,根据Modbus协议可知,41是高字节,00是低字节。因为STM32是小端模式,所以高字节要存放在内存中的高地址。从机把四个字节存储好之后,我再把这个存储区域的首地址强制转换为float指针类型,这样就可以提取出这个浮点数了。

*作用:把u8四字节数组转为float *note:低地址放float的低字节 float U8_to_Float ( u8 * str ) float data ; data = * ( ( float * ) str ) ; return data ;

另外一种方式就是定义一个float变量,然后定义u8类型指针数组指向float变量地址,Modbus协议解析的时候只管向地址指向的存储单元填充数据,需要用浮点数的时候直接拿过来用就可以了。
这段过程可以在VS中模拟,主要分了两步实现。
仿真代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)  
    float freq;
    char recv[4] = {0x41, 0xbc, 0x00, 0x00}; //接收到的数据,高字节到低字节排列
    char *Modbus_HoldReg[4];				 //定义保持寄存器指针数组
    //第一步:指针初始化
    Modbus_HoldReg[0] = ((char*)(&freq)) + 3;	 //低地址指向高位
    Modbus_HoldReg[1] = ((char*)(&freq)) + 2;     
    Modbus_HoldReg[2] = ((char*)(&freq)) + 1;     
    Modbus_HoldReg[3] = ((char*)(&freq)) + 0;	 //高地址指向低位
    //第二步:给地址指定的内存单元赋值(对应Modbus协议中的数据解析)
    *Modbus_HoldReg[0] = recv[0];
    *Modbus_HoldReg[1] = recv[1];
    *Modbus_HoldReg[2] = recv[2];
    *Modbus_HoldReg[3] = recv[3];
    printf("%f\r\n", freq);
    return 0;

Modbus协议参考网址:
http://www.openedv.com/forum.php?mod=viewthread&tid=77263&highlight=modbus

Modbus通信协议之四字节转浮点数一、Modbus协议0x10功能码0x10功能码:写多个寄存器 例: 请求在从机设备 17 中的 2 个寄存器中放入预置值, 起 始寄存器为 40002 , 预置值为 00 0AH 和 01 02H。Modbus主机查询 Modbus从机回复 二、数据在内存中存储方式要想把字节正确组合成浮点数,首先要了解数据在内存中... 这里S 代表符号位,1是负,0是正 E 偏移127的幂,二进制阶=(EEEEEEEE)-127。 M 24位的尾数保存在23位中,只存储23位,最高位固定为1。此方法用最较少的位数实现了较高的有效位数,提高了精度。 零是一个特定值,幂是0 尾数也是0。...
modbus协议通信时浮点数如何发送和接收处理的解决办法   在本次做项目的时候,发现需要威纶通屏幕与stm32芯片采用modbus通信,很多时候需要处理float小数。最开始一直在纠结大小端的问题,坑了一天,理出了下面的解决办法。   注意:主机发送给从机的小数是以32位的形式发送的,所以会占用2个保持寄存器。并且本次项目的威纶通屏幕作为主机时,是以小端形式发送数据,与stm32f103芯片一致,此处大小端问题我不在详细说明(主要是自己太菜了,太懒了,画图来说明很耽误时间) 一、如何将保持寄存器中存放的
在LabVIEW中,我们可以使用函数“Unflatten From Byte Stream”将四个字节的数据换为一个浮点数。在这个函数中,我们需要输入包含四个字节数据的字节数组和一个布尔常量来指定数据的字节顺序(大端或小端)。 一旦我们把这个四字节字节数组通过“Unflatten From Byte Stream”函数换成单精度浮点数,我们可以进行各种计算和处理。例如,我们可以使用这个浮点数与其他浮点数进行加、减、乘、除等运算,或者将它换成字符串、布尔值或其他数据类型。 需要注意的是,字节数组中的四个字节必须是按正确的顺序组合的。如果字节数组中的字节顺序与系统的字节顺序不同,我们需要在使用“Unflatten From Byte Stream”函数之前对字节数组进行字节顺序反操作。 总之,将四个字节数据换为单精度浮点数是一个简单而常见的操作,并且使用LabVIEW中的“Unflatten From Byte Stream”函数可以很容易地实现。