版权声明:博客搬运自个人博客www.bigxiangbaobao.com,转载须经本人同意 https://blog.csdn.net/Zx_SSSS/article/details/81636925
工业总线协议都是比较简单的,其实不管什么协议都不难,只要你愿意仔仔细细的看看协议的标准.这里具体协议我就不讲了,主要介绍一下通过libmodbus来搭建自己的通信协议,libmodbus是github上一个开源的modbus实现,维护的比较好,项目地址如下https://github.com/stephane/libmodbus;拿到源码之后编译如下:
./autogen.sh
./configure --host=arm-linux-gnueabihf --prefix=/home/luckyxiang/Workspace/github/libmodbus/build
make
make install
我这里是交叉编译,通过–host指定编译工具链,然后–prefix指定安装目录,这样编译出来是动态so库,如果需要静态编译,去修改src目录下的Makefile文件,加上-static选项,’CFLAGS = -g -O2 -static’
放一段demo代码,
int modbus_data_get(void)
{
modbus_t *ctx = NULL;
int ret = -1;
uint16_t tab_rp_bits[DATA_FRAME];
int i = 0;
int k = 0;
printf("work satrt....\n");
ctx = modbus_new_rtu("/dev/ttyO2", 9600, 'N', 8, 1);
if(ctx == NULL)
{
printf("Unable to allocate libmodbus context\n");
return -1;
}
// modbus_set_debug(ctx, TRUE);
// modbus_set_error_recovery(ctx,
// MODBUS_ERROR_RECOVERY_LINK |
// MODBUS_ERROR_RECOVERY_PROTOCOL);
modbus_set_slave(ctx, SERVER_ID);
if (modbus_connect(ctx) == -1)
{
printf("Connection failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
memset(tab_rp_bits, 0, DATA_FRAME);
for(k = 0; k < 100; k++)
{
ret = modbus_read_registers(ctx, UT_BITS_ADDRESS + k * DATA_FRAME, DATA_FRAME, tab_rp_bits);
for(i = 0; i < DATA_FRAME; i++)
{
if(i != (DATA_FRAME - 1))
printf("%d-", tab_rp_bits[i]);
else
printf("%d", tab_rp_bits[i]);
}
printf("\n");
}
modbus_free(ctx);
}
- 第一步: modbus_new_rtu,我用的是485接口,485和232都是硬件协议,上边跑的软件一般都是串口协议,所以我这里需要配置相关参数.如果是其他协议的可以去看源码里边的test代码.
- 第二步: modbus_set_slave 设置主机地址
- 第三步: modbus_connect 这里会去打开串口设备
- 第四步: modbus_read_registers 读取数据,注意还有其他读取数据的函数,这个是读功能码03的,协议上是读保存寄存器,第二个参数是寄存器地址,第三个是读取的数据长度,第四个是buf
- 第五步: modbus_free 退出系统的时候释放串口和空间
- 注意: 可以打开modbus_set_debug查看通信过程.