嵌入式Libmodbus之RTU模式Master端程序示例
Posted 沧海一笑-dj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嵌入式Libmodbus之RTU模式Master端程序示例相关的知识,希望对你有一定的参考价值。
00. 目录
文章目录
01. 软件开发流程
Modbus结合libmodbus开发库可以自由开发主设备端或从设备端的应用程序,而且支持RTU和TCP两种常用的模式。
开发主设备端(Master或者Client)程序的基本流程如下图所示:
开发从设备端(Slave或者Server)程序的基本流程如下图所示:
02. 获取版本信息
程序示例
#include <stdio.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <errno.h>
//包含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 <stdio.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <errno.h>
//包含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 <stdio.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
//包含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 <stdio.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
//包含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;以上是关于嵌入式Libmodbus之RTU模式Master端程序示例的主要内容,如果未能解决你的问题,请参考以下文章
基于libmodbus库实现modbus TCP/RTU通信