modbus協議及modbus TCP協議

一、Modbus協議
  • 1.起源

Modbus由Modicon公司于1979年開發,是一種工業現場總線協議標準

Modbus通信協議具有多個變種,其中有支持串口,以太網多個版本,其中最著名的是Modbus?RTU(通信效率最高,基于串口)、Modbus?ASCII和Modbus?TCP(基于以太網)三種

其中Modbus?TCP是在施耐德收購Modicon后1997年發布的。

2.分類

1)Modbus?RTU

運行在串口上的協議,采用二進制表現形式以及緊湊的數據結構,通信效率較高,應用比較廣泛

2)Modbus?ASCII

運行在串口上的協議,采用ASCII碼進行傳輸,并且每個字節的開始和結束都有特殊字符作為標志,傳輸效率遠遠低于Modbus?RTU,一般只有通訊量比較少時才會考慮它。

3)Modbus?TCP

運行在以太網上的協議

3.優勢:

免費、簡單、容易使用

4.應用場景:

Modbus協議是現在國內工業領域應用最多的協議,不只PLC設備,各種終端設備,比如水控機、水表、電表、工業秤、各種采集設備

二、Modbus?tcp協議

1.特點

1)采用主從問答式通信

(一個主機可以對應多個從機,可以發出請求采集數據,發出請求控制設備)

2)Modbus?TCP是應用層協議,基于傳輸層的TCP進行通信的

3)Modbus?TCP端口號默認502

2.組成

ModbusTcp協議包含三部分:報文頭、功能碼、數據????????

報文頭7個字節,功能碼1個字節,Modbus?TCP/IP協議最大數據幀長度為260字節,最大252,(1?byte?=?8?bit)

1)報文頭

包含一個7字節報文頭

事物處理標識符:沒有限制,主機按照啥發,從機按照什么回

協議標識符:為啥是4個0?寫一個0行不行?每一位都是16進制數?一位十六進制由4位2進制組成,8位2進制為一個字節

長度:

單元標識符:從機id

注意:報文頭包含內容個數順序均不可調換

2)寄存器

Modbus?TCP通過寄存器的方式存儲數據。

一共有四種類型的寄存器,分別是:離散量輸入、線圈、輸入寄存器、保持寄存器

離散量和線圈其實就是位寄存器(每個寄存器數據占1字節),工業上主要用于控制IO設備輸入和保持寄存器是字寄存器(每個寄存器數據占2個字節),工業上主要用于存儲工業設備的值

1)?離散量和線圈其實就是位寄存器(每個寄存器數據占1字節),工業上主要用于控制IO設備

線圈寄存器,類比為開關量,每一個bit都對應一個信號的開關狀態。所以一個byte就可以同時控制8路的信號。比如控制外部8路io的高低。?線圈寄存器支持讀也支持寫,寫在功能碼里面又分為寫單個線圈寄存器和寫多個線圈寄存器。

離散輸入寄存器離散輸入寄存器就相當于線圈寄存器的只讀模式,他也是每個bit表示一個開關量,而他的開關量只能讀取輸入的開關信號,是不能夠寫的。比如我讀取外部按鍵的按下還是松開。

2)?輸入和保持寄存器是字寄存器(每個寄存器數據占2個字節),工業上主要用于存儲工業設備的值

保持寄存器,這個寄存器的單位不再是bit而是兩個byte,也就是可以存放具體的數據量的,并且是可讀寫的。比如我我設置時間年月日,不但可以寫也可以讀出來現在的時間。寫也分為單個寫和多個寫

輸入寄存器,這個和保持寄存器類似,但是也是只支持讀而不能寫。一個寄存器也是占據兩個byte的空間。類比我我通過讀取輸入寄存器獲取現在的AD采集值?

3)功能碼(16進制)

寄存器PLC地址和寄存器的對應關系:

00001-09999?:線圈

10001-19999:離散量輸入

30001-39999:輸入寄存器

40001-49999:保持寄存器

點亮一個燈:05

讀溫濕度:04?03

具體協議分析:

實例分享 | ModbusTCP報文詳解

4)總結

讀數據:

主機--》從機:

報文頭--功能碼--起始地址--數量

從機--》主機:

報文頭(長度可能發生變化)--功能碼(不變)--字節計數--數據

在讀數據和寫單個的時候,字節長度都是0x06(?一個字節的單元標識符,一個字節的功能碼,兩個字節的地址,兩個字節的數據)

寫數據:

寫單個:

主機--》從機:

報文頭--功能碼--地址--數據/斷通標志(保持寄存器:數據:線圈:斷通標志)

從機--》主機:

原文返回

寫多個:

主機--》從機:

報文頭----功能碼----起始地址----數量----字節計數----數據

從機--》主機:??

原文返回

5)練習

練習一

主機詢問數據流

00?03?00?00?00?06?01 03 00?63 00?02

00?00:事務處理標識符?

00?00:協議標識符

00?06?:字節?長度

03:功能碼(保持寄存器)

0063:起始地址:6*16+3=99,40100

0002:寄存器的數量??40100-40101

00?03?00?00?00?07?01 03 04 05?83 00?76

00?00:事務處理標識符

00?00:協議標識符

00?07:字節長度

03:功能碼

04:字節計數

0583:40100寄存器的數據

0076:40101寄存器的數據

練習2

1.讀傳感器數據,讀1個寄存器數據,寫出主從數據收發協議。

00?00?00?00? 00?06 01 03 00?60 00?01

00?00?00?00? 00?05 01 03 02 00?62

  1. 寫出控制IO設備開關的協議數據,操作1個線圈,置1。

線圈單個置零:0000?置一:FF00

00?00?00?00? 00?06 01 05 00?60 FF?00

00?00?00?00? 00?06 01 05 00?60 FF?00

  • 工具安裝
    1. Modbus?Salve/Poll

1)安裝過程:軟件默認安裝

2)破解:點擊connection-》connect,輸入序列號(序列號在SN.txt)

3)使用

從機:

先設置,先打開salve端,

再連接:點擊connection-》connect

主機:

    1. 網絡調試助手

    1. Wireshark

捕獲器選擇:

windows如果連接有線網絡,選擇本地連接/以太網

?????如果連接無線網絡,選擇WLAN

如果只是在本機上的通信,選擇NPCAP?Loopback?apdater

或Adapter?for?loopback?traffic?capture

過濾條件:

過濾端口:tcp.port==502

過濾IP:ip.addr?==?192.168.3.11(windows?的ip)

  1. 練習

在虛擬機寫程序實現poll端功能,編寫客戶端實現和Slave通信。

發送:發送Modbus?TCP協議???03功能碼

發送:uint8_t?data[12]={0x00,0x00,0x00,0x00,0x00,0x06,0x01,0x03,0x00,0x00,0x00,0x02};

接收:recv

#include?<stdio.h>
#include?<stdlib.h>?//?atoi
#include?<sys/types.h>
#include?<sys/socket.h>
#include?<netinet/in.h>
#include?<netinet/ip.h>
#include?<arpa/inet.h>
#include?<unistd.h>int main(int?argc, char const *argv[])
{uint8_t?data[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x06,0x01, 0x03, 0x00, 0x00, 0x00, 0x03};uint8_t?buf[32] = {0};//1.創建套接字int?sockfd?= socket(AF_INET,?SOCK_STREAM, 0);if (sockfd?< 0){perror("socket?err");return -1;}//2.填充結構體struct sockaddr_in?caddr;
????caddr.sin_family?=?AF_INET;
????caddr.sin_port?= htons(502);
????caddr.sin_addr.s_addr?= inet_addr(argv[1]);//3.鏈接if (connect(sockfd, (struct sockaddr *)&caddr, sizeof(caddr)) < 0){perror("connect?err");return -1;}//4.發送send(sockfd,?data, sizeof(data), 0);//5.接收recv(sockfd,?buf, sizeof(buf), 0);for (int?i?= 0;?i?<?buf[8];?i++)printf("%#x?",?buf[9+i]);putchar(10);//6.關閉close(sockfd);return 0;
}

作業:

  1. 復習今天內容
  2. 完成05功能碼??,寫一個線圈
  3. 封裝函數。。

/*客戶端創建代碼?*/
#include?<stdio.h>
#include?<sys/types.h>?/*?See?NOTES?*/
#include?<sys/socket.h>
#include?<netinet/in.h>
#include?<netinet/ip.h>?/*?superset?of?previous?*/
#include?<arpa/inet.h>
#include?<unistd.h>
#include?<stdlib.h>
#include?<string.h>
int?sockfd;
uint8_t?buf[32];
void?writecoil(uint8_t?*p,?int?addr,?int?num)
{
????p[7]?=?0x05;
????p[8]?=?addr?>>?8;???//寄存器高位
????p[9]?=?addr?&?0xff;?//寄存器低位
????if?(num?==?1)
????{
????????p[10]?=?0xff;?//置1
????}
????else?if?(num?==?0)
????{
????????p[10]?=?0x00;?//置0
????}
????p[11]?=?0x00;
????for?(int?j?=?0;?j?<?12;?j++)
????{
????????printf("%#x?",?*(p+j));
????}
????send(sockfd,?p,?12,?0);
????recv(sockfd,?buf,?sizeof(buf),?0);
????for?(int?i?=?0;?i?<?12;?i++)
????{
????????printf("%#x?",?buf[i]);
????}
????putchar(10);
}
void?readregster(uint8_t?*p,?int?addr,?int?num)
{
????p[7]?=?0x03;
????p[8]?=?addr?>>?8;???//寄存器高位
????p[9]?=?addr?&?0xff;?//寄存器低位
????p[10]?=?num?>>?8;???//數量高位
????p[11]?=?num?&?0xff;?//數量低位
????for?(int?j?=?0;?j?<?12;?j++)
????{
????????printf("%#x?",?*(p?+?j));
????}
????putchar(10);
????send(sockfd,?p,?12,?0);
????recv(sockfd,?buf,?sizeof(buf),?0);????for?(int?i?=?0;?i?<?buf[8];?i++)
????{
????????printf("%#x?",?buf[9?+?i]);
????}
????putchar(10);
}
void?set_selve_id(uint8_t?*p)
{
????p[6]?=?0x01;
}
int?main(int?argc,?char?const?*argv[])
{
????if?(argc?<?3)
????{
????????printf("input?err\n");
????????return?-1;
????}
????//創建套接字
????sockfd?=?socket(AF_INET,?SOCK_STREAM,?0);
????if?(sockfd?<?0)
????{
????????perror("socket?err.");
????????return?-1;
????}
????//填充結構體
????struct?sockaddr_in?caddr;
????caddr.sin_family?=?AF_INET;
????caddr.sin_port?=?htons(atoi(argv[2]));
????caddr.sin_addr.s_addr?=?inet_addr(argv[1]);
????socklen_t?len?=?sizeof(caddr);
????//鏈接
????if?(connect(sockfd,?(struct?sockaddr?*)&caddr,?len)?<?0)
????{
????????perror("connect?err.");
????????return?-1;
????}
????//?uint8_t?data[12]?=?{0x00,?0x00,?0x00,?0x00,?0x00,?0x06,?0x01,?0x01,?0x00,?0x07,?0xFF,?0x00};
????//?uint8_t?data1[12]?=?{0x00,?0x00,?0x00,?0x00,?0x00,?0x06,?0x01,?0x01,?0x00,?0x00,?0x00,?0x03};
????uint8_t?data[12]?=?{0x00,?0x00,?0x00,?0x00,?0x00,?0x06};
????int?th?=?sizeof(data);
????int?addr?=?0x0101;
????int?num?=?0x0000;
????set_selve_id(data);
????//?readregster(data,?0,?2);
????writecoil(data,?6,?1);
????return?0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/161568.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/161568.shtml
英文地址,請注明出處:http://en.pswp.cn/news/161568.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

springboot前后端分離項目配置https接口(ssl證書)

文章目錄 說明vue.js前端部署vue.js項目axios請求配置本地創建日志文件創建Dockerfile文件配置ssl證書nginx.confvue項目打包上傳創建容器部署 后端springboot項目部署配置ssl證書打包部署 補充&#xff1a;jsk證書和pfx證書補充&#xff1a;兩種證書的轉化JKS轉PFXPFX 轉 JKS …

Elasticsearch:將最大內積引入 Lucene

作者&#xff1a;Benjamin Trent 目前&#xff0c;Lucene 限制 dot_product (點積) 只能在標準化向量上使用。 歸一化迫使所有向量幅度等于一。 雖然在許多情況下這是可以接受的&#xff0c;但它可能會導致某些數據集的相關性問題。 一個典型的例子是 Cohere 構建的嵌入&#x…

使用 Lhotse 高效管理音頻數據集

Lhotse 是一個旨在使語音和音頻數據準備更具靈活性和可訪問性的 Python 庫&#xff0c;它與 k2 一起&#xff0c;構成了下一代 Kaldi 語音處理庫的一部分。 主要目標&#xff1a; 1. 以 Python 為中心的設計吸引更廣泛的社區參與語音處理任務。 2. 為有經驗的 Kaldi 用戶提供…

SpringBoot——啟動類的原理

優質博文&#xff1a;IT-BLOG-CN SpringBoot啟動類上使用SpringBootApplication注解&#xff0c;該注解是一個組合注解&#xff0c;包含多個其它注解。和類定義SpringApplication.run要揭開SpringBoot的神秘面紗&#xff0c;我們要從這兩位開始就可以了。 SpringBootApplicati…

Spring實例化對象

默認proxyBeanMethods true&#xff0c;這種方法是用的代理模式創建對象&#xff0c;每次創建都是同一個對象&#xff0c;如果改為false每次都是不同的對象 FactoryBean的使用 定義的類A&#xff0c;造出來一個類B&#xff0c;可以在創造bean之前做一些自己的個性化操作

MFS分布式文件系統

目錄 集群部署 Master Servers ?Chunkservers ?編輯Clients Storage Classes LABEL mfs高可用 pacemaker高可用 ?編輯ISCSI 添加集群資源 主機 ip 角色 server1 192.168.81.11 Master Servers server2 192.168.81.12 Chunkservers server3 192.168.81.13 Chunkserver…

【產品安全平臺】上海道寧與Cybellum將整個產品安全工作流程整合到一個專用平臺中,保持構建的互聯產品的網絡安全和網絡合規性

Cybellum將 整個產品安全工作流程 整合到一個專用平臺中 使設備制造商能夠 保持他們構建的互聯產品的 網絡安全和網絡合規性 產品安全性對 每個人來說都不一樣 每個行業的系統、工作流程和 法規都存在根本差異 因此&#xff0c;Cybellum量身定制了 Cybellum的平臺和技…

為何內存不夠用?微服務改造啟動多個Spring Boot的陷阱與解決方案

在生產環境中我們會遇到一些問題&#xff0c;此文主要記錄并復盤一下當時項目中的實際問題及解決過程。 背景簡述 最初系統上線后都比較正常風平浪靜的。在系統運行了一段時間后&#xff0c;業務量上升后&#xff0c;生產上發現java應用內存占用過高&#xff0c;服務器總共64…

打印出一個底部有n個*的漏斗c語言

題目描述 打印出一個底部有n個*的漏斗 輸入 第一行輸入一個T;表示有T組測試數據 下面每一行都有一個n表示漏斗底部*的個數 n保證是奇數 輸出 輸出打印結果 兩個測試答案之間要用換行分割 /*printf("這是第%d行 我要打印%d個* \n",Num,i); */ *********** *…

愛創科技總裁謝朝暉榮獲“推動醫藥健康產業高質量發展人物”

中國醫藥市場規模已經成為全球第二大醫藥市場&#xff0c;僅次于美國。近年來&#xff0c;隨著中國經濟的持續增長和人民生活水平的提高&#xff0c;醫藥市場需求不斷擴大。政府對醫療衛生事業的投入也在不斷加大&#xff0c;為醫藥行業的發展創造了良好的政策環境。為推動醫藥…

SparkSession介紹

一、 介紹 SparkSession是Spark 2.0中引入的新概念&#xff0c;它是Spark SQL、DataFrame和Dataset API的入口點&#xff0c;是Spark編程的統一API&#xff0c;也可看作是讀取數據的統一入口&#xff1b;它將以前的SparkContext、SQLContext和HiveContext組合在一起&#xff0…

結構體與指針_sizeof_static_extern_函數指針數組_函數指針_回調函數

一、結構體與指針 #include <stdint.h> #include <stdlib.h> #include <stdio.h> #define up_to_down(uuu) (downdemo_t *)(uuu->beg) #define __plc__ typedef struct updemo_s{uint8_t *head;uint8_t *beg;uint8_t *end; }updemo_t; typedef struct do…

陪玩圈子系統APP小程序H5,詳細介紹,源碼交付,支持二開!

陪玩圈子系統&#xff0c;頁面展示&#xff0c;源碼交付&#xff0c;支持二開&#xff01; 陪玩后端下載地址&#xff1a;電競開黑陪玩系統小程序&#xff0c;APP&#xff0c;H5: 本系統是集齊開黑&#xff0c;陪玩&#xff0c;陪聊于一體的專業APP&#xff0c;小程序&#xff…

2:kotlin集合(Collections)

集合有助于數據分組&#xff0c;方便后續操作 集合類型說明Lists有序的可重復的集合Sets無序的不可重復的集合Maps鍵值對映射集合&#xff0c;鍵唯一&#xff0c;且一個鍵只能映射到一個值 每個集合類型都可以是可變的或者只讀的 List List按照添加的順序存儲內容&#xff…

Linux進程通信——共享內存

概念 共享內存&#xff08;Shared Memory&#xff09;&#xff0c;指兩個或多個進程共享一個給定的存儲區。 特點 共享內存是最快的一種 IPC&#xff0c;因為進程是直接對內存進行存取。 因為多個進程可以同時操作&#xff0c;所以需要進行同步。 信號量共享內存通常結合在一…

Open3D (C++) 計算兩點云之間的最小距離

目錄 一、 算法原理二、代碼實現三、結果展示本文由CSDN點云俠原創,原文鏈接。如果你不是在點云俠的博客中看到該文章,那么此處便是不要臉的爬蟲與GPT。 一、 算法原理 Open3D中ComputePointCloudDistance函數提供了計算從源點云到目標點云的距離的方法,計算點云的距離。也…

python數據結構與算法-05_棧

棧 棧這個詞實際上在計算機科學里使用很多&#xff0c;除了數據結構外&#xff0c;還有內存里的棧區 &#xff08;和堆對應&#xff09;&#xff0c;熟悉 C 系語言的話應該不會陌生。 上一章我們講到了先進先出 queue&#xff0c;其實用 python 的內置類型 collections.deque …

【C語法學習】26 - strcmp()函數

文章目錄 1 函數原型2 參數3 返回值4 比較機制5 示例5.1 示例1 1 函數原型 strcmp()&#xff1a;比較str1指向的字符串和str2指向的字符串&#xff0c;函數原型如下&#xff1a; int strcmp(const char *str1, const char *str2);2 參數 strcmp()函數有兩個參數str1和str2&a…

HCIP-四、MUX-vlanSuper-vlan+端口安全

四、MUX-vlan&Super-vlan端口安全 MUX-vlan實驗拓撲實驗需求及解法1. 在SW1/2/3分別創建vlan10 20 30 402. SW1/2/3之間使用trunk鏈路&#xff0c;僅允許vlan10 20 30 40 通過。3. SW與PC/Server之間使用access鏈路。4. ping驗證&#xff1a; Super-vlan端口安全實驗拓撲實…

【騰訊云云上實驗室-向量數據庫】騰訊云開創新時代,發布全新向量數據庫Tencent Cloud VectorDB

前言 隨著人工智能、數據挖掘等技術的飛速發展&#xff0c;海量數據的存儲和分析越來越成為重要的研究方向。在海量數據中找到具有相似性或相關性的數據對于實現精準推薦、搜索等應用至關重要。傳統關系型數據庫存在一些缺陷&#xff0c;例如存儲效率低、查詢耗時長等問題&…