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

注:
* 此處可能會因網(wǎng)絡(luò)原因造成卡頓,請耐心等待。
* 如果實在要在gitHub網(wǎng)頁上下載,也要把整個倉庫下載下來,不能單獨下載本實例對應(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 例程運行及效果
進(jìn)入Release目錄,執(zhí)行下方命令,運行示例程序:
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/。用戶可通過源代碼了解接口實現(xiàn),甚至可對源碼進(jìn)行修改。
3.2 創(chuàng)建實例
以TCP方式創(chuàng)建Modbus實例,并初始化:
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:端口號 |
返回值 |
成功:Modbus實例 失敗:NULL |
注意事項 | 無 |
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實例 slave:從機(jī)ID |
返回值 |
成功:0 失敗:-1 |
注意事項 | 無 |
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實例 |
返回值 |
成功:0 失敗:-1 |
注意事項 | 無 |
3.5 寄存器進(jìn)行操作,功能碼對應(yīng)函數(shù)
3.5.1 讀取線圈狀態(tài),可讀取多個連續(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實例 |
addr :寄存器起始地址 | |
nb :寄存器個數(shù) | |
dest :得到的狀態(tài)值 | |
返回值 | 無 |
注意事項 | 無 |
3.5.2 讀取輸入狀態(tài),可讀取多個連續(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實例 |
addr :寄存器起始地址 | |
nb :寄存器個數(shù) | |
dest :得到的狀態(tài)值 | |
返回值 | 成功:返回nb的值 |
注意事項 | 無 |
3.5.3 讀取保持寄存器的值,可讀取多個連續(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實例 |
addr :寄存器起始地址 | |
nb :寄存器個數(shù) | |
dest :得到的寄存器的值 | |
返回值 |
成功:讀到寄存器的個數(shù) 失敗:-1 |
注意事項 | 無 |
3.5.4 讀輸入寄存器的值,可讀取多個連續(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實例 |
addr :寄存器起始地址 | |
nb :寄存器個數(shù) | |
dest :得到的寄存器的值 | |
返回值 |
成功:讀到寄存器的個數(shù) 失敗:-1 |
注意事項 | 無 |
3.5.5 寫入單個線圈的狀態(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實例 |
addr :線圈地址 | |
status:線圈狀態(tài) | |
返回值 |
成功:0 失敗:-1 |
注意事項 | 無 |
3.5.6 寫入多個連續(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實例 |
addr :線圈地址 | |
nb :線圈個數(shù) | |
src:多個線圈狀態(tài) | |
返回值 |
成功:0 失敗:-1 |
注意事項 | 無 |
3.5.7 寫入單個寄存器(對應(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實例 |
addr :寄存器地址 | |
value :寄存器的值 | |
返回值 |
成功:0 失敗:-1 |
注意事項 | 無 |
3.5.8 寫入多個連續(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實例 |
addr :寄存器地址 | |
nb :寄存器的個數(shù) | |
src:多個寄存器的值 | |
返回值 |
成功:0 失敗:-1 |
注意事項 | 無 |
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實例 |
返回值 | 無 |
注意事項 | 無 |
3.7 釋放實例
和從機(jī)建立連接的函數(shù)原型為:
void modbus_free(modbus_t *ctx);
具體介紹如下所示。
函數(shù)名: modbus_free() | |
頭文件 | easyeai-api/common/modbus/modbus.h |
輸入?yún)?shù) | ctx:Modbus實例 |
返回值 | 無 |
注意事項 | 無 |
4. 使用實例
示例主機(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文章
1963瀏覽量
78757 -
服務(wù)器
+關(guān)注
關(guān)注
12文章
9623瀏覽量
87088 -
開發(fā)板
+關(guān)注
關(guān)注
25文章
5435瀏覽量
101284 -
rk3576
+關(guān)注
關(guān)注
1文章
127瀏覽量
497
發(fā)布評論請先 登錄
米爾RK3576開發(fā)板特惠活動!

基于RK3576開發(fā)板的MIPI-DSI使用

評論