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

注:
* 此處可能會因網絡原因造成卡頓,請耐心等待。
* 如果實在要在gitHub網頁上下載,也要把整個倉庫下載下來,不能單獨下載本實例對應的目錄。
2.2 開發環境搭建
通過adb shell進入板卡開發環境,如下圖所示。
通過以下命令,把nfs目錄掛載上nfs服務器。
mount -t nfs -o nolock : /home/orin-nano/Desktop/nfs/

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

2.4 例程運行及效果
進入Release目錄,執行下方命令,運行示例程序:
cd Release ./test-modbus_tcp_master & ./test-modbus_tcp_slave
TCP模式執行效果如下所示:
如果需要更換RTU模式可自行修改代碼
代碼路徑:EASY-EAI-Toolkit-3576/Demos/common-modbus/ test-modbus_tcp_slave.c
API的詳細說明,以及API的調用(本例程源碼),詳細信息見下方說明。
3. MODBUS庫函數說明
本章節介紹EASY EAI的MODBUS庫函數的使用方法。
3.1 引用方式
EASY EAI api庫位于本倉庫的easyeai-api目錄中。為方便客戶在本地工程中直接調用我們的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 |
庫文件目錄 | 無 | 無 |
庫鏈接參數 | ${MODBUS_LIBS} | 無 |
API源代碼路徑為EASY-EAI-Toolkit-3576/easyeai-api/common/modbus/。用戶可通過源代碼了解接口實現,甚至可對源碼進行修改。
3.2 創建實例
以TCP方式創建Modbus實例,并初始化:
modbus_t* modbus_new_tcp(const char *ip, int port);
具體介紹如下所示。
函數名:modbus_new_tcp() | |
頭文件 | easyeai-api/common/modbus/modbus.h |
輸入參數 |
ip:ip地址 port:端口號 |
返回值 |
成功:Modbus實例 失敗:NULL |
注意事項 | 無 |
3.3 設置從機ID
設置從機ID的函數原型為:
void modbus_set_slave(modbus_t *ctx, int slave);
具體介紹如下所示。
函數名:modbus_set_slave() | |
頭文件 | easyeai-api/common/modbus/modbus.h |
輸入參數 |
ctx:Modbus實例 slave:從機ID |
返回值 |
成功:0 失敗:-1 |
注意事項 | 無 |
3.4 和從機進行連接
和從機建立連接的函數原型為:
void modbus_connect(modbus_t *ctx);
具體介紹如下所示。
函數名: modbus_connect() | |
頭文件 | easyeai-api/common/modbus/modbus.h |
輸入參數 | ctx:Modbus實例 |
返回值 |
成功:0 失敗:-1 |
注意事項 | 無 |
3.5 寄存器進行操作,功能碼對應函數
3.5.1 讀取線圈狀態,可讀取多個連續線圈的狀態(對應功能碼為0x01)
int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);
具體介紹如下所示。
函數名: modbus_read_bits() | |
頭文件 | easyeai-api/common/modbus/modbus.h |
輸入參數 | ctx :Modbus實例 |
addr :寄存器起始地址 | |
nb :寄存器個數 | |
dest :得到的狀態值 | |
返回值 | 無 |
注意事項 | 無 |
3.5.2 讀取輸入狀態,可讀取多個連續輸入的狀態(對應功能碼為0x02)
int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);
具體介紹如下所示。
函數名: modbus_read_input_bits() | |
頭文件 | easyeai-api/common/modbus/modbus.h |
輸入參數 | ctx :Modbus實例 |
addr :寄存器起始地址 | |
nb :寄存器個數 | |
dest :得到的狀態值 | |
返回值 | 成功:返回nb的值 |
注意事項 | 無 |
3.5.3 讀取保持寄存器的值,可讀取多個連續保持寄存器的值(對應功能碼為0x03)
int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
函數名: modbus_read_registers() | |
頭文件 | easyeai-api/common/modbus/modbus.h |
輸入參數 | ctx :Modbus實例 |
addr :寄存器起始地址 | |
nb :寄存器個數 | |
dest :得到的寄存器的值 | |
返回值 |
成功:讀到寄存器的個數 失敗:-1 |
注意事項 | 無 |
3.5.4 讀輸入寄存器的值,可讀取多個連續輸入寄存器的值(對應功能碼為0x04)
int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
具體介紹如下所示。
函數名: modbus_read_input_registers() | |
頭文件 | easyeai-api/common/modbus/modbus.h |
輸入參數 | ctx :Modbus實例 |
addr :寄存器起始地址 | |
nb :寄存器個數 | |
dest :得到的寄存器的值 | |
返回值 |
成功:讀到寄存器的個數 失敗:-1 |
注意事項 | 無 |
3.5.5 寫入單個線圈的狀態(對應功能碼為0x05)
int modbus_write_bit(modbus_t *ctx, int addr, int status);
具體介紹如下所示。
函數名:modbus_write_bit() | |
頭文件 | easyeai-api/common/modbus/modbus.h |
輸入參數 | ctx :Modbus實例 |
addr :線圈地址 | |
status:線圈狀態 | |
返回值 |
成功:0 失敗:-1 |
注意事項 | 無 |
3.5.6 寫入多個連續線圈的狀態(對應功能碼為15)
int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src);
具體介紹如下所示。
函數名: modbus_write_bits() | |
頭文件 | easyeai-api/common/modbus/modbus.h |
輸入參數 | ctx :Modbus實例 |
addr :線圈地址 | |
nb :線圈個數 | |
src:多個線圈狀態 | |
返回值 |
成功:0 失敗:-1 |
注意事項 | 無 |
3.5.7 寫入單個寄存器(對應功能碼為0x06)
int modbus_write_register(modbus_t *ctx, int addr, int value);
具體介紹如下所示。
函數名:modbus_write_register() | |
頭文件 | easyeai-api/common/modbus/modbus.h |
輸入參數 | ctx :Modbus實例 |
addr :寄存器地址 | |
value :寄存器的值 | |
返回值 |
成功:0 失敗:-1 |
注意事項 | 無 |
3.5.8 寫入多個連續寄存器(對應功能碼為16)
int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src);
具體介紹如下所示。
函數名: modbus_write_registers() | |
頭文件 | easyeai-api/common/modbus/modbus.h |
輸入參數 | ctx :Modbus實例 |
addr :寄存器地址 | |
nb :寄存器的個數 | |
src:多個寄存器的值 | |
返回值 |
成功:0 失敗:-1 |
注意事項 | 無 |
3.6 關閉套接字
關閉套接字函數原型為:
void modbus_close(modbus_t *ctx);
具體介紹如下所示。
函數名: modbus_close() | |
頭文件 | easyeai-api/common/modbus/modbus.h |
輸入參數 | ctx:Modbus實例 |
返回值 | 無 |
注意事項 | 無 |
3.7 釋放實例
和從機建立連接的函數原型為:
void modbus_free(modbus_t *ctx);
具體介紹如下所示。
函數名: modbus_free() | |
頭文件 | easyeai-api/common/modbus/modbus.h |
輸入參數 | ctx:Modbus實例 |
返回值 | 無 |
注意事項 | 無 |
4. 使用實例
示例主機代碼路徑EASY-EAI-Toolkit-3576/Demos/common-modbus/ test-modbus_tcp_master.c。
示例從機代碼路徑EASY-EAI-Toolkit-3576/Demos/common-modbus/ test-modbus_tcp_slave.c。
-
MODBUS
+關注
關注
28文章
1960瀏覽量
78742 -
服務器
+關注
關注
12文章
9618瀏覽量
87070 -
開發板
+關注
關注
25文章
5432瀏覽量
101236 -
rk3576
+關注
關注
1文章
125瀏覽量
497
發布評論請先 登錄
基于RK3576開發板的MIPI-DSI使用

評論