个人理解,轻喷,欢迎交流
最近由于工作原因需要使用ADAM-6050工业级IO数据采集模块,由于官方提供的支持库里面只提供了win32与winCE的版本,而项目使用的linux系统,查询资料后了解到libmodbus开源库。
废话不多说,直接上正文:
libmodbus提供了多个功能函数对应modbus不同的功能码:
部分数据读取函数:
int modbus_read_bits(); //function code 0x01
int modbus_read_input_bits(); //function code 0x02
int modbus_read_registers(); //function code 0x03
int modbus_read_input_registers(); //function code 0x04
部分数据写入函数:
int modbus_write_bit(); //function code 0x05
int modbus_write_register(); //function code 0x06
int modbus_write_registers(); //function code 0x10
int modbus_write_bits(); //function code 0x0F
由于ADAM-6050为以太网数据采集模块,支持TCP/UDP;
使用时,先创建TCP连接:
modbus_t *pContext;
pContext = modbus_new_tcp(pUserConfParams.moduleIP.c_str(), pUserConfParams.modulePort);
if (modbus_connect(pContext) == -1) {
printf("Connection failed: %s\n", strerror(errno));
modbus_free(pContext);
return OpetError;
}
使用ADAM-6050的功能码0x01对应的modbus地址(0001)读取DI0~12的状态:
#define ADAM6050ModbusAddr_DI 0001 //功能码0x01对应的地址
#define ADAM6050DataLength_DI 12 //数据长度
uint8_t tabBits[ADAM6050DataLength_DI ] = {0};
uint16_t mInterval = 500;
while(1){
Resp = modbus_read_bits( //使用功能码0x01对应的函数
pContext,
ADAM6050ModbusAddr_DI - 1, //地址需要减1,后面解释
ADAM6050DataLength_DI,
tabBits);
if (Resp == -1) {
printf("%s\n", strerror(errno));
return OpetError;
}
for(int j = 0; j < ADAM6050DataLength_DI; ++j){
printf("<%02x>",tabBits[j]);
}
printf("\n");
usleep(mInterval * 1000);
}
备注:
对于为什么modbus地址需要减1,是由于在功能验证中使用研华的官方工具与其他第三方工具填入对应地址码都能正常读取数据,但是使用libmodbus就会出现数据少一个的情况,并且都是缺失第一个数据,所以尝试地址-1,发现即能读取完整数据,目前还不知道原因。