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一個寄存器占兩個字節。大小端有區分。