提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、准备工作
- 二、认识工具箱
- 三、认识属性
- 四、程序编写
前言
既然是做上位机那么必然会有下位机,当前上位机和下位机的通信主要是通过串口,网络,CAN几种方式进行通信,先进行最简单的串口通信,本章主要建立一个串口上位机的模板,之后的使用串口通信的上位机都通过这个模板来编写。
一、准备工作
.NET API浏览器 在.NET API浏览器输入System.IO.Ports.SerialPort第一个就是主要用到的串口类,通过微软提供的API编写串口通信程序。
打开上一章新建的工程,在代码中包含System.IO.Ports,并新建一个串口对象。
如果报错则右键项目选择管理NuGet程序包,选择浏览在搜索中输入System.IO.Ports,然后安装。
二、认识工具箱
切换到窗口界面中,在vs上方的视窗选项中打开工具箱,工具箱中是一些已经定义好的控件供我们使用,我们可以在工具箱中选中一个控件拖拽到窗口中,现在从工具箱中拖拽一个ComboBox(下拉选择)和Button(按钮)控件到窗口中。
三、认识属性
在窗口界面中,在vs上方的视窗选项中打开属性窗口,选中窗口中的控件,可以看到属性窗口中出现了一些选项设置,选择刚刚拖拽到窗口中的Button控件,将Text选项修改为打开串口,并且可以看到在我们选择对应的选项时下方也出现了对应的解释。
选择属性窗口中的闪电符号(事件),这里是一些在对控件做出一些行为是程序执行对应的操作,可以看到在选中时下方出现了对应的描述,双击Click进入代码界面会发现多出了一个函数button1_Click,这个函数就是在点击这个Button后要执行的一些操作。
现在切换回窗口界面选中添加的ComboBox控件,在属性-事件中双击DropDown,启用下拉事件。
四、程序编写
程序想要实现的功能:在接收到串口发送来的数据时判断是否接受到了换行,如果接收到换行就将之前接收的数据发送回去。
串口配置:波特率:115200,数据位:8,停止位:1,校验位:无校验
在窗口加载事件中添加串口配置
private void Form1_Load(object sender, EventArgs e)
{
port.DataBits = 8;//设置数据位数为8位
port.StopBits = StopBits.One;//设置停止位为1
port.Parity = Parity.None;//设置为无校验
port.BaudRate = 115200;//波特率设置为115200
string[] ports = SerialPort.GetPortNames();//获取已连接的串口
for(int i = 0; i < ports.Length; i++)
{
comboBox1.Items.Add(ports[i]);//添加进下拉框中
}
if(ports.Length > 0)
comboBox1.SelectedIndex = 0;//选中第一个
port.DataReceived += Port_DataReceived;//绑定接收事件
port.ErrorReceived += Port_ErrorReceived;//绑定错误事件
}
在comboBox1控件的事件中添加如下代码,功能为在下拉时重新加载连接的串口
private void comboBox1_DropDown(object sender, EventArgs e)
{
string[] ports = SerialPort.GetPortNames();//获取已连接的串口
comboBox1.Items.Clear();//清除下拉框中的数据
for (int i = 0; i < ports.Length; i++)
{
comboBox1.Items.Add(ports[i]);//添加进下拉框中
}
if (ports.Length > 0)
comboBox1.SelectedIndex = 0;//选中第一个
}
在按钮的点击事件中添加以下代码,功能为打开和关闭串口
private void button1_Click(object sender, EventArgs e)
{
if(button1.Text == "打开串口")
{
try
{
port.PortName = comboBox1.Text;//设置端口号
port.Open();//打开串口
button1.Text = "关闭串口";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);//弹出框显示出现的错误
}
}
else
{
if(port.IsOpen)//判断串口是否打开
{
port.Close();//关闭串口
}
button1.Text = "打开串口";
}
}
在串口接收事件中添加如下代码,功能为在接收的是数据时判断是否为换行,如果是就将之前累积的数据发送出去,如果事件类型不是数据就关闭串口。
有一点需要注意根据微软文档中描述不保证接收的每一个字节都触发接收事件。
/// <summary>
/// 串口接收事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if(e.EventType == SerialData.Eof)//关闭串口
{
port.Close();
this.Invoke(new Action(() =>//不能从其他线程修改本线程UI
{
button1.Text = "关闭串口";
}));
}
else//接收到字符
{
while(port.BytesToRead > 0)//根据API中描述不一定接收到一个字符就触发接收事件
{
data[index] = (byte)port.ReadByte();
if (data[index] == (byte)'\n')
{
port.Write(data, 0, index + 1);//接收到换行,通过串口将数据发送出去
index = 0;
}
else
{
index++;
}
}
}
}