C#开发串口助手


没有学过C#,但不妨碍开发上位机,有C语言基础即可,过程较为简单~

常用控件

1.文本标签控件(Label)
显示文本,在代码中通过更改Text属性实现

2.下拉组合框控件(ComboBox)
存在一个下拉列表来存放可选的内容,在前台的属性中设置为DropDownList模式。
添加下拉选项的模式:
(1)在属性的Items中手动添加
(2)在代码中使用API进行添加

comboBox2.Items.Add( i.ToString() );

3.按钮控件(Button)
点击时触发一个事件,在代码中有一对应的事件响应函数。

4.文本框控件(TextBox)
用于显示发送数据或者接受数据,使用时需要将属性ScrollBars设置为Vertical,并设置Multiline为true(点击控件时右上方会出现图标,点击即可设置)

5.串口控件(SerialPort)
隐式控件,一般通过代码进行配置,使用系统的接口可以用来获取当前电脑的端口

//获取电脑当前可用的串口号并设置默认值
comboBox1.Items.AddRange( System.IO.Ports.SerialPort.GetPortNames() );
if ( comboBox1.Items.Count != 0 ) 
	comboBox1.SelectedIndex = 0;

6.单选按钮控件(RadioButton)
用在多选一的情况下,例如选择接受数据通过ASCII或者HEX模式显示,这里注意要和容器控件(Panel)一起使用,几个选项中选一个就需要把这几个选项放到一个容器中去。

7.容器控件(Panel)
作用即上述,注意其不可见

整体前台效果如下:
在这里插入图片描述

后台逻辑控制

概述: GUI界面的开发几乎都是事件驱动型机制
事件源:控件
事件:对控件的一些操作
事件处理:当事件发生时,在后台对事件的处理

  • 初始化工作
    1.添加各下拉列表的下拉选项
    2.获取电脑当前可用的串口号并设置默认值
    3.手动添加串口接收中断函数
private void Form1_Load(object sender, EventArgs e)
{
    //添加波特率下拉表
    for (int i = 300; i <= 38400; i = i * 2) {
        comboBox2.Items.Add(i.ToString());
    }
    string[] baud = { "43000", "56000", "57600", "115200", "128000", "230400", "256000", "460800" };
    comboBox2.Items.AddRange( baud );

    //添加数据位下拉表
    string[] databit = { "8", "7", "9" };
    comboBox3.Items.AddRange( databit );

    //添加校验位下拉表
    string[] judgebit = { "None", "odd", "Even", "Mard", "Space" };
    comboBox4.Items.AddRange( judgebit );

    //添加停止位下拉表
    string[] stopbit = { "1", "1.5", "2" };
    comboBox5.Items.AddRange( stopbit );

    //获取电脑当前可用的串口号并设置默认值
    comboBox1.Items.AddRange( System.IO.Ports.SerialPort.GetPortNames() );
    if ( comboBox1.Items.Count != 0 ) 
        comboBox1.SelectedIndex = 0;

    //设置默认值
    comboBox2.Text = "115200";
    comboBox3.Text = "8";
    comboBox4.Text = "None";
    comboBox5.Text = "1";

    //手动添加串口接收中断函数
    serialPort1.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
}
  • 打开(关闭)串口控件事件
    1.条件判断当前串口状态
    2.如果串口当前是开启状态则对串口进行关闭,使能各个更改串口状态的comboBox控件,失能发送数据的button控件
    3.如果串口当前是关闭状态则对串口进行开启(根据各comboBox的属性),失能各个更改串口状态的comboBox控件,使能发送数据的button控件
    注:try…catch…的使用可以避免死机
 private void button1_Click(object sender, EventArgs e)
 {
     try 
     {
         //判断串口是否处于打开状态
         if (serialPort1.IsOpen)
         {
             serialPort1.Close();
             //表示串口此时处于关闭状态
             button1.Text = "打开串口";
             label6.Text = "串口已关闭";
             label6.ForeColor = Color.Red;

             //使能comboBox
             comboBox1.Enabled = true;
             comboBox2.Enabled = true;
             comboBox3.Enabled = true;
             comboBox4.Enabled = true;
             comboBox5.Enabled = true;

             //失能发送控件
             button2.Enabled = false;
         }
         else
         {
             //此时串口处于打开状态
             //失能comboBox
             comboBox1.Enabled = false;
             comboBox2.Enabled = false;
             comboBox3.Enabled = false;
             comboBox4.Enabled = false;
             comboBox5.Enabled = false;

             //配置串口的相关属性
             serialPort1.PortName = comboBox1.Text;
             serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
             serialPort1.DataBits = Convert.ToInt16(comboBox3.Text);

             if (comboBox4.Text.Equals("None"))
                 serialPort1.Parity = System.IO.Ports.Parity.None;
             else if (comboBox4.Text.Equals("Odd"))
                 serialPort1.Parity = System.IO.Ports.Parity.Odd;
             else if (comboBox4.Text.Equals("Even"))
                 serialPort1.Parity = System.IO.Ports.Parity.Even;
             else if (comboBox4.Text.Equals("Mark"))
                 serialPort1.Parity = System.IO.Ports.Parity.Mark;
             else if (comboBox4.Text.Equals("Space"))
                 serialPort1.Parity = System.IO.Ports.Parity.Space;

             if (comboBox5.Text.Equals("1"))
                 serialPort1.StopBits = System.IO.Ports.StopBits.One;
             else if (comboBox5.Text.Equals("1.5"))
                 serialPort1.StopBits = System.IO.Ports.StopBits.OnePointFive;
             else if (comboBox5.Text.Equals("2"))
                 serialPort1.StopBits = System.IO.Ports.StopBits.Two;
             
             //打开串口
             serialPort1.Open();

             //表示此时串口处于打开状态
             button1.Text = "关闭串口";
             label6.Text = "串口已打开";
             label6.ForeColor = Color.Red;
             //使能发送控件
             button2.Enabled = true;
         }
     }
     catch
     {
         MessageBox.Show("端口错误,请检查串口", "错误");
     }
 }
  • 发送数据
    1.字符(ASCII)模式发送
    直接利用函数接口发送文本框控件中的内容(因为是字符串形式),注意Write和Writeline的区别,后者多发送一个0x0A
    2.16进制(HEX)模式发送
    (1)首先取出文本框控件中的内容(字符串形式,每两个字符后有一个空格,用于划分两个16进制数)
    (2)利用正则表达式对空格进行匹配然后替换为空字符
    (3)每两个字符表示一个8bit的16进制数,将这两个字符转化为一个byte型变量,然后用一个byte型的数组存储(为了方便时用Write发送)
    (4)使用Write发送刚刚得到的byte型的数组
private void button2_Click(object sender, EventArgs e)
{
    byte[] temp = new byte[1];
    try
    {
        if (radioButton4.Checked)
        {
            //串口处于开启状态,将发送区文本发送
            //ASCII发送模式
            serialPort1.Write(textBox2.Text);
    
        }
        else
        {
            //HEX发送模式
            //用正则表达式去除空格
            string buf = textBox2.Text;
            string pattern = @"\s";
            string replacement = "";
            Regex rgx = new Regex(pattern);
            string str_send = rgx.Replace(buf, replacement);

            //发送数据
            int num = (str_send.Length - str_send.Length % 2) / 2;
            for (int i = 0; i < num; i ++)
            {
                temp[0] = Convert.ToByte(str_send.Substring(i*2, 2),16);    //将两个发送字符转换为16进制的数
                serialPort1.Write(temp, 0, 1);
            }
            //若还存在最后一位,截取1位并发送
            if (str_send.Length%2 != 0)
            {
                temp[0] = Convert.ToByte(str_send.Substring(str_send.Length - 1, 1), 16);
                serialPort1.Write(temp, 0, 1);
            }
        }
        
    }
    catch
    {
        MessageBox.Show("串口数据写入错误", "错误");
    }
}
  • 接收数据
    1.字符(ASCII)模式接收
    利用ReadExiting读取接收缓存区中的所有字节,然后采用委托的方式显示到文本框控件上(因为和main不是一个线程)
    2.16进制(HEX)模式接收
    (1)利用Read将接收到的字符存入一个byte型的数组中
    (2)数组中每一个byte型的变量(8bit)转换为对应的用2个字符表示一个16进制的数的形式(2×8bit)
    (3)将转换得到的2个字符送到文本框控件上去显示
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    if (radioButton1.Checked)
    {
        //接收到的用ASCII模式显示
        string str = serialPort1.ReadExisting();
        //采用委托的方式
        this.Invoke(new EventHandler(delegate
        {
            textBox1.AppendText(str);
        }));
    }
    else
    {
        //将接收到的字符存入数组中
        int num = serialPort1.BytesToRead;  //接收到的字节数
        byte[] receive_buf = new byte[num];
        serialPort1.Read(receive_buf, 0, num);

        sb.Clear();
        //接收到的用HEX模式显示
        foreach (byte b in receive_buf)
        {
            sb.Append("0X"+b.ToString("X2")+" ");
        }
        this.Invoke(new EventHandler(delegate
        {
            textBox1.AppendText(sb.ToString());
        }));
    }
}

源码附上:
https://github.com/zyxstronger/SerialAssistant

Reference:
https://blog.csdn.net/mculover666/category_9375094.html
杜洋工作室视频:入门C#设计

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值