uip+freemodbus网络通信
前言:
TCP/IP協議通過uip協議棧來實現,應用層的modbus協議使用freemodbus來實現,另外還需要一個網卡(筆者使用的是KSZ8851網卡控制器)來實現底層的數據傳輸(包括物理層、數據鏈路層)。
下面先介紹uip協議棧和freemodbus庫的使用,后續移植過程和測試結果再更新
一、uip協議棧
uIP協議棧去掉了完整的TCP/IP中不常用的功能,簡化了通訊流程,但保存了網絡通訊必須使用的協議,設計重點放在了IP/TCP/ICMP/UDP/ARP這些網絡層和傳輸層協議上,保證了其代碼的通用性和結構的穩定性。UIP提供的是封裝的策略。
由上往下逐步封裝用戶的數據,如:
應用層----------傳輸層--------網絡層------數據鏈路層-----物理層
應用數據—TCP封裝頭部—IP封裝頭部-----mac封裝+尾部-----發送
uIP提供了三個函數到底層,既uip_init(), uip_input() 和uip_periodic(),同時還提供了許多函數與堆棧交互。當設備驅動放一個輸入包到包緩存里(up_buf),系統將調用uip_input()函數.函數將會處理這個包和需要時調用應用程序。當uip_input()返回,一個輸出包放在包緩存里。包的大小由全局變量uip_len約束。如果uip_len是0,則說明沒有包要發送。周期計時是用于驅動所有的uIP內部時鐘事件。當周期計時激發,每一個TCP連接應該調用uIP函數uip_periodic()。連接編號傳遞的是作為自變量給uip_periodic()函數的。類似于uip_input()函數,當uip_periodic()函數返回,輸出的IP包要放到包緩存里。任何的事物需要經過一定的初始階段,在UIP協議里面通過uip_init()來初始化。
應用程序作為單獨的模塊由用戶實現,uIP協議棧提供一系列接口函數供用戶程序調用。用戶需要將應用層入口程序作為接口提供給uIP協議棧,定義為宏UIP_APPCALL()。uIP在接受到底層傳來的數據包后,若需要送到上層應用程序處理,它就調用UIP_APPCALL()。在uIP協議中有一個uip_buf緩沖用來接收和發送數據。
? 初始化 uIP 協議棧:uip_init()
? 處理輸入包:uip_input()
? 處理周期計時事件:uip_periodic()
? 開始監聽端口:uip_listen()
? 連接到遠程主機:uip_connect()
? 接收到連接請求:uip_connected()
? 主動關閉連接:uip_close()
? 連接被關閉:uip_closed()
? 發出去的數據被應答:uip_acked()
? 在當前連接發送數據:uip_send()
? 在當前連接上收到新的數據:uip_newdata()
? 告訴對方要停止連接:uip_stop()
? 連接被意外終止:uip_aborted()
二、應用層modbus協議(FreeModbus)
FreeModbus是針對通用的Modbus協議棧在嵌入式系統中應用的一個實現。Modbus協議是一個在工業制造領域中得到廣泛應用的一個網絡協議。一個Modbus通信協議棧包括兩層:定義了數據結構和功能Modbus應用協議和網絡層。目前版本的FreeModbus支持如下的功能碼:讀輸入寄存器 (0x04);讀保持寄存器 (0x03);寫單個寄存器 (0x06);寫多個寄存器 (0x10);讀/寫多個寄存器 (0x17);讀取線圈狀態 (0x01);寫單個線圈 (0x05);寫多個線圈 (0x0F);讀輸入狀態 (0x02);報告從機標識 (0x11);
應用Modbus TCP協議,當準備處理一個新數據幀的時候,移植層就必須首先向協議棧發送一個事件標志。然后,協議棧調用一個返回值為接收到的Modbus TCP數據幀的函數,并且開始處理這個數據幀。如果數據有效,則相應的Modbus反饋幀將提供給移植層生成反饋幀。最后,該反饋被發送到客戶端。
FreeModbus必須首先調用初始化功能eMBInit()函數(使用modbus TCP模式時使用eMBTCPInit()函數),然后調用eMBEnable(),最后在循環體中調用eMBPoll()函數。
該函數主要設置偵聽的端口和對需要調用的函數指針進行復制:
pvMBFrameStartCur = eMBTCPStart;
pvMBFrameStopCur = eMBTCPStop;
peMBFrameReceiveCur = eMBTCPReceive;
peMBFrameSendCur = eMBTCPSend;
pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBTCPPortClose : NULL;
ucMBAddress = MB_TCP_PSEUDO_ADDRESS;
eMBCurrentMode = MB_TCP;
eMBState = STATE_DISABLED;
右邊的函數如eMBTCPStart、eMBTCPStop等定義在mbtcp.c中
? 檢查modbus功能是否都被關閉,如果不是關閉(可能是沒有初始化或者已經打開),就返回錯誤;
? 如果是disable狀態,主要做兩件事:首先調用pvMBFrameStartCur,在eMBTCPInit()函數中指向了eMBTCPStart函數;然后將eMB狀態改為使能狀態,即初始化結束。
檢查是否有事件發送,如果有,則根據不太類型的事件響應:
? EV_READY事件,表示系統剛剛進入偵聽狀態,則什么都不做;
? EV_FRAME_RECEIVED事件,表示接收到完整的幀,做兩件事情:調用peMBFrameReceiveCur()函數,解析出地址、數據和長度;然后檢查地址,如果是廣播地址或本機地址(廣播地址表示從機接收,本機地址表示從機發送),就調用xMBPortEventPost( EV_EXECUTE ),將接收器的狀態更改為EV_EXECUTE;
? EV_EXECUTE事件,在函數列表中檢查,有沒有與命令字段相符合的函數,若有則執行響應的函數,否則返回非法功能碼;然后再次檢查地址,如果不等于廣播地址(即表示從機為發送狀態),則調用peMBFrameSendCur()函數,開始發送數據包
? EV_FRAME_SENT事件,直接break(響應寫進EV_EXECUTE事件中)
三、移植過程
先展示一下加入的uip協議棧和freemodbus庫在工程中的示例
運行的主函數
四、測試
局域網下板卡與路由器采用網線連接,PC端模擬上位機通過wifi接入局域網,使用Modbus Poll模擬modbus主機,向從機發出查詢指令。
? 串口打印信息:初始化各模塊、建立連接、收到請求、關閉連接
? Wireshark抓包信息:TCP三次握手、keep-alive幀、modbus的收發。
? Modbus poll讀值:Modbus poll作為modbus主機能讀到從機對應傳感器值的變化
? 串口打印信息
? Wireshark抓包信息
下圖中192.168.2.2是PC的ip地址,而192.168.2.10為板卡設置的ip地址。
? Modbus poll讀值
下圖中左邊一列為傳感器的名稱,右邊為讀取相應傳感器的數據。
總結
以上是生活随笔為你收集整理的uip+freemodbus网络通信的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【笔记】研究生的早期科研之路(作者:中国
- 下一篇: 学习使用php的stripslashe(