C#串口通信助手

来源:互联网 发布:淘宝开店卖景点门票 编辑:程序博客网 时间:2024/05/17 02:03

  简介:

  使用C#,开发平台VS2010,功能是串口通讯。功能很简单,仅供大家学习,效果如图:


1.使用控件

控件类型命名用途说明ComboBoxcbSerival串口ComboBoxcbBuadRate波特率ComboBoxcbDataBits数据位ComboBoxcbStop停止位ComboBoxcbParity校验位ButtonbtnOpen打开ButtonbtnClear清除ButtonbtnSend发送RadioButtonrbRecHEX接收格式:HEXRadioButtonrbRecASCII接收格式:ASCIIRadioButtonrbSendHEX发送格式:HEXRadioButtonrbSendASCII发送格式:ACSIICheckBoxcbRTSRTSCheckBoxcbDTRDTRCheckBoxcbNewLine换行TextBoxtbRec接收编辑框ReadOnly:True,Multiline:TrueTextBoxtbSend发送编辑框SerialPortserialPort1表示串行端口资源StatusStripstatusStrip1状态栏LayoutStyle:TableToolStripStatusLabeltsslDateTime时间BorderSiders:RightToolStripStatusLabeltoolStripStatusLabel1让R和S在状态栏的右边紧跟tsslDateTime后边,Spring:TrueToolStripStatusLabeltoolStripStatusLabel2发送字节统计 S:BorderSiders:LeftToolStripStatusLabeltsslSendCount发送总字节数BorderSiders:RightToolStripStatusLabeltoolStripStatusLabel3接收字节统计 R:ToolStripStatusLabeltsslRecCount接收总字节数

2.操作一波

(1)控件添加

  要做到本界面的效果需要把上面控件全添加进去,StatusStrip下面的控件,是在StatusStrip中添加的,小白请勿发懵。


(2)初始化

  说明:串口和控件初始化。

        private void Form1_Load(object sender, EventArgs e)        {            //串口            string[] str = SerialPort.GetPortNames();            foreach (string port in str)            {                cbSerial.Items.Add(port);            }            cbSerial.SelectedIndex = 0;            //波特率            cbBuadRate.Items.Add("300");            cbBuadRate.Items.Add("1200");             cbBuadRate.Items.Add("2400");            cbBuadRate.Items.Add("4800");            cbBuadRate.Items.Add("9600");            cbBuadRate.Items.Add("19200");            cbBuadRate.Items.Add("38400");            cbBuadRate.Items.Add("43000");            cbBuadRate.Items.Add("56000");            cbBuadRate.Items.Add("115200");            cbBuadRate.SelectedIndex = 4;            //数据位            cbDataBits.Items.Add("5");            cbDataBits.Items.Add("6");            cbDataBits.Items.Add("7");            cbDataBits.Items.Add("8");            cbDataBits.SelectedIndex = 3;            //停止位            cbStop.Items.Add("0");            cbStop.Items.Add("1");            cbStop.Items.Add("1.5");            cbStop.Items.Add("2");            cbStop.SelectedIndex = 1;            //校验位            cbParity.Items.Add("无");            cbParity.Items.Add("奇校验");            cbParity.Items.Add("偶校验");            cbParity.SelectedIndex = 0;            btnSend.Enabled = false;            rbRecASCII.Checked = true;            rbSendASCII.Checked = true;            //状态控件            tsslDateTime.Text = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");            tsslRecCount.Text = "0";            tsslSendCount.Text = "0";                    }

(3)“打开”按钮

  

 private void btnOpen_Click(object sender, EventArgs e)        {            if(cbSerial.Items.Count <= 0)            {                MessageBox.Show("当前无可用串口!");                return;            }            if (serialPort1.IsOpen == false)            {                serialPort1.PortName = cbSerial.SelectedItem.ToString();                serialPort1.BaudRate = Convert.ToInt32(cbBuadRate.SelectedItem.ToString());                serialPort1.DataBits = Convert.ToInt32(cbDataBits.SelectedItem.ToString());                serialPort1.StopBits = (StopBits)Convert.ToInt32(cbStop.SelectedItem.ToString());                serialPort1.Parity = (Parity)Convert.ToInt32(cbParity.SelectedIndex);                try                {                    serialPort1.Open();                    btnSend.Enabled = true;                }                catch (Exception ex)                {                    MessageBox.Show(ex.Message, "打开COM错误", MessageBoxButtons.OK, MessageBoxIcon.Error);                    return;                }                btnOpen.Text = "关闭";                        }            else            {                try                {                    serialPort1.Close();                    btnSend.Enabled = false;                }                catch (Exception ex)                {                    MessageBox.Show(ex.Message, "关闭COM错误", MessageBoxButtons.OK, MessageBoxIcon.Error);                    return;                }                btnOpen.Text = "打开";                            }            cbSerial.Enabled = !serialPort1.IsOpen;            cbBuadRate.Enabled = !serialPort1.IsOpen;            cbDataBits.Enabled = !serialPort1.IsOpen;            cbStop.Enabled = !serialPort1.IsOpen;            cbParity.Enabled = !serialPort1.IsOpen;        }

(4)“清除”按钮

        private void btnClear_Click(object sender, EventArgs e)        {            tbRec.Clear();            tbSend.Clear();        }

(5)“发送”按钮

        private void btnSend_Click(object sender, EventArgs e)        {            byte[] sendData = null;            string strData = null;            if (cbNewLine.Checked)            {                strData = tbSend.Text.Trim() + "\r\n";            }            else            {                strData = tbSend.Text.Trim();            }            if (rbSendHEX.Checked)            {                sendData = strToHexByte(strData);            }            else if (rbSendASCII.Checked)            {                sendData = Encoding.ASCII.GetBytes(strData);            }            if (this.Send(sendData))            {                statusStrip1.Invoke(new MethodInvoker(delegate                {                     if (tsslSendCount.Text == "0")                     {                         tsslSendCount.Text = tbSend.Text.Length.ToString();                     }                     else                     {                         try                         {                             tsslSendCount.Text = (int.Parse(tsslSendCount.Text) + tbSend.Text.Length).ToString();                         }                         catch (Exception ex)                         {                             MessageBox.Show(ex.Message, "发送字节计数错误", MessageBoxButtons.OK, MessageBoxIcon.Error);                         }                                              }                }));            }                    }

(6)格式切换

  说明:rbSendHEX和rbSendASCII添加CheckedChanged事件,接收格式同理。

private void rbSendHEX_CheckedChanged(object sender, EventArgs e)        {            byte[] data = null;                  data = System.Text.Encoding.Default.GetBytes(tbSend.Text.Trim());            if (rbSendHEX.Checked)            {                StringBuilder sb = new StringBuilder();                for (int i = 0; i < data.Length; i++)                {                    sb.AppendFormat("{0:x2}" + " ", data[i]);                }                tbSend.Text = sb.ToString().ToUpper();            }        }        private void rbSendASCII_CheckedChanged(object sender, EventArgs e)        {            if (rbSendASCII.Checked)            {                byte[] data = null;                                if (tbSend.Text == "")                {                    return;                }                data = HexStringToByte(tbSend.Text.Trim());                tbSend.Text = new ASCIIEncoding().GetString(data);            }        }

3.数据类型转换

(1) 16进制转字节数组

        public static byte[] HexStringToByte(string hexstring)        {            string[] tmpary = hexstring.Trim().Split(' ');            byte[] buff = new byte[tmpary.Length];            for (int i = 0; i < buff.Length; i++)            {                buff[i] = Convert.ToByte(tmpary[i], 16);            }            return buff;        }

(2)字符串转换16进制字节数组

            private byte[] strToHexByte(string hexString)        {            hexString = hexString.Replace(" ", "");            if ((hexString.Length % 2) != 0)                hexString += " ";            byte[] returnBytes = new byte[hexString.Length / 2];            try            {                for (int i = 0; i < returnBytes.Length; i++)                    returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2).Replace(" ", ""), 16);            }            catch (Exception ex)            {                MessageBox.Show(ex.Message, "转换成HEX错误", MessageBoxButtons.OK, MessageBoxIcon.Error);            }            return returnBytes;        }


4.串口

(1)串口发送

        public bool Send(byte[] data)        {            if (serialPort1.IsOpen)            {                try                 {                    serialPort1.Write(data, 0, data.Length);                    return true;                }                catch(Exception ex)                {                    MessageBox.Show(ex.Message, "发送数据错误", MessageBoxButtons.OK, MessageBoxIcon.Error);                }            }            else            {                MessageBox.Show("未打开串口", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);            }            return false;        }

(2)串口接收

       说明:添加serialPort1的DataReceived事件

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)        {            byte[] ReDatas = new byte[serialPort1.BytesToRead];            serialPort1.Read(ReDatas, 0, ReDatas.Length);            this.AddData(ReDatas);        }        public void AddData(byte[] data)        {            if (rbRecHEX.Checked)            {                StringBuilder sb = new StringBuilder();                for (int i = 0; i < data.Length; i ++ )                {                    sb.AppendFormat("{0:x2}" + " ", data[i]);                }                AddContent(sb.ToString().ToUpper());            }            else if (rbRecASCII.Checked)            {                AddContent(new ASCIIEncoding().GetString(data));            }            statusStrip1.Invoke(new MethodInvoker(delegate             {                if (tsslRecCount.Text == "0")                {                    tsslRecCount.Text = tbRec.Text.Length.ToString();                }                else                {                    try                    {                        tsslRecCount.Text = (int.Parse(tsslRecCount.Text) + data.Length).ToString();                    }                    catch (Exception ex)                    {                        MessageBox.Show(ex.Message, "接收字节计数错误", MessageBoxButtons.OK, MessageBoxIcon.Error);                    }                }            }));        }        private void AddContent(string content)        {            this.BeginInvoke(new MethodInvoker(delegate                {                    tbRec.AppendText(content);                }));        }

5.疑难点

  说明:在WinForm中使用多线程时,当在子线程中修改一个控件的值或者进行其它操作时,会出错。不过此工程未使用子线程,可直接对控件控制,效果是等价的。

                     if (tsslRecCount.Text == "0")             {                  tsslRecCount.Text = tbRec.Text.Length.ToString();             }             else             {                      tsslRecCount.Text = (int.Parse(tsslRecCount.Text) + data.Length).ToString();                }          

            statusStrip1.Invoke(new MethodInvoker(delegate            {                if (tsslRecCount.Text == "0")                {                    tsslRecCount.Text = tbRec.Text.Length.ToString();                }                else                {                    try                    {                        tsslRecCount.Text = (int.Parse(tsslRecCount.Text) + data.Length).ToString();                    }                    catch (Exception ex)                    {                        MessageBox.Show(ex.Message, "接收字节计数错误", MessageBoxButtons.OK, MessageBoxIcon.Error);                    }                }            }));

注意:BeginInvoke与Invoke一个是同步执行,一个是异步执行。简单的可以理解为,当使用Invoke时,当前线程(非UI线程)会阻塞然后UI线程执行Invoke里传入的方法,之后再继续执行当前线程。而使用BeginInvoke时,当前线程不会阻塞,而是继续执行,当当前线程执行完毕后,UI线程才会执行BeginInvoke传入的方法。

原创粉丝点击