1. MODBUS簡介
MODBUS是一項(xiàng)應(yīng)用層報(bào)文傳輸協(xié)議,用于在通過不同類型的總線或網(wǎng)絡(luò)連接的設(shè)備之間的客戶機(jī)/服務(wù)器通信。Modbus比其他通信協(xié)議使用的更廣泛的主要原因是因?yàn)樗_發(fā)表并且無版權(quán)要求;而且易于部署和維護(hù);對供應(yīng)商來說,修改移動(dòng)本地的比特或字節(jié)沒有很多限制。
1.1 協(xié)議版本與內(nèi)容
Modbus協(xié)議目前存在用于串口、以太網(wǎng)以及其他支持互聯(lián)網(wǎng)協(xié)議的網(wǎng)絡(luò)的版本。
大多數(shù)Modbus設(shè)備通信通過串口EIA-485物理層進(jìn)行。對于串行連接,存在兩個(gè)變種,它們在數(shù)值數(shù)據(jù)表示不同和協(xié)議細(xì)節(jié)上略有不同。MODBUS模式分為三類,一種模式是RTU(遠(yuǎn)程終端設(shè)備),另一種模式是ASCII(美國信息交換碼),第三種模式為TCP(運(yùn)行在以太網(wǎng)上的協(xié)議)?!綧odbus RTU】是一種緊湊的,采用二進(jìn)制表示數(shù)據(jù)的方式(Modbus協(xié)議上規(guī)定,且默認(rèn)模式必須是RTU,ASCII作為選項(xiàng)),【Modbus ASCII】是一種人類可讀的,冗長的表示方式。這兩個(gè)變種都使用串行通信(serial communication)方式。對于通過TCP/IP(例如以太網(wǎng))的連接,存在多個(gè)【Modbus/TCP】變種,這種方式不需要校驗(yàn)和計(jì)算。對于所有的這三種通信協(xié)議在數(shù)據(jù)模型和功能調(diào)用上都是相同的,只有封裝方式是不同的。
1.2 通信和設(shè)備
Modbus協(xié)議是一個(gè)master/slave架構(gòu)的協(xié)議。有一個(gè)節(jié)點(diǎn)是master節(jié)點(diǎn),其他使用Modbus協(xié)議參與通信的節(jié)點(diǎn)是slave節(jié)點(diǎn)。每一個(gè)slave設(shè)備都有一個(gè)唯一的地址。在串行和MB+網(wǎng)絡(luò)中,只有被指定為主節(jié)點(diǎn)的節(jié)點(diǎn)可以啟動(dòng)一個(gè)命令(在以太網(wǎng)上,任何一個(gè)設(shè)備都能發(fā)送一個(gè)Modbus命令,但是通常也只有一個(gè)主節(jié)點(diǎn)設(shè)備啟動(dòng)指令)。
一個(gè)ModBus命令包含了打算執(zhí)行的設(shè)備的Modbus地址。所有設(shè)備都會(huì)收到命令,但只有指定位置的設(shè)備會(huì)執(zhí)行及回應(yīng)指令(地址0例外,指定地址0的指令是廣播指令,所有收到指令的設(shè)備都會(huì)運(yùn)行,不過不回應(yīng)指令)。所有的Modbus命令包含了檢查碼,以確定到達(dá)的命令沒有被破壞?;镜腗odBus命令能指令一個(gè)RTU改變它的寄存器的某個(gè)值,控制或者讀取一個(gè)I/O端口,以及指揮設(shè)備回送一個(gè)或者多個(gè)其寄存器中的數(shù)據(jù)。
1.3 MODBUS使用要點(diǎn)
通過以上敘述可知,使用Modubs需要時(shí)刻圍繞以下幾點(diǎn):
Modbus是主從方式通信,不能同步進(jìn)行通信;
主機(jī)不發(fā)送,總線上就沒有數(shù)據(jù)通信;
設(shè)備必須要有RTU協(xié)議,這是Modbus協(xié)議上規(guī)定的;
基本流程如下
發(fā)送:從機(jī)的地址+功能碼+寄存器的地址+寄存器地址的個(gè)數(shù)+校驗(yàn)碼
回復(fù):從機(jī)的地址+功能碼+要發(fā)送給主機(jī)數(shù)據(jù)的字節(jié)數(shù)+數(shù)據(jù)+校驗(yàn)碼
我司的easyeai-api軟件開源庫將復(fù)雜的報(bào)文格式、收發(fā)操作做了統(tǒng)一的封裝,為客戶提供簡單便捷的調(diào)用方式實(shí)現(xiàn)Modubs通訊功能。
2. 快速上手
如果您初次閱讀此文檔,請閱讀:《入門指南/源碼管理及編程介紹/源碼工程管理》,按需管理自己工程源碼(注:此文檔必看,并建議采用【遠(yuǎn)程掛載管理】方式,否則有代碼丟失風(fēng)險(xiǎn)!!!)。
2.1 源碼工程下載
先在PC虛擬機(jī)定位到nfs服務(wù)目錄,再在目錄中創(chuàng)建存放源碼倉庫的管理目錄:
cd ~/nfsroot mkdir GitHub cd GitHub
再通過git工具,在管理目錄內(nèi)克隆遠(yuǎn)程倉庫(需要設(shè)備能對外網(wǎng)進(jìn)行訪問)
git clone https://github.com/EASY-EAI/EASY-EAI-Toolkit-3576.git

注:
* 此處可能會(huì)因網(wǎng)絡(luò)原因造成卡頓,請耐心等待。
* 如果實(shí)在要在gitHub網(wǎng)頁上下載,也要把整個(gè)倉庫下載下來,不能單獨(dú)下載本實(shí)例對應(yīng)的目錄。
2.2 開發(fā)環(huán)境搭建
通過adb shell進(jìn)入板卡開發(fā)環(huán)境,如下圖所示。

通過以下命令,把nfs目錄掛載上nfs服務(wù)器。
mount -t nfs -o nolock : /home/orin-nano/Desktop/nfs/

2.3 例程編譯
然后定位到nfs的掛載目錄,再在目錄中創(chuàng)建存放源碼倉庫的管理目錄:
cd /home/orin-nano/Desktop/nfs/GitHub
進(jìn)入到對應(yīng)的例程目錄執(zhí)行編譯操作,具體命令如下所示:
cd EASY-EAI-Toolkit-3576/Demos/common-modbus/ ./build.sh

2.4 例程運(yùn)行及效果
進(jìn)入Release目錄,執(zhí)行下方命令,運(yùn)行示例程序:
cd Release ./test-modbus_tcp_master & ./test-modbus_tcp_slave
TCP模式執(zhí)行效果如下所示:

如果需要更換RTU模式可自行修改代碼
代碼路徑:EASY-EAI-Toolkit-3576/Demos/common-modbus/ test-modbus_tcp_slave.c

API的詳細(xì)說明,以及API的調(diào)用(本例程源碼),詳細(xì)信息見下方說明。
3. MODBUS庫函數(shù)說明
本章節(jié)介紹EASY EAI的MODBUS庫函數(shù)的使用方法。
3.1 引用方式
EASY EAI api庫位于本倉庫的easyeai-api目錄中。為方便客戶在本地工程中直接調(diào)用我們的EASY EAI api庫,此處列出工程中需要鏈接的庫以及頭文件等,方便用戶直接添加。
| 描述 | CMake寫法 | Makefile寫法 |
| api.cmake | ${common_root}/modbus/api.cmake | 無 |
| 頭文件目錄 | ${MODBUS_INCLUDE_DIRS} | -I ../../easyeai-api/common/modbus |
| 源文件目錄 | ${MODBUS_SOURCE_DIRS} | ../../easyeai-api/common/modbus |
| 庫文件目錄 | 無 | 無 |
| 庫鏈接參數(shù) | ${MODBUS_LIBS} | 無 |
API源代碼路徑為EASY-EAI-Toolkit-3576/easyeai-api/common/modbus/。用戶可通過源代碼了解接口實(shí)現(xiàn),甚至可對源碼進(jìn)行修改。
3.2 創(chuàng)建實(shí)例
以TCP方式創(chuàng)建Modbus實(shí)例,并初始化:
modbus_t* modbus_new_tcp(const char *ip, int port);
具體介紹如下所示。
| 函數(shù)名:modbus_new_tcp() | |
| 頭文件 | easyeai-api/common/modbus/modbus.h |
| 輸入?yún)?shù) |
ip:ip地址 port:端口號(hào) |
| 返回值 |
成功:Modbus實(shí)例 失?。篘ULL |
| 注意事項(xiàng) | 無 |
3.3 設(shè)置從機(jī)ID
設(shè)置從機(jī)ID的函數(shù)原型為:
void modbus_set_slave(modbus_t *ctx, int slave);
具體介紹如下所示。
| 函數(shù)名:modbus_set_slave() | |
| 頭文件 | easyeai-api/common/modbus/modbus.h |
| 輸入?yún)?shù) |
ctx:Modbus實(shí)例 slave:從機(jī)ID |
| 返回值 |
成功:0 失?。?1 |
| 注意事項(xiàng) | 無 |
3.4 和從機(jī)進(jìn)行連接
和從機(jī)建立連接的函數(shù)原型為:
void modbus_connect(modbus_t *ctx);
具體介紹如下所示。
| 函數(shù)名: modbus_connect() | |
| 頭文件 | easyeai-api/common/modbus/modbus.h |
| 輸入?yún)?shù) | ctx:Modbus實(shí)例 |
| 返回值 |
成功:0 失敗:-1 |
| 注意事項(xiàng) | 無 |
3.5 寄存器進(jìn)行操作,功能碼對應(yīng)函數(shù)
3.5.1 讀取線圈狀態(tài),可讀取多個(gè)連續(xù)線圈的狀態(tài)(對應(yīng)功能碼為0x01)
int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);
具體介紹如下所示。
| 函數(shù)名: modbus_read_bits() | |
| 頭文件 | easyeai-api/common/modbus/modbus.h |
| 輸入?yún)?shù) | ctx :Modbus實(shí)例 |
| addr :寄存器起始地址 | |
| nb :寄存器個(gè)數(shù) | |
| dest :得到的狀態(tài)值 | |
| 返回值 | 無 |
| 注意事項(xiàng) | 無 |
3.5.2 讀取輸入狀態(tài),可讀取多個(gè)連續(xù)輸入的狀態(tài)(對應(yīng)功能碼為0x02)
int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);
具體介紹如下所示。
| 函數(shù)名: modbus_read_input_bits() | |
| 頭文件 | easyeai-api/common/modbus/modbus.h |
| 輸入?yún)?shù) | ctx :Modbus實(shí)例 |
| addr :寄存器起始地址 | |
| nb :寄存器個(gè)數(shù) | |
| dest :得到的狀態(tài)值 | |
| 返回值 | 成功:返回nb的值 |
| 注意事項(xiàng) | 無 |
3.5.3 讀取保持寄存器的值,可讀取多個(gè)連續(xù)保持寄存器的值(對應(yīng)功能碼為0x03)
int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
| 函數(shù)名: modbus_read_registers() | |
| 頭文件 | easyeai-api/common/modbus/modbus.h |
| 輸入?yún)?shù) | ctx :Modbus實(shí)例 |
| addr :寄存器起始地址 | |
| nb :寄存器個(gè)數(shù) | |
| dest :得到的寄存器的值 | |
| 返回值 |
成功:讀到寄存器的個(gè)數(shù) 失?。?1 |
| 注意事項(xiàng) | 無 |
3.5.4 讀輸入寄存器的值,可讀取多個(gè)連續(xù)輸入寄存器的值(對應(yīng)功能碼為0x04)
int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
具體介紹如下所示。
| 函數(shù)名: modbus_read_input_registers() | |
| 頭文件 | easyeai-api/common/modbus/modbus.h |
| 輸入?yún)?shù) | ctx :Modbus實(shí)例 |
| addr :寄存器起始地址 | |
| nb :寄存器個(gè)數(shù) | |
| dest :得到的寄存器的值 | |
| 返回值 |
成功:讀到寄存器的個(gè)數(shù) 失?。?1 |
| 注意事項(xiàng) | 無 |
3.5.5 寫入單個(gè)線圈的狀態(tài)(對應(yīng)功能碼為0x05)
int modbus_write_bit(modbus_t *ctx, int addr, int status);
具體介紹如下所示。
| 函數(shù)名:modbus_write_bit() | |
| 頭文件 | easyeai-api/common/modbus/modbus.h |
| 輸入?yún)?shù) | ctx :Modbus實(shí)例 |
| addr :線圈地址 | |
| status:線圈狀態(tài) | |
| 返回值 |
成功:0 失?。?1 |
| 注意事項(xiàng) | 無 |
3.5.6 寫入多個(gè)連續(xù)線圈的狀態(tài)(對應(yīng)功能碼為15)
int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src);
具體介紹如下所示。
| 函數(shù)名: modbus_write_bits() | |
| 頭文件 | easyeai-api/common/modbus/modbus.h |
| 輸入?yún)?shù) | ctx :Modbus實(shí)例 |
| addr :線圈地址 | |
| nb :線圈個(gè)數(shù) | |
| src:多個(gè)線圈狀態(tài) | |
| 返回值 |
成功:0 失?。?1 |
| 注意事項(xiàng) | 無 |
3.5.7 寫入單個(gè)寄存器(對應(yīng)功能碼為0x06)
int modbus_write_register(modbus_t *ctx, int addr, int value);
具體介紹如下所示。
| 函數(shù)名:modbus_write_register() | |
| 頭文件 | easyeai-api/common/modbus/modbus.h |
| 輸入?yún)?shù) | ctx :Modbus實(shí)例 |
| addr :寄存器地址 | |
| value :寄存器的值 | |
| 返回值 |
成功:0 失敗:-1 |
| 注意事項(xiàng) | 無 |
3.5.8 寫入多個(gè)連續(xù)寄存器(對應(yīng)功能碼為16)
int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src);
具體介紹如下所示。
| 函數(shù)名: modbus_write_registers() | |
| 頭文件 | easyeai-api/common/modbus/modbus.h |
| 輸入?yún)?shù) | ctx :Modbus實(shí)例 |
| addr :寄存器地址 | |
| nb :寄存器的個(gè)數(shù) | |
| src:多個(gè)寄存器的值 | |
| 返回值 |
成功:0 失?。?1 |
| 注意事項(xiàng) | 無 |
3.6 關(guān)閉套接字
關(guān)閉套接字函數(shù)原型為:
void modbus_close(modbus_t *ctx);
具體介紹如下所示。
| 函數(shù)名: modbus_close() | |
| 頭文件 | easyeai-api/common/modbus/modbus.h |
| 輸入?yún)?shù) | ctx:Modbus實(shí)例 |
| 返回值 | 無 |
| 注意事項(xiàng) | 無 |
3.7 釋放實(shí)例
和從機(jī)建立連接的函數(shù)原型為:
void modbus_free(modbus_t *ctx);
具體介紹如下所示。
| 函數(shù)名: modbus_free() | |
| 頭文件 | easyeai-api/common/modbus/modbus.h |
| 輸入?yún)?shù) | ctx:Modbus實(shí)例 |
| 返回值 | 無 |
| 注意事項(xiàng) | 無 |
4. 使用實(shí)例
示例主機(jī)代碼路徑EASY-EAI-Toolkit-3576/Demos/common-modbus/ test-modbus_tcp_master.c。
示例從機(jī)代碼路徑EASY-EAI-Toolkit-3576/Demos/common-modbus/ test-modbus_tcp_slave.c。
-
MODBUS
+關(guān)注
關(guān)注
28文章
2530瀏覽量
83848 -
服務(wù)器
+關(guān)注
關(guān)注
14文章
10371瀏覽量
91774 -
開發(fā)板
+關(guān)注
關(guān)注
26文章
6433瀏覽量
121221 -
rk3576
+關(guān)注
關(guān)注
1文章
304瀏覽量
1686
發(fā)布評論請先 登錄
【作品合集】米爾RK3576開發(fā)板測評
米爾RK3576開發(fā)板特惠活動(dòng)!
基于RK3576開發(fā)板的MIPI-DSI使用
基于RK3576開發(fā)板的modbus通訊
評論