ModBus協議是莫迪康公司為了讓PLC之間進行數據通信而設計出來的協議。它是一種總線協議,是一種一對多,上下級的關系。
它的應用廣泛,具有免費開源,操作簡單的有點,并且可以兼容串口和網絡通訊,兼容也不錯。
數據類型:輸入布爾(輸入線圈),輸入寄存器,輸出布爾(輸出線圈),輸出寄存器
布爾就是bool值,寄存器可以是int或者float類型
常用功能碼
1、讀取
讀取輸出線圈(Read Coils) 0x01
讀取輸入線圈 (Read DisCrete Input)0x02,(主機只讀)
讀取輸出寄存器(Read Holding Registers)0x03,
讀取輸入寄存器(Read Inpute Registers)0x04,(主機只讀)
2、寫入
寫入單個線圈(Write Single Coil)0x05
寫入單個寄存器(Write Single Register)0x06
寫入多個線圈(Write Multple Coils)0x0F
寫入多個寄存器(Write Multple Register)0x10
三種傳輸類型
1、ModbusRTU,用于串口通信,傳遞字節碼,效率更高
流程是主機向從機發出請求,從站響應請求后,主站才能接收到數據。
主機報文:從站地址+功能碼+起始地址+數據長度+校驗位(從站地址,功能碼占1個字節,起始地址、數據長度、檢驗位占2個字節)
數據長度可以看做是讀取的行數
例如:從機的設備地址是01,功能碼是讀取輸出寄存器03,起始寄存器地址是從第0開始讀取,讀取的數量是9,得出的報文就是:01 03 00 00 00 09 XX XX
從機報文:從站地址+功能碼+數據的字節位數+數據+校驗位(從站地址,功能碼,數據的字節位數占1個字節,數據、檢驗位占2個字節)
例如:從機的設備地址是01,功能碼是讀取輸出寄存器03,每次讀取4個字節,從機傳輸的值都是65,得出的報文就是:01 03 04 00 41 00 41 XX XX
2、ModBusAscii,用于串口通信,傳遞Ascii碼
3、ModBusTCP,用于網絡傳輸
4、ModBusUDP,用于網絡傳輸
5、ModBusRTUOverTCP/UDP,串口轉網口通信
6、ModBusAsciiOverTCP/UDP,串口轉網口通信
使用C#完成ModBus的RTU和TCP通訊
進行測試前需要用到Modbus Slave開啟一個ModBus服務
1、RTU通訊(串口通訊)
var modbus = new HslCommunication.ModBus.ModbusRtu();modbus.SerialPortInni(cfg => {cfg.BaudRate = 9600;cfg.PortName = "COM2";cfg.Parity = System.IO.Ports.Parity.None;cfg.DataBits = 8;cfg.StopBits = System.IO.Ports.StopBits.One;// 每次寫falsecfg.RtsEnable = false;});// 設置超時時間modbus.ReceiveTimeOut = 5000;// 設置起始地址是否從0開始,有些情況是從1開始modbus.AddressStartWithZero = true;// 設置數據大小端modbus.DataFormat = HslCommunication.Core.DataFormat.CDAB;// 設置設備地址modbus.Station = 1;modbus.Crc16CheckEnable = true;modbus.IsClearCacheBeforeRead = false;var openResult = modbus.Open();if(openResult.IsSuccess == false){MessageBox.Show("打開ModBus失敗");return;}// 讀取數據,從第0位開始,讀取5個數據var readResult = await modbus.ReadInt16Async("0", 5);if(readResult.IsSuccess == true){this.textBox1.Text = this.textBox1.Text + string.Join(",", readResult.Content) + Environment.NewLine;}// 繼續讀取另一個設備地址的Bool類型modbus.Station = 2;var readBool = await modbus.ReadBoolAsync("5");if (readResult.IsSuccess == true){this.textBox1.Text = this.textBox1.Text + readBool.Content + Environment.NewLine;}// 寫入數據modbus.Station = 1;var writeResult = await modbus.WriteAsync("0", (short)90);if (writeResult.IsSuccess == true){this.textBox1.Text = this.textBox1.Text + "寫入成功" + Environment.NewLine;}
2、TCP通訊
var modBus = new HslCommunication.ModBus.ModbusTcpNet("127.0.0.1");modBus.Port = 502;modBus.Station = 1;modBus.ConnectTimeOut = 10000;modBus.ReceiveTimeOut = 5000;modBus.AddressStartWithZero = true;modBus.IsStringReverse = false;modBus.DataFormat = HslCommunication.Core.DataFormat.CDAB;// 讀取數據var result = await modBus.ReadInt16Async("0");if (result.IsSuccess){this.textBox1.Text = this.textBox1.Text + result.Content + Environment.NewLine;}// 寫入數據var resultWrite = await modBus.WriteAsync("1", 66);if (resultWrite.IsSuccess){this.textBox1.Text = this.textBox1.Text + "寫入成功" + Environment.NewLine;}