一、错误情况
[55][06][00][80][00][00][85][F6]
Waiting for a confirmation...
<55><02><00><3F><00>
ERROR CRC received 0x3F00 != CRC calculated 0x60B0
回复指令只接受了一部分就开始校验,导致校验失败
(回复的指令是自定义的)
二、我的代码
modbus_t *ctx = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1);
if (ctx == NULL) {
modbus_free(ctx);
log_info(lg) << "new rtu failed";
return board_error_t::error;
} else {
log_info(lg) << "new rtu 设置成功";
}
modbus_set_slave(ctx, my_device_id);
modbus_set_debug(ctx, TRUE);
modbus_connect(ctx);
modbus_write_register(ctx, 0x80, 0x0);
三、原因分析
1、回复超时
可以从两方面解决问题:波特率变大 或者 设置超时时间到最大值
但是主机设置的波特率一定要和从机保持一致
//波特率增大
modbus_t *ctx = modbus_new_rtu("/dev/ttyUSB0", 38400, 'N', 8, 1);
//设置超时时间
modbus_set_response_timeout(ctx, 0, 999999);
2、功能码问题
02 | 读离散输入状态 |
06 | 写单个保持寄存器 |
我的就是因为这个原因!
因为从机回复的数据是自定义的,使用了02功能码,modbus认为数据是0,因此只接受了5个字节就结束
四、其他失败情况
1、回复的数据前多了一个字节
比如应该收到 <55><06><00><80><00><00><85><F6>
结果收到了 <00><55><06><00><80><00><00><85>
那就在connect之后,清空数据流
modbus_connect(ctx);
modbus_flush(ctx);
2、没有回复任何数据
1)奇偶校验,波特率这些属性 , 确定主从机保持一致
2)串口问题:可能是串口用错了,也会出现这种情况
五、参考
CRC calculation issue · Issue #304 · stephane/libmodbus
https://github.com/stephane/libmodbus/issues/304
无法读取 AcuRev 电能表:CRC 无效
https://groups.google.com/g/libmodbus/c/D0kvsYvcWPA
无法读取直流电表:无效的 CRC · 问题 #116 · stephane/libmodbus
https://github.com/stephane/libmodbus/issues/116
MODBUS RTU通信讲解
http://www.jiiizi.com/article/104