CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
IBM Rational 系统开发最佳实践工具包 WebSphere MQ 最佳实践 TOP 15
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  基础类

串口通信,比如接收6个字节,会触发两次,第一次接收6个字节,第二次接收0个字节

楼主south2000(south2000)2006-03-04 16:56:11 在 VC/MFC / 基础类 提问

使用API编程,异步通信方式。  
  计算机仅仅从串口读数据,不用向串口写数据,因此比较简单。  
  思路:使用一个辅助线程来读串口。  
  发现问题:当设备向计算机发送数据时候,比如发送6个字节,计算机会接收两次,第一次接收6个字节,第二次接收0个字节。  
   
  这里,我给出主要代码:  
  一、打开串口1,以及串口主要设置信息:  
  g_hCom1   =   CreateFile("COM1",  
  GENERIC_WRITE   |   GENERIC_READ,  
  0,  
  NULL,  
  OPEN_EXISTING,  
  FILE_ATTRIBUTE_NORMAL   |   FILE_FLAG_OVERLAPPED,  
  NULL  
  );  
  波特率9600,校验,缓冲区大小,超时等等,都设置好。  
   
  //超时  
  tmOuts.ReadIntervalTimeout   =   500;  
  tmOuts.ReadTotalTimeoutMultiplier   =   0;  
  tmOuts.ReadTotalTimeoutConstant   =   1000;  
   
  //设置触发事件为  
  SetCommMask(hCom,   EV_RXCHAR);  
   
   
  二、监控串口1的线程,主要代码:  
  UINT   WatchComm1Thread(LPVOID   pParam)  
  {  
      DWORD   dwMask,   dwTransfered;  
      OVERLAPPED   ol;  
      memset(&ol,   0,   sizeof(OVERLAPPED));  
      ol.hEvent   =   CreateEvent(NULL,   TRUE,   FALSE,   NULL);  
   
      while(1)  
      {  
          if(!WaitCommEvent(g_hCom1   ,   &dwMask,   &ol))//语句1  
          {  
              if(GetLastError()   ==   ERROR_IO_PENDING)  
                      GetOverlappedResult(g_hCom1,   &ol,   &dwTransfered,   TRUE);//语句2  
          }  
   
          if((dwMask   &   EV_RXCHAR)   ==   EV_RXCHAR)  
          {  
              int   iReadLen   =   ReadComm1();//语句3  
          }  
      }  
  }  
   
   
  三、读串口函数ReadComm1()主要代码:  
  int   ReadComm1()  
  {  
      DWORD   dwError,   dwRecvedLen   =   0,   dwTansfered;  
      COMSTAT   comStat;  
      OVERLAPPED   olRead1;  
       
      memset(&olRead1,   0,   sizeof(OVERLAPPED));  
      olRead1.hEvent   =   CreateEvent(NULL,   TRUE,   FALSE,   NULL);  
       
      ClearCommError(g_hCom1,   &dwError,   &comStat);  
   
      if(comStat.cbInQue   >   0)  
      {  
          if(!ReadFile(g_hCom1,   g_RecvBuf1,   comStat.cbInQue,   &dwRecvedLen,   &olRead1))  
          {  
              if(GetLastError()   ==   ERROR_IO_PENDING)  
                  GetOverlappedResult(g_hCom1,   &olRead1,   &dwTansfered,   TRUE);  
          }  
      }  
   
      CloseHandle(olRead1.hEvent);  
      return   (int)dwRecvedLen;  
  }  
   
   
  /////////////////////////////////////////  
  我开始调试了:  
  我在“语句1”设置断点。  
   
  程序运行起来,很快执行到“语句1”处,单步运行,使其执行到“语句2”,再单步运行,因为设备一直不向计算机发送数据,“语句2”一直不会返回,这些都表明程序是好的。  
   
  设备向计算机发送6个字节,“语句2”立即返回,通过单步,可以发现“语句3”读取了6个字节,一切正常。然后继续单步,使其运行到“语句1”处,单步运行,使其执行到“语句2”,再单步运行,却发现“语句2”立即返回,(可是现在并串口中没有数据可读啊,“语句2”为什么会立即返回呢),再单步,程序符合“if((dwMask   &   EV_RXCHAR)   ==   EV_RXCHAR)”的条件,运行到“语句3”,解下来就可以发现“语句3”读到了0个字节,怎么回事?  
   
  问题点数:60、回复次数:10Top

1 楼CUG122032(烫烫烫烫烫烫?烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫?烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫)回复于 2006-03-04 17:01:33 得分 0

为什么不用MScomm呢?Top

2 楼js_gary(李祥)回复于 2006-03-04 17:09:30 得分 0

you   could   try   to   use   SearialCOM   Class  
  may   be   which   could   help   you   anythingTop

3 楼south2000(south2000)回复于 2006-03-04 17:25:28 得分 0

用MScomm,程序给其他人使用的时候要涉及到控件的注册问题。  
   
  SearialCOM我不知道,也不想用。Top

4 楼BBirdlyh(BBird)回复于 2006-03-05 00:17:46 得分 60

EV_RXCHAR  
  A   character   was   received   and   placed   in   the   input   buffer  
  串口向计算机发送六个字节,系统会受到六次EV_RXCHAR消息,第一次你就收了六个字节,以后的五次就只能收0字节了  
  至于为什么只受到2次EV_RXCHAR,我觉得原因应该是  
          if(!ReadFile(g_hCom1,   g_RecvBuf1,   comStat.cbInQue,   &dwRecvedLen,   &olRead1))  
          {  
              if(GetLastError()   ==   ERROR_IO_PENDING)  
                  GetOverlappedResult(g_hCom1,   &olRead1,   &dwTansfered,   TRUE);  
          }  
  这里做了GetOverlappedResult的缘故,只有第一次和最后一次被受到了  
   
  另:其实SearialCOM真的很好用,而且和你的程序很相似,可以比较一下Top

5 楼south2000(south2000)回复于 2006-03-05 11:01:04 得分 0

BBirdlyh(BBird),感谢你的分析。  
   
  我又调试看了看,发现情况不像你说的那样,不像你分析语句GetOverlappedResult那样。  
   
  在int   ReadComm1()函数中,“if(GetLastError()   ==   ERROR_IO_PENDING)”,“GetOverlappedResult(g_hCom1,   &olRead1,   &dwTansfered,   TRUE);”这两句都没有执行,  
  也就是说,在读串口的时候,一次性就读完了comStat.cbInQue数量的字节,ReadFile语句返回了TRUE。  
   
  呵呵。  
   
  Top

6 楼south2000(south2000)回复于 2006-03-06 11:18:20 得分 0

我发现,如果设备仅仅向计算机发送一个字节的话,就不会出现触发两次的情况,而是仅仅触发一次,然后正确接收到数据。  
   
  请问这是怎么回事?Top

7 楼jjiaming(阿熊)回复于 2006-03-06 13:08:12 得分 0

我觉得BBirdlyh(BBird)言之有理Top

8 楼south2000(south2000)回复于 2006-03-08 19:43:21 得分 0

没有人知道么?Top

9 楼BBirdlyh(BBird)回复于 2006-03-09 12:41:47 得分 0

正是因为你一次读完了6个字节,但没有阻止EV_RXCHAR消息,所以下次还会去处理  
   
  但安道理来说应该会受到6次,我所说的GetOverlappedResult的情况是在分析你为什么会受到2次  
   
  还有一个函数是用来清除接下来的EV_RXCHAR   或是其他消息的,也就是说你第一次收到EV_RXCHAR后,全部读出6个字节,然后调用该函数清除后续的EV_RXCHAR消息,msdn上有(DEVICE   IO)你可以查一下  
   
  一般最好的办法是一次只收一个字节,然后攒着,知道受到要求的字节数并且验证正确再向处理模块发消息处理Top

10 楼shmily1280(锄禾)回复于 2006-03-09 13:45:02 得分 0

同意楼上的  
  可以一个一个读  
  完了之后再处理.否则在语句3处加个对comStat.cbInQue是否为空的判断  
  另:BBirdlyh(BBird)说的没错Top

相关问题

  • 串口通信,比如接收6个字节,会触发两次,第一次接收6个字节,第二次接收0个字节
  • 求教:有关串口通信问题:下位机每5ms发送一帧32字节大小数据到pc,如何接收?谢谢谢
  • 串口通信中不能触发事件 ,救?
  • 串口通信中是不是一次只能接收一个字符??
  • 急急急!!!在串口通信中接收时数据总有丢失出现.
  • 急急急!!!在串口通信中接收时数据总有丢失出现.
  • 串口通信中数据怎么按照数据位传送,接收那
  • 串口通信
  • 串口通信
  • 串口通信协议设计:请问一般串口的发送缓冲区的字节为多少

关键词

  • 语句
  • 函数
  • 计算机
  • 数据
  • 执行
  • 代码
  • rxchar
  • 串口
  • 接收
  • 单步

得分解答快速导航

  • 帖主:south2000
  • BBirdlyh

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo