【嵌入式】Libmodbus之RTU模式Master端程序示例
发布日期:2021-06-29 20:52:06
浏览次数:2
分类:技术文章
本文共 13287 字,大约阅读时间需要 44 分钟。
00. 目录
文章目录
01. 软件开发流程
Modbus结合libmodbus开发库可以自由开发主设备端或从设备端的应用程序,而且支持RTU和TCP两种常用的模式。
开发主设备端(Master或者Client)程序的基本流程如下图所示:
开发从设备端(Slave或者Server)程序的基本流程如下图所示:
02. 获取版本信息
程序示例
#include#ifndef _MSC_VER#include #endif#include #include #include //包含Modbus相关头文件#include "modbus.h"int main(void){ printf("hello world\n"); //输出libmodbus版本信息 printf("Compiled with libmodbus version: %s (%06X)\n", LIBMODBUS_VERSION_STRING, LIBMODBUS_VERSION_HEX); //判断当前版本是否大于或者等于3.1.5 if (LIBMODBUS_VERSION_CHECK(3, 1, 5)) { printf("The functions to read/write float values are available (2.1.0).\n"); } //判断当前版本是否大于或者等于3.1.6 if (LIBMODBUS_VERSION_CHECK(3, 1, 6)) { printf("Oh gosh, brand new API(3.1.6)!\n"); } return 0;}
执行结果
03. 读写单个线圈程序示例
程序示例
#include#ifndef _MSC_VER#include #endif#include #include #include //包含Modbus相关头文件#include "modbus.h"//相关参数设置#define LOOP 1 //循环次数#define SERVER_ID 17 //从设备地址#define ADDRESS_START 0 //测试寄存器起始地址#define ADDRESS_END 99 //测试寄存器结束地址int main(void){ modbus_t* ctx = NULL; int ret = -1; int nums = 0; int addr = 0; int i = 0; int tmp = 0; uint8_t* tab_rq_bits = NULL; uint8_t* tab_rp_bits = NULL; //1. 创建一个RTU类型的变量 //设置串口设备 波特率 奇偶校验 数据位 停止位 ctx = modbus_new_rtu("COM4", 9600, 'N', 8, 1); if (NULL == ctx) { fprintf(stderr, "Error: %s\n", modbus_strerror(errno)); return 1; } else { printf("设置串口信息成功\n"); } //2. 设置从机地址 ret = modbus_set_slave(ctx, SERVER_ID); if (-1 == ret) { fprintf(stderr, "Error: 设置从机地址失败\n"); modbus_free(ctx); return 1; } //3. 设置Debug模式 ret = modbus_set_debug(ctx, TRUE); if (-1 == ret) { fprintf(stderr, "Error: 设置Debug模式失败"); modbus_free(ctx); return 1; } //4. 在RTU模式下打开串口 ret = modbus_connect(ctx); if (-1 == ret) { fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno)); modbus_free(ctx); return 1; } //5. 计算需测试的寄存器个数 nums = ADDRESS_END - ADDRESS_START; //6. 申请内存 保存发送和接收的数据 tab_rq_bits = (uint8_t*)malloc(nums * sizeof(uint8_t)); if (NULL == tab_rq_bits) { fprintf(stderr, "malloc failed\n"); modbus_free(ctx); return 1; } else { memset(tab_rq_bits, 0, nums * sizeof(uint8_t)); } tab_rp_bits = (uint8_t*)malloc(nums * sizeof(uint8_t)); if (NULL == tab_rp_bits) { fprintf(stderr, "malloc failed\n"); modbus_free(ctx); return 1; } else { memset(tab_rp_bits, 0, nums * sizeof(uint8_t)); } //7. 写单个线圈 addr = ADDRESS_START; tmp = rand() / 100; tab_rq_bits[0] = tmp % 2; ret = modbus_write_bit(ctx, addr, tab_rq_bits[0]); if (1 != ret) { printf("Error modbus_write_bit: %d\n", ret); printf("Address: %d value: %d\n", addr, tab_rq_bits[0]); } else { //读取单个线圈 ret = modbus_read_bits(ctx, addr, 1, tab_rp_bits); if (1 != ret) { printf("Error modbus_read_bits: %d\n", ret); } else { printf("tab_rp_bits[0]: %d tab_rq_bits[0]: %d\n", tab_rp_bits[0], tab_rq_bits[0]); } } //8. 释放内存 free(tab_rp_bits); free(tab_rq_bits); //9. 断开连接 modbus_close(ctx); modbus_free(ctx); return 0;}
执行结果
04. 读写多个线圈程序示例
程序示例
#include#ifndef _MSC_VER#include #endif#include #include #include #include //包含Modbus相关头文件#include "modbus.h"//相关参数设置#define LOOP 1 //循环次数#define SERVER_ID 17 //从设备地址#define ADDRESS_START 0 //测试寄存器起始地址#define ADDRESS_END 99 //测试寄存器结束地址int main(void){ modbus_t* ctx = NULL; int ret = -1; int nums = 0; int addr = 0; int i = 0; int tmp = 0; uint8_t* tab_rq_bits = NULL; uint8_t* tab_rp_bits = NULL; //设置随机种子 srand((int)time(0)); //1. 创建一个RTU类型的变量 //设置串口设备 波特率 奇偶校验 数据位 停止位 ctx = modbus_new_rtu("COM4", 9600, 'N', 8, 1); if (NULL == ctx) { fprintf(stderr, "Error: %s\n", modbus_strerror(errno)); return 1; } else { printf("设置串口信息成功\n"); } //2. 设置从机地址 ret = modbus_set_slave(ctx, SERVER_ID); if (-1 == ret) { fprintf(stderr, "Error: 设置从机地址失败\n"); modbus_free(ctx); return 1; } //3. 设置Debug模式 ret = modbus_set_debug(ctx, TRUE); if (-1 == ret) { fprintf(stderr, "Error: 设置Debug模式失败"); modbus_free(ctx); return 1; } //4. 在RTU模式下打开串口 ret = modbus_connect(ctx); if (-1 == ret) { fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno)); modbus_free(ctx); return 1; } //5. 计算需测试的寄存器个数 nums = ADDRESS_END - ADDRESS_START; //6. 申请内存 保存发送和接收的数据 tab_rq_bits = (uint8_t*)malloc((nums + 1) * sizeof(uint8_t)); if (NULL == tab_rq_bits) { fprintf(stderr, "malloc failed\n"); modbus_free(ctx); return 1; } else { memset(tab_rq_bits, 0, (nums + 1) * sizeof(uint8_t)); } tab_rp_bits = (uint8_t*)malloc((nums + 1) * sizeof(uint8_t)); if (NULL == tab_rp_bits) { fprintf(stderr, "malloc failed\n"); modbus_free(ctx); return 1; } else { memset(tab_rp_bits, 0, (nums + 1) * sizeof(uint8_t)); } //7. 写多个线圈 //随机数字 for (i = 0; i < nums; i++) { tmp = rand() % 100; tab_rq_bits[i] = tmp % 2; if (0 == i) { printf("写入的值: "); } printf("%hd ", tab_rq_bits[i]); } //换行 printf("\n"); addr = ADDRESS_START; ret = modbus_write_bits(ctx, addr, nums + 1, tab_rq_bits); if (nums + 1 != ret) { printf("Error modbus_write_bit: %d\n", ret); printf("Address: %d nums: %d\n", addr, nums); } else { //读取多个线圈 ret = modbus_read_bits(ctx, addr, nums + 1, tab_rp_bits); if (nums + 1 != ret) { printf("Error modbus_read_bits: %d\n", ret); } else { //输出 for (i = 0; i < nums; i++) { if (0 == i) { printf("读取到的值: "); } printf("%hd ", tab_rp_bits[i]); } //换行 printf("\n"); } } //8. 释放内存 free(tab_rp_bits); free(tab_rq_bits); //9. 断开连接 modbus_close(ctx); modbus_free(ctx); return 0;}
执行结果
05. 读写单个保持寄存器程序示例
程序示例
#include#ifndef _MSC_VER#include #endif#include #include #include #include //包含Modbus相关头文件#include "modbus.h"//相关参数设置#define LOOP 1 //循环次数#define SERVER_ID 17 //从设备地址#define ADDRESS_START 0 //测试寄存器起始地址#define ADDRESS_END 99 //测试寄存器结束地址int main(void){ modbus_t* ctx = NULL; int ret = -1; int nums = 0; int addr = 0; int i = 0; int tmp = 0; uint16_t* tab_rq_registers = NULL; uint16_t* tab_rp_registers = NULL; //设置随机种子 srand((int)time(0)); //1. 创建一个RTU类型的变量 //设置串口设备 波特率 奇偶校验 数据位 停止位 ctx = modbus_new_rtu("COM4", 9600, 'N', 8, 1); if (NULL == ctx) { fprintf(stderr, "Error: %s\n", modbus_strerror(errno)); return 1; } else { printf("设置串口信息成功\n"); } //2. 设置从机地址 ret = modbus_set_slave(ctx, SERVER_ID); if (-1 == ret) { fprintf(stderr, "Error: 设置从机地址失败\n"); modbus_free(ctx); return 1; } //3. 设置Debug模式 ret = modbus_set_debug(ctx, TRUE); if (-1 == ret) { fprintf(stderr, "Error: 设置Debug模式失败"); modbus_free(ctx); return 1; } //4. 在RTU模式下打开串口 ret = modbus_connect(ctx); if (-1 == ret) { fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno)); modbus_free(ctx); return 1; } //5. 计算需测试的寄存器个数 nums = ADDRESS_END - ADDRESS_START; //6. 申请内存 保存发送和接收的数据 tab_rq_registers = (uint16_t*)malloc((nums + 1) * sizeof(uint16_t)); if (NULL == tab_rq_registers) { fprintf(stderr, "malloc failed\n"); modbus_free(ctx); return 1; } else { memset(tab_rq_registers, 0, (nums + 1) * sizeof(uint16_t)); } tab_rp_registers = (uint16_t*)malloc((nums + 1) * sizeof(uint16_t)); if (NULL == tab_rp_registers) { fprintf(stderr, "malloc failed\n"); modbus_free(ctx); return 1; } else { memset(tab_rp_registers, 0, (nums + 1) * sizeof(uint16_t)); } //7. 测试保持寄存器的单个读写 //随机数字 tab_rq_registers[0] = rand() % 100; printf("写入的值为: %hd\n", tab_rq_registers[0]); //换行 printf("\n"); addr = ADDRESS_START; ret = modbus_write_register(ctx, addr, tab_rq_registers[0]); if (1 != ret) { printf("Error modbus_write_register: %d\n", ret); } else { //读取数据 ret = modbus_read_registers(ctx, addr, 1, tab_rp_registers); if (1 != ret) { printf("Error modbus_read_registers: %d\n", ret); } else { //输出 printf("读取到的值为: %hd\n", tab_rp_registers[0]); } } //8. 释放内存 free(tab_rp_registers); free(tab_rq_registers); //9. 断开连接 modbus_close(ctx); modbus_free(ctx); return 0;}
执行结果
06. 读写多个保持寄存器程序示例
程序示例
#include#ifndef _MSC_VER#include #endif#include #include #include #include //包含Modbus相关头文件#include "modbus.h"//相关参数设置#define LOOP 1 //循环次数#define SERVER_ID 17 //从设备地址#define ADDRESS_START 0 //测试寄存器起始地址#define ADDRESS_END 99 //测试寄存器结束地址int main(void){ modbus_t* ctx = NULL; int ret = -1; int nums = 0; int addr = 0; int i = 0; int tmp = 0; uint16_t* tab_rq_registers = NULL; uint16_t* tab_rp_registers = NULL; //设置随机种子 srand((int)time(0)); //1. 创建一个RTU类型的变量 //设置串口设备 波特率 奇偶校验 数据位 停止位 ctx = modbus_new_rtu("COM4", 9600, 'N', 8, 1); if (NULL == ctx) { fprintf(stderr, "Error: %s\n", modbus_strerror(errno)); return 1; } else { printf("设置串口信息成功\n"); } //2. 设置从机地址 ret = modbus_set_slave(ctx, SERVER_ID); if (-1 == ret) { fprintf(stderr, "Error: 设置从机地址失败\n"); modbus_free(ctx); return 1; } //3. 设置Debug模式 ret = modbus_set_debug(ctx, TRUE); if (-1 == ret) { fprintf(stderr, "Error: 设置Debug模式失败"); modbus_free(ctx); return 1; } //4. 在RTU模式下打开串口 ret = modbus_connect(ctx); if (-1 == ret) { fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno)); modbus_free(ctx); return 1; } //5. 计算需测试的寄存器个数 nums = ADDRESS_END - ADDRESS_START; //6. 申请内存 保存发送和接收的数据 tab_rq_registers = (uint16_t*)malloc((nums + 1) * sizeof(uint16_t)); if (NULL == tab_rq_registers) { fprintf(stderr, "malloc failed\n"); modbus_free(ctx); return 1; } else { memset(tab_rq_registers, 0, (nums + 1) * sizeof(uint16_t)); } tab_rp_registers = (uint16_t*)malloc((nums + 1) * sizeof(uint16_t)); if (NULL == tab_rp_registers) { fprintf(stderr, "malloc failed\n"); modbus_free(ctx); return 1; } else { memset(tab_rp_registers, 0, (nums + 1) * sizeof(uint16_t)); } //7. 测试保持寄存器的单个读写//随机数字 for (i = 0; i < nums; i++) { tmp = rand() % 100; tab_rq_registers[i] = tmp; if (0 == i) { printf("写入的值: "); } printf("%hd ", tab_rq_registers[i]); } //换行 printf("\n"); addr = ADDRESS_START; ret = modbus_write_registers(ctx, addr, nums + 1, tab_rq_registers); if (nums + 1 != ret) { printf("Error modbus_write_registers: %d\n", ret); printf("Address: %d nums: %d\n", addr, nums + 1); } else { //读取 ret = modbus_read_registers(ctx, addr, nums + 1, tab_rp_registers); if (nums + 1 != ret) { printf("Error modbus_read_registers: %d\n", ret); } else { //输出 for (i = 0; i < nums; i++) { if (0 == i) { printf("读取到的值: "); } printf("%hd ", tab_rp_registers[i]); } //换行 printf("\n"); } } //8. 释放内存 free(tab_rp_registers); free(tab_rq_registers); //9. 断开连接 modbus_close(ctx); modbus_free(ctx); return 0;}
执行结果
07. 读写多个寄存器测试(功能码0X17)
程序示例
#include#ifndef _MSC_VER#include #endif#include #include #include #include //包含Modbus相关头文件#include "modbus.h"//相关参数设置#define LOOP 1 //循环次数#define SERVER_ID 17 //从设备地址#define ADDRESS_START 0 //测试寄存器起始地址#define ADDRESS_END 99 //测试寄存器结束地址int main(void){ modbus_t* ctx = NULL; int ret = -1; int nums = 0; int addr = 0; int i = 0; int tmp = 0; uint16_t* tab_rq_registers = NULL; uint16_t* tab_rp_registers = NULL; //设置随机种子 srand((int)time(0)); //1. 创建一个RTU类型的变量 //设置串口设备 波特率 奇偶校验 数据位 停止位 ctx = modbus_new_rtu("COM4", 9600, 'N', 8, 1); if (NULL == ctx) { fprintf(stderr, "Error: %s\n", modbus_strerror(errno)); return 1; } else { printf("设置串口信息成功\n"); } //2. 设置从机地址 ret = modbus_set_slave(ctx, SERVER_ID); if (-1 == ret) { fprintf(stderr, "Error: 设置从机地址失败\n"); modbus_free(ctx); return 1; } //3. 设置Debug模式 ret = modbus_set_debug(ctx, TRUE); if (-1 == ret) { fprintf(stderr, "Error: 设置Debug模式失败"); modbus_free(ctx); return 1; } //4. 在RTU模式下打开串口 ret = modbus_connect(ctx); if (-1 == ret) { fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno)); modbus_free(ctx); return 1; } //5. 计算需测试的寄存器个数 nums = ADDRESS_END - ADDRESS_START; //6. 申请内存 保存发送和接收的数据 tab_rq_registers = (uint16_t*)malloc((nums + 1) * sizeof(uint16_t)); if (NULL == tab_rq_registers) { fprintf(stderr, "malloc failed\n"); modbus_free(ctx); return 1; } else { memset(tab_rq_registers, 0, (nums + 1) * sizeof(uint16_t)); } tab_rp_registers = (uint16_t*)malloc((nums + 1) * sizeof(uint16_t)); if (NULL == tab_rp_registers) { fprintf(stderr, "malloc failed\n"); modbus_free(ctx); return 1; } else { memset(tab_rp_registers, 0, (nums + 1) * sizeof(uint16_t)); } //7. 测试保持寄存器的单个读写 //随机数字 for (i = 0; i < nums; i++) { tmp = rand() % 100; tab_rq_registers[i] = tmp; if (0 == i) { printf("写入的值: "); } printf("%hd ", tab_rq_registers[i]); } //换行 printf("\n"); addr = ADDRESS_START; //先写入,后读取该数据到指定的内存中 ret = modbus_write_and_read_registers(ctx, addr, nums + 1, tab_rq_registers, addr, nums + 1, tab_rp_registers); if (nums + 1 != ret) { printf("Error modbus_write_and_read_registers: %d\n", ret); printf("Address: %d nums: %d\n", addr, nums + 1); } else { //输出 for (i = 0; i < nums; i++) { if (0 == i) { printf("读取到的值: "); } printf("%hd ", tab_rp_registers[i]); } //换行 printf("\n"); } //再次读取数据 memset(tab_rp_registers, 0, (nums + 1) * sizeof(uint16_t)); ret = modbus_read_registers(ctx, addr, nums + 1, tab_rp_registers); if (nums + 1 != ret) { printf("Error modbus_read_registers: %d\n", ret); } else { //输出 for (i = 0; i < nums; i++) { if (0 == i) { printf("读取到的值: "); } printf("%hd ", tab_rp_registers[i]); } //换行 printf("\n"); } //8. 释放内存 free(tab_rp_registers); free(tab_rq_registers); //9. 断开连接 modbus_close(ctx); modbus_free(ctx); return 0;}
执行结果
08. 附录
源码下载:
转载地址:https://dengjin.blog.csdn.net/article/details/116795320 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月07日 22时45分49秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
数据库访问接口
2019-04-30
启动 MySQL服务
2019-04-30
登录MySQL数据库
2019-04-30
MySQL 常用图形管理工具
2019-04-30
MySQL 创建数据库
2019-04-30
查看MySQL数据库定义信息
2019-04-30
MySQL 查看存储引擎
2019-04-30
MySQL 删除数据库
2019-04-30
TypeScript 安装
2019-04-30
TypeScript 基础类型
2019-04-30
typescript 用name作为变量名报错的原因
2019-04-30
TypeScript 变量声明
2019-04-30
typeScript 变量作用域
2019-04-30
TypeScript 运算符
2019-04-30
TypeScript 条件语句
2019-04-30
微信小程序 响应的数据绑定
2019-04-30
微信小程序框架
2019-04-30
微信小程序 场景值
2019-04-30
微信小程序 APP() 的那些事
2019-04-30
python 第一个程序 hello python
2019-04-30