加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

如何从串口中读取自己想要的数据(C#)

(2007-06-15 20:06:01)
分类: “挨踢”秘籍
很多C#新手在使用串口控件(MSComm)编程时可能都和小嫚儿一样疏忽,没想到可能会接收到乱码,以至于软件在使用中接收不到完整的数据,现在小嫚儿将完整的串口接收程序和大家分享,让大家避免成为象小嫚儿一样的马大哈:
//定义全局变量:
int UnsettledDataNum=0;//未处理的数据个数
int WorkedDataNum=0;//已处理的数据个数
int ReceiveDataNum=0;//收到数据的个数
byte[] ReceivedData=new byte[1024];//接收到的所有数据
private void Form1_Load(object sender, System.EventArgs e)//串口初始化
{
  MSComm.CommPort=1;//设置串口号
  MSComm.RThreshold = 1;//接收缓冲区收到每一个字符都会使MSComm控件产生OnComm事件
  MSComm.Settings = "9600,O,8,1";//设置并返回数据传输速率、奇偶校验、数据比特、停止比特参数      MSComm.InputMode=MSCommLib.InputModeConstants.comInputModeBinary;//用于设置或返回传输数据的类型,此例程是通过Input属性以二进制方式检取回数据
  MSComm.PortOpen =true ;//打开端口 
  MSComm.InBufferCount=0;//用于返回输入缓冲区内的等待读取得字节个数
}

private void MSComm_OnComm(object sender, System.EventArgs e)//触发OnComm事件
{
   switch  (MSComm.CommEvent )  //查询CommEvent属性
  {
    case (short)(MSCommLib.OnCommConstants.comEvReceive): //当接收缓冲区内字符数达到RThreshold值,进入CommData()子程序
     CommData (); //接收缓冲区内数据
     break;   
   }
 }

private void CommData() //接收数据

{
    int BufferDataNumStart=0; //定义第一次查询缓冲区内数据个数
    int BufferDataNumEnd=0; //定义最后一次查询缓冲区内数据个数
    byte[] CommBufferData=new byte[1024];
    byte[] ComByte=new byte[8];
        
   BufferDataNumStart=MSCommSoundBait.InBufferCount; //将缓冲区内等待读取的字节个数赋给BufferDataNumStart
   if(BufferDataNumStart==0) return; //如果缓冲区为空,说明还没有数据传来,则返回;若不为空,进入下面的循环
   MSCommSoundBait.InputLen = 0; //读取缓冲区内全部内容
   while(true)
   {
     System.Threading.Thread.Sleep(50); //延时,以确保数据完全接收
     BufferDataNumEnd=MSCommSoundBait.InBufferCount; //再次读取缓冲区内字节个数
    if(BufferDataNumStart==BufferDataNumEnd) break; //如果BufferDataNumStart==BufferDataNumEnd,说明本帧数据已经读完,退出循环
    BufferDataNumStart=BufferDataNumEnd; //否则,将BufferDataNumEnd赋给BufferDataNumStart,并继续循环,直到完全接收
   }
   object objIn;
   objIn=MSComm.Input ; //这里注意MSComm.Input返回的是一个object的类型,所以必须使用显式的类型转换     
   CommBufferData =(byte[])objIn;   //CommBufferData为串口缓冲区内所有数据
   //存取最后一次接收到的缓冲区的数据,存储部分时作为后期数据处理所用,以便于程序员分析数据。使用StreamWriter,需在添加命名控件using System.IO;
   string sTime=DateTime.Now.ToString(); //记录当前时间
   StreamWriter strmWriter=new StreamWriter("E:\\CommData\\ReceiveData\\CommData.txt",true);
   strmWriter.Write("\r\n");
   strmWriter.Write(sTime);
   strmWriter.Write("\r\n");     
   string StrRead="";
   string StrReadSub="";
   for (int j=0;j< BufferDataNumEnd;j++)
      
    StrReadSub=(CommBufferData[j]).ToString("x");
    if (StrReadSub.Length<2)StrReadSub="0"+StrReadSub;
    StrRead=StrRead+" "+StrReadSub;    
   }
   strmWriter.Write(StrRead.ToUpper());
   strmWriter.Close();
   //将上次未处理的数据和本次存储数据在ReceivedData相连,此部分是防止发送过来的数据本身就不完整,以至于数据处理不能进行完全,故保留并与新接收的数据相连
   for(int i=0;i<BufferDataNumEnd;i++)
   {
       ReceiveDataNum++;
       UnsettledDataNum++;
       ReceivedData[ReceiveDataNum-1]=CommBufferData[i];
   }
   //进入数据处理字程序
   DealData();
  }

  private void DealData() //数据处理
  {
   while(ReceivedData[WorkedDataNum]!=0xAA) //判断是否是通讯头,如果是,跳出循环;否则,丢弃乱码
   {
     WorkedDataNum++;
     UnsettledDataNum--; //目前没有处理的字节总数
     if(UnsettledDataNum==0) return;
   }
   if(ReceivedData[WorkedDataNum+1]==0xAA & UnsettledDataNum>=7) //第二个字节也为AA且剩下字节等于或超过7个,通讯头和剩下字节数以实际情况而定
   {
      DealUsefulData(); //处理有用的数据
   }
   return;

  }

  private void DealUsefulData () 
  {
   //处理部分根据实际要求来做,这里只给出处理完成之后仍需注意的地方:
            WorkedDataNum+=7;
            UnsettledDataNum-=7;
            DealData();
 }

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有