• 串口通信


    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.IO.Ports;
    using System.Text.RegularExpressions;
    using System.Threading;
    
    namespace Serial_T
    {
        public partial class Form1 : Form
        {
            private SerialPort comm = new SerialPort();
            private StringBuilder builder = new StringBuilder();//避免在事件处理方法中反复的创建,定义到外面。  
            private long received_count = 0;//接收计数  
            private long send_count = 0;//发送计数
            private System.Timers.Timer timer = new System.Timers.Timer();
    
            public Form1()
            {
                InitializeComponent();
                Init();
                //添加事件注册  
                comm.DataReceived += comm_DataReceived; 
            }
    
            /// <summary>
            /// 打开/关闭当前串口
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void buttonOpenClose_Click(object sender, EventArgs e)
            {
                //根据当前串口对象,来判断操作  
                if (comm.IsOpen)
                {
                    //打开时点击,则关闭串口  
                    comm.Close();
                }
                else
                {
                    OpenPort();
                }
                //设置按钮的状态  
                BthStatus();
            }
    
            /// <summary>
            /// 初始化系统
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnInit_Click(object sender, EventArgs e)
            {
                Init();
            }
    
            /// <summary>
            /// 应用端口配置
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnSetPort_Click(object sender, EventArgs e)
            {
                SetPort();
            }
    
            /// <summary>
            /// 发送消息
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void buttonSend_Click(object sender, EventArgs e)
            {
                string sendData = txSend.Text;
    
                // 循环发送
                if (cirSend.Checked)
                {
                    int _interval = 0;
                    if (int.TryParse(txInterval.Text.Trim(), out _interval))
                    {
                        buttonSend.Invoke(new MethodInvoker(delegate
                        {
                            if (buttonSend.Text.Trim() == "发送")
                            {
                                buttonSend.Text = "停止";
                            }
                            else
                            {
                                buttonSend.Text = "发送";
                            }
                        }));
    
                        timer.Enabled = true;
                        timer.Interval = _interval;
                        timer.AutoReset = true;
                        timer.Elapsed += new System.Timers.ElapsedEventHandler((s, erg) => comm_DataSend(s, erg, sendData));
                        timer.Start();
                    }
                    else
                    {
                        MessageBox.Show("请填入正确间隔时间!");
                    }
                }
                else
                {
                    comm_DataSend(sendData);
                }
            }
    
            /// <summary>
            /// 清空
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void clearData_Click(object sender, EventArgs e)
            {
                //复位接受和发送的字节数计数器并更新界面。   
                send_count = received_count = 0;
                NumReceive.Text = "接收量:0";
                NumSend.Text = "发送量:0";
                txReceive.Text = "";
                txSend.Text = "";
            }
    
            /// <summary>
            /// 接收文本换行状态改变
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void checkBoxNewlineGet_CheckedChanged(object sender, EventArgs e)
            {
                txReceive.WordWrap = checkBoxNewlineGet.Checked;
            }
    
            /// <summary>
            /// 十六进制发送状态改变
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void checkBoxHexSend_CheckedChanged(object sender, EventArgs e)
            {
                if (checkBoxHexSend.Checked)
                {
                    checkBoxNewlineSend.Checked = false;
                    checkBoxNewlineSend.Enabled = false;
                }
                else
                {
                    checkBoxNewlineSend.Enabled = true;
                }
            }
    
            /// <summary>
            /// 初始化系统
            /// </summary>
            private void Init()
            {
                //关闭当前串口   
                if (comm.IsOpen)
                {
                    comm.Close();
                }
    
                //初始化下拉串口名称列表框  
                string[] ports = SerialPort.GetPortNames();
                Array.Sort(ports);
                comboPortName.Items.Clear();
                comboPortName.Items.AddRange(ports);
                comboPortName.SelectedIndex = comboPortName.Items.Count > 0 ? 0 : -1;
                comboBaudrate.SelectedIndex = comboBaudrate.Items.IndexOf("9600");
                dataBits.SelectedIndex = dataBits.Items.IndexOf("8");
                StopBits.SelectedIndex = StopBits.Items.IndexOf("1");
                ParityBits.SelectedIndex = ParityBits.Items.IndexOf("None");
    
                //初始化SerialPort对象  
                comm.NewLine = "/r/n";
                comm.RtsEnable = true;//根据实际情况吧。  
    
                //复位接受和发送的字节数计数器并更新界面。
                checkBoxNewlineGet.Checked = false;
                hexReceive.Checked = false;
                cirSend.Checked = false;
                checkBoxHexSend.Checked = false;
                checkBoxNewlineSend.Checked = false;
                txReceive.Text = "";
                txSend.Text = "";
                send_count = received_count = 0;
                NumReceive.Text = "接收量:0";
                NumSend.Text = "发送量:0";
                BthStatus();
            }
    
            /// <summary>
            /// 串口数据接收事件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                int n = comm.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致  
                byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据  
                received_count += n;//增加接收计数  
                comm.Read(buf, 0, n);//读取缓冲数据  
                builder.Clear();//清除字符串构造器的内容
                //因为要访问ui资源,所以需要使用invoke方式同步ui。
                this.Invoke((EventHandler)(delegate
                {
                    //判断是否是显示为16禁止  
                    if (hexReceive.Checked)
                    {
                        //依次的拼接出16进制字符串
                        foreach (byte b in buf)
                        {
                            builder.Append(b.ToString("X2") + " ");
                        }
                    }
                    else
                    {
                        //直接按ASCII规则转换成字符串  
                        builder.Append(Encoding.ASCII.GetString(buf));
                    }
                    //追加的形式添加到文本框末端,并滚动到最后。  
                    this.txReceive.AppendText(builder.ToString());
                    //修改接收计数  
                    NumReceive.Text = "接收量:" + received_count.ToString();
                }));
            }
    
            /// <summary>
            /// 串口发送数据
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            void comm_DataSend(string str)
            {
                str =localName.Text.Trim() +  str;
                //定义一个变量,记录发送了几个字节  
                int n = 0;
                //16进制发送  
                if (checkBoxHexSend.Checked)
                {
                    //我们不管规则了。如果写错了一些,我们允许的,只用正则得到有效的十六进制数  
                    MatchCollection mc = Regex.Matches(str, @"[0-9a-fA-F]{2}");
                    List<byte> buf = new List<byte>();//填充到这个临时列表中  
                    //依次添加到列表中  
                    foreach (Match m in mc)
                    {
                        buf.Add(Convert.ToByte(m.ToString(), 16));
                    }
                    //转换列表为数组后发送  
                    comm.Write(buf.ToArray(), 0, buf.Count);
                    //记录发送的字节数
                    n = buf.Count;
                }
                else//ascii编码直接发送  
                {
                    //包含换行符  
                    if (checkBoxNewlineSend.Checked)
                    {
                        comm.WriteLine(str);
                        n = txSend.Text.Length + 2;
                    }
                    else//不包含换行符  
                    {
                        comm.Write(str);
                        n = txSend.Text.Length;
                    }
                }
                send_count += n;//累加发送字节数  
                NumSend.Text = "发送量:" + send_count.ToString();//更新界面
            }
    
            /// <summary>
            /// 串口发送数据(定时)
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            void comm_DataSend(object sender, System.Timers.ElapsedEventArgs e, string str)
            {
                if (cirSend.Checked && comm.IsOpen && (buttonSend.Text == "停止"))
                {
                    //定义一个变量,记录发送了几个字节  
                    int n = 0;
                    //16进制发送  
                    if (checkBoxHexSend.Checked)
                    {
                        //我们不管规则了。如果写错了一些,我们允许的,只用正则得到有效的十六进制数  
                        MatchCollection mc = Regex.Matches(str, @"[0-9a-fA-F]{2}");
                        List<byte> buf = new List<byte>();//填充到这个临时列表中  
                        //依次添加到列表中  
                        foreach (Match m in mc)
                        {
                            buf.Add(Convert.ToByte(m.ToString(), 16));
                        }
                        //转换列表为数组后发送  
                        comm.Write(buf.ToArray(), 0, buf.Count);
                        //记录发送的字节数
                        n = buf.Count;
                    }
                    else//ascii编码直接发送  
                    {
                        //包含换行符  
                        if (checkBoxNewlineSend.Checked)
                        {
                            comm.WriteLine(str);
                            n = txSend.Text.Length + 2;
                        }
                        else//不包含换行符  
                        {
                            comm.Write(str);
                            n = txSend.Text.Length;
                        }
                    }
                    send_count += n;//累加发送字节数  
                    NumSend.Invoke(new MethodInvoker(delegate { NumSend.Text = "发送量:" + send_count.ToString(); }));
                    //NumSend.Text = "发送量:" + send_count.ToString();//更新界面
                }
                else
                {
                    timer.Stop();
                }
                
            }
    
            /// <summary>
            /// 同步按钮状态
            /// </summary>
            private void BthStatus()
            {
                //设置按钮的状态  
                buttonOpenClose.Text = comm.IsOpen ? "关闭串口" : "启动串口";
                buttonSend.Enabled = comm.IsOpen;  
            }
    
            /// <summary>
            /// 打开串口
            /// </summary>
            /// <returns>返回BOOL型,True为成功,False为失败</returns>
            public void OpenPort()
            {
                if (!comm.IsOpen)
                {
                    SetPort();
                    try
                    {
                        comm.Open();
                    }
                    catch (Exception ex)
                    {
                        //捕获到异常信息,创建一个新的comm对象,之前的不能用了。  
                        comm = new SerialPort();
                        //添加事件注册  
                        comm.DataReceived += comm_DataReceived; 
                        //现实异常信息给客户。  
                        MessageBox.Show(ex.Message);
                    }
                }
            }
    
            /// <summary>
            /// 应用串口配置
            /// </summary>
            /// <returns>返回BOOL型,True为成功,False为失败</returns>
            public void SetPort()
            {
                if (string.IsNullOrEmpty(comboPortName.Text.Trim()))
                {
                    MessageBox.Show("串口号不能为空!");
                }
                else
                {
                    //关闭当前串口   
                    if (comm.IsOpen)
                    {
                        comm.Close();
                    }
                    comm.PortName = comboPortName.Text;
                    comm.BaudRate = int.Parse(comboBaudrate.Text);
                    comm.DataBits = int.Parse(dataBits.Text);
                    //comm.Parity = Parity.None;
                    //comm.StopBits = new StopBits();
                    BthStatus();
                }
            }
    
            private void cirSend_CheckedChanged(object sender, EventArgs e)
            {
                if (!cirSend.Checked && buttonSend.Text.Trim() == "停止")
                {
                    buttonSend.Text = "发送";
                }
            }
        }
    }
  • 相关阅读:
    HTML里使用CSS 的几种方式?
    Dmoz介绍及怎么提交?
    delphi实现自动填写表单和调用网页上的函数
    SEO之Head标签
    location.replace()和location.href=的区别?
    css几种选择器举例
    如何让百度认为你的站是一个好网站?
    桌面被恶意软件放上几个ie图标删除不了怎么办?
    Delphi正则表达式使用方法(TPerlRegEx)
    mysql中limit的用法详解(数据分页常用)
  • 原文地址:https://www.cnblogs.com/ariter/p/5856865.html
Copyright © 2020-2023  润新知