本帖最后由 story_xjj 于 2018-6-4 12:34 编辑
试用5 Modbus-RTU主机代码测试
在试用4中,我已经成功的将串口设备引出了,接下来可以使用这些串口与外设通讯了。
本次试用的主题
在ttymxc1接口上运行Modbus-RTU主机代码,管理外部Modbus-RTU子站
1、 Libmodbus库
通过网络搜索,linux下比较推崇的modbus库是libmodbus,他支持主站和子站两种模式,我准备采用这个库来测试一下。
本次采用稳定版libmodbus-3.0.6.tar.gz
解压后的基本目录结构为
libmodbus.JPG (148.63 KB, 下载次数: 45)
2018-6-4 12:32 上传
我准备在windows下开发,所以其它文件对我来说没什么用。
2、 测试modbus-client代码与仿真子站通讯
Windows下通过eclipse建立开发环境这里不介绍了,大家自己网上搜索吧。
建立一个工程,将tests目录下的modbus-client.c文件添加进入,把src目录下的所有文件添加进去。
注意修改modbus-client.c文件中的SERVERID,他是我们准备操作的子站地址,原文中为17,我这里修改为1.
/*The goal of this program is to check all major functions of
libmodbus:
- write_coil
- read_bits
- write_coils
- write_register
- read_registers
- write_registers
- read_registers
All these functions are called with randomvalues on a address
range defined by the following defines.
*/
#define LOOP 1
#define SERVER_ID 1
#define ADDRESS_START 0
#define ADDRESS_END 10
接下来介绍几个函数,用来写入和读取相关寄存器的内容。
1)写1位线圈函数 int modbus_write_bit(modbus_t *ctx, int addr, int status)
ctx — 用来执行modbus操作的设备指针
addr— 写入子站的寄存器地址
status — 写入子站的线圈状态
使用例子:
rc =modbus_write_bit(ctx,addr, tab_rq_bits[0]);
if (rc != 1) {
printf("ERROR modbus_write_bit(%d)\n", rc);
printf("Address = %d, value =%d\n", addr, tab_rq_bits[0]);
nb_fail++;
}
2) 写多线圈函数
/* Write the bits of the array inthe remote device */
int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src)
ctx — 用来执行modbus操作的设备指针
addr— 写入子站的寄存器地址
nb —— 写子站线圈个数
src — 写入子站的线圈状态指针
使用例子:
rc =modbus_write_bits(ctx,addr, nb, tab_rq_bits);
if (rc != nb) {
printf("ERROR modbus_write_bits(%d)\n", rc);
printf("Address = %d, nb =%d\n", addr, nb);
}
3) 读取多线圈函数
/* Reads the boolean status ofbits and sets the array elements
in the destination to TRUE or FALSE (single bits). */
int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)
ctx — 用来执行modbus操作的设备指针
addr— 读取子站的寄存器地址
nb —— 读取子站线圈个数
dest — 读取子站的线圈状态保存指针
使用例子:
rc = modbus_read_bits(ctx, addr, nb, tab_rp_bits);
if (rc != nb) {
printf("ERRORmodbus_read_bits\n");
printf("Address = %d, nb =%d\n", addr, nb);
}
4) 写单寄存器
/* Writes a value in one registerof the remote device */
int modbus_write_register(modbus_t *ctx, int addr, int value)
ctx — 用来执行modbus操作的设备指针
addr— 写入子站的寄存器地址
value — 写入子站的寄存器值
使用例子:
rc = modbus_write_register(ctx,addr, tab_rq_registers[0]);
if (rc != 1) {
printf("ERRORmodbus_write_register (%d)\n", rc);
printf("Address = %d, value = %d(0x%X)\n",
addr, tab_rq_registers[0],tab_rq_registers[0]);
}
5) 写多寄存器
/* Write the values from the arrayto the registers of the remote device */
int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src)
ctx — 用来执行modbus操作的设备指针
addr— 写入子站的寄存器地址
nb —— 写子站寄存器个数
src — 写入子站的整型字数组指针
使用例子:
rc = modbus_write_registers(ctx, addr, nb, tab_rq_registers);
if (rc != nb) {
printf("ERRORmodbus_write_registers (%d)\n", rc);
printf("Address = %d, nb =%d\n", addr, nb);
}
6) 读取多寄存器函数
/* Reads the holding registers ofremote device and put the data into an array */
int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)
ctx — 用来执行modbus操作的设备指针
addr— 读取子站的寄存器地址
nb —— 读取子站寄存器个数
dest — 读取子站的寄存器保存指针
使用例子:
rc= modbus_read_registers(ctx,addr, nb, tab_rp_registers);
if (rc != nb) {
printf("ERRORmodbus_read_registers (%d)\n", rc);
printf("Address = %d, nb =%d\n", addr, nb);
}
7) 读写多寄存器函数
/* Write multiple registers from “src”array to remote device and read multiple registers from remote device to “dest”array. */
int modbus_write_and_read_registers(modbus_t *ctx,
int write_addr, int write_nb, const uint16_t *src,
int read_addr, int read_nb, uint16_t *dest
)
ctx — 用来执行modbus操作的设备指针
write_addr—写子站的寄存器地址
write_nb ——写子站寄存器个数
src — 写子站的数据指针
read_addr—读子站的寄存器地址
read_nb ——读子站寄存器个数
dest — 读子站的数据保存指针
使用例子:
rc = modbus_write_and_read_registers(ctx,
addr, nb,tab_rw_rq_registers,
addr, nb,tab_rp_registers);
if (rc != nb) {
printf("ERRORmodbus_read_and_write_registers (%d)\n", rc);
printf("Address = %d, nb =%d\n", addr, nb);
}
3、 modbusslave模拟子站软件
网上搜索可以找到modbus的子站仿真软件,用来配合调试比较方便。
modbus子站.JPG (150.39 KB, 下载次数: 38)
2018-6-4 12:32 上传