由于每次重新打开串口,比较麻烦,我们给串口赋予记忆功能。
1.窗体设计
2.串口扫描
//扫描串口事件
private void SearchAndSerialComboBox(SerialPort MyPort, ComboBox MyBox)
{
//定义一个内存缓存变量
string Buffer;
//清空ComboBox下拉控件内容
MyBox.Items.Clear();
//遍历20个串口
for (int i = 1; i < 20; i++)
{
//如果运行成功,就将相应的串口信息添加至ComboBox。
try
{
//将读取的串口信息存在内存中
Buffer = "COM" + i.ToString();
//将内存中的串口信息给相应的控件
MyPort.PortName = Buffer;
//打开串口如果运行失败,后面的代码就不执行了,直接跳转至catch。
MyPort.Open();
//将获取的串口添加到ComboBox
MyBox.Items.Add(Buffer);
//关闭串口
MyPort.Close();
}
catch
{
}
}
}
3.AD数据显示
//将进度条控件存放在一个数组中,并返回一个对象数组。
ProgressBar[] GetProgressBar()
{
return new ProgressBar[]
{progressBar1,progressBar2,progressBar3,progressBar4,progressBar5,
progressBar6,progressBar7,progressBar8,progressBar9,progressBar10
};
}
//串口事件
private void PortDataReceivedEvent(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
//获取进度条数组
ProgressBar[] MyProgressBar = GetProgressBar();
//读取串口的数据,存入自己定义的缓冲区data中。
byte[] Data = new byte[serialPort1.BytesToRead];
//读串口的缓冲区数据
serialPort1.Read(Data, 0, Data.Length);
//遍历数组
foreach (byte Mydata in Data)
{
for (int i = 0; i < 10; i++)//MyProgressBar.Length其实就是10
{
//给数组赋值获取的方式,给进度条赋值,获取波形。
MyProgressBar[10 - i].Value = MyProgressBar[10 - i - 1].Value;
}
//将串口数据的值默认给progressBar1控件
progressBar1.Value = (int)Mydata;
//将缓冲区的数据转化为16进制。
string str = Mydata.ToString("x");
//标准化格式输出数据的值。
textBox1.Text = "0x" + (str.Length == 1 ? "0" + str : str);
}
}
//打开串口按钮事件
private void button1_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen)
{
//================串口关闭====================
//让第二个groupBox2组件不显示
groupBox2.Visible = false;
//设置窗体大小--缩小
this.Size = new Size(815, 147);
//串口关闭一般不会有异常,因此不需要try catch
serialPort1.Close();
//获取进度条数组
ProgressBar[] MyProgressBar = GetProgressBar();
//遍历进度条
foreach (ProgressBar MyBar in MyProgressBar)
{
//关闭串口后,让进度条值归零
MyBar.Value = 0;
}
button1.Text = "打开串口";
}
else
{
//===============串口打开=====================
try
{
//获取串口号
serialPort1.PortName = comboBox1.Text;
//打开串口
serialPort1.Open();
//让第二个groupBox2组件不显示
groupBox2.Visible = true;
//设置窗体大小--放大
this.Size = new Size(815, 549);
button1.Text = "关闭串口";
}
catch (Exception)
{
MessageBox.Show("串口打开错误", "错误提示");
throw;
}
}
}
上述代码在之前的博客中有详细介绍,今天主要介绍上位机如何对串口号具备记忆功能。
4.串口记忆功能
4.1 全局变量设置
//系统dll导入ini写函数
[DllImport("kernel32")]
private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
//读取系统导入ini读函数
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retval,int size,string filePath);
//存储读出的ini内容变量
StringBuilder temp = new StringBuilder(255);
//创建并生成ini文件名--System.AppDomain.CurrentDomain.BaseDirectory用来得到exe文件的路径
string FileName = System.AppDomain.CurrentDomain.BaseDirectory + "data.ini";
string CurrentPortName = "COM1";
4.2 窗体事件
public Form1()
{
InitializeComponent();
//为了防止进程之间出错,用到串口必须把检查线程置于关闭
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
//扫描串口信息,为了之后方便使用,此处进行封装一个串口扫描的函数
SearchAndSerialComboBox(serialPort1, comboBox1);
//添加窗体关闭事件--手动创建。注册一个窗口关闭的一个处理函数,在关闭窗口的时候记忆串口号
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(Form1_FormClosing);
}
该函数创建了一个窗口关闭的一个处理函数,在关闭窗口的时候记忆串口号
4.3 窗体关闭事件
//窗体关闭事件
private void Form1_FormClosing(object sender, EventArgs e)
{
//串口关闭,保存
WritePrivateProfileString("PortData", "PortName", CurrentPortName, FileName);
}
4.4 双击窗体函数事件
//窗体函数
private void Form1_Load(object sender, EventArgs e)
{
//窗体缩小
this.Size = new Size(700,146);
//groupBox2不显示
groupBox2.Visible = false;
//读取ini值,如果没有串口,则默认为com1
GetPrivateProfileString("PortData", "PortName", "COM1", temp, 256, FileName);//读取ini值,默认是COM1
//初始化
comboBox1.Text = temp.ToString();
}
1.在data.ini文件中保存的内容如下:
[PortData]
PorName=COM3
2.WritePrivateProfileString函数四个参数表示:
第一个:串口总类。比如PortData
第二个:自定义的串口名字。比如PortName
第三个:要保存的串口号。
第四个:data.ini文件的绝对路径。
3.GetPrivateProfileString读函数参数说明如下:
第一个:在PortData串口总类下面读。
第二个:在PortData串口总类下面读名为PortName的值。
第三个:如果PortName变量中的值没有或读失败,就把COM1作为默认值。
第四个:把从PortName变量中读出的值保存在temp变量中。
第五个:读的字节数最大为256。
第六个:在FileName变量保存的路径下读ini文件。
4.5 运行结果