Windows10中VS2017环境下使用libmodbus库Modbus TCP读取设备的数据
libmodbus库中使用Modbus TCP协议
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:%sn", 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 ppmVn",
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)中的浓度。
非甲烷总烃设备的Modbus寄存器地址定义表
例如,要读取非甲烷总烃设备的总烃、甲烷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
在Windows10下VS2017中,使用libmodbus库,使用Modbus TCP协议读取对应寄存器中的数据
相关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:%sn", 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 ppmVn",
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中的运行结果如下图所示:
- FHQ Treap小结(神级数据结构!)
- vuex在页面中以对象展开运算符形式引入报错解决
- 手机网页调用相机拍照或者图库
- P1903 【模板】分块/带修改莫队(数颜色)
- 前端如何获取http状态码400的返回值
- 不确定行数的多行文本垂直水平居中的css
- Vue slot简单理解
- css实现图片横向排列滚动
- windows下nvm安装node之后npm命令找不到问题解决办法
- 元素加了position:absolute则该元素的text-align:center居中失效的解决办法
- Chrome设置断点的各种姿势
- React-native踩坑小记
- 带修改莫队算法
- P2590 [ZJOI2008]树的统计
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法