11.3libmodbus情景分析
以“modbus_write_bits”函數(shù)為例,分析下圖的執(zhí)行流程:
11.3.1
初始化
1. 主設(shè)備初始化
主設(shè)備程序先調(diào)用“modbus_new_rtu”函數(shù),僅僅是分配一個(gè)modbus結(jié)構(gòu)體,在里面記錄要使用的串口設(shè)備、參數(shù):
左右滑動(dòng)查看完整內(nèi)容
modbus_t * modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bi t);
再調(diào)用“modbus_set_slave”,是設(shè)置“要訪問(wèn)哪個(gè)從設(shè)備”。每當(dāng)訪問(wèn)不同地址的設(shè)備之前,都應(yīng)該調(diào)用這個(gè)函數(shù)。
最后調(diào)用“modbus_connect”函數(shù),這個(gè)函數(shù)只是打開(kāi)串口、設(shè)置串口參數(shù),并沒(méi)有跟從設(shè)備進(jìn)行數(shù)據(jù)交互。
2. 從設(shè)備初始化
從設(shè)備的初始化,跟主設(shè)備類似,不過(guò)多了使用“modbus_mapping_new_start_address”函數(shù)創(chuàng)建寄存器 buffer。
modbus_mapping_t結(jié)構(gòu)體如下定義:
左右滑動(dòng)查看完整內(nèi)容
typedef struct _modbus_mapping_t { int nb_bits; int start_bits; int nb_input_bits; int start_input_bits; int nb_input_registers; int start_input_registers; int nb_registers; int start_registers; uint8_t *tab_bits; uint8_t *tab_input_bits; uint16_t *tab_input_registers; uint16_t *tab_registers; } modbus_mapping_t;
它被用來(lái)描述DI、DO、AI、AO四類寄存器。以DO寄存器為例,這個(gè)結(jié)構(gòu)體里有3個(gè)成員:
①nb_bits:DO寄存器個(gè)數(shù)。
②start_bits:DO寄存器起始寄存器地址。
③tab_bits:指向一個(gè)“uint8_t”類型的數(shù)組,里面每個(gè)數(shù)組項(xiàng)表示一個(gè)DO寄存器,這個(gè)數(shù)組大小為nb_bits。數(shù)組中第0項(xiàng),對(duì)應(yīng)第“start_bits”個(gè)DO寄存器。
“modbus_mapping_new_start_address”函數(shù)原型
如下:
左右滑動(dòng)查看完整內(nèi)容
/* Allocates 4 arrays to store bits, input bits, registers and inputs registers. The pointers are stored in modbus_mapping structure. The modbus_mapping_new_start_address() function shall return the new allocated structure if successful. Otherwise it shall return NULL and set errno to ENOMEM. */ modbus_mapping_t *modbus_mapping_new_start_address(unsigned int start_bits, unsigned int nb_bits, unsigned int start_input_bits, unsigned int nb_input_bits, unsigned int start_registers, unsigned int nb_registers, unsigned int start_input_registers, unsigned int nb_input_registers);
假設(shè)從設(shè)備執(zhí)行了如下代碼:
左右滑動(dòng)查看完整內(nèi)容
modbus_mapping_t *mb_mapping; mb_mapping = modbus_mapping_new_start_address(0, 4, /* DO, 4 個(gè)寄存器 */ 0, 3, /* DI, 3 個(gè)寄存器 */ 0, 2, /* AO, 2 個(gè)寄存器 */ 0, 1; /* AI, 1 個(gè)寄存器 */
將會(huì)分配出如下結(jié)構(gòu)體:
modbus傳輸?shù)谋举|(zhì),就是讀寫上圖中4個(gè)數(shù)組。
11.3.2
主設(shè)備發(fā)送請(qǐng)求
主設(shè)備調(diào)用“modbus_write_bits”函數(shù),想寫若干個(gè)DO寄存器,比如:
左右滑動(dòng)查看完整內(nèi)容
01 uint8_t buf[2] = {1, 0}; 02 int rc = modbus_write_bits(ctx, 0, 2, buf);
根據(jù)Modbus RTU協(xié)議,它必定執(zhí)行如下操作:
①構(gòu)造數(shù)據(jù)包
②通過(guò)串口發(fā)送數(shù)據(jù)包
③等待、讀取回復(fù)
對(duì)于上述代碼,數(shù)據(jù)包的內(nèi)容如下:
1. 先構(gòu)造包頭
函數(shù)調(diào)用關(guān)系如下:
2. 再構(gòu)造數(shù)據(jù)
代碼如下:
3. 計(jì)算檢驗(yàn)碼
在發(fā)送數(shù)據(jù)包的函數(shù)里,先計(jì)算檢驗(yàn)碼,代碼如下:
4. 發(fā)送數(shù)據(jù)包
前面構(gòu)造好了數(shù)據(jù)包,發(fā)送就比較簡(jiǎn)單:調(diào)用write函數(shù)進(jìn)行發(fā)送即可。代碼如下:
11.3.3
從設(shè)備接收請(qǐng)求
從設(shè)備的程序一直在等待主機(jī)發(fā)來(lái)的消息,示例代碼如下:
“modbus_receive”函數(shù)內(nèi)部實(shí)現(xiàn)為:
①使用select機(jī)制,逐個(gè)讀取字符
②根據(jù)讀到的字符,分辨還需要讀多少數(shù)據(jù)
1. 讀取單個(gè)字符
函數(shù)調(diào)用關(guān)系如下:
2. 判斷還需要讀取多少數(shù)據(jù)
從設(shè)備讀取主設(shè)備發(fā)來(lái)的請(qǐng)求包時(shí),步驟為:
①先讀取“功能碼”
②再根據(jù)功能碼判斷后續(xù)要的包頭數(shù)據(jù)還剩多少,讀取包頭
③最后根據(jù)包頭數(shù)據(jù)解析要讀多少數(shù)據(jù),讀取數(shù)據(jù)。
流程如下圖所示:
確定第1個(gè)階段數(shù)據(jù)長(zhǎng)度的代碼如下:
讀到功能碼后,根據(jù)功能碼計(jì)算剩下的包頭的數(shù)據(jù):
讀到完整的包頭后,計(jì)算剩下的數(shù)據(jù)長(zhǎng)度:
3. 判斷數(shù)據(jù)完整性
就是根據(jù)校驗(yàn)碼判斷數(shù)據(jù)是否有錯(cuò)誤,代碼如下:
11.3.4
從設(shè)備回應(yīng)
從設(shè)備接收到請(qǐng)求后,調(diào)用如下函數(shù)進(jìn)行處理、回應(yīng):
在“modbus_reply”函數(shù)內(nèi)部,它會(huì):
①對(duì)于寫請(qǐng)求:把請(qǐng)求包中的數(shù)據(jù)解析出入,填入 mb_mapping中對(duì)應(yīng)的寄存器buffer;
②對(duì)于讀請(qǐng)求:從mb_mapping中對(duì)應(yīng)的寄存器buffer取出數(shù)據(jù);
③構(gòu)造回復(fù)包,發(fā)送給主設(shè)備。
本情景分析中,主設(shè)備調(diào)用“modbus_write_bits”函數(shù),想寫兩個(gè)DO寄存器,比如:
左右滑動(dòng)查看完整內(nèi)容
01 uint8_t buf[2] = {1, 0}; 02 int rc = modbus_write_bits(ctx, 0, 2, buf);
從設(shè)備使用“modbus_reply”函數(shù)處理。
1. 根據(jù)請(qǐng)求包設(shè)置寄存器buffer
代碼如下:
2. 構(gòu)造回復(fù)包
對(duì)于“寫多個(gè)DO寄存器”的請(qǐng)求,它的回復(fù)包格式如下:
下面的代碼,構(gòu)造的回復(fù)包里含有上圖1、2的信息(在發(fā)送回復(fù)包時(shí)才構(gòu)造校驗(yàn)碼):
3. 發(fā)送回復(fù)包
最后,從設(shè)備發(fā)送回復(fù)包:
-
MODBUS
+關(guān)注
關(guān)注
28文章
2025瀏覽量
78984 -
MPU
+關(guān)注
關(guān)注
0文章
409瀏覽量
49668 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4371瀏覽量
64229 -
LibModbus
+關(guān)注
關(guān)注
0文章
10瀏覽量
7404
原文標(biāo)題:libmodbus情景分析 - RZ MPU工業(yè)控制教程連載(39)
文章出處:【微信號(hào):瑞薩MCU小百科,微信公眾號(hào):瑞薩MCU小百科】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
第6章_libmodbus使用

【圖書(shū)分享】《Linux內(nèi)核源代碼情景分析》
Linux內(nèi)核情景分析_上下全集高清版pdf
libmodbus使用ubuntu系統(tǒng)
基于select操作的libmodbus庫(kù)
Linux內(nèi)核源代碼情景分析(上冊(cè))浙江大學(xué)

Linux內(nèi)核源代碼情景分析(下冊(cè))浙江大學(xué)
Linux內(nèi)核源代碼情景分析(全冊(cè)高清帶書(shū)簽)
libmodbus之嵌入式Linux使用及測(cè)試

libmodbus源碼框架分析

評(píng)論