C# 使用SerialPort控件用类及线程实现串口通信

来源:互联网 发布:网络信息推广的文字 编辑:程序博客网 时间:2024/05/29 16:53

  1. using System;    
  2.  using System.Collections.Generic;    
  3.  using System.ComponentModel;    
  4.  using System.Data;    
  5.  using System.Drawing;    
  6.  using System.Text;    
  7.  using System.Windows.Forms;    
  8.  using System.IO.Ports;    
  9.  using System.Threading;    
  10.  namespace TestSerialPort    
  11.  {    
  12.      public partial class frmTESTSerialPort : Form    
  13.      {    
  14.          public frmTESTSerialPort()    
  15.          {    
  16.              InitializeComponent();    
  17.              Control.CheckForIllegalCrossThreadCalls = false;    
  18.          }    
  19.          private Button button1;    
  20.          private TextBox txtSend;    
  21.          private TextBox txtReceive;    
  22.          private Label label1;    
  23.          private Label label2;    
  24.          /// <summary>    
  25.          /// 必需的设计器变量。    
  26.          /// </summary>    
  27.          private System.ComponentModel.IContainer components = null;    
  28.          /// <summary>    
  29.          /// 清理所有正在使用的资源。    
  30.          /// </summary>    
  31.          /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>    
  32.          protected override void Dispose(bool disposing)    
  33.          {    
  34.              if (disposing && (components != null))    
  35.              {    
  36.                  components.Dispose();    
  37.              }    
  38.              base.Dispose(disposing);    
  39.          }    
  40.          #region Windows 窗体设计器生成的代码    
  41.          /// <summary>    
  42.          /// 设计器支持所需的方法 - 不要    
  43.          /// 使用代码编辑器修改此方法的内容。    
  44.          /// </summary>    
  45.          private void InitializeComponent()    
  46.          {    
  47.              this.button1 = new System.Windows.Forms.Button();    
  48.              this.txtSend = new System.Windows.Forms.TextBox();    
  49.              this.txtReceive = new System.Windows.Forms.TextBox();    
  50.              this.label1 = new System.Windows.Forms.Label();    
  51.              this.label2 = new System.Windows.Forms.Label();    
  52.              this.SuspendLayout();    
  53.              //    
  54.              // button1    
  55.              //    
  56.              this.button1.Location = new System.Drawing.Point(440, 379);    
  57.              this.button1.Name = "button1";    
  58.              this.button1.Size = new System.Drawing.Size(75, 23);    
  59.              this.button1.TabIndex = 0;    
  60.              this.button1.Text = "发送";    
  61.              this.button1.UseVisualStyleBackColor = true;    
  62.              this.button1.Click += new System.EventHandler(this.button1_Click);    
  63.              //    
  64.              // txtSend    
  65.              //    
  66.              this.txtSend.Location = new System.Drawing.Point(59, 12);    
  67.              this.txtSend.Multiline = true;    
  68.              this.txtSend.Name = "txtSend";    
  69.              this.txtSend.Size = new System.Drawing.Size(456, 164);    
  70.              this.txtSend.TabIndex = 2;    
  71.              //    
  72.              // txtReceive    
  73.              //    
  74.              this.txtReceive.Location = new System.Drawing.Point(59, 200);    
  75.              this.txtReceive.Multiline = true;    
  76.              this.txtReceive.Name = "txtReceive";    
  77.              this.txtReceive.Size = new System.Drawing.Size(456, 164);    
  78.              this.txtReceive.TabIndex = 2;    
  79.              //    
  80.              // label1    
  81.              //    
  82.              this.label1.Location = new System.Drawing.Point(13, 15);    
  83.              this.label1.Name = "label1";    
  84.              this.label1.Size = new System.Drawing.Size(41, 12);    
  85.              this.label1.TabIndex = 0;    
  86.              this.label1.Text = "发送";    
  87.              //    
  88.              // label2    
  89.              //    
  90.              this.label2.Location = new System.Drawing.Point(13, 213);    
  91.              this.label2.Name = "label2";    
  92.              this.label2.Size = new System.Drawing.Size(41, 12);    
  93.              this.label2.TabIndex = 0;    
  94.              this.label2.Text = "接收";    
  95.              //    
  96.              // frmTESTSerialPort    
  97.              //    
  98.              this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);    
  99.              this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;    
  100.              this.ClientSize = new System.Drawing.Size(546, 434);    
  101.              this.Controls.Add(this.label2);    
  102.              this.Controls.Add(this.label1);    
  103.              this.Controls.Add(this.txtReceive);    
  104.              this.Controls.Add(this.txtSend);    
  105.              this.Controls.Add(this.button1);    
  106.              this.Name = "frmTESTSerialPort";    
  107.              this.Text = "串口试验";    
  108.              this.ResumeLayout(false);    
  109.              this.PerformLayout();    
  110.          }    
  111.          #endregion    
  112.  private void button1_Click(object sender, EventArgs e)    
  113.          {    
  114.              //实例化串口对象(默认:COMM1,9600,e,8,1)                
  115.              SerialPort serialPort1 = new SerialPort();    
  116.              //更改参数    
  117.              serialPort1.PortName = "COM1";    
  118.              serialPort1.BaudRate = 19200;    
  119.              serialPort1.Parity = Parity.Odd;    
  120.              serialPort1.StopBits = StopBits.Two;    
  121.              //上述步骤可以用在实例化时调用SerialPort类的重载构造函数    
  122.              //SerialPort serialPort = new SerialPort("COM1", 19200, Parity.Odd, StopBits.Two);    
  123.              //打开串口(打开串口后不能修改端口名,波特率等参数,修改参数要在串口关闭后修改)    
  124.              serialPort1.Open();    
  125.              //发送数据    
  126.              SendStringData(serialPort1);    
  127.              //也可用字节的形式发送数据    
  128.              //SendBytesData(serialPort1);    
  129.                  
  130.              //开启接收数据线程    
  131.              ReceiveData(serialPort1);    
  132.                  
  133.          }    
  134.              
  135.          //发送字符串数据    
  136.          private void SendStringData(SerialPort serialPort)    
  137.          {    
  138.              serialPort.Write(txtSend.Text);    
  139.          }    
  140.          /// <summary>    
  141.          /// 开启接收数据线程    
  142.          /// </summary>    
  143.          private void ReceiveData(SerialPort serialPort)    
  144.          {    
  145.              //同步阻塞接收数据线程    
  146.              Thread threadReceive=new Thread(new ParameterizedThreadStart(SynReceiveData));    
  147.              threadReceive.Start(serialPort);    
  148.                  
  149.               //也可用异步接收数据线程    
  150.              //Thread threadReceiveSub = new Thread(new ParameterizedThreadStart(AsyReceiveData));    
  151.              //threadReceiveSub.Start(serialPort);    
  152.                  
  153.          }    
  154.          //发送二进制数据    
  155.          private void SendBytesData(SerialPort serialPort)    
  156.          {    
  157.              byte[] bytesSend=System.Text.Encoding.Default.GetBytes(txtSend.Text );    
  158.              serialPort.Write(bytesSend, 0, bytesSend.Length);    
  159.          }    
  160.          //同步阻塞读取    
  161.          private void SynReceiveData(object serialPortobj)    
  162.          {    
  163.              SerialPort serialPort = (SerialPort)serialPortobj;    
  164.              System.Threading.Thread.Sleep(0);    
  165.              serialPort.ReadTimeout = 1000;    
  166.              try    
  167.              {    
  168.                  //阻塞到读取数据或超时(这里为2秒)    
  169.                  byte firstByte=Convert.ToByte(serialPort.ReadByte());    
  170.                  int bytesRead=serialPort.BytesToRead ;                   
  171.                  byte[] bytesData=new byte[bytesRead+1];    
  172.                  bytesData[0] = firstByte;    
  173.                  for (int i = 1; i <=bytesRead; i++)    
  174.                      bytesData = Convert.ToByte( serialPort.ReadByte());    
  175.                  txtReceive.Text = System.Text.Encoding.Default.GetString(bytesData);    
  176.              }    
  177.              catch(Exception e)    
  178.              {    
  179.                  MessageBox.Show(e.Message);    
  180.                  //处理超时错误    
  181.              }    
  182.                  
  183.              serialPort.Close();    
  184.          }    
  185.          //异步读取    
  186.          private void AsyReceiveData(object serialPortobj)    
  187.          {    
  188.              SerialPort serialPort = (SerialPort)serialPortobj;    
  189.              System.Threading.Thread.Sleep(500);    
  190.              try    
  191.              {    
  192.                   txtReceive.Text =   serialPort.ReadExisting();    
  193.              }    
  194.              catch (Exception e)    
  195.              {    
  196.                  MessageBox.Show(e.Message);    
  197.                  //处理错误    
  198.              }    
  199.              serialPort.Close();    
  200.          }    
  201.      }    
  202.      
  203.      static class Program    
  204.      {    
  205.          /// <summary>    
  206.          /// 应用程序的主入口点。    
  207.          /// </summary>    
  208.          [STAThread]    
  209.          static void Main()    
  210.          {    
  211.              Application.EnableVisualStyles();    
  212.              Application.SetCompatibleTextRenderingDefault(false);    
  213.              Application.Run(new frmTESTSerialPort());    
  214.          }    
  215.      }    
  216.  }  

SerialPort 类:

(以下是附加同步和异步线程)

 

[c-sharp] view plaincopy
  1. using System;   
  2. using System.Collections.Generic;   
  3. using System.Text;   
  4. using System.IO.Ports;   
  5. using System.ComponentModel;   
  6. using System.Threading;   
  7.     
  8. namespace Cserver   
  9. {   
  10.     class ToCom   
  11.     {   
  12.         priva  
  13. using System;  
  14. using System.Collections.Generic;  
  15. using System.Text;  
  16. using System.IO.Ports;  
  17. using System.ComponentModel;  
  18. using System.Threading;  
  19.    
  20. namespace Cserver  
  21. {  
  22.     class ToCom  
  23.     {  
  24.         private System.IO.Ports.SerialPort serialPort1 = new SerialPort();  
  25.         public delegate byte[] getDate(byte[] bts);  
  26.         private getDate mygetDate;  
  27.         private string com;  
  28.    
  29.         public ToCom(string com)  
  30.         {  
  31.             this.com = com;  
  32.             serialPort1.PortName = com;  //端口号  
  33.             serialPort1.BaudRate = 9600;   //比特率  
  34.             serialPort1.Parity = Parity.None;//奇偶校验  
  35.             serialPort1.StopBits = StopBits.One;//停止位  
  36.             serialPort1.ReadTimeout = 1000; //读超时,即在1000内未读到数据就引起超时异常  
  37.        }  
  38.        #region 发送接收数据  
  39.         public void SendMsg(string senStr)  
  40.         {  
  41.              
  42.             serialPort1.Open();  
  43.    
  44.             byte[] myByte = StringToByte_2(senStr);  
  45.    
  46.             serialPort1.Write(myByte, 0, myByte.Length);  
  47.             serialPort1.Close();  
  48.    
  49.         }  
  50.         public string  ReadMsg()  
  51.         {  
  52.             serialPort1.Open();  
  53.             string rd="null ";  
  54.             #region 读数据老方法  
  55.             ////------------mothed1----  
  56.             //int i = serialPort1.ReadBufferSize;  
  57.            // byte[] data = Convert.FromBase64String(serialPort1.ReadLine());  
  58.               
  59.    
  60.            // rd = Encoding.Unicode.GetString(data);  
  61.             // //  mothed2  
  62.             //int DataLength = serialPort1.BytesToRead;  
  63.    
  64.             //int i = 0;  
  65.    
  66.             //StringBuilder sb = new StringBuilder();  
  67.    
  68.             //while (i  < DataLength)  
  69.             //{  
  70.    
  71.             //    byte[] ds = new byte[1024];  
  72.    
  73.             //    int len = serialPort1.Read(ds, 0, 1024);  
  74.    
  75.             // //   sb.Append(Encoding.ASCII.GetString(ds, 0, len));  
  76.             //    sb.Append(ByteToString(ds));  
  77.    
  78.             //    i += len;  
  79.    
  80.             //}  
  81.             // //  mothed2  
  82.             //byte[] data= new byte[serialPort1.BytesToRead];  
  83.             //int i = serialPort1.Read(data, 0, serialPort1.BytesToRead);  
  84.              
  85.             //rd = ByteToString(data);  
  86.              
  87.         #endregion  
  88.    
  89.             //  mothed3  
  90.             byte[] data = new byte[serialPort1.BytesToRead];  
  91.             int i = serialPort1.Read(data, 0, serialPort1.BytesToRead);  
  92.    
  93.             rd = ByteToString(data);  
  94.             return rd;  
  95.    
  96.         }  
  97.        // string getdate(byte[])  
  98.    
  99.         public  void Sp_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)  
  100.         {  
  101.             byte[] readBuffer = new byte[serialPort1.ReadBufferSize];  
  102.             serialPort1.Read(readBuffer, 0, readBuffer.Length);  
  103.             //this.Invoke(interfaceUpdataHandle, new string[] { Encoding.UTF8.GetString(readBuffer) });  
  104.    
  105.            // this.Invoke(interfaceUpdataHandle, new string[] { ToCom.ByteToString(readBuffer) });  
  106.             string s = ToCom.ByteToString(readBuffer);  
  107.               
  108.         }  
  109.        #endregion  
  110.    
  111.         ///  <summary>  
  112.         /// 串口读(非阻塞方式读串口,直到串口缓冲区中没有数据  
  113.         ///  </summary>  
  114.         ///  <param name="readBuf">串口数据缓冲 </param>  
  115.         ///  <param name="bufRoom">串口数据缓冲空间大小 </param>  
  116.         ///  <param name="HowTime">设置串口读放弃时间 </param>  
  117.         ///  <param name="ByteTime">字节间隔最大时间 </param>  
  118.         ///  <returns>串口实际读入数据个数 </returns>  
  119.         public int ReadComm(out Byte[] readBuf, int bufRoom, int HowTime, int ByteTime)  
  120.         {  
  121.             //throw new System.NotImplementedException();  
  122.             readBuf = new Byte[64];  
  123.             Array.Clear(readBuf, 0, readBuf.Length);  
  124.    
  125.             int nReadLen, nBytelen;  
  126.             if (serialPort1.IsOpen == false)  
  127.                 return -1;  
  128.             nBytelen = 0;  
  129.             serialPort1.ReadTimeout = HowTime;  
  130.    
  131.    
  132.             try  
  133.             {  
  134.                 readBuf[nBytelen] = (byte)serialPort1.ReadByte();  
  135.                 byte[] bTmp = new byte[1023];  
  136.                 Array.Clear(bTmp, 0, bTmp.Length);  
  137.    
  138.                 nReadLen = ReadBlock(out bTmp, bufRoom - 1, ByteTime);  
  139.    
  140.                 if (nReadLen > 0)  
  141.                 {  
  142.                     Array.Copy(bTmp, 0, readBuf, 1, nReadLen);  
  143.                     nBytelen = 1 + nReadLen;  
  144.    
  145.                 }  
  146.    
  147.                 else if (nReadLen == 0)  
  148.                     nBytelen = 1;  
  149.             }  
  150.             catch (Exception ex)  
  151.             {  
  152.                 throw new Exception(ex.Message);  
  153.                 
  154.             }  
  155.    
  156.             return nBytelen;  
  157.         }  
  158.         ///  <summary>  
  159.         /// 串口同步读(阻塞方式读串口,直到串口缓冲区中没有数据,靠字符间间隔超时确定没有数据)  
  160.         ///  </summary>  
  161.         ///  <param name="ReadBuf">串口数据缓冲 </param>  
  162.         ///  <param name="ReadRoom">串口数据缓冲空间大小 </param>  
  163.         ///  <param name="ByteTime">字节间隔最大时间 </param>  
  164.         ///  <returns>从串口实际读入的字节个数 </returns>  
  165.         public int ReadBlock(out byte[] ReadBuf, int ReadRoom, int ByteTime)  
  166.         {  
  167.             //throw new System.NotImplementedException();  
  168.             ReadBuf = new byte[1024];  
  169.             Array.Clear(ReadBuf, 0, ReadBuf.Length);  
  170.    
  171.             sbyte nBytelen;  
  172.             //long nByteRead;  
  173.    
  174.             if (serialPort1.IsOpen == false)  
  175.                 return 0;  
  176.             nBytelen = 0;  
  177.             serialPort1.ReadTimeout = ByteTime;  
  178.    
  179.             while (nBytelen  < (ReadRoom - 1))  
  180.             {  
  181.                 try  
  182.                 {  
  183.                     ReadBuf[nBytelen] = (byte)serialPort1.ReadByte();  
  184.                     nBytelen++; // add one  
  185.                 }  
  186.                 catch (Exception ex)  
  187.                 {  
  188.                      throw new Exception( ex.Message);  
  189.                     break;  
  190.                 }  
  191.             }  
  192.             ReadBuf[nBytelen] = 0x00;  
  193.             return nBytelen;  
  194.    
  195.         }  
  196.    
  197.    
  198.         ///  <summary>  
  199.         /// 字符数组转字符串16进制  
  200.         ///  </summary>  
  201.         ///  <param name="InBytes"> 二进制字节 </param>  
  202.         ///  <returns>类似"01 02 0F" </returns>  
  203.         public static string ByteToString(byte[] InBytes)  
  204.         {  
  205.             string StringOut = "";  
  206.             foreach (byte InByte in InBytes)  
  207.             {  
  208.                 StringOut = StringOut + String.Format("{0:X2}", InByte) + " ";  
  209.             }  
  210.    
  211.             return StringOut.Trim();  
  212.         }  
  213.         ///  <summary>  
  214.         /// strhex 转字节数组  
  215.         ///  </summary>  
  216.         ///  <param name="InString">类似"01 02 0F" 用空格分开的  </param>  
  217.         ///  <returns> </returns>  
  218.         public static byte[] StringToByte(string InString)  
  219.         {  
  220.             string[] ByteStrings;  
  221.             ByteStrings = InString.Split(" ".ToCharArray());  
  222.             byte[] ByteOut;  
  223.             ByteOut = new byte[ByteStrings.Length];  
  224.             for (int i = 0; i  <= ByteStrings.Length - 1; i++)  
  225.             {  
  226.                 ByteOut[i] = byte.Parse(ByteStrings[i], System.Globalization.NumberStyles.HexNumber);  
  227.             }  
  228.             return ByteOut;  
  229.         }  
  230.    
  231.         ///  <summary>  
  232.         /// strhex 转字节数组  
  233.         ///  </summary>  
  234.         ///  <param name="InString">类似"01 02 0F" 中间无空格 </param>  
  235.         ///  <returns> </returns>  
  236.         public static byte[] StringToByte_2(string InString)  
  237.         {  
  238.             byte[] ByteOut;  
  239.             InString = InString.Replace(" ","");  
  240.             try  
  241.             {  
  242.                 string[] ByteStrings = new string[InString.Length/2];  
  243.                 int j = 0;  
  244.                 for (int i = 0; i  < ByteStrings.Length ; i++)  
  245.                 {  
  246.                       
  247.                     ByteStrings[i] = InString.Substring(j,2);  
  248.                     j += 2;  
  249.                 }  
  250.                  
  251.                 ByteOut = new byte[ByteStrings.Length];  
  252.                 for (int i = 0; i  <= ByteStrings.Length - 1; i++)  
  253.                 {  
  254.                     ByteOut[i] = byte.Parse(ByteStrings[i], System.Globalization.NumberStyles.HexNumber);  
  255.                 }  
  256.             }  
  257.             catch (Exception ex)  
  258.             {  
  259.                   
  260.                 throw new Exception(ex.Message);  
  261.             }  
  262.    
  263.             return ByteOut;  
  264.         }  
  265.         ///  <summary>  
  266.         /// 字符串 转16进制字符串  
  267.         ///  </summary>  
  268.         ///  <param name="InString">unico </param>  
  269.         ///  <returns>类似“01 0f” </returns>  
  270.         public static string  Str_To_0X(string InString)  
  271.         {  
  272.             return ByteToString (UnicodeEncoding.Default.GetBytes(InString));  
  273.         }  
  274.     }  
  275. }  

0 0