这两天在开发STM32的Modbus主站,就买了一个RS485总线的温湿度传感器来,温湿度传感器说明要求将传感器返回的Modbus报文数据转换为10进制后再除以10得到真实数据,以下是举例
Modbus主站发送报文:
01 04 00 01 00 01 60 0A
意思是读取从站地址01的输入寄存器1号位1位数据
SlaveID | FunctionCode | StartADDR | Length | CRC |
---|---|---|---|---|
从站ID | 功能码 | 起始地址 | 寄存器数量 | CRC校验 |
01 | 04 | 00 01 | 00 01 | 60 0A |
Modbus主站接收报文:
01 04 02 01 2D 78 BD
意思是从站ID为01,功能码为04,数据有两位(一个数据是通过两位来返回),数据高位01,数据低位2D
SlaveID | FunctionCode | Length | Data | CRC |
---|---|---|---|---|
从站ID | 功能码 | 寄存器数量 | 数据 | CRC校验 |
01 | 04 | 02 | 01 2D | 78 BD |
以上是数据解析
那么问题来了,返回的01 2D怎么变成我们需要的数据
根据传感器说明书,我们需要将返回值变成10进制数据后除以10得到温度值,可以理解为以下流程
要做的就是将01 2D转化成30.1这个数字
一开始我还各种骚操作,结果最后发现就很简单,怪自己C语言基础还是有点问题
在计算机中,16进制数字表示的数值和10进制表示的数值其实是一样的,计算上并不存在进制转换问题,存在的是进位的时候是按照10进制进位还是16进制进位
例如:
一个十六进制数2D,以%x形式打印为2d,以%d打印为45
本质上是同一个数
所以在处理Modbus的数据时,设高位为NUM_H,低位为NUM_L,需要的10进制数为Data,高位进位为16的平方,即
Data=NUM_H×16×16+NUM_L
例如2F 3D
计算器转换为10进制为12093
2F代表的10进制为47,3D代表的10进制为61
所以
Data=2F×16×16+3D
=47×16×16+61
=12093
所以我接收到的数据01 2D根据公式换算为
Data=01×16×16+2D
=1×16×16+45
=301
温度=301/10
=30.1°
可知我当前室温30.1摄氏度。
所以结论就是,Modbus接收的数据不需要转换进制,只需要进位按照16进制的百位进位既可,也就是16的平方公式就是:
Data:需要的数据
NUM_H:Modbus数据高位
NUM_L:Modbus数据低位
Data=NUM_H×16×16+NUM_L
因为我说过不给结果的博客都是耍流氓,但是这个结果不好给所以以下是我按照公式计算出来的我的室温和湿度,通过STM32串口发送出来的,当作是结果吧!哈哈哈哈
我看别人转进制代码都是要钱的,我这里就把公式白给了,很多小白也会遇到这个坑,希望能帮助一下和我以前有一样疑问的人
听说给我点赞评论关注三连的人写代码都不会有BUG!
ASWaterbenben 原创文章 27获赞 78访问量 2万+ 关注 私信 展开阅读全文