ModbusRTU协议帧详解

一.协议帧表格

在这里插入图片描述

二.读取发送帧和返回帧格式

读取帧格式:地址功能码起始地址高字节起始地址低字节读取寄存个数高字节读取寄存个数低字节CRC低字节CRC高字节
读取帧格式:0X010x030x000x000x000x02xxxx
返回帧格式:地址功能码数据长度(读取寄存器个数乘以2)数据部分CRC低字节CRC高字节
返回帧格式:0X010x030x04xxxxxxxxx

三.写数据发送帧和返回帧格式

0x10(16功能码,写多个寄存器)写数据格式

写入帧格式:地址功能码起始地址高字节起始地址低字节写入寄存个数高字节写入寄存个数低字节写入数据长度写入数据CRC低字节CRC高字节
写入帧格式:0X010x100x000x000x000x020x04xxxxxxxx
返回帧格式:地址功能码起始地址高字节起始地址低字节写入寄存个数高字节写入寄存个数低字节CRC低字节CRC高字节
返回帧格式:0X010x100x000x000x000x02xxxx

0x06(06功能码,写单个寄存器)写数据格式

写入帧格式:地址功能码起始地址高字节起始地址低字节写入数据高字节写入数据低字节CRC低字节CRC高字节
写入帧格式:0X010x060x000x00xxxxxxxx

返回格式个写入格式一致

返回帧格式:地址功能码起始地址高字节起始地址低字节写入数据高字节写入数据低字节CRC低字节CRC高字节
返回帧格式:0X010x060x000x00xxxxxxxx

0x05(05功能码,写开关位)写数据格式

写入帧格式:地址功能码起始地址高字节起始地址低字节写入数据高字节写入数据低字节CRC低字节CRC高字节
写入帧格式(置1):0X010x050x000x000xFF0x00xxxx
写入帧格式(置0):0X010x050x000x000x000x00xxxx

返回格式个写入格式一致

写入帧格式:地址功能码起始地址高字节起始地址低字节写入数据高字节写入数据低字节CRC低字节CRC高字节
返回帧格式(置1):0X010x050x000x000xFF0x00xxxx
返回帧格式(置0):0X010x050x000x000x000x00xxxx

四.功能码定义

功能码描述
0x01读取开关量输出,可读写(开关量读取是按位读取的(不是按寄存数目读取的),所以返回的字节数目并不是读取的寄存器个数乘以2,是读取的开关量个数除以8的商值加1(加不加1看余数是不是0,余数非零就加1)),可以被05和0F(15)功能码写
0x02读取开关量输入,只读(开关量读取是按位读取的(不是按寄存数目读取的),所以返回的字节数目并不是读取的寄存器个数乘以2,是读取的开关量个数除以8的商值加1(加不加1看余数是不是0,余数非零就加1))
0x03读取数值量,定义上能被03的读取的可以被06和10写
0x04读取数值量,定义只能读不能写,实际需要根据实际情况来(如果开放可以被06和10写)
0x05写开关量,只对01可以读取的数据写
0x06写单个寄存,对能被03功能码读取的寄存器进行写数据操作
0x10写多个寄存器,对能被03功能码读取的寄存器进行写数据操作

五.注意事项,必看

1.一个寄存器等于两个字节
2.(01和02功能码)开关量读取是按位读取的(不是按寄存数目读取的),所以返回的字节数目并不是读取的寄存器个数乘以2,是读取的开关量个数除以8的商值加1(加不加1看余数是不是0,余数非零就加1),比如读取7个开关量,返回数据长度就是(7/8),商是0余数是1,所以数据部分返回1个字节的长度,比如读取10个开关量,返回数据长度就是(10/8),商是1余数是2,所以数据部分返回2个字节的长度

六.CRC校验计算C/C++

xxx.h

unsigned short int CheckCRC_16(const  unsigned char* data,const unsigned int sIndex=0,const unsigned int length=0);

xxx.c

unsigned short int CheckCRC_16(const unsigned char *data, const unsigned int sIndex, const unsigned int length)
{
    unsigned int CRCreg=0xFFFF;
    int len=length+sIndex;
    for(int i=sIndex;i<len;i++)
    {
        CRCreg=CRCreg^data[i];
        for(int j=0;j<=7;j++)
        {
            if(CRCreg&0x01)
            {
                CRCreg=(CRCreg>>1)^0xa001;
            }
            else
            {
                CRCreg=CRCreg>>1;
            }
        }
    }
    return CRCreg;
}

七.字节和浮点型相互转换C/C++

//以C语言转换为例:转换30.96(16进制41 F7 AE 14)

#include<stdio.h>
//使用联合体来实现
typedef union _HexFloat
{

char hex[4];
float fval;
}_HexFloat;

int main()
{
    _HexFloat HexFloat;
    //将16进制值分别放进去 ,如果得出的值不对就交换位置
    HexFloat.hex[3]=0x41;
    HexFloat.hex[2]=0xf7;
    HexFloat.hex[1]=0xae;
    HexFloat.hex[0]=0x14;
    printf("fval十进制的值为=%f\n",HexFloat.fval);
	return 0;
}

八.Qt实现modbusRTU/TCP主站demo

程序只做了modbusRTU的串口demo,但是封装的类可以选择摩登busTCP协议
demo链接Qt ModbusRTU通讯demo,多线程通讯

  • 7
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值