前言
最近在用c#写上位机软件,将自己入门的过程记录下来。入门嘛,实操很重要,先弄一个例子来尝尝鲜。
环境
IDE: VS 2019
环境: .NET Core 3.1
依赖: System.IO.Ports、thinger.DataConvertLib
测试工具: Modbus Slave
引入依赖
在.NET Core 3.1中SerialPort不是自带的库了,需要自行引入;thinger.DataConvertLib是一个数据转换库,在码云上开源;推荐使用Nuget安装。
结构
SerialPortDemo-01
└── MarinForm.cs
└── Program.cs
界面
控件初始化
private void MainForm_Load(object sender, EventArgs e)
{
// 获取当前可识别的串口
string[] port = System.IO.Ports.SerialPort.GetPortNames();
// 初始化界面
comboBoxPortName.Items.AddRange(port);
// 如果有数据显示第0个
comboBoxPortName.SelectedIndex = comboBoxPortName.Items.Count > 0 ? 0 : -1;
comboBoxBaudRate.Items.Add(1200);
comboBoxBaudRate.Items.Add(4800);
comboBoxBaudRate.Items.Add(9600);
comboBoxBaudRate.Items.Add(14400);
comboBoxBaudRate.Items.Add(19200);
comboBoxBaudRate.Items.Add(38400);
comboBoxBaudRate.SelectedItem = 9600;
}
发送读取命令
private void buttonRead_Click(object sender, EventArgs e)
{
try {
// 0x01 -- 从机地址; 0x03 -- 功能码; 0x00 -- 高位起始地址
// 0x00 -- 低位起始地址; 0x00 -- 高位读取寄存器个数
// 0x09 -- 低位读取寄存器个数
// 0x85 0xCC -- 校验位
byte[] request = new byte[] { 0x01, 0x03, 0x00, 0x00, 0x00, 0x9, 0x85, 0xCC };
//byte[] request = new byte[] { 0x01, 0x03, 0x00, 0x00, 0x00, 0x64, 0x44, 0x21 }
textBoxLog.AppendText("发送请求:" +
StringLib.GetHexStringFromByteArray(request) + "\r\n");
serialPort.Write(request, 0, request.Length);
} catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
打开串口
private void buttonOpen_Click(object sender, EventArgs e)
{
try
{
if(!open)
{
// 订阅串口接收事件
serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPortDataReceived);
serialPort.PortName = comboBoxPortName.Text;
serialPort.BaudRate = int.Parse(comboBoxBaudRate.Text);
serialPort.DataBits = 8;
serialPort.StopBits = StopBits.One;
serialPort.Parity = Parity.None;
serialPort.Open();
buttonOpen.Text = "关闭串口";
open = true;
}
else
{
serialPort.Close();
buttonOpen.Text = "打开串口";
open = false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
接收事件
private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
serialPort = (SerialPort)sender;
byte[] bytebuffer = new byte[serialPort.BytesToRead];
serialPort.Read(bytebuffer, 0, bytebuffer.Length);
// 接收事件与界面并不是同一个线程;所以需要用Invoke()方法同步更新界面
Invoke(new Action(() => textBoxLog
.AppendText("收到响应:" + StringLib.GetHexStringFromByteArray(bytebuffer) + "\r\n")));
}
catch (Exception)
{
throw;
}
}
测试
启动Modbus Slave
使用Modbus Slave连接到虚拟串口中,并开启100个寄存器作为测试使用。