CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VB >  非技术类

串口通信问题求帮助~~!(急急急)

楼主langlg855(毛毛)2004-11-03 11:56:31 在 VB / 非技术类 提问

我这里自己编了个串口通信的程序,但是接受的数据不对。哪位有经验的请给予帮助。能解决肯定给分~~~!我的QQ:12012109越快越好~~~!  
  Private   Sub   MSComm1_OnComm()  
  On   Error   Resume   Next  
  Dim   i   As   Integer  
  Dim   tmp(1   To   2)   As   Byte  
  Dim   istart   As   Integer  
  Select   Case   Me.MSComm1.CommEvent  
          Case   comEvReceive:  
                  Me.MSComm1.InputLen   =   Me.MSComm1.InBufferCount  
                  dataReceive   =   Me.MSComm1.Input  
                  Me.Text1.Text   =   dataReceive  
                  If   IsNumeric(Me.Text14)   Then  
                          Me.Text14   =   Me.Text1   +   (UBound(dataReceive)   -   LBound(dataReceive)   +   1)  
                  Else  
                          Me.Text14   =   (UBound(dataReceive)   -   LBound(dataReceive)   +   1)  
                  End   If  
                  If   Check1.Value   =   1   Then  
                          For   i   =   LBound(dataReceive)   To   UBound(dataReceive)  
                                  str(tmp)   =   str(tmp)   +   FormatHex(dataReceive(i))   +   "   "  
                          Next   i  
                          Me.Text1.Text   =   Me.Text1.Text   +   str(tmp)  
                  Else  
                          istart   =   0  
                          If   havelast   =   True   Then  
                                  tmp(1)   =   lastdata  
                                  tmp(2)   =   dataReceive(LBound(dataReceive))  
                                  istart   =   1  
                                  havelast   =   False  
                                  str(tmp)   =   str(tmp)   +   StrConv(CStr(tmp),   vbUnicode)  
                          End   If  
                          For   i   =   LBound(dataReceive)   +   istart   To   UBound(dataReceive)  
                                  If   dataReceive(i)   >   127   Then  
                                          If   i   =   UBound(dataReceive)   Then  
                                                  havelast   =   True  
                                                  lastdata   =   dataReceive(i)  
                                          Else  
                                                  tmp(1)   =   dataReceive(i)  
                                                  tmp(2)   =   dataReceive(i   +   1)  
                                                  i   =   i   +   1  
                                                  havelast   =   False  
                                                  str(tmp)   =   str(tmp)   +   StrConv(CStr(tmp),   vbUnicode)  
                                          End   If  
                                  Else  
                                          str(tmp)   =   str(tmp)   +   CStr(Chr(dataReceive(i)))  
                                          havelast   =   False  
                                  End   If  
                          Next   i  
                          Me.Text1.Text   =   Me.Text1.Text   +   str(tmp)  
                  End   If  
                  If   LenB(StrConv(Me.Text1,   vbFromUnicode))   >   4000   Then  
                          Me.Text1   =   ""  
                  End   If  
  End   Select  
  End   Sub 问题点数:100、回复次数:10Top

1 楼hellobcb(学海无涯,回头是岸)回复于 2004-11-03 13:32:51 得分 30

 
  Me.MSComm1.InputLen   =   Me.MSComm1.InBufferCount  
  这句话放的位置不对吧!  
  假设你的传输模式为ComInputModeText,当收到Rthreshold个字符时,触发ComEvReceive事件,此时如果用InPut属性,可以读走InputLen(如果InputLen=0,全部读走)个字符。  
  所以你应该在初始化MSComm的时候就设置InputLen属性。Top

2 楼langlg855(毛毛)回复于 2004-11-03 22:18:17 得分 0

那你的意思就是把Me.MSComm1.InputLen   =   Me.MSComm1.InBufferCount这句话放到MSComm属性设置的时候了?上面这段程序也能收到东西,譬如我发“1111”,则收到“??”。而且收到一次后就不能再收了。(你有QQ号吗,想弄清楚,真的比较急啊~~~~)Top

3 楼aohan(aohan)回复于 2004-11-03 23:16:57 得分 20

'叶帆的例子,看看是否有帮助,说明部分乱码了,哎~~~~~~~~~  
  Option   Explicit  
  Private   Declare   Function   GetCurrentTime   Lib   "kernel32"   Alias   "GetTickCount"   ()   As   Long  
   
  Private   Sub   cmdSend_Click()  
      Dim   bytData(10)   As   Byte  
      bytData(0)   =   &HA                                                       'Êý¾Ý  
      txtMsg.Text   =   SendData(1,   bytData,   1)             '·¢ËÍÃüÁî  
  End   Sub  
   
  Private   Sub   Form_Load()  
        OpenPort   1                         '´ò¿ª´®¿Ú  
  End   Sub  
  Public   Function   OpenPort(PortNo   As   Integer,   Optional   InBufferSize   As   Integer   =   1024,   Optional   OutBufferSize   As   Integer   =   512)   As   Long  
        On   Error   GoTo   ErrExit  
          MSComm1.CommPort   =   PortNo                                       '²ÉÓÃCOM¶Ë¿Ú  
          MSComm1.Settings   =   "9600,n,8,1"  
          MSComm1.InputMode   =   comInputModeBinary             '²ÉÓöþ½øÖÆ´«Êä  
          MSComm1.NullDiscard   =   False                                   'NULL×Ö·û´Ó¶Ë¿Ú´«Ë͵½½ÓÊÜ»º³åÇø  
          MSComm1.DTREnable   =   False                                       'DTRÏßÎÞЧ  
          MSComm1.EOFEnable   =   False                                       '²»Ñ°ÕÒEOF·û  
          MSComm1.RTSEnable   =   False                                       'RTSÏßÎÞЧ  
          MSComm1.InBufferCount   =   0                                       'Çå¿Õ½ÓÊÜ»º³åÇø  
          MSComm1.OutBufferCount   =   0                                     'Çå¿Õ´«Ê仺³åÇø  
          MSComm1.SThreshold   =   1                                             'Èç¹û´«Ê仺³åÇøÍêÈ«¿Õʱ²úÉúMSCommʼþ  
          MSComm1.RThreshold   =   0                                             '²»²úÉúMSCommʼþ  
          MSComm1.InBufferSize   =   InBufferSize                   '½ÓÊÕ»º³åÇø     ĬÈÏΪ1024¸ö×Ö½Ú  
          MSComm1.OutBufferSize   =   OutBufferSize               '·¢ËÍ»º³åÇø     ĬÈÏΪ512¸ö×Ö½Ú  
          MSComm1.PortOpen   =   True                                           '´ò¿ª¶Ë¿Ú  
          OpenPort   =   0  
        Exit   Function  
  ErrExit:  
        OpenPort   =   1  
  End   Function  
   
  Public   Sub   ClosePort()  
        On   Error   GoTo   ErrExit  
            MSComm1.PortOpen   =   False                                             '¹Ø±Õ¶Ë¿Ú  
        Exit   Sub  
  ErrExit:  
         
  End   Sub  
  Public   Function   SendData(bytAddr   As   Byte,   bytData()   As   Byte,   Optional   bytNum   As   Byte   =   1)   As   Long  
          On   Error   GoTo   ErrExit  
   
          Dim   bytSendArray()   As   Byte                                           '·¢ËÍÊý¾Ý»º³åÇø  
          Dim   intGetDataLen   As   Integer                                       'Òª½ÓÊÕµÄÊý¾Ý³¤¶È  
          Dim   sngTimeSpace   As   Single                                           'ÑÓʱʱ¼ä  
          Dim   sngTime   As   Single  
          Dim   bytReceiveArray()   As   Byte                                     '½ÓÊÕµÄÊý¾Ý  
          Dim   VarReceiveData   As   Variant                                     '½ÓÊյıäÌåÊý¾Ý  
          Dim   i   As   Long  
          ReDim   bytSendArray(0   To   bytNum   *   2   +   2)   As   Byte     '·¢ËÍÊý¾Ý»º³åÇø  
          bytSendArray(0)   =   &HAC                                                   'ͬ²½×ÖÍ·  
          bytSendArray(1)   =   bytAddr                                             'ÏÂλ»úµØÖ·  
          bytSendArray(2)   =   bytAddr                                             '¸±±¾  
          For   i   =   0   To   bytNum   *   2   -   1   Step   2  
                  bytSendArray(i   +   3)   =   bytData(i   /   2)  
                  bytSendArray(i   +   4)   =   bytData(i   /   2)  
          Next  
          MSComm1.InBufferCount   =   0                                             'Çå¿Õ½ÓÊÕ»º³åÇø  
          MSComm1.Output   =   bytSendArray                                     '·¢ËÍÊý¾Ý  
   
          Do  
                  DoEvents  
          Loop   Until   MSComm1.OutBufferCount   =   0                     'µÈ´ý£¬Ö±µ½Êý¾Ý·¢ËÍÍê±Ï  
          intGetDataLen   =   5  
          sngTimeSpace   =   intGetDataLen   *   (11000#   /   9600#)   *   10#  
          sngTime   =   GetCurrentTime()                                                     '  
          Do   While   True                                                                     'Êý¾Ý½ÓÊÕ  
                  DoEvents  
                  If   MSComm1.InBufferCount   >=   intGetDataLen   Then   Exit   Do  
                  If   Abs(GetCurrentTime()   -   sngTime)   >   sngTimeSpace   Then         '³¬Ê±  
                          SendData   =   1  
                          Exit   Function  
                  End   If  
   
          Loop  
   
          VarReceiveData   =   MSComm1.Input  
          bytReceiveArray   =   VarReceiveData  
          SendData   =   2                                                 'Ïȸ³Öµ½ÓÊÕµÄÊý¾Ý´íÎó  
          If   bytReceiveArray(0)   =   &HAC   Then       '×ÖÍ·  
                  If   bytReceiveArray(1)   =   bytReceiveArray(2)   And   bytReceiveArray(3)   =   bytReceiveArray(4)   Then  
                          If   bytReceiveArray(1)   =   bytSendArray(1)   And   bytReceiveArray(3)   =   &HAA   Then  
                                  SendData   =   0                                 'ÃüÁîÕýÈ·  
                          End   If  
                  End   If  
          End   If  
  Exit   Function  
  ErrExit:  
          SendData   =   3  
  End   Function  
  Private   Sub   Form_Unload(Cancel   As   Integer)  
        ClosePort     '¹Ø±Õ´®¿Ú  
  End   Sub  
  Top

4 楼langlg855(毛毛)回复于 2004-11-04 16:55:22 得分 0

Private   Declare   Function   GetCurrentTime   Lib   "kernel32"   Alias   "GetTickCount"   ()   As   Long这个句子的具体意思是什么?谁能和我QQ联系一下,我可以把程序发过去让看看。真的很急。Top

5 楼tztz520(午夜逛街)回复于 2004-11-04 16:58:41 得分 5

GetCurrentTime   一般用来取得鼠标或键盘的空闲时间.Top

6 楼langlg855(毛毛)回复于 2004-11-05 10:45:03 得分 0

Private   Declare   Function   ShellExecute   Lib   "shell32.dll"   Alias   "ShellExecuteA"   _  
                  (ByVal   hwnd   As   Long,   ByVal   lpOperation   As   String,   ByVal   lpFile   As   String,   _  
                  ByVal   lpParameters   As   String,   ByVal   lpDirectory   As   String,   ByVal   nShowCmd   As   Long)   As   Long  
  这个语句又是什么意思?希望熟悉这方面的高手点播。(谁能和我QQ联系一下,我可以把程序发过去让看看。)帖子已经加分到100!!Top

7 楼cosio()回复于 2004-11-05 11:02:36 得分 15

调   用动态链接库   shell32.dll  
   
  (ByVal   hwnd   As   Long,   ByVal   lpOperation   As   String,   ByVal   lpFile   As   String,   _  
                  ByVal   lpParameters   As   String,   ByVal   lpDirectory   As   String,   ByVal   nShowCmd   As   Long)   As   Long  
   
   
  这个它的参数Top

8 楼yijiangmingyue(一江明月)回复于 2004-11-05 11:27:24 得分 5

我没看你程序,但有一点不知有没有用,通讯的上位机与下位机之间的波特率要一致.否则可能接收的字符出现乱码或没有.Top

9 楼WoLoveXYL(阿刺)回复于 2004-11-05 14:57:13 得分 10

单步调试一下就知道了。oncomm事件里不要坐判断。会导致延迟,你收不全的。代码越多丢的越多。  
  最好的方法,用事件驱动,收到数据,只坐一步,缓存累加,缓存设置事件,去检查收到的数据。Top

10 楼aohan(aohan)回复于 2004-11-05 21:31:42 得分 15

//转贴  
  用Win32   API实现串行通信      
  2003-1-30   14:44:25      
        串口是常用的计算机与外部串行设备之间的数据传输通道,由于串行通信方便易行,所以应用广泛。我们可以利用Windows   API   提供的通信函数编写出高可移植性的串行通信程序。    
        在Win16中,可以利用OpenComm、CloseComm和WriteComm等函数打开、关闭和读写串口。但在Win32中,串口和其他通信设备均被作为文件处理,串口的打开、关闭和读写等操作所用的API函数与操作文件的函数相同。可通过CreateFile函数打开串口,通过CloseFile函数关闭串口,通过CommProp、DCB结构、GetCommProperties、SetCommProperties、GetCommState及SetCommState等函数设置串口状态,通过函数ReadFile和WritFile读写串口。    
          VC++   6.0是Windows应用程序开发的主流语言之一,它具有良好的图形设计界面并支持面向对象的程序设计方法。本文结合一个实例介绍在VC++   6.0下如何利用Win32   API   实现串行通信程序。    
  实现原理    
          本文的实例来自一个水泥发货系统,在系统中,需要将通过总量传感器采集到的仓重值传入到计算机中,以便系统做出相应的处理。这需要使用串行通信来完成采集数据的传递工作。    
          对于串行通信设备,Win32   API支持同步和异步两种I/O操作。同步操作方式的程序设计相对比较简单,但I/O操作函数在I/O操作结束前不能返回,这将挂起调用线程,直到I/O操作结束。异步操作方式相对要复杂一些,但它可让耗时的I/O操作在后台进行,不会挂起调用线程,这在大数据量通信的情况下对改善调用线程的响应速度是相当有效的。异步操作方式特别适合同时对多个串行设备进行I/O操作和同时对一个串行设备进行读/写操作。这两种操作方式的程序设计基本思想是相似的,本文将针对同步操作方式给出具体的通信程序设计,同时简单说明如何实现异步的I/O操作。    
  串行设备的初始化    
          串行设备的初始化是利用CreateFile函数实现的。该函数获得串行设备句柄并对其进行通信参数设置,包括设置输出/接收缓冲区大小、超时控制和事件监视等。      
  //串行设备句柄;      
  HANDLE   hComDev=0;        
  //串口打开标志;      
  BOOL   bOpen=FALSE;      
  //线程同步事件句柄;      
  HANDLE   hEvent=0;        
  BOOL   SetupSynCom()      
  {        
   DCB   dcb;      
   COMMTIMEOUTS   timeouts;      
   //设备已打开      
   if(bOpen)   return   FALSE;         
   //打开COM1      
  if((hComDev=CreateFile(“COM1”,GENERICREAD|GENERICWRITE,0,NULL,OPENEXISTING,FILEATTRIBUTENORMAL,NULL))==      
  INVALIDHANDLEVALUE)       
  return   FALSE;      
  //设置超时控制      
  SetCommTimeouts(hComDev,&timeouts);        
   //设置接收缓冲区和输出缓冲区的大小      
   SetupComm(hComDev,1024,512);        
  //获取缺省的DCB结构的值      
   GetCommState(hComDev,&dcb);        
  //设定波特率为9600   bps      
   dcb.BaudRate=CBR9600;        
  //设定无奇偶校验      
   dcb.fParity=NOPARITY;        
  //设定数据位为8      
   dcb.ByteSize=8;        
   //设定一个停止位      
   dcb.StopBits=ONESTOPBIT;        
  //监视串口的错误和接收到字符两种事件      
   SetCommMask(hComDev,EVERR|EVRXCHAR);        
  //设置串行设备控制参数      
   SetCommState(hComDev,&dcb);        
  //设备已打开      
   bOpen=TRUE;        
   //创建人工重设、未发信号的事件      
   hEvent=CreateEvent(NULL,FALSE,FALSE,      
  “WatchEvent”);      
  //创建一个事件监视线程来监视串口事件      
   AfxBeginThread(CommWatchProc,pParam);        
  }      
          在设置串口DCB结构的参数时,不必设置每一个值。首先读出DCB缺省的参数设置,然后只修改必要的参数,其他参数都取缺省值。由于对串口进行的是同步I/O操作,所以除非指定进行监测的事件发生,否则WaitCommEvent函数不会返回。在串行设备初始化的最后要建立一个单独的监视线程来监视串口事件,以免挂起当前调用线程,其中pParam可以是一个对事件进行处理的窗口类指针。    
  如果要进行异步I/O操作,打开设备句柄时,CreateFile的第6个参数应增加FILEFLAGOVERLAPPED   标志。    
  数据发送      
          数据发送利用WriteFile函数实现。对于同步I/O操作,它的最后一个参数可为NULL;而对异步I/O操作,它的最后一个参数必需是一个指向OVERLAPPED结构的指针,通过OVERLAPPED结构来获得当前的操作状态。      
  BOOL   WriteComm(LPCVOID   lpSndBuffer,DWORD        
  dwBytesToWrite)      
  {   //lpSndBuffer为发送数据缓冲区指针,      
  dwBytesToWrite为将要发送的字节长度      
  //设备已打开      
   BOOL   bWriteState;        
  //实际发送的字节数      
   DWORD   dwBytesWritten;        
  //设备未打开      
   if(!bOpen)   return   FALSE;        
   bWriteState=WriteFile(hComDev,lpSndBuffer,      
  dwBytesToWrite,&dwBytesWritten,NULL);      
   if(!bWriteState   ||   dwBytesToWrite!=dwBytesWritten)      
  //发送失败      
    return   FALSE;        
   else      
  //发送成功      
    return   TRUE;        
  }      
  数据接收      
          接收数据的任务由ReadFile函数完成。该函数从串口接收缓冲区中读取数据,读取数据前,先用ClearCommError函数获得接收缓冲区中的字节数。接收数据时,同步和异步读取的差别同发送数据是一样的。      
  DWORD   ReadComm(LPVOID   lpInBuffer,DWORD        
  dwBytesToRead)      
  {   //lpInBuffer为接收数据的缓冲区指针,   dwBytesToRead为准备读取的数据长度(字节数)      
  //串行设备状态结构      
   COMSTAT   ComStat;        
   DWORD   dwBytesRead,dwErrorFlags;       
  //设备未打开      
   if(!bOpen)   return   0;      
   //读取串行设备的当前状态      
   ClearCommError(hComDev,&dwErrorFlags,&ComStat);        
   //应该读取的数据长度      
  dwBytesRead=min(dwBytesToRead,ComStat.cbInQue);        
   if(dwBytesRead>0)      
    //读取数据      
    if(!ReadFile(hComDev,lpInBuffer,dwBytesRead,&dwBytesRead,NULL))        
       dwBytesRead=0;      
   return   dwBytesRead;      
  }      
  事件监视线程      
          事件监视线程对串口事件进行监视,当监视的事件发生时,监视线程可将这个事件发送(SendMessage)或登记(PostMessage)到对事件进行处理的窗口类(由pParam指定)中。      
  UINT   CommWatchProc(LPVOID   pParam)      
  {   DWORD   dwEventMask=0;   //发生的事件;      
   while(bOpen)      
   {   //等待监视的事件发生      
  WaitCommEvent(hComDev,   &dwEventMask,        
  NULL);        
   if   ((dwEventMask   &   EVRXCHAR)   ==        
  EVRXCHAR)      
  ……//接收到字符事件后,可以将此消息登记到由pParam有指定的窗口类中进行处理      
    if(dwEventMask   &   EVERR)==EVERROR)      
     ……//发生错误时的处理      
   }      
   SetEvent(hEvent);        
   //发信号,指示监视线程结束      
   return   0;      
  }      
  关闭串行设备      
          在整个应用程序结束或不再使用串行设备时,应将串行设备关闭,包括取消事件监视,将设备打开标志bOpen置为FALSE以使事件监视线程结束,清除发送/接收缓冲区和关闭设备句柄。      
  void   CloseSynComm()      
  {        
  if(!bOpen)   return;      
  //结束事件监视线程      
   bOpen=FALSE;        
   SetCommMask(hComDev,0);        
   //取消事件监视,此时监视线程中的WaitCommEvent将返回      
   WaitForSingleObject(hEvent,INFINITE);      
   //等待监视线程结束      
   CloseHandle(hEvent);   //关闭事件句柄      
   //停止发送和接收数据,并清除发送和接收缓冲区      
  PurgeComm(hComDev,PURGETXABORT|      
  PURGERXABORT|PURGETXCLEAR|      
  PURGERXCLEAR);      
  //关闭设备句柄      
   CloseHandle(hComDev);        
  }    
  小结    
          以上给出了用Win32   API   设计串行通信的基本思路,对这个同步I/O操作的串行通信程序稍加改造就可进行异步I/O操作。在实际应用中,我们可以将这些串行通信函数和成员变量加到一个已有的CWnd类或其派生类中来实现串行通信,也可设计一个新的串行通信类来包含这些成员函数和成员变量。总之,利用Win32   API可以设计出满足各种需要的串行通信程序。    
  Top

相关问题

  • 急!急!急!CE下的串口通信,高手急救!!!
  • 急!急!!急!!!高分求救!!!串口通信问题...(up有分)
  • 串口通信的高手请指教!!急急!
  • 急急急,在delphi中用汇编语言编写串口通信程序。
  • 急急急!!!在串口通信中接收时数据总有丢失出现.
  • 急急急!!!在串口通信中接收时数据总有丢失出现.
  • 关于串口通信!急。。。。
  • 串口通信问题,急!!!
  • 一个串口通信的问题!急!!!
  • 关于串口通信的问题,急!!!

关键词

  • win32 api
  • 函数
  • 监视
  • 线程
  • 数据
  • 通信
  • 字符
  • datareceive
  • 串行
  • 串口

得分解答快速导航

  • 帖主:langlg855
  • hellobcb
  • aohan
  • tztz520
  • cosio
  • yijiangmingyue
  • WoLoveXYL
  • aohan

相关链接

  • Visual Basic类图书
  • Visual Basic类源码下载

广告也精彩

反馈

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