TCP(IPv4)环境 TCP后端实现了用于通过TCP / IPv4网络进行通信的Modbus变体。它不需要校验和计算,因为底层TCP会处理相同的功能。
//例子:
modbus_t *ctx;
int rc = 0;
// 以下申请内存块,用以保存接收数据
uint16_t *tab_rp_registers = (uint16_t*)malloc(10 * sizeof(uint16_t));
memset(tab_rp_registers, 0, 10 * sizeof(uint16_t));
// TCP
// 创建Modbus TCP连接,IP是15.18.200.23,端口502
ctx = modbus_new_tcp(15.18.200.23", 502); // 创建一个TCP类型的容器
modbus_set_debug(ctx, TRUE); // 设置Debug模式
if (modbus_connect(ctx) == -1) // TCP 模式下连接Server
{
fprintf(stderr, "Connection failed:%s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
// 读取非甲烷总烃的关于总烃、甲烷、NMHC这3个寄存器(寄存器地址分别为22,25,28)中的浓度
// 从寄存器地址22开始读取,读10个寄存器到data数组中
//进行读取测试,起始地址为22,读取寄存器数目为10
rc = modbus_read_registers(ctx, 22, 10, tab_rp_registers);
printf("----------------- 甲烷/非甲烷总烃分析仪 TE_5900 -------------------------------\n");
printf("CH4的浓度为:%.3f ppmV,NMHC的浓度为:%.3f ppmV,总烃的浓度为:%.3f ppmV\n",
tab_rp_registers[3] / 100.0f, tab_rp_registers[6] / 100.0f, tab_rp_registers[0] / 100.0f);
创建Modbus TCP环境 modbus_t *modbus_new_tcp(const char *ip, int port); ip:希望连接的服务器ip地址
port:要使用的 TCP 端口。将端口设置为MODBUS_TCP_DEFAULT_PORT使用默认值之一 (502)。使用大于或等于1024的端口号很方便, 因为没有必要拥有管理员权限。
返回:成功返回指向modbus_t结构体的指针。否则, 它应返回 NULL 并将 errno 设置为An invalid IP address was given.
下面使用Modbus TCP
协议读取甲烷/非甲烷总烃 (5900)
设备中总烃、甲烷、NMHC这3个寄存器(寄存器地址分别为22,25,28)中的浓度。
例如,要读取非甲烷总烃设备的总烃、甲烷CH4、NMHC非甲烷总烃对应的浓度, 相关监测因子参数的Modbus寄存器定义如下:
名称 | 数据 | 地址 | 系数 | 值 |
---|---|---|---|---|
系统参数 | 仪器状态 | 1 | 1 | 0 |
系统参数 | 运行状态 | 2 | 1 | 1 |
系统参数 | 控制指令 | 3 | 1 | 8 |
采样时间 | 年 | 10 | 1 | 2019 |
采样时间 | 月 | 11 | 1 | 11 |
采样时间 | 日 | 12 | 1 | 14 |
采样时间 | 时 | 13 | 1 | 14 |
采样时间 | 分 | 14 | 1 | 26 |
采样时间 | 秒 | 15 | 1 | 22 |
TVOC | 状态 | 20 | 1 | 0 |
TOVC | 峰面积 | 21 | 0.01 | 1908 |
总烃 | 浓度 | 22 | 0.01 | 254 |
CH4 | 状态 | 23 | 1 | 0 |
CH4 | 峰面积 | 24 | 0.01 | 1729 |
CH4 | 浓度 | 25 | 0.01 | 200 |
NMHC | 状态 | 26 | 1 | 0 |
NMHC | 峰面积 | 27 | 0.01 | 0 |
NMHC | 浓度 | 28 | 0.01 | 57 |
苯 | 状态 | 29 | 1 | 8 |
苯 | 峰面积 | 30 | 0.01 | 0 |
苯 | 浓度 | 31 | 0.01 | 0 |
甲苯 | 状态 | 32 | 1 | 8 |
甲苯 | 峰面积 | 33 | 0.01 | 0 |
甲苯 | 浓度 | 34 | 0.01 | 0 |
乙苯 | 状态 | 35 | 1 | 8 |
乙苯 | 峰面积 | 36 | 0.01 | 0 |
乙苯 | 浓度 | 37 | 0.01 | 0 |
间二甲苯 | 状态 | 38 | 1 | 8 |
间二甲苯 | 峰面积 | 39 | 0.01 | 0 |
间二甲苯 | 浓度 | 40 | 0.01 | 0 |
对二甲苯 | 状态 | 41 | 1 | 8 |
对二甲苯 | 峰面积 | 42 | 0.01 | 0 |
对二甲苯 | 浓度 | 43 | 0.01 | 0 |
间-对二甲苯 | 状态 | 44 | 1 | 8 |
间-对二甲苯 | 峰面积 | 45 | 0.01 | 0 |
间-对二甲苯 | 浓度 | 46 | 0.01 | 0 |
苯乙烯 | 状态 | 47 | 1 | 8 |
苯乙烯 | 峰面积 | 48 | 0.01 | 0 |
苯乙烯 | 浓度 | 49 | 0.01 | 0 |
邻二甲苯 | 状态 | 50 | 1 | 8 |
邻二甲苯 | 峰面积 | 51 | 0.01 | 0 |
邻二甲苯 | 浓度 | 52 | 0.01 | 0 |
非甲烷总烃分析仪有三个关键参数,即总烃、CH4、NMHC的浓度,对应Modbus寄存器地址分别为:22,25,28,获取对应寄存器数据后还需要乘以0.01
相关C语言测试代码如下:
#include <stdio.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "modbus.h" // 引入libmodbus库
#pragma comment(lib, "modbus.lib")
int modbus_tcp_client_test02()
{
// 主机地址:15.18.200.23 主机端口:502
modbus_t *ctx;
int rc = 0;
// 读取的寄存器起始地址
int addr = 22;
// 读取的寄存器数据个数
int nb = 10;
// 用于保存接收数据
uint16_t *tab_rp_registers;
// TCP
// 创建Modbus TCP连接,IP是15.18.200.23,端口502
ctx = modbus_new_tcp("15.18.200.23", 502); // 创建一个TCP类型的容器
modbus_set_debug(ctx, TRUE); // 设置Debug模式
if (modbus_connect(ctx) == -1) // TCP 模式下连接Server
{
fprintf(stderr, "Connection failed:%s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
// 以下申请内存块,用以保存接收数据
tab_rp_registers = (uint16_t*)malloc(nb * sizeof(uint16_t));
memset(tab_rp_registers, 0, nb * sizeof(uint16_t));
// 读取非甲烷总烃的关于总烃、甲烷、NMHC这3个寄存器(寄存器地址分别为22,25,28)中的浓度
// 从寄存器地址22开始读取,读10个寄存器到data数组中
//进行读取测试,起始地址为22,读取寄存器数目为10
rc = modbus_read_registers(ctx, addr, nb, tab_rp_registers);
printf("----------------- 甲烷/非甲烷总烃分析仪 TE_5900 -------------------------------\n");
printf("CH4的浓度为:%.3f ppmV,NMHC的浓度为:%.3f ppmV,总烃的浓度为:%.3f ppmV\n",
tab_rp_registers[3] / 100.0f, tab_rp_registers[6] / 100.0f, tab_rp_registers[0]/ 100.0f);
return 0;
}
int main(int argc, char *argv[])
{
modbus_tcp_client_test02();
getchar();
system("pasue");
return 0;
}
在VS2017中的运行结果如下图所示: