环境:
说明:
C++代码:
#include <stdio.h>
#include <modbus.h>
#include <cerrno>
#include <iostream>
int main() {
// The ID of the device being queried
const int REMOTE_ID = 33;
modbus_t *ctx;
uint16_t tab_reg[4];
// Creating a Modbus connection
ctx = modbus_new_rtu("/dev/ttyUSB0", 9600, 'O', 8, 1);
modbus_set_slave(ctx, 33); // Setting the Slave ID
modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
modbus_rtu_set_rts(ctx, MODBUS_RTU_RTS_UP);
modbus_rtu_set_rts_delay(ctx, 3);
modbus_set_debug(ctx, 1); // Enabling debugging
if (ctx == NULL) {
fprintf(stderr, "Unable to create the libmodbus context\n");
return -1;
}
// Establishing the connection
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
// Reading the registers
int rc = modbus_read_registers(ctx, 0, 3, tab_reg);
if (rc == -1) {
fprintf(stderr, "%s\n", modbus_strerror(errno));
std::cout << "Reading register error";
return -1;
}
// Printing the read data
for (int i = 0; i < sizeof(tab_reg) / sizeof(tab_reg[0]); i++) {
printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
}
// Closing the connection and freeing memory
modbus_close(ctx);
modbus_free(ctx);
}
调试输出:
Opening /dev/ttyUSB0 at 9600 bauds (O, 8, 1)
[21][03][00][00][00][03][02][AB]
Sending request using RTS signal
Waiting for a confirmation...
<21><03><06><00><00><00><00><00><21><78><AC>
reg[0]=0 (0x0)
reg[1]=0 (0x0)
reg[2]=33 (0x21)
reg[3]=0 (0x0)
更多信息:
int rc = modbus_read_registers(ctx, 30001, 3, tab_reg);
欢迎来到Modbus的精彩世界。 “30000”仅表示“寄存器”,20000 和 40000 仅表示“输入寄存器”和“线圈”。
有点像“modbus_operation(3000x)”会自动执行“read_registers(x)”,而“modbus_operation(4000x)”会自动执行“read_holding_registers(x)”。
libmodbus 不支持 30000 样式,仅支持“完整”样式。
您正在使用
modbus_read_registers(ctx, 0, 3, tab_reg)
;这个函数可能应该被称为modbus_read_holding_registers
,因为这就是它的作用(发送命令03
-“读取保持寄存器”)。
根据屏幕截图,您真正想要的是“输入寄存器”(使用命令
04
读取)。这是两组不同的寄存器(输入寄存器是只读的,而您可以更改保持寄存器的值)。尝试一下modbus_read_input_registers
,我相信你会得到你期望的数据。
欢迎来到 Modbus 的精彩世界! (推荐本文中的“Modbus:当40001真正意味着1,或0真正意味着1”部分)