- 1 using System;
- 2 using System.Collections.Generic;
- 3 using System.ComponentModel;
- 4 using System.Data;
- 5 using System.Drawing;
- 6 using System.Linq;
- 7 using System.Text;
- 8 using System.Threading.Tasks;
- 9 using System.Windows.Forms;
- 10 using Modbus.Device;
- 11 using System.Net.Sockets;
- 12 using System.Threading;
- 13 using System.IO.Ports;
- 14
- 15 namespace ModbusRtu
- 16 {
- 17 public partial class Form1 : Form
- 18 {
- 19 private static IModbusMaster master;
- 20 private static SerialPort port;
- 21 //写线圈或写寄存器数组
- 22 private bool[] coilsBuffer;
- 23 private ushort[] registerBuffer;
- 24 //功能码
- 25 private string functionCode;
- 26 //参数(分别为站号,起始地址,长度)
- 27 private byte slaveAddress;
- 28 private ushort startAddress;
- 29 private ushort numberOfPoints;
- 30 //串口参数
- 31 private string portName;
- 32 private int baudRate;
- 33 private Parity parity;
- 34 private int dataBits;
- 35 private StopBits stopBits;
- 36
- 37 public Form1()
- 38 {
- 39 InitializeComponent();
- 40 }
- 41 private void Form1_Load(object sender, EventArgs e)
- 42 {
- 43 cmb_portname.SelectedIndex = 0;
- 44 cmb_baud.SelectedIndex = 5;
- 45 cmb_parity.SelectedIndex = 2;
- 46 cmb_databBits.SelectedIndex = 1;
- 47 cmb_stopBits.SelectedIndex = 0;
- 48 }
- 49 private SerialPort InitSerialPortParameter()
- 50 {
- 51 if (cmb_portname.SelectedIndex < 0 || cmb_baud.SelectedIndex < 0 || cmb_parity.SelectedIndex < 0 || cmb_databBits.SelectedIndex < 0 || cmb_stopBits.SelectedIndex < 0)
- 52 {
- 53 MessageBox.Show("请选择串口参数");
- 54 return null;
- 55 }
- 56 else
- 57 {
- 58
- 59 portName = cmb_portname.SelectedItem.ToString();
- 60 baudRate = int.Parse(cmb_baud.SelectedItem.ToString());
- 61 switch (cmb_parity.SelectedItem.ToString())
- 62 {
- 63 case "奇":
- 64 parity = Parity.Odd;
- 65 break;
- 66 case "偶":
- 67 parity = Parity.Even;
- 68 break;
- 69 case "无":
- 70 parity = Parity.None;
- 71 break;
- 72 default:
- 73 break;
- 74 }
- 75 dataBits = int.Parse(cmb_databBits.SelectedItem.ToString());
- 76 switch (cmb_stopBits.SelectedItem.ToString())
- 77 {
- 78 case "1":
- 79 stopBits = StopBits.One;
- 80 break;
- 81 case "2":
- 82 stopBits = StopBits.Two;
- 83 break;
- 84 default:
- 85 break;
- 86 }
- 87 port = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
- 88 return port;
- 89 }
- 90 }
- 91 /// <summary>
- 92 /// 读/写
- 93 /// </summary>
- 94 /// <param name="sender"></param>
- 95 /// <param name="e"></param>
- 96 private void button1_Click(object sender, EventArgs e)
- 97 {
- 98 try
- 99 {
- 100 //初始化串口参数
- 101 InitSerialPortParameter();
- 102
- 103 master = ModbusSerialMaster.CreateRtu(port);
- 104
- 105 ExecuteFunction();
- 106 }
- 107 catch (Exception)
- 108 {
- 109 MessageBox.Show("初始化异常");
- 110 }
- 111 }
- 112
- 113 private async void ExecuteFunction()
- 114 {
- 115 try
- 116 {
- 117 //每次操作是要开启串口 操作完成后需要关闭串口
- 118 //目的是为了slave更换连接是不报错
- 119 if (port.IsOpen == false)
- 120 {
- 121 port.Open();
- 122 }
- 123 if (functionCode != null)
- 124 {
- 125 switch (functionCode)
- 126 {
- 127 case "01 Read Coils"://读取单个线圈
- 128 SetReadParameters();
- 129 coilsBuffer = master.ReadCoils(slaveAddress, startAddress, numberOfPoints);
- 130
- 131 for (int i = 0; i < coilsBuffer.Length; i++)
- 132 {
- 133 SetMsg(coilsBuffer[i] + " ");
- 134 }
- 135 SetMsg("\r\n");
- 136 break;
- 137 case "02 Read DisCrete Inputs"://读取输入线圈/离散量线圈
- 138 SetReadParameters();
- 139
- 140 coilsBuffer = master.ReadInputs(slaveAddress, startAddress, numberOfPoints);
- 141 for (int i = 0; i < coilsBuffer.Length; i++)
- 142 {
- 143 SetMsg(coilsBuffer[i] + " ");
- 144 }
- 145 SetMsg("\r\n");
- 146 break;
- 147 case "03 Read Holding Registers"://读取保持寄存器
- 148 SetReadParameters();
- 149 registerBuffer = master.ReadHoldingRegisters(slaveAddress, startAddress, numberOfPoints);
- 150 for (int i = 0; i < registerBuffer.Length; i++)
- 151 {
- 152 SetMsg(registerBuffer[i] + " ");
- 153 }
- 154 SetMsg("\r\n");
- 155 break;
- 156 case "04 Read Input Registers"://读取输入寄存器
- 157 SetReadParameters();
- 158 registerBuffer = master.ReadInputRegisters(slaveAddress, startAddress, numberOfPoints);
- 159 for (int i = 0; i < registerBuffer.Length; i++)
- 160 {
- 161 SetMsg(registerBuffer[i] + " ");
- 162 }
- 163 SetMsg("\r\n");
- 164 break;
- 165 case "05 Write Single Coil"://写单个线圈
- 166 SetWriteParametes();
- 167 await master.WriteSingleCoilAsync(slaveAddress, startAddress, coilsBuffer[0]);
- 168 break;
- 169 case "06 Write Single Registers"://写单个输入线圈/离散量线圈
- 170 SetWriteParametes();
- 171 await master.WriteSingleRegisterAsync(slaveAddress, startAddress, registerBuffer[0]);
- 172 break;
- 173 case "0F Write Multiple Coils"://写一组线圈
- 174 SetWriteParametes();
- 175 await master.WriteMultipleCoilsAsync(slaveAddress, startAddress, coilsBuffer);
- 176 break;
- 177 case "10 Write Multiple Registers"://写一组保持寄存器
- 178 SetWriteParametes();
- 179 await master.WriteMultipleRegistersAsync(slaveAddress, startAddress, registerBuffer);
- 180 break;
- 181 default:
- 182 break;
- 183 }
- 184
- 185 }
- 186 else
- 187 {
- 188 MessageBox.Show("请选择功能码!");
- 189 }
- 190 port.Close();
- 191 }
- 192 catch (Exception ex)
- 193 {
- 194
- 195 MessageBox.Show(ex.Message);
- 196 }
- 197 }
- 198 private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
- 199 {
- 200 if (comboBox1.SelectedIndex >= 4)
- 201 {
- 202 groupBox2.Enabled = true;
- 203 groupBox1.Enabled = false;
- 204 }
- 205 else
- 206 {
- 207 groupBox1.Enabled = true;
- 208 groupBox2.Enabled = false;
- 209 }
- 210 comboBox1.Invoke(new Action(() => { functionCode = comboBox1.SelectedItem.ToString(); }));
- 211 }
- 212
- 213 /// <summary>
- 214 /// 初始化读参数
- 215 /// </summary>
- 216 private void SetReadParameters()
- 217 {
- 218 if (txt_startAddr1.Text == "" || txt_slave1.Text == "" || txt_length.Text == "")
- 219 {
- 220 MessageBox.Show("请填写读参数!");
- 221 }
- 222 else
- 223 {
- 224 slaveAddress = byte.Parse(txt_slave1.Text);
- 225 startAddress = ushort.Parse(txt_startAddr1.Text);
- 226 numberOfPoints = ushort.Parse(txt_length.Text);
- 227 }
- 228 }
- 229 /// <summary>
- 230 /// 初始化写参数
- 231 /// </summary>
- 232 private void SetWriteParametes()
- 233 {
- 234 if (txt_startAddr2.Text == "" || txt_slave2.Text == "" || txt_data.Text == "")
- 235 {
- 236 MessageBox.Show("请填写写参数!");
- 237 }
- 238 else
- 239 {
- 240 slaveAddress = byte.Parse(txt_slave2.Text);
- 241 startAddress = ushort.Parse(txt_startAddr2.Text);
- 242 //判断是否写线圈
- 243 if (comboBox1.SelectedIndex == 4 || comboBox1.SelectedIndex == 6)
- 244 {
- 245 string[] strarr = txt_data.Text.Split(' ');
- 246 coilsBuffer = new bool[strarr.Length];
- 247 //转化为bool数组
- 248 for (int i = 0; i < strarr.Length; i++)
- 249 {
- 250 // strarr[i] == "0" ? coilsBuffer[i] = true : coilsBuffer[i] = false;
- 251 if (strarr[i] == "0")
- 252 {
- 253 coilsBuffer[i] = false;
- 254 }
- 255 else
- 256 {
- 257 coilsBuffer[i] = true;
- 258 }
- 259 }
- 260 }
- 261 else
- 262 {
- 263 //转化ushort数组
- 264 string[] strarr = txt_data.Text.Split(' ');
- 265 registerBuffer = new ushort[strarr.Length];
- 266 for (int i = 0; i < strarr.Length; i++)
- 267 {
- 268 registerBuffer[i] = ushort.Parse(strarr[i]);
- 269 }
- 270 }
- 271 }
- 272 }
- 273
- 274 /// <summary>
- 275 /// 清除文本
- 276 /// </summary>
- 277 /// <param name="sender"></param>
- 278 /// <param name="e"></param>
- 279 private void button2_Click(object sender, EventArgs e)
- 280 {
- 281 richTextBox1.Clear();
- 282 }
- 283 /// <summary>
- 284 /// SetMessage
- 285 /// </summary>
- 286 /// <param name="msg"></param>
- 287 public void SetMsg(string msg)
- 288 {
- 289 richTextBox1.Invoke(new Action(() => { richTextBox1.AppendText(msg); }));
- 290 }
- 291
- 292 }
- 293 }