不想让人了解到的ModbusTCP简介

  一,简介  

  modbus协议是现在国内工业领域用的最多的协议,不只国内的PLC设备,各种终端设备,比如水控机、水表、电表、工业秤、各种采集设备,凡是厂家没有能力设计协议的,都会直接上modbus协议。这个协议也是经过市场验证,经久不衰的协议。modbus分两种,一类是通过串口(232 485 422)采集的modbus RTU协议,一类是通过网口采集的modbus TCP协议,我们项目中用的是modbus TCP。

modbus 都是主从式问答,主机发送查询指令,从机响应;主机发送设置指令,主机响应。项目里我们的程序作为主机,发送指令查询。从机我们用modbus slave软件模拟,可以模拟任意设备,任意地址。

二,函数接口

modbus_t*   modbus_new_tcp(const char *ip, int port)
功能:以TCP方式创建Modbus实例,并初始化
参数:
    ip   :ip地址
    port:端口号
返回值:成功:Modbus实例
      失败:NULL
int modbus_set_slave(modbus_t *ctx, int slave)
功能:设置从机ID
参数:
    ctx   :Modbus实例
    slave:从机ID
返回值:成功:0
       失败:-1
int   modbus_connect(modbus_t *ctx)
功能:和从机(slave)建立连接
参数:
    ctx:Modbus实例
返回值:成功:0
       失败:-1
void   modbus_free(modbus_t *ctx)
功能:释放Modbus实例
参数:ctx:Modbus实例
void   modbus_close(modbus_t *ctx)
功能:关闭套接字
参数:ctx:Modbus实例
int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)
功能:读取线圈状态,可读取多个连续线圈的状态(对应功能码为0x01)
参数:
    ctx   :Modbus实例
    addr :寄存器起始地址
    nb    :寄存器个数
    dest :得到的状态值
int  modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)
功能:读取输入状态,可读取多个连续输入的状态(对应功能码为0x02)
参数:
    ctx   :Modbus实例
    addr :寄存器起始地址
    nb   :寄存器个数
    dest :得到的状态值
返回值:成功:返回nb的值
int  modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)
功能:读取保持寄存器的值,可读取多个连续保持寄存器的值(对应功能码为0x03)
参数:
    ctx   :Modbus实例
    addr :寄存器起始地址
    nb    :寄存器个数
    dest :得到的寄存器的值
返回值:成功:读到寄存器的个数
       失败:-1
int   modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)
功能:读输入寄存器的值,可读取多个连续输入寄存器的值(对应功能码为0x04)
参数:
    ctx   :Modbus实例
    addr :寄存器起始地址
    nb    :寄存器个数
    dest :得到的寄存器的值
返回值:成功:读到寄存器的个数
       失败:-1
int  modbus_write_bit(modbus_t *ctx, int addr, int status);
功能:写入单个线圈的状态(对应功能码为0x05)
参数:
    ctx     :Modbus实例
    addr  :线圈地址
    status:线圈状态
返回值:成功:0
      失败:-1
int  modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src);
功能:写入多个连续线圈的状态(对应功能码为15)
参数:
    ctx     :Modbus实例
    addr  :线圈地址
    nb     :线圈个数
    src    :多个线圈状态
返回值:成功:0
      失败:-1
int  modbus_write_register(modbus_t *ctx, int addr, int value);
功能:  写入单个寄存器(对应功能码为0x06)
参数: 
    ctx    :Modbus实例
    addr  :寄存器地址
    value :寄存器的值 
返回值:成功:0
       失败:-1
int  modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src);
功能:写入多个连续寄存器(对应功能码为16)
参数:
    ctx    :Modbus实例
    addr  :寄存器地址
    nb     :寄存器的个数
    src    :多个寄存器的值 
返回值:成功:0
      失败:-1

三,类型

typedef struct _modbus_mapping_t {
    int nb_bits;                    //线圈寄存器的数量
    int start_bits;                 //线圈寄存器的起始地址
    int nb_input_bits;              //离散输入寄存器的数量       
    int start_input_bits;           //离散输入寄存器的起始地址
    int nb_input_registers;         //输入寄存器的数量
    int start_input_registers;      //输入寄存器的起始地址
    int nb_registers;               //保持寄存器的数量
    int start_registers;            //保持寄存器的起始地址
    uint8_t *tab_bits;              //指向线圈寄存器的值
    uint8_t *tab_input_bits;        //指向离散输入寄存器的值
    uint16_t *tab_input_registers;  //指向输入寄存器的值

    uint16_t *tab_registers;        //指向保持寄存器的值
} modbus_mapping_t;

四,读写


//读取线圈或者离散量输出状态(功能码 0x1)
MODBUS_API int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);
//读取离散量输入值(功能码 0x2)
MODBUS_API int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);
//读取保持寄存器(功能码 0x3)
MODBUS_API int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
//读取输入寄存器(功能码 0x4)
MODBUS_API int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
//写单个线圈或者单个离散量(功能码 0x5)
MODBUS_API int modbus_write_bit(modbus_t *ctx, int coil_addr, int status);
//写单个保持寄存器(功能码 0x6)
MODBUS_API int modbus_write_register(modbus_t *ctx, int reg_addr, const uint16_t value);
//写多个线圈(功能码 0xF)
MODBUS_API int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *data);
//写多个保持寄存器(功能码 0x10)

五,uint ?_t解析

根据POSIX标准,对应的*T类型:1字节uint8ut,2字节uint16ut,4字节uint32ut,8字节Uint64ut,POSIX代表UNIX的可移植操作系统接口(简称POSIX)。POSIX标准定义了操作系统应该为应用程序提供的接口标准。它是IEEE为运行在各种UNIX操作系统上的软件定义的一系列API标准的总称。它的正式名称是IEEE1003,而国际标准名称是ISO/IEC9945。

uint8和uint16是什么数据类型?
Int8是一个8位无符号整数,uint16是一个16位无符号整数。

整数有两种类型:有符号和无符号。默认情况下,声明的整数变量是有符号的(char有点特殊)。如果需要声明一个未签名的类型,则需要在该类型之前添加signed。当不可能取负值时,可以将其定义为无符号。在一些底层嵌入式编程中,数据通常是无符号的。

uint8是什么类型?
这是一个C99整数类型,包括header和ltinttypes。H>//此文件中定义的整数类型uint8utu=>unsignedintinteger8是8位的Unit8ut它相当于一个char,Unit8ut可以是32位,但编译器将只使用它的8位,这是由C99和类似的intleast32ut定义的,至少是32位的整数。具体位数取决于编译器。它保证整数将被分配给您至少32位。

uint8_t就是typedefunsignedintuint8_t?
是

uint8ut实际上是一个char无符号字符,char是一个数据类型

定义:typedefunsignedcharuint8ut[T

注意:uint8ut类型变量的输出将输出什么,如下面的代码?

uint8utid=67

cout

结果是:LD=C而不是LD=67

这是因为typedefunsignedcharuint8ut

uint8ut实际上是一个char

cout

所以,输出uint8ut类型的变量的实际输出是它对应的字符,而不是实数

输出67,您可以这样做:

cout

(typedefunsignedshortintuint16ut)

结果是:LD=67

六,通过读取字节数组来设置位

void modbus_set_bits_from_bytes(uint8_t *dest, int index, unsigned int nb_bits, const uint8_t *tab_byte);
	% 本函数的功能是通过读取字节数组来设置位,从tab_byte数组的第1个开始的所有字节都会被写到dest数组中从index索引开始的位置;

七,DCBA顺序获取浮点值float

modbus_get_float_dcba(const uint16_t *src);

DCBA顺序存储浮点值

void modbus_set_float_dcba(float f, uint16_t *dest)

float modbus_get_float(const uint16_t *src);

void modbus_set_float(float f, uint16_t *des

       这个两个函数主要是将整型数据转换成float,和将float转换成整型的。
在用modbus_read_registers或者modbus_read_input_registers得到寄存器的值int16_t *dest,如果里面存的是浮点数,把dest当做参数传入到modbus_get_float里面,如果得到的值不对,你需要弄清楚PLC对应传出数据的模式是DCBA还是BADC,CDAB,ABC

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值