文章目錄
- 一、Modbus/TCP協議
- 1.查詢報文
- 2.回應報文
- 二、從機代碼
- 1.初始化從機網路
- 2.簡單回應函式
- 3.main函式回圈等待連接
- 三、效果
- 四、總結
- 五、原始碼
一、Modbus/TCP協議
| 功能碼 | 作用 |
|---|---|
| 01 | 讀取線圈狀態 |
| 02 | 讀取輸入狀態 |
| 03 | 讀取保持暫存器 |
| 04 | 讀取輸入暫存器 |
| 05 | 強置單線圈 |
| 06 | 預置單暫存器 |
| 07 | 讀取例外狀態 |
| 08 | 回送診斷校驗 |
| 09 | 編程(只用于484) |
| 0A | 控詢 |
| 0B | 讀取事件計數 |
| 0C | 讀取通信事件記錄 |
| 0D | 編程(184/384/484/584等) |
| 0E | 探尋 |
| 0F | 強置多線圈 |
| 10 | 預置多線圈 |
| 11 | 報告多暫存器 |
| 12 | 可使主機模擬編程功能 |
| 13 | 重置通信鏈路 |
| 14 | 讀取通用引數 |
| 15 | 寫入通用引數 |
| 16 | 屏蔽寫暫存器 |
| 17 | 讀/寫多個暫存器 |
1.查詢報文
00 6D 00 00 00 06 01 03 00 00 00 01
00 6D 查詢編號
00 00 協議
00 06 資料包長度
01 設備編號
03 功能碼
00 00 起始地址
00 01 查詢暫存器個數
2.回應報文
00 6D 00 00 00 05 01 03 02 00 17
00 6D 查詢編號
00 00 協議
00 05 資料包長度
01 設備地址
03 功能碼
02 資料長度
00 17 資料值
二、從機代碼
1.初始化從機網路
void Load_Net_Parameters(void)
{
Gateway_IP[0] = 192;//加載網關引數
Gateway_IP[1] = 168;
Gateway_IP[2] = 1;
Gateway_IP[3] = 1;
Sub_Mask[0]=255;//加載子網掩碼
Sub_Mask[1]=255;
Sub_Mask[2]=255;
Sub_Mask[3]=0;
Phy_Addr[0]=0x0c;//加載物理地址
Phy_Addr[1]=0x29;
Phy_Addr[2]=0xab;
Phy_Addr[3]=0x7c;
Phy_Addr[4]=0x00;
Phy_Addr[5]=0x01;
IP_Addr[0]=192;//加載本機IP地址
IP_Addr[1]=168;
IP_Addr[2]=1;
IP_Addr[3]=199;
S0_Port[0] = 0x13;//加載埠0的埠號5000
S0_Port[1] = 0x88;
S0_Mode=TCP_SERVER;//加載埠0的作業模式,TCP服務端模式
}
2.簡單回應函式
回傳一個全域變數data,并且每次回應后自增1,
void Process_Socket_Data(SOCKET s)
{
int len;
unsigned char msg[11]={0x00,0x00,0x00 ,0x00, 0x00, 0x05, 0x01, 0x03, 0x02, 0x00, 0x70};
len=sizeof(msg);
unsigned short size;
size=Read_SOCK_Data_Buffer(s, Rx_Buffer);
memcpy(Tx_Buffer, Rx_Buffer, size);
//列印查詢報文
for (int j=0;j<size;j++){
printf("0x%02X ",Tx_Buffer[j]);
}
//寫回應報文
//檢驗碼
msg[0]=Tx_Buffer[0];
msg[1]=Tx_Buffer[1];
//協議
msg[2]=0x00;
msg[3]=0x00;
//資料包長度
msg[4]=0x00;
msg[5]=0x05;
//設備編號
msg[6]=Tx_Buffer[6];
//功能碼
msg[7]=Tx_Buffer[7];
//資料長度
msg[8]=0x02;
//低八位
msg[10]=data&0XFF;
//高八位
msg[9]=data>>8;
memcpy(Tx_Buffer, msg, len);
//發送回應報文
Write_SOCK_Data_Buffer(0, Tx_Buffer, len);
data++;
}
3.main函式回圈等待連接
while (1)
{
W5500_Socket_Set();//W5500埠初始化配置
W5500_Interrupt_Process();//W5500中斷處理程式框架
if((S0_Data & S_RECEIVE) == S_RECEIVE)//如果Socket0接收到資料
{
S0_Data&=~S_RECEIVE;
Process_Socket_Data(0);//W5500接收并發送接收到的資料
}
//從機狀態標志
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
}
三、效果
使用modbus poll建立連接
設定id、地址、讀取位數

使用TCP/IP建立連接,設定地址、埠,

效果
可以看到可以成功讀取到data的值

四、總結
這次實驗只是簡單的讀取了一個暫存器的值,多個暫存器思路類似,
五、原始碼
https://github.com/TangtangSix/Modbus_TCP
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/382106.html
標籤:其他
