c# com口通讯(2)- 代码及16CRC校验

using System.IO.Ports;

SerialPort comm = new SerialPort();

 

    public partial class SerialportSampleForm : Form
    {
        private SerialPort comm = new SerialPort();
        private StringBuilder builder = new StringBuilder();//避免在事件处理方法中反复的创建,定义到外面。
        private long received_count = 0;//接收计数
        private long send_count = 0;//发送计数

        private bool Listening = false;//是否没有执行完invoke相关操作  
        private bool Closing = false;//是否正在关闭串口,执行Application.DoEvents,并阻止再次invoke  


        public SerialportSampleForm()
        {
            InitializeComponent();
        }

        //窗体初始化
        private void Form1_Load(object sender, EventArgs e)
        {
            //初始化串口名称列表,波特率列表
            string[] ports = SerialPort.GetPortNames();
            Array.Sort(ports);
            comboPortName.Items.AddRange(ports);
            comboPortName.SelectedIndex = comboPortName.Items.Count > 0 ? 0 : -1;
            comboBaudrate.SelectedIndex = comboBaudrate.Items.IndexOf("9600");

            DropCRC.SelectedIndex = DropCRC.Items.IndexOf("16 CRC ,低字节在前");

            //初始化SerialPort对象
            comm.NewLine = "\r\n";//回车换行
            comm.RtsEnable = true;//根据实际情况吧。

            //添加事件注册(串口监听线程)
            comm.DataReceived += comm_DataReceived;
        }

        /// <summary>
        /// 接受数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {   
            if (Closing) return;//如果正在关闭端口,忽略操作,直接返回,尽快的完成串口监听线程的一次循环
            try  
            {  
                Listening = true;//设置标记,说明我已经开始处理数据,一会儿要使用系统UI的。  
                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 (checkBoxHexView.Checked)  
                    {  
                        //依次的拼接出16进制字符串  
                        foreach (byte b in buf)  
                        {  
                            builder.Append(b.ToString("X2") + " ");  
                        }  
                    }  
                    else  
                    {  
                        //直接按ASCII规则转换成字符串  
                        builder.Append(Encoding.ASCII.GetString(buf));
                    }
                    //追加的形式添加到文本框末端,并滚动到最后。  
                    this.txGet.AppendText(builder.ToString());
                    //修改接收计数  
                    labelGetCount.Text = "Get:" + received_count.ToString();  
                }));  
            }  
            finally  
            {
                Listening = false;//我用完了,ui可以关闭串口了。  
            }  

        }

        /// <summary>
        /// 打开串口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonOpenClose_Click(object sender, EventArgs e)
        {
            if (comm.IsOpen)
            {
                Closing = true;
                while (Listening) Application.DoEvents();//处理当前队列的window消息
                comm.Close();//关闭串口
                Closing = false; 
            }
            else
            {
                comm.PortName = comboPortName.Text;//设置通讯端口
                comm.BaudRate = int.Parse(comboBaudrate.Text);//设置串口波特率
                try
                {
                    comm.Open();//打开串口
                }
                catch(Exception ex)
                {
                    comm = new SerialPort();//捕获到异常信息,创建一个新的comm对象,之前的不能用了
                    MessageBox.Show(ex.Message);//现实异常信息给客户。
                }
            }
            //设置按钮的状态
            buttonOpenClose.Text = comm.IsOpen ? "关闭端口" : "打开端口";
            buttonSend.Enabled = comm.IsOpen;
        }

        //动态的修改获取文本框是否支持自动换行。
        private void checkBoxNewlineGet_CheckedChanged(object sender, EventArgs e)
        {
            txGet.WordWrap = checkBoxNewlineGet.Checked;
        }

        /// <summary>
        /// 发送
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonSend_Click(object sender, EventArgs e)
        {
            if (comm.IsOpen==false)
            {
                MessageBox.Show("请打开串口!");
                return;
            }
            //定义一个变量,记录发送了几个字节
            int n = 0;
            //16进制发送
            if (checkBoxHexSend.Checked)
            {
                //我们不管规则了。如果写错了一些,我们允许的,只用正则得到有效的十六进制数
                MatchCollection mc = Regex.Matches(txSend.Text, @"(?i)[\da-f]{2}");
                List<byte> buf = new List<byte>();//填充到这个临时列表中
                //依次添加到列表中
                foreach (Match m in mc)
                {
                    //buf.Add(byte.Parse(m.Value));
                    buf.Add(byte.Parse(m.Value, System.Glob
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tiz198183

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值