玩转Libmodbus(二) 写代码体验
libmodbus在线文档
https://www.jianshu.com/p/d93c17485c0a
原创篇
参考上一篇转载的博客,我的ubuntu上的最终生成的动态库的路径,下图所示
我的linux板子上( 权限最好 777):
我的ubuntu主机上的C语言源代码的路径,四个头文件modbus.h、modbus-rtu.h、modbus-tcp.h、modbus-version.h也都放在了这里
我的C源代码:
/************************* ** ** modbus-rtu-test.c ** 移植libmodbus库到ARM开发板,并测试成功 ** **************************/ #include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include "modbus.h" //modbus动态库文件 unsigned char log[6] = {0x11,0x12,0x13,0x14,0x15,0x16}; #define Path_dat "/root/Test_Data_Dir/record.dat" #define Path_log1 "/root/Test_Data_Dir/log1.dat" #define Path_log2 "/root/Test_Data_Dir/log2.dat" #define Path_log3 "/root/Test_Data_Dir/log3.dat" #define Path_log4 "/root/Test_Data_Dir/log4.dat" /* int read_data_hex(unsigned char *buf, int length, char *string) { FILE *fp; fp = fopen(string, "rb"); if (NULL == fp) { // printf("read: file open Fail!\n"); return -1; } fread(buf, sizeof(unsigned char), length, fp); fclose(fp); fp = NULL; return 0; } */ int write_data_hex(unsigned char *my_array, int length, char *string) { int i = 0; FILE *fp; fp = fopen(string, "wb+"); // b 二进制操作 if (NULL == fp) { // printf("write: file open Fail!\n"); return -1; } while (i < length) { fwrite(&my_array[i], sizeof(unsigned char), 1, fp); i++; } fclose(fp); fp = NULL; return 0; } //如果手边只有一根USB转串口线,那么只能连接板子的modbus串口和PC机,就不能 //连接PC机和板子的串口调试口了。如何调试?使用write_data_hex()写log观察过程。 int main(int argc, char *argv[]) { struct timeval t; uint16_t tab_reg[64] = {0}; //定义存放数据的数组 modbus_t *ctx = NULL; int rc; int i; //以串口的方式创建libmodbus实例,并设置参数 //ttySAC0 /dev/ttyS1 ctx = modbus_new_rtu("/dev/ttySAC0", 115200, 'N', 8, 1); if (ctx == NULL) { fprintf(stderr, "Unable to allocate libmodbus contex\n"); return -1; } printf("MY_Debug: usleep begin! \n"); //这里我给了40秒延时,在这个时间内:你把串口线从板子的串口调试口转为 //连接到板子的modbus串口,打开一个事先设置好串口参数的PC机上的模拟modbus从机的软件 //(我使用的是和modsim32) //注意:如果前后接的是同一个电脑com口,注意还要把之前的串口调试口对应的上位机软件 // 关闭一下,以便modsim32能够顺利打开该com口。 usleep(40000000); modbus_set_debug(ctx, 0); //设置1可看到调试信息 modbus_set_slave(ctx, 1); //设置slave ID t.tv_sec = 0; t.tv_usec = 50000; // 50ms超时时间,下位机回复帧的限制时间:主机发完后,下位机需要在50ms内回应 // *** 必须设置从站的响应超时 小于 主站的响应超时 *** // 总之,在确保速度满足你所需应用的情况下,把主站的响应超时适当设置大一点,是保险措施 modbus_set_response_timeout(ctx,&t); if (modbus_connect(ctx) == -1) //连接设备 { write_data_hex(&log[0], 1, Path_log1); printf("MY_Debug: modbus_connect Fail! \n"); fprintf(stderr, "Connection failed:%s\n", modbus_strerror(errno)); modbus_close(ctx); //关闭modbus连接 modbus_free(ctx); //释放modbus资源,libmodbus需要释放掉 } else{ printf("MY_Debug: modbus_connect Success! \n"); } while (1) { printf("\n 这里的代码只执行一次 return -1,或者 break \n"); rc = modbus_read_registers(ctx, 0, 10, tab_reg); if (rc == -1) //读取保持寄存器的值,可读取多个连续输入保持寄存器 { write_data_hex(&log[1], 1, Path_log2); fprintf(stderr,"%s\n", modbus_strerror(errno)); printf("MY_Debug: modbus_read_registers Fail! \n"); return -1; } // 这里保存为文件,如果你只有一根串口线,方便你观察结果。 write_data_hex(&log[2], 1, Path_log3); write_data_hex(tab_reg, 10, Path_dat); for (i=0; i<10; i++) { printf("reg[%d] = %d(0x%x)\n", i, tab_reg[i], tab_reg[i]); } break; } write_data_hex(&log[3], 1, Path_log4); //标记代码已顺利结束 modbus_close(ctx); //关闭modbus连接 modbus_free(ctx); //释放modbus资源,使用完libmodbus需要释放掉 return 0; }
我的makefile:
CC = arm-none-linux-gnueabi-gcc #CFLAGS += -I../include -std=gnu99 -lm -lpthread -O3 -lstdc++ LIBS += -L /home/aston/LibModbus_Study/installHere/lib -lmodbus TARGET=main.out SRCS = Lib_Modbus_test.c OBJS = $(SRCS:.c=.o) $(TARGET):$(OBJS) $(CC) $(LDFLAGS) $^ -o $@ $(LIBS) clean: rm -rf $(TARGET) $(OBJS)
我使用到的工具软件: ModSim32
D:\Study_2019\LibModbus\使用到的工具软件\ModSim32 v1.A00-04
软件使用介绍:
先点击New, 就可以出现‘’2’的界面,并配置好参数,以便后面使用
待linux板子上的程序跑起来以后,用USB转串口线连接好板子的MODBUS串口和PC机的USB口,再点击下图所示的‘3’的Connect
代码中读取到的寄存器的值展示:
实验成功。注意,modbus一个寄存器占两个字节。大小端有区分。
/************* 社会的有色眼光是:博士生、研究生、本科生、车间工人; 重点大学高材生、普通院校、二流院校、野鸡大学; 年薪百万、五十万、五万; 这些都只是帽子,可以失败千百次,但我和社会都觉得,人只要成功一次,就能换一顶帽子,只是社会看不见你之前的失败的帽子。 当然,换帽子决不是最终目的,走好自己的路就行。 杭州.大话西游 *******/