IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Modbus学习记录(3) -> 正文阅读

[系统运维]Modbus学习记录(3)

本文只列举了常用的API,其他的API参考官方API文档:https://libmodbus.org/docs/v3.1.4/

初始化相关API

modbus_new_rtu()

modbus_t *modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit);

功能:
函数应该分配和初始化一个modbus_t结构,以便在串行线上以RTU模式通信。

参数:

  • device:参数指定操作系统处理的串口的名称,例如。“/ dev / ttyS0”或“/ dev /
    ttyUSB0”。
  • baud:指定通信的波特率,例如。9600、19200、57600、115200等
  • parity:奇偶校验参数可以有以下值之一: N没有 E为偶校验 O为奇校验
  • data_bits参数指定数据的位数,允许的值为5、6、7和8。
  • stop_bits参数指定stop的位,允许的值是1和2。

一旦modbus_t结构被初始化,你必须用modbus_set_slave(3)设置你的设备的从机,并用modbus_connect(3)连接到串行总线。

返回值:
如果成功,函数将返回一个指向modbus_t结构体的指针。否则,它将返回NULL并将errno设置为EINVAL(给出了一个无效参数)

例子:

modbus_t *ctx;

ctx = modbus_new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1);
if (ctx == NULL) {
    fprintf(stderr, "Unable to create the libmodbus context\n");
    return -1;
}

modbus_set_slave(ctx, YOUR_DEVICE_ID);

if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

modbus_new_tcp()

modbus_t *modbus_new_tcp(const char *ip, int port);

功能:
modbus_new_tcp()函数应该分配和初始化一个modbus_t结构体来与Modbus TCP IPv4服务器通信。

参数:

  • ip指定客户端想要建立连接的服务器的ip地址。NULL值可以用来监听服务器模式下的任何地址。
  • port参数是要使用的TCP端口。将端口设置为MODBUS_TCP_DEFAULT_PORT,使用默认的502端口。使用大于或等于1024的端口号很方便,因为它不需要拥有管理员权限。

返回:
如果成功,函数将返回一个指向modbus_t结构体的指针。否则,它将返回NULL并将errno设置为EINVAL(An invalid IP address was given.)

例子:

modbus_t *ctx;

ctx = modbus_new_tcp("127.0.0.1", 1502);
if (ctx == NULL) {
    fprintf(stderr, "Unable to allocate libmodbus context\n");
    return -1;
}

if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

modbus_new_tcp_pi()

modbus_t *modbus_new_tcp_pi(const char *node, const char *service);

功能:
modbus_new_tcp_pi()函数应该分配和初始化一个modbus_t结构体来与Modbus TCP IPv4或IPv6服务器通信。

参数:

  • node参数指定要连接的主机的主机名或IP地址,例如。192.168.0.5、::1或server.com。NULL值可以用来监听服务器模式下的任何地址。
  • service参数是要连接的服务名/端口号。如果使用默认的Modbus端口,请使用字符串“502”。在许多Unix系统上,使用大于或等于1024的端口号是很方便的,因为它不需要拥有管理员权限。

返回:
如果成功,函数将返回一个指向modbus_t结构体的指针。否则,它将返回NULL并将errno设置为EINVAL(节点字符串为空或已被截断。服务字符串为空或已被截断)。

例子:

modbus_t *ctx;

ctx = modbus_new_tcp_pi("::1", "1502");
if (ctx == NULL) {
    fprintf(stderr, "Unable to allocate libmodbus context\n");
    return -1;
}

if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

连接相关API

建立和关闭与Modbus设备的连接提供以下功能:

modbus_connect()

int modbus_connect(modbus_t *ctx);

功能:
函数应该使用参数中给出的libmodbus上下文信息建立到Modbus服务器、网络或总线的连接。

参数:
ctx:指向modbus_t结构体的指针

返回:
如果成功,函数将返回0。否则,它将返回-1,并将errno设置为底层平台的系统调用定义的值之一。

例子:

modbus_t *ctx;

ctx = modbus_new_tcp("127.0.0.1", 502);
if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

modbus_close()

void modbus_close(modbus_t *ctx);

功能:
函数应该关闭与上下文中设置的后端建立的连接。

参数:
ctx:指向modbus_t结构体的指针

无返回值

例子:

modbus_t *ctx;

ctx = modbus_new_tcp("127.0.0.1", 502);
if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

modbus_close(ctx);
modbus_free(ctx);

modbus_flush()

int modbus_flush(modbus_t *ctx);

功能:
函数将丢弃接收到的数据,但不将数据读到套接字或与上下文ctx相关的文件描述符中。

参数:
ctx:指向modbus_t结构体的指针

返回:
如果成功,函数将返回0或刷新的字节数。否则返回-1并设置errno。

Client/Master中的相关API

modbus_read_bits()

int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);

功能:
modbus_read_bits()函数将从远端设备的地址addr开始读取数量为nb的bits(线圈)的状态。

参数:

  • ctx:指向modbus_t结构体的指针
  • addr:要读取的远端设备的起始地址
  • nb:读取的线圈数量
  • dest:读取的结果以无符号字节(8位)的形式存储在dest数组中

你必须注意分配足够的内存来存储结果在dest(至少nb * sizeof(uint8_t))。
该功能使用Modbus功能码0x01(读取线圈状态)。
返回:
如果成功,函数将返回读取的位数。否则返回-1并设置errno。
错误:EMBMDATA(请求的位太多)

例子:

addr = ADDRESS_START;
ret = modbus_write_bits(ctx, addr,nums, tab_rq_bits);
if (nums != ret)
{
	printf("Error modbus_write_bit: %d\n", ret);
	printf("Address: %d value: %d\n", addr, tab_rq_bits[0]);
}

modbus_read_input_bits()

int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);

功能:
modbus_read_bits()函数将从远端设备的地址addr开始读取数量为nb的bits(输入离散量)的状态。

参数:

  • ctx:指向modbus_t结构体的指针
  • addr:要读取的远端设备的起始地址
  • nb:读取的输入离散量数量
  • dest:读取的结果以无符号字节(8位)的形式存储在dest数组中

你必须注意分配足够的内存来存储结果在dest(至少nb * sizeof(uint8_t))。
该功能使用Modbus功能码0x02(读取输入离散量状态)。

返回:
如果成功,函数将返回读取的位数。否则返回-1并设置errno。
错误:EMBMDATA(请求的位太多)

modbus_read_registers()

int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);

功能:
函数将从远端设备的地址addr开始读取数量为nb的保持寄存器的内容。

参数:

  • ctx:指向modbus_t结构体的指针
  • addr:要读取的远端设备的起始地址
  • nb:读取的保持寄存器数量
  • dest:读取结果以字值(16位)的形式存储在dest数组中。

你必须注意分配足够的内存来存储结果在dest(至少nb * sizeof(uint16_t))。
该函数使用Modbus函数代码0x03(读取保持寄存器)。

返回:
如果成功,函数将返回读取的位数。否则返回-1并设置errno。
错误:EMBMDATA(请求的位太多)

例子:

modbus_t *ctx;
uint16_t tab_reg[64];
int rc;
int i;

ctx = modbus_new_tcp("127.0.0.1", 1502);
if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

rc = modbus_read_registers(ctx, 0, 10, tab_reg);
if (rc == -1) {
    fprintf(stderr, "%s\n", modbus_strerror(errno));
    return -1;
}

for (i=0; i < rc; i++) {
    printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
}

modbus_close(ctx);
modbus_free(ctx);

modbus_read_input_registers()

int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);

功能:
函数将从远端设备的地址addr开始读取数量为nb的输入寄存器的内容。

参数:

  • ctx:指向modbus_t结构体的指针
  • addr:要读取的远端设备的起始地址
  • nb:读取的输入寄存器数量
  • dest:读取结果以字值(16位)的形式存储在dest数组中。

你必须注意分配足够的内存来存储结果在dest(至少nb * sizeof(uint16_t))。
该函数使用Modbus函数代码0x04(读取输入寄存器)。持有寄存器和输入寄存器有不同的历史意义,但现在更常见的是只使用保持寄存器。

返回:
如果成功,函数将返回读取的位数。否则返回-1并设置errno。
错误:EMBMDATA(请求的位太多)

modbus_write_bit()

int modbus_write_bit(modbus_t *ctx, int addr, int status);

功能:
函数将单个线圈状态写入远端设备的地址addr。

参数:

  • ctx:指向modbus_t结构体的指针
  • addr:要读取的远端设备的起始地址
  • status:开关量 0或1

该函数使用Modbus函数代码0x05(强制单线圈)。

返回:
如果成功,函数将返回1。否则返回-1并设置errno。

modbus_write_register()

int modbus_write_register(modbus_t *ctx, int addr, int value);

功能:
函数的作用是:将保存值寄存器的值写入远端设备的地址addr。

参数:

  • ctx:指向modbus_t结构体的指针
  • addr:要读取的远端设备的起始地址
  • status:要写入的字数据(16位)

该函数使用Modbus函数代码0x06(预设单寄存器)。

返回:
如果成功,函数将返回1。否则返回-1并设置errno。

modbus_write_bits()

int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src);

功能:
函数将从src写入远端设备地址addr的nb个bits(线圈)的状态。

参数:
src数组必须包含设置为TRUE或FALSE的字节。
该函数使用Modbus函数代码0x0F(写多个线圈)。

返回:
如果成功,函数将返回写入的位数。否则返回-1并设置errno。

modbus_write_registers()

int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src);

功能:
函数的作用是:从远端设备的地址addr的数组src中写入nb持有寄存器的内容。

参数:

  • ctx:指向modbus_t结构体的指针
  • addr:要写入的远端设备的起始地址
  • nb:写入的保持寄存器数量
  • dest:写入的数据以字值(16位)的形式存储在dest数组中。

该函数使用Modbus函数代码0x10(写多个保持寄存器)。

返回:
如果成功,函数将返回写入的位数。否则返回-1并设置errno。

Server/Slave中的相关API

modbus_tcp_listen()

int modbus_tcp_listen(modbus_t *ctx, int nb_connection);

功能:函数应该创建一个套接字并监听指定IP地址上的最大nb_connection传入连接。

参数:

  • ctx:必须是已经被分配并使用modbus_new_tcp(3)初始化的才能设置监听的IP地址,如果IP地址设置为NULL,则任何地址都将被监听。
  • nb_connection:最大连接个数

返回:
如果成功,函数将返回一个新的套接字。否则返回-1并设置errno。

modbus_tcp_accept()

int modbus_tcp_accept(modbus_t *ctx, int *socketfd);

功能:
函数将提取挂起连接队列中的第一个连接,创建一个新的套接字并将其存储在参数中给出的libmodbus上下文中。如果可用,将调用带有SOCK_CLOEXEC的accept4(),而不是accept()。
参数:

  • ctx:已分配的modbus_t结构体。
  • socketfd:连接队列中的第一个套接字指针

返回:
如果成功,函数将返回一个新的套接字。否则返回-1并设置errno。

例子:

...

ctx = modbus_new_tcp("127.0.0.1", 502);
s = modbus_tcp_listen(ctx, 1);
modbus_tcp_accept(ctx, &s);

...

close(s)
modbus_free(ctx);

modbus_mapping_new()

modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, int nb_registers, int nb_input_registers);

功能:函数应该分配四个数组来存储位、输入位、寄存器和输入寄存器。指针存储在modbus_mapping_t结构中。数组中的所有值都初始化为0。
这个函数相当于调用modbus_mapping_new_start_address()函数,所有起始地址都为0。
如果不需要为特定类型的数据分配数组,则可以在参数中传递零值,相关指针将为NULL。
这个函数是方便处理请求在ModbusServer/Slave。

参数:
nb_bits:存放线圈寄存器需要的内存大小
nb_input_bits:存放离散输入寄存器需要的内存大小
nb_registers:存放保持寄存器需要的内存大小
nb_input_registers:存放输入寄存器需要的数据大小

返回:
如果成功,函数将返回新分配的结构体指针。否则返回NULL并设置errno。

modbus_mapping_free()

void modbus_mapping_free(modbus_mapping_t *mb_mapping);

功能:
该函数将释放mb_mapping_t结构的四个数组,最后释放mb_mapping_t指针。

参数:
mb_mapping:modbus_mapping_new()返回的结构体指针。

无返回值

modbus_receive()

int modbus_receive(modbus_t *ctx, uint8_t *req);

功能:
函数将从ctx的套接字接收一个指示请求。Modbus从机/服务器接收和分析主机/客户端发送的指示请求。

参数:

  • ctx:已经建立连接的modbus_t结构体指针
  • req:获取到的请求ADU队列

返回:
函数将指示请求存储在req中,如果成功则返回请求长度。如果指示请求被忽略,返回的请求长度可以为0。(例如在RTU模式下查询另一个slave)。否则返回-1并设置errno。

modbus_reply()

int modbus_reply(modbus_t *ctx, const uint8_t *req, int req_length, modbus_mapping_t *mb_mapping);

功能:
函数将对收到的请求发送响应。对参数中给出的请求req进行分析,然后通过modbus上下文ctx的信息构建并发送响应。
如果请求指示读或写一个值,操作将根据操作数据的类型在modbus映射mb_mapping中完成。
如果发生错误,将发送异常响应。
本功能是针对Modbus服务器设计的。

参数:

  • ctx:已经建立连接的modbus_t结构体指针
  • req:modbus_receive从ctx的套接字接收到的指示请求
  • req_length:req的长度,一般就是modbus_receive()的返回值
  • mb_mapping:modbus_mapping_new()分配的map结构体指针

返回:
如果成功,函数将返回响应的长度。否则返回-1并设置errno。

通用的相关API

modbus_free()

void modbus_free(modbus_t *ctx);

功能:
函数的作用是释放一个已分配的modbus_t结构体。

参数:
已分配的modbus_t结构体。

无返回值

modbus_set_slave()

int modbus_set_slave(modbus_t *ctx, int slave);

功能:
modbus_set_slave()函数将在libmodbus上下文中设置从机号。

参数:
这种行为取决于网络和设备的角色:
RTU
定义远端设备在主模式下通话的从机ID,或者在从模式下设置内部从机ID。根据协议,Modbus设备必须只接受持有其从机号或特殊广播号的消息。
TCP
只有当消息必须到达串行网络上的设备时,从机号才需要在TCP中。但没有从机值,故障的远端设备或软件将丢弃请求!特殊值MODBUS_TCP_SLAVE (0xFF)可以在TCP模式下使用,使用默认值。
广播地址为“MODBUS_BROADCAST_ADDRESS”。当您希望网络中的所有Modbus设备都接收到请求时,必须使用这个特殊值。

返回值:
如果成功,函数将返回0。否则,它将返回-1并将errno设置为EINVAL(设置了错误的从机号)

例子:

modbus_t *ctx;

ctx = modbus_new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1);
if (ctx == NULL) {
    fprintf(stderr, "Unable to create the libmodbus context\n");
    return -1;
}

rc = modbus_set_slave(ctx, YOUR_DEVICE_ID);
if (rc == -1) {
    fprintf(stderr, "Invalid slave ID\n");
    modbus_free(ctx);
    return -1;
}

if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}

modbus_set_debug()

int modbus_set_debug(modbus_t *ctx, int flag);

功能:
modbus_set_debug()函数应该通过使用参数标志来设置modbus_t上下文的调试标志。

参数:

  • ctx:指向modbus_t结构体的指针
  • flag:默认情况下,布尔标志设置为FALSE。当标志值设置为TRUE时,许多详细消息将显示在stdout和stderr上。例如,该标志用于显示Modbus消息的字节:
[00][14][00][00][00][06][12][03][00][6B][00][03]
Waiting for a confirmation…
<00><14><00><00><00><09><12><03><06><02><2B><00><00><00><00>

返回:
如果成功,函数将返回0。否则返回-1并设置errno。

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-03-16 22:58:21  更:2022-03-16 23:01:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 1:33:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码