博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

C#实现串口监听

Posted on 2009-11-24 14:01  孙潇楠  阅读(11076)  评论(2编辑  收藏  举报

Visual Stdio 2005中,对于串口操作Framework提供了一个很好的类接口-SerialPort,在这当中,串口数据的读取与写入有较大的不同。由于串口不知道数据何时到达,因此有两种方法可以实现串口数据的读取。

       1.用线程实时读串口

       2.用事件触发方式实现。

        但由于线程实时读串口的效率不是十分高效,因此比较好的方法是事件触发的方式。在SerialPort类中有DataReceived事件,当串口的读缓存有数据到达时则触发DataReceived事件,其中SerialPort.ReceivedBytesThreshold属性决定了当串口读缓存中数据多少个时才触发DataReceived事件,默认为1。

       此外,SerialPort.DataReceived事件运行比较特殊,其运行在辅线程,不能与主线程中的显示数据控件直接进行数据传输,必须用间接的方式实现。

一.创建WIndow项目,设计界面

二,编写实现代码

 

  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. using Microsoft.Win32;
  11. namespace ComMonitor
  12. {
  13.     public partial class Form1 : Form
  14.      {
  15.         public Form1()
  16.          {
  17.              InitializeComponent();
  18.          }
  19.         private SerialPort Sp = new SerialPort();
  20.         public delegate void HandleInterfaceUpdataDelegate(string text); //委托,此为重点
  21.         private HandleInterfaceUpdataDelegate interfaceUpdataHandle;
  22.         private bool qiii = false;
  23.         private void btENT_Click(object sender, EventArgs e)
  24.          {
  25.             if ((cmID.Text.Trim() != "") && (cmRate.Text != ""))
  26.              {
  27.                  interfaceUpdataHandle = new HandleInterfaceUpdataDelegate(UpdateTextBox);//实例化委托对象
  28.                  Sp.PortName = cmID.Text.Trim();
  29.                  Sp.BaudRate = Convert.ToInt32(cmRate.Text.Trim());
  30.                  Sp.Parity = Parity.None;
  31.                  Sp.StopBits = StopBits.One;
  32.                  Sp.DataReceived += new SerialDataReceivedEventHandler(Sp_DataReceived);
  33.                  Sp.ReceivedBytesThreshold = 1;
  34.                 try
  35.                  {
  36.                      Sp.Open();
  37.                      ATCommand3("AT+CLIP=1\r", "OK");
  38.                      btPause.Enabled = true;
  39.                      btENT.Enabled = false;
  40.                  }
  41.                 catch
  42.                  {
  43.                      MessageBox.Show("端口" + cmID.Text.Trim() + "打开失败!");
  44.                  }
  45.              }
  46.             else
  47.              {
  48.                  MessageBox.Show("请输入正确的端口号和波特率!");
  49.                  cmID.Focus();
  50.              }
  51.          }
  52.         private void btPause_Click(object sender, EventArgs e)
  53.          {
  54.              Sp.Close();
  55.              btENT.Enabled = true;
  56.              btPause.Enabled = false;
  57.          }
  58.         private void Form1_FormClosing(object sender, FormClosingEventArgs e)
  59.          {
  60.              Sp.Close();
  61.          }
  62.         private void Form1_Load(object sender, EventArgs e)
  63.          {
  64.              GetComList();
  65.              btPause.Enabled = false;
  66.          }
  67.         public void Sp_DataReceived(object sender,System.IO.Ports.SerialDataReceivedEventArgs e)
  68.          {
  69.             string strTemp = "";
  70.             double iSecond = 0.5;
  71.              DateTime dtOld = System.DateTime.Now;
  72.              DateTime dtNow = System.DateTime.Now;
  73.              TimeSpan dtInter;
  74.              dtInter = dtNow - dtOld;
  75.             int i = Sp.BytesToRead;
  76.             if (i > 0)
  77.              {
  78.                 try
  79.                  {
  80.                      strTemp = Sp.ReadExisting();
  81.                  }
  82.                 catch
  83.                  { }
  84.                 if (strTemp.ToLower().IndexOf("\r") < 0)
  85.                  {
  86.                      i = 0;
  87.                  }
  88.                 else
  89.                  {
  90.                     this.Invoke(interfaceUpdataHandle, strTemp);
  91.                  }
  92.              }
  93.             while (dtInter.TotalSeconds < iSecond && i <= 0)
  94.              {
  95.                  dtNow = System.DateTime.Now;
  96.                  dtInter = dtNow - dtOld;
  97.                  i = Sp.BytesToRead;
  98.                 if (i > 0)
  99.                  {
  100.                     try
  101.                      {
  102.                          strTemp += Sp.ReadExisting();
  103.                      }
  104.                     catch
  105.                      { }
  106.                     if (strTemp.ToLower().IndexOf("\r") < 0)
  107.                      {
  108.                          i = 0;
  109.                      }
  110.                     else
  111.                      {
  112.                         this.Invoke(interfaceUpdataHandle, strTemp);
  113.                      }
  114.                  }
  115.              }
  116.             // do null
  117.          }
  118.         private void UpdateTextBox(string text)
  119.          {
  120.              tbData.Text = text;
  121.          }
  122.         /// <summary>
  123.         /// 执行AT指令并返回 成功失败
  124.         /// </summary>
  125.         /// <param name="ATCmd">AT指令</param>
  126.         /// <param name="StCmd">AT指令标准结束标识</param>
  127.         /// <returns></returns>
  128.         private void ATCommand3(string ATCmd, string StCmd)
  129.          {
  130.             string response = "";
  131.              response = ATCommand(ATCmd, StCmd);
  132.          }
  133.         /// <summary>
  134.         /// 执行AT指令并返回结果字符
  135.         /// </summary>
  136.         /// <param name="ATCmd">AT指令</param>
  137.         /// <param name="StCmd">AT指令标准结束标识</param>
  138.         /// <returns></returns>
  139.         private string ATCommand(string ATCmd, string StCmd)
  140.          {
  141.             string response = "";
  142.             int i;
  143.             if (!ATCmd.EndsWith("\x01a"))
  144.              {
  145.                 if (!(ATCmd.EndsWith("\r") || ATCmd.EndsWith("\r\n")))
  146.                  {
  147.                      ATCmd = ATCmd + "\r";
  148.                  }
  149.              }
  150.              Sp.WriteLine(ATCmd);
  151.             //第一次读响应数据
  152.             if (Sp.BytesToRead > 0)
  153.              {
  154.                  response = Sp.ReadExisting();
  155.                 //去除前端多可能多读取的字符
  156.                 if (response.IndexOf(ATCmd) > 0)
  157.                  {
  158.                      response = response.Substring(response.IndexOf(ATCmd));
  159.                  }
  160.                 else
  161.                  {
  162.                  }
  163.                 if (response == "" || response.IndexOf(StCmd) < 0)
  164.                  {
  165.                     if (response != "")
  166.                      {
  167.                         if (response.Trim() == "ERROR")
  168.                          {
  169.                             //throw vError = new UnknowException("Unknown exception in sending command:" + ATCmd);
  170.                          }
  171.                         if (response.IndexOf("+CMS ERROR") >= 0)
  172.                          {
  173.                             string[] cols = new string[100];
  174.                              cols = response.Split(';');
  175.                             if (cols.Length > 1)
  176.                              {
  177.                                 string errorCode = cols[1];
  178.                              }
  179.                          }
  180.                      }
  181.                  }
  182.              }
  183.             //读第一次没有读完的响应数据,直到读到特征数据或超时
  184.             for (i = 0; i < 3; i++)
  185.              {
  186.                  Thread.Sleep(1000);
  187.                  response = response + Sp.ReadExisting();
  188.                 if (response.IndexOf(StCmd) >= 0)
  189.                  {
  190.                     break;
  191.                  }
  192.              }
  193.             return response;
  194.          }
  195.         /// <summary>
  196.         /// 从注册表获取系统串口列表
  197.         /// </summary>
  198.         private void GetComList()
  199.          {
  200.              RegistryKey keyCom = Registry.LocalMachine.OpenSubKey("Hardware\\DeviceMap\\SerialComm");
  201.             if (keyCom != null)
  202.              {
  203.                 string[] sSubKeys = keyCom.GetValueNames();
  204.                 this.cmID.Items.Clear();
  205.                 foreach (string sName in sSubKeys)
  206.                  {
  207.                     string sValue = (string)keyCom.GetValue(sName);
  208.                     this.cmID.Items.Add(sValue);
  209.                  }
  210.              }
  211.          }
  212.         private void cmID_DropDown(object sender, EventArgs e)
  213.          {
  214.              GetComList();
  215.          }
  216.      }
  217. }