1.VS2022环境安装
1.1 官网下载VS2022
进入登录界面(无账号需要注册一个):https://my.visualstudio.com/Benefits?mkt=zh-cn
选择下载界面
根据电脑配置选择不同的软件版本
1.2 下载完成后安装VS2022,项目基于C#语言的winfrom开发,必须安装如下两个组件
可自定义安装路径等(安装路径磁盘大小必须满足安装需求)
2.新建工程项目
安装完成后启动软件,选择创建新的项目
配置项目
创建完成后进入图形化界面,底框大小可调
从工具箱中可选择需要的组件拉入底框中,同时可配置组件的属性
可根据需求添加单个/多个串口,将串口组件拖入底框在底部就会出现串口组件
双击组件可生成组件的实现接口,如button1组件,注意:生成的接口函数不能删除,不然图形化界面就会报错
3.整体实现
3.1 图形界面
3.2 组件介绍
串口1和串口2配置使用groupBox组件
端口号、波特率、停止位、数据位、校验位、校准方式都是使用label组件,之后跟着的复选框都是使用comboBox组件
打开串口和开启校准都是使用button组件
数据接收区使用textBox组件,需要打开Multiline属性调为true,打开多行接收
3.3 接口实现
代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.InteropServices;
using System.IO;
namespace CalibrationShow
{
public partial class Form1 : Form
{
bool readFlag = false;
[DllImport("user32.dll")]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, Keys vk);
[DllImport("user32.dll")]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
const int WM_DEVICECHANGE = 0x219;
const int DBT_DEVICEARRIVAL = 0x8000;
const int DBT_DEVICEREMOVECOMPLETE = 0x8004;
// 事件触发接口
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_DEVICECHANGE)
{
string[] ports = System.IO.Ports.SerialPort.GetPortNames(); //获取电脑上可用串口号
switch (m.WParam.ToInt32())
{
case DBT_DEVICEARRIVAL:
// USB设备插入
//MessageBox.Show("有新设备接入!");
comboBox1.Items.Clear();
comboBox10.Items.Clear();
Thread.Sleep(2); // 延时
comboBox1.Items.AddRange(ports); // 添加端口必须分开写
Thread.Sleep(2); // 延时
comboBox10.Items.AddRange(ports);
Thread.Sleep(2); // 延时
comboBox1.SelectedIndex = comboBox1.Items.Count > 0 ? 0 : -1;
comboBox10.SelectedIndex = comboBox10.Items.Count > 0 ? 0 : -1;
break;
case DBT_DEVICEREMOVECOMPLETE:
// USB设备移除
//MessageBox.Show("有设备移除!");
comboBox1.Items.Clear();
comboBox10.Items.Clear();
Thread.Sleep(2);
comboBox1.Items.AddRange(ports);
Thread.Sleep(2);
comboBox10.Items.AddRange(ports);
Thread.Sleep(2); // 延时
comboBox1.SelectedIndex = comboBox1.Items.Count > 0 ? 0 : -1;
comboBox10.SelectedIndex = comboBox10.Items.Count > 0 ? 0 : -1;
break;
}
}
}
// 此接口暂时不用
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
// 注销WM_DEVICECHANGE消息
UnregisterHotKey(this.Handle, 1001);
}
public Form1()
{
InitializeComponent();
// 注册WM_DEVICECHANGE消息,包括窗口句柄、消息ID、修饰键(0表示无修饰键)、按键
RegisterHotKey(this.Handle, 1001, 0, Keys.None);
}
private void Form1_Load(object sender, EventArgs e)
{
string[] ports = System.IO.Ports.SerialPort.GetPortNames(); //获取电脑上可用串口号
comboBox1.Items.AddRange(ports);
comboBox10.Items.AddRange(ports);
comboBox1.SelectedIndex = comboBox1.Items.Count > 0 ? 0 : -1;
comboBox10.SelectedIndex = comboBox1.Items.Count > 0 ? 0 : -1;
// 波特率
comboBox2.Text = "115200";
comboBox9.Text = "115200";
//停止位
comboBox3.Text = "1";
comboBox8.Text = "1";
//数据位
comboBox4.Text = "8";
comboBox7.Text = "8";
//校验位
comboBox5.Text = "无";
comboBox6.Text = "无";
label14.Visible = false;
comboBox12.Visible = false;
}
private void button1_Click(object sender, EventArgs e)
{
if (button1.Text == "打开串口")
{
try
{
//通信端口设置
serialPort1.PortName = comboBox1.Text;
serialPort2.PortName = comboBox10.Text;
//设置波特率
serialPort1.BaudRate = int.Parse(comboBox2.Text);
serialPort2.BaudRate = int.Parse(comboBox9.Text);
//设置停止位
if (comboBox3.Text == "1")
{
serialPort1.StopBits = System.IO.Ports.StopBits.One;
}
else if(comboBox3.Text == "1.5")
{
serialPort1.StopBits = System.IO.Ports.StopBits.OnePointFive;
}
else if (comboBox3.Text == "2")
{
serialPort1.StopBits = System.IO.Ports.StopBits.Two;
}
if (comboBox8.Text == "1")
{
serialPort2.StopBits = System.IO.Ports.StopBits.One;
}
else if (comboBox8.Text == "1.5")
{
serialPort2.StopBits = System.IO.Ports.StopBits.OnePointFive;
}
else if (comboBox8.Text == "2")
{
serialPort2.StopBits = System.IO.Ports.StopBits.Two;
}
//设置数据位
serialPort1.DataBits = int.Parse(comboBox4.Text);
serialPort2.DataBits = int.Parse(comboBox7.Text);
//设置奇偶校验位
if (comboBox5.Text == "无")
{
serialPort1.Parity = System.IO.Ports.Parity.None;
}
else if (comboBox5.Text == "奇校验")
{
serialPort1.Parity = System.IO.Ports.Parity.Odd;
}
else if (comboBox5.Text == "偶校验")
{
serialPort1.Parity = System.IO.Ports.Parity.Even;
}
if (comboBox6.Text == "无")
{
serialPort2.Parity = System.IO.Ports.Parity.None;
}
else if (comboBox6.Text == "奇校验")
{
serialPort2.Parity = System.IO.Ports.Parity.Odd;
}
else if (comboBox6.Text == "偶校验")
{
serialPort2.Parity = System.IO.Ports.Parity.Even;
}
//打开串口
serialPort1.Open();
serialPort2.Open();
button1.Text = "关闭串口";
comboBox1.Enabled = false;
comboBox2.Enabled = false;
comboBox3.Enabled = false;
comboBox4.Enabled = false;
comboBox5.Enabled = false;
comboBox6.Enabled = false;
comboBox7.Enabled = false;
comboBox8.Enabled = false;
comboBox9.Enabled = false;
comboBox10.Enabled = false;
}
catch (Exception err)
{
MessageBox.Show("打开失败"+ err.ToString(),"提示!");
}
}
else
{
try
{
if (button2.Text == "关闭校准")
{
byte[] buff = new byte[8];
buff[0] = 0xFA;
buff[1] = 0x08;
buff[2] = 0x00;
buff[3] = 0x01;
buff[4] = 0x39;
buff[5] = 0x04;
buff[6] = 0x00;
buff[7] = 0x46;
serialPort2.Write(buff, 0, buff.Length);
button2.Text = "开启校准";
comboBox11.Enabled = true;
comboBox12.Enabled = true;
}
serialPort1.Close();
serialPort2.Close();
button1.Text = "打开串口";
comboBox1.Enabled = true;
comboBox2.Enabled = true;
comboBox3.Enabled = true;
comboBox4.Enabled = true;
comboBox5.Enabled = true;
comboBox6.Enabled = true;
comboBox7.Enabled = true;
comboBox8.Enabled = true;
comboBox9.Enabled = true;
comboBox10.Enabled = true;
}
catch (Exception err)
{
MessageBox.Show("关闭失败" + err.ToString(), "提示!");
}
}
}
private void button2_Click(object sender, EventArgs e)
{
if (serialPort2.IsOpen)
{
if (comboBox11.Text == "全流程校准")
{
if (button2.Text == "开启校准")
{
if (textBox1.Text == "")
{
byte[] buff = new byte[8];
buff[0] = 0xFA;
buff[1] = 0x08;
buff[2] = 0x00;
buff[3] = 0x01;
buff[4] = 0x39;
buff[5] = 0x03;
buff[6] = 0x01;
buff[7] = 0x46;
serialPort2.Write(buff, 0, buff.Length);
button2.Text = "关闭校准";
comboBox11.Enabled = false;
}
else
{
MessageBox.Show("请先清除数据!");
}
}
else
{
byte[] buff = new byte[8];
buff[0] = 0xFA;
buff[1] = 0x08;
buff[2] = 0x00;
buff[3] = 0x01;
buff[4] = 0x39;
buff[5] = 0x03;
buff[6] = 0x00;
buff[7] = 0x45;
serialPort2.Write(buff, 0, buff.Length);
button2.Text = "开启校准";
comboBox11.Enabled = true;
}
}
else if (comboBox11.Text == "单阻抗校准")
{
if (button2.Text == "开启校准")
{
if (textBox1.Text == "")
{
byte[] buff = new byte[8];
buff[0] = 0xFA;
buff[1] = 0x08;
buff[2] = 0x00;
buff[3] = 0x01;
buff[4] = 0x39;
buff[5] = 0x01;
buff[6] = 0x01;
buff[7] = 0x44;
serialPort2.Write(buff, 0, buff.Length);
button2.Text = "关闭校准";
comboBox11.Enabled = false;
}
else
{
MessageBox.Show("请先清除数据!");
}
}
else
{
byte[] buff = new byte[8];
buff[0] = 0xFA;
buff[1] = 0x08;
buff[2] = 0x00;
buff[3] = 0x01;
buff[4] = 0x39;
buff[5] = 0x01;
buff[6] = 0x00;
buff[7] = 0x43;
serialPort2.Write(buff, 0, buff.Length);
button2.Text = "开启校准";
comboBox11.Enabled = true;
}
}
else if (comboBox11.Text == "单功率校准")
{
if (button2.Text == "开启校准")
{
if (textBox1.Text == "")
{
byte[] buff = new byte[8];
buff[0] = 0xFA;
buff[1] = 0x08;
buff[2] = 0x00;
buff[3] = 0x01;
buff[4] = 0x39;
buff[5] = 0x02;
buff[6] = 0x01;
buff[7] = 0x45;
serialPort2.Write(buff, 0, buff.Length);
button2.Text = "关闭校准";
comboBox11.Enabled = false;
}
else
{
MessageBox.Show("请先清除数据!");
}
}
else
{
byte[] buff = new byte[8];
buff[0] = 0xFA;
buff[1] = 0x08;
buff[2] = 0x00;
buff[3] = 0x01;
buff[4] = 0x39;
buff[5] = 0x02;
buff[6] = 0x00;
buff[7] = 0x44;
serialPort2.Write(buff, 0, buff.Length);
button2.Text = "开启校准";
comboBox11.Enabled = true;
}
}
else if (comboBox11.Text == "自定义校准")
{
if (button2.Text == "开启校准")
{
if (textBox1.Text == "")
{
byte[] buff = new byte[8];
UInt16 value = Convert.ToUInt16(comboBox12.Text);
buff[0] = 0xFA;
buff[1] = 0x08;
buff[2] = 0x00;
buff[3] = (byte)(value & 0xFF);
buff[4] = (byte)((value >> 8) & 0xFF);
buff[5] = 0x04;
buff[6] = 0x01;
buff[7] = 0x47;
serialPort2.Write(buff, 0, buff.Length);
button2.Text = "关闭校准";
comboBox11.Enabled = false;
comboBox12.Enabled = false;
}
else
{
MessageBox.Show("请先清除数据!");
}
}
else
{
byte[] buff = new byte[8];
buff[0] = 0xFA;
buff[1] = 0x08;
buff[2] = 0x00;
buff[3] = 0x01;
buff[4] = 0x39;
buff[5] = 0x04;
buff[6] = 0x00;
buff[7] = 0x46;
serialPort2.Write(buff, 0, buff.Length);
button2.Text = "开启校准";
comboBox11.Enabled = true;
comboBox12.Enabled = true;
}
}
else if (comboBox11.Text == "手动功率校准")
{
if (button2.Text == "开启校准")
{
byte[] buff = new byte[8];
buff[0] = 0xFA;
buff[1] = 0x08;
buff[2] = 0x00;
buff[3] = 0x01;
buff[4] = 0x39;
buff[5] = 0x05;
buff[6] = 0x01;
buff[7] = 0x48;
serialPort2.Write(buff, 0, buff.Length);
button2.Text = "关闭校准";
comboBox11.Enabled = false;
}
else
{
byte[] buff = new byte[8];
buff[0] = 0xFA;
buff[1] = 0x08;
buff[2] = 0x00;
buff[3] = 0x01;
buff[4] = 0x39;
buff[5] = 0x05;
buff[6] = 0x00;
buff[7] = 0x47;
serialPort2.Write(buff, 0, buff.Length);
button2.Text = "开启校准";
comboBox11.Enabled = true;
}
}
else
{
MessageBox.Show("请选择校准模式!");
}
}
else
{
MessageBox.Show("请先打开串口!");
}
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
int len = serialPort1.BytesToRead;//获取可以读取的字节数
byte[] buff = new byte[len];//创建缓存数据数组
byte[] buff1 = new byte[len+1];//创建缓存数据数组
serialPort1.Read(buff, 0, len);//把数据读取到buff数组
string str = Encoding.Default.GetString(buff);//Byte值根据ASCII码表转为 String
if (len > 2)
{
Invoke((new Action(() => //C# 3.0以后代替委托的新方法
{
textBox1.AppendText(str);//对话框追加显示数据
})));
buff1[0] = 0xFB;
// 从buff的第0个元素(索引为0)开始复制len个元素,从buff1的第二个元素开始保存这复制的len个元素
Array.Copy(buff, 0, buff1, 1, len);
if(readFlag)
{
serialPort2.Write(buff1, 0, buff1.Length);
readFlag = false;
}
}
}
private void serialPort2_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
int len = serialPort2.BytesToRead;//获取可以读取的字节数
byte[] buff = new byte[len];//创建缓存数据数组
serialPort2.Read(buff, 0, len);//把数据读取到buff数组
string str = Encoding.Default.GetString(buff);//Byte值根据ASCII码表转为 String
Invoke((new Action(() => //C# 3.0以后代替委托的新方法
{
textBox2.AppendText(str);//对话框追加显示数据
})));
if (str == "Calibra")
{
MessageBox.Show("阻抗校准完成!");
button2.Invoke(new Action(() =>
{
button2.Text = "开启校准";
}));
comboBox11.Invoke(new Action(() =>
{
comboBox11.Enabled = true;
}));
}
else if (str == "Power")
{
MessageBox.Show("功率校准完成!");
button2.Invoke(new Action(() =>
{
button2.Text = "开启校准";
}));
comboBox11.Invoke(new Action(() =>
{
comboBox11.Enabled = true;
}));
if (comboBox11.Text == "自定义校准")
{
comboBox12.Invoke(new Action(() =>
{
comboBox12.Enabled = true;
}));
}
}
else if (str == "ALL")
{
MessageBox.Show("全流程校准完成!");
button2.Invoke(new Action(() =>
{
button2.Text = "开启校准";
}));
comboBox11.Invoke(new Action(() =>
{
comboBox11.Enabled = true;
}));
if (comboBox11.Text == "自定义校准")
{
comboBox12.Invoke(new Action(() =>
{
comboBox12.Enabled = true;
}));
}
}
else if (str == "error")
{
MessageBox.Show("ready按键被关闭!");
button2.Invoke(new Action(() =>
{
button2.Text = "开启校准";
}));
comboBox11.Invoke(new Action(() =>
{
comboBox11.Enabled = true;
}));
if(comboBox11.Text == "自定义校准")
{
comboBox12.Invoke(new Action(() =>
{
comboBox12.Enabled = true;
}));
}
}
else if (str == "power data error!\r\n")
{
}
else if (str == "curr data error!\r\n")
{
}
else
{
if (str.Length > 5)
{
serialPort1.Write(str);
if(str == "READ:ALL?\r\n")
{
readFlag = true;
}
}
}
}
private void comboBox11_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox11.Text == "自定义校准")
{
label14.Visible = true;
comboBox12.Visible = true;
}
else
{
label14.Visible = false;
comboBox12.Visible = false;
}
}
private void button3_Click(object sender, EventArgs e)
{
if (textBox3.Text == "")
{
MessageBox.Show("请先输入设备编号");
}
else
{
if(textBox1.Text == "")
{
MessageBox.Show("无数据需要保存!");
}
else
{
if (button2.Text == "开启校准")
{
string text = textBox1.Text;
string text1 = textBox3.Text + ".txt"; //追加文件后缀名
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string filePath = Path.Combine(desktopPath, text1);
File.WriteAllText(filePath, text); //将数据保存到本地桌面
}
else
{
MessageBox.Show("请关闭校准后再保存数据!");
}
}
}
}
private void button4_Click(object sender, EventArgs e)
{
if (button2.Text == "开启校准")
{
textBox1.Text = "";
textBox2.Text = "";
}
else
{
MessageBox.Show("请关闭校准后再清除数据!");
}
}
}
}