呵呵,无人响应,
我有一篇剪下来的文章:“用C++BUILDER4.0编写win95下的串行异步通讯程序”
是API的,出自98年的计算机世界,没法输进去,作者例子也不详细,

解决方案 »

  1.   

    核心:
    1.hcon=CreateFile("COM2",GENERIC_READ|GENERIC_WRITE,
            0,NULL,OPEN_EXISTING,FILE_ATTRIB_NORMAL|FILE_FLAG_OVERLAPPED,NULL);
    2.BuildCommDCB("9600,0,8,1",&dcb);    
    3.SetCommState(hcon,&dcb);           
    4.SetupComm(hcon,512,512);   //读写缓冲大小
    5.e.hEvent=CreateEvent(NULL,false,false,NULL);  // 事件
    6.SetCommMask(hcon,EV_RXCHAR|EV_TXEMPTY);       //事件掩码
       ReadFile() 与 WriteFile( )读写串口作者没写了,对照上面查一查API邦助
      

  2.   

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
        HANDLE hcon=CreateFile("COM2",GENERIC_READ|GENERIC_WRITE,
                    0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|
                     FILE_FLAG_OVERLAPPED,NULL);
        DCB  dcb;
        OVERLAPPED e;    BuildCommDCB("9600,0,8,1",&dcb);
        SetCommState(hcon,&dcb);
        SetupComm(hcon,512,512);  //读写缓冲大小
        e.hEvent=CreateEvent(NULL,false,false,NULL);  // 事件
        SetCommMask(hcon,EV_RXCHAR|EV_TXEMPTY);      //事件掩码
       //    ReadFile() 与 WriteFile( )读写串口
        CloseHandle(hcon);
    }
    编译能通过
      

  3.   

    串口的初始化都可以了。
    问题在readfile,writefile可以写出readfile,writefile代码吗?
    调试通过马上给分。 
      

  4.   

    作者还提示:
        WaitCommEvent()监视通讯事件,参数lpEvtMask指向产生事件的掩码地址,
    用于什么事件,事件产生时,ReadFile()与WriteFile()就可读写了,
    核心就是通讯事件的设定了,快了!!!!!!!!!!!!!
      

  5.   

    以下是摘自自己写的 CMSComm类中的两个函数LPSTR CMSComm::GetInput()
    {
    DWORD dwModemStatus ;
    do
    {
    WaitCommEvent( m_hComDev , &dwModemStatus , 0 ) ;
    GetCommModemStatus( m_hComDev , &dwModemStatus ) ;
    }while( dwModemStatus&(EV_RLSD|EV_RXCHAR) == 0 ) ;
    ;
    while ( !::ReadFile( m_hComDev , m_cpInBuffer , m_nInputLen , &m_nInBufferCount , 0 ) )
    {
    dwModemStatus = GetLastError() ;
    m_bOpen = FALSE ;
    if ( dwModemStatus != ERROR_INVALID_HANDLE )
    {
    CloseHandle( m_hComDev ) ;
    SetPortOpen( TRUE ) ;
    }
    SetPortOpen( TRUE ) ;
    }
    }int CMSComm::SetOutput(VARIANT varOut)
    {
    CString sOut = varOut.bstrVal ;
    DWORD m_nOutBufferCount , dwModemStatus;
    do
    {
    WaitCommEvent( m_hComDev , &dwModemStatus , 0 ) ;
    GetCommModemStatus( m_hComDev , &dwModemStatus ) ;
    }while( dwModemStatus&MS_RLSD_ON == 0 ) ; while (!::WriteFile( m_hComDev , sOut , sOut.GetLength() , &m_nOutBufferCount , 0 ) )
    {
    dwModemStatus = GetLastError() ;
    m_bOpen = FALSE ;
    if ( dwModemStatus != ERROR_INVALID_HANDLE )
    {
    CloseHandle( m_hComDev ) ;
    SetPortOpen( TRUE ) ;
    }
    m_nOutBufferCount = 0 ;
    } return m_nOutBufferCount ;
    }
      

  6.   

    最简单的:
    {
      Read(COM1);
      Send(COM2);
      return;
    }
      

  7.   

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
        HANDLE hcon=CreateFile("COM2",GENERIC_READ|GENERIC_WRITE,
                    0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|
                     FILE_FLAG_OVERLAPPED,NULL);
        DCB  dcb;
        OVERLAPPED e;    BuildCommDCB("9600,0,8,1",&dcb);
        SetCommState(hcon,&dcb);
        SetupComm(hcon,512,512);  //读写缓冲大小
        e.hEvent=CreateEvent(NULL,false,false,NULL);  // 事件
        SetCommMask(hcon,EV_RXCHAR|EV_TXEMPTY);      //事件掩码
       //    ReadFile() 与 WriteFile( )读写串口    COMMTIMEOUTS  commtime={1000,1000,1000,1000,1000};
        SetCommTimeouts(hcon,&commtime);  // 超时设定    DWORD EvtMask;   // 掩码
        while ( !Application->Terminated  &&
                   WaitCommEvent(hcon,&EvtMask,0) )
          {
             switch (EvtMask)
               {
                  case EV_RXCHAR:                          break;
                  case EV_TXEMPTY:                          break;
               }
             Application->ProcessMessages();
          }    CloseHandle(hcon);
    }
    // 好象进入死循环了
      

  8.   

    你不想要DELPHI的吗???
      

  9.   

    to hlbl11:
      有delphi的请贴出来。
      

  10.   

    to hlbl11:
      有delphi的请贴出来。
      

  11.   

    转(用DELPHI进行 Win32环境下串行通讯的程序设计 ) 张秀德 姜新通   张冬生  
    利用一条串行数据线连接在两台计算机Com2之间就可以进行文本文件传输。对于Delphi的具体编程方法这里不再赘述。实例中有详细注释。
    unit comunate;
    interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
      Dialogs, Buttons, StdCtrls, ComCtrls;
    const
      WM_COMMNOTIFY = WM_USER + 1;  // 通讯消息type
      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        Button3: TButton;
        Button4: TButton;
       OpenDialog1: TOpenDialog;
       Label1: TLabel;
       BitBtn1: TBitBtn;
       RichEdit1: TRichEdit;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure Button3Click(Sender: TObject);
        procedure Button4Click(Sender: TObject);
      private
        { Private declarations }
        procedure WMCOMMNOTIFY(var Message :TMessage);message WM_COMMNOTIFY;
      public
        { Public declarations }
      end;
    var
      Form1: TForm1;
    implementation{$R *.DFM}
    var
      hNewCommFile,Post_Event: THandle;
      Read_os : Toverlapped;
      Receive :Boolean;
      ReceiveData : Dword;
      
    procedure AddToMemo(Str:PChar;Len:Dword);  // 接收的数据送入显示区
    begin
      str[Len]:=#0;
      Form1.RichEdit1.Text:=Form1.RichEdit1.Text+StrPas(str);
    end;
      
    procedure CommWatch(Ptr:Pointer);stdcall;     // 通讯监视线程
    var
      dwEvtMask,dwTranser : Dword;
      Ok : Boolean;
      Os : Toverlapped;
    begin
      Receive :=True;
      FillChar(Os,SizeOf(Os),0);
      Os.hEvent :=CreateEvent(nil,True,False,nil); // 创建重叠读事件对象
      if Os.hEvent=null then
        begin
          MessageBox(0,'Os.Event Create Error !','Notice',MB_OK);
          Exit;
        end;
      if (not SetCommMask(hNewCommFile,EV_RXCHAR)) then
        begin
          MessageBox(0,'SetCommMask Error !','Notice',MB_OK);
          Exit;
        end;
      while(Receive) do
        begin
          dwEvtMask:=0;
          // 等待通讯事件发生
          if not WaitCommEvent(hNewCommFile,dwEvtMask,@Os) then
            begin
              if ERROR_IO_PENDING=GetLastError then
                 GetOverLappedResult(hNewCommFile,Os,dwTranser,True)
            end;
          if ((dwEvtMask and EV_RXCHAR)=EV_RXCHAR) then
            begin
              // 等待允许传递WM_COMMNOTIFY通讯消息
              WaitForSingleObject(Post_event,INFINITE);
              // 处理WM_COMMNOTIFY消息时不再发送WM_COMMNOTIFY消息
              ResetEvent(Post_Event);
              // 传递WM_COMMNOTIFY通讯消息
              Ok:=PostMessage(Form1.Handle,WM_COMMNOTIFY,hNewCommFile,0);
              if (not Ok) then
                begin
                  MessageBox(0,'PostMessage Error !','Notice',MB_OK);
                  Exit;
                end;
            end;
        end;
      CloseHandle(Os.hEvent); // 关闭重叠读事件对象
    end;procedure TForm1.WMCOMMNOTIFY(var Message :TMessage);  // 消息处理函数
    var
      CommState : ComStat;
      dwNumberOfBytesRead : Dword;
      ErrorFlag : Dword;
      InputBuffer : Array [0..1024] of Char;
    begin
      if not ClearCommError(hNewCommFile,ErrorFlag,@CommState) then
        begin
          MessageBox(0,'ClearCommError !','Notice',MB_OK);
          PurgeComm(hNewCommFile,Purge_Rxabort or Purge_Rxclear);
          Exit;
        end;
      if (CommState.cbInQue>0) then
        begin
          fillchar(InputBuffer,CommState.cbInQue,#0);
          // 接收通讯数据
          if (not ReadFile( hNewCommFile,InputBuffer,CommState.cbInQue,
                            dwNumberOfBytesRead,@Read_os )) then
            begin
              ErrorFlag := GetLastError();
              if (ErrorFlag <> 0) and (ErrorFlag <> ERROR_IO_PENDING) then
                begin
                  MessageBox(0,'ReadFile Error!','Notice',MB_OK);
                  Receive :=False;
                  CloseHandle(Read_Os.hEvent);
                  CloseHandle(Post_Event);
                  CloseHandle(hNewCommFile);
                  Exit;
                end
              else
                begin           
                  WaitForSingleObject(hNewCommFile,INFINITE); // 等待操作完成
                  GetOverlappedResult(hNewCommFile,Read_os,
                                      dwNumberOfBytesRead,False);
                end;
            end;
          if dwNumberOfBytesRead>0 then
            begin
              Read_Os.Offset :=Read_Os.Offset+dwNumberOfBytesRead;
              ReceiveData := Read_Os.Offset;
              // 处理接收的数据
              AddToMemo(InputBuffer,dwNumberOfBytesRead);
            end;
    end;
      // 允许发送下一个WM_COMMNOTIFY消息
      SetEvent(Post_Event);
    end;procedure TForm1.Button1Click(Sender: TObject); // 打开文件用于发送
    begin
      if OpenDialog1.Execute then
        begin
          Button3.Enabled :=False;
          Button4.Enabled :=False;
          RichEdit1.Lines.LoadFromFile(OpenDialog1.FileName);
          Form1.Caption := IntToStr(RichEdit1.GetTextLen);
        end;
        Button1.Enabled :=False;
    end;
      
    procedure TForm1.Button2Click(Sender: TObject); // 发送数据
    var
      dcb : TDCB;
      Error :Boolean;
      dwNumberOfBytesWritten,dwNumberOfBytesToWrite,
      ErrorFlag,dwWhereToStartWriting : DWORD;
      pDataToWrite : PChar;
      write_os: Toverlapped;
    begin
      Form1.Caption :='';
      // 打开通讯端口COM2
      hNewCommFile:=CreateFile( 'COM2',GENERIC_WRITE,0,
                               nil, OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0 );
      if hNewCommFile = INVALID_HANDLE_VALUE then
         MessageBox(0,'Error opening com port!','Notice',MB_OK);
      SetupComm(hNewCommFile,1024,1024); // 设置缓冲区大小及主要通讯参数
      GetCommState( hNewCommFile,dcb);
      dcb.BaudRate :=9600;
      dcb.ByteSize :=8;
      dcb.Parity :=NOPARITY;
      dcb.StopBits := ONESTOPBIT;
      Error := SetCommState( hNewCommFile, dcb );
      if ( not Error) then MessageBox(0,'SetCommState Error!','Notice',MB_OK);
      dwWhereToStartWriting := 0;
      dwNumberOfBytesWritten := 0;
      dwNumberOfBytesToWrite :=RichEdit1.GetTextLen;
      if (dwNumberOfBytesToWrite=0) then
        begin
          ShowMessage('Text Buffer is Empty!');
          Exit;
        end
      else
        begin
          pDataToWrite:=StrAlloc(dwNumberOfBytesToWrite+1);
          try
            RichEdit1.GetTextBuf(pDataToWrite,dwNumberOfBytesToWrite);
            Label1.Font.Color :=clRed;
            FillChar(Write_Os,SizeOf(write_os),0);
            // 为重叠写创建事件对象
            Write_Os.hEvent := CreateEvent(nil,True,False,nil);
            SetCommMask(hNewCommFile,EV_TXEMPTY);
            Label1.Caption:='正在发送数据...!';
               repeat
               Label1.Repaint;
               // 发送通讯数据
               if not WriteFile( hNewCommFile,pDataToWrite[dwWhereToStartWriting],
                                  dwNumberOfBytesToWrite,dwNumberOfBytesWritten,
                             @write_os ) then
               begin
                   ErrorFlag :=GetLastError;
                   if ErrorFlag<>0 then
                     begin
                      if ErrorFlag=ERROR_IO_PENDING then
                         begin
                           WaitForSingleObject(Write_Os.hEvent,INFINITE);
                           GetOverlappedResult(hNewCommFile,Write_os,
                                               dwNumberOfBytesWritten,False);
                         end
                       else
                         begin
                           MessageBox(0,'WriteFile Error!','Notice',MB_OK);
                           Receive :=False;
                           CloseHandle(Read_Os.hEvent);
                           CloseHandle(Post_Event);
                           CloseHandle(hNewCommFile);
                           Exit;
                         end;
                    end;
                 end;
             Dec( dwNumberOfBytesToWrite, dwNumberOfBytesWritten );
               Inc( dwWhereToStartWriting, dwNumberOfBytesWritten );
            until (dwNumberOfBytesToWrite <= 0);  // Write the whole thing!
            Form1.Caption:=IntToStr(dwWhereToStartWriting);
          finally
            StrDispose(pDataToWrite);
          end;
          CloseHandle(hNewCommFile);
        end;
      Label1.Font.Color :=clBlack;
      Label1.Caption:='发送成功!';
      Button1.Enabled :=True;
      Button3.Enabled :=True;
      Button4.Enabled :=True;
    end;
      
    procedure TForm1.Button3Click(Sender: TObject); // 接收处理
    var
      Ok : Boolean;
      dcb : TDCB;
      com_thread: Thandle;
      ThreadID:DWORD;
    begin
      ReceiveData :=0;
      Button1.Enabled :=False;
      Button2.Enabled :=False;
      RichEdit1.Clear;
      // 打开COM2
      hNewCommFile:=CreateFile( 'COM2',GENERIC_READ,0,
                             nil, OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0 );
      if hNewCommFile = INVALID_HANDLE_VALUE then
         begin
           MessageBox(0,'Error opening com port!','Notice',MB_OK);
           Exit;
         end;
      Ok:=SetCommMask(hNewCommFile,EV_RXCHAR);
      if ( not Ok) then
        begin
          MessageBox(0,'SetCommMask Error!','Notice',MB_OK);
          Exit;
        end;
      SetupComm(hNewCommFile,1024,1024);
      GetCommState( hNewCommFile, dcb );
      dcb.BaudRate :=9600;
      dcb.ByteSize :=8;
      dcb.Parity :=NOPARITY;
      dcb.StopBits := ONESTOPBIT;
      Ok := SetCommState( hNewCommFile, dcb );
      if ( not Ok) then MessageBox(0,'SetCommState Error!','Notice',MB_OK);
      FillChar(Read_Os,SizeOf(Read_Os),0);
      Read_Os.Offset := 0;
      Read_Os.OffsetHigh := 0;
      // Create Event for Overlapped Read
      Read_Os.hEvent :=CreateEvent(nil,true,False,nil);
      if Read_Os.hEvent=null then
        begin
          CloseHandle(hNewCommFile);
          MessageBox(0,'CreateEvent Error!','Notice',MB_OK);
          Exit;
        end;  // Create Event for PostMessage
      Post_Event:=CreateEvent(nil,True,True,nil);
      if Post_Event=null then
        begin
          CloseHandle(hNewCommFile);
          CloseHandle(Read_Os.hEvent);
          MessageBox(0,'CreateEvent Error!','Notice',MB_OK);
          Exit;
    end;  // 建立通信监视线程
      Com_Thread:=CreateThread(nil,0,@CommWatch,nil,0,ThreadID);
      if (Com_Thread=0) then
        MessageBox(Handle,'No CraeteThread!',nil,mb_OK);
      EscapeCommFunction(hNewCommFile,SETDTR);
      Label1.Font.Color :=clRed;
      Label1.Caption:='正在接收数据...!';
    end;procedure TForm1.Button4Click(Sender: TObject); // 停止通讯处理
    begin
      Label1.Font.Color :=clBlack;
      Label1.Caption:='infomation';
      Form1.Caption := IntToStr(ReceiveData);
      Receive :=False;
      CloseHandle(Read_Os.hEvent);
      CloseHandle(Post_Event);
      CloseHandle(hNewCommFile);
      Button1.Enabled :=True;
      Button2.Enabled :=True;
    end;
    end.
    参考文献 
    1.Windows95 Windows NT3.5高级编程技术 Jeffrey Richter著
    2.基于Windows 95&NT的串行通信编程 李柯 <<微电脑世界>> 1997。5
    3.Windows 95中的串行通信 王齐 <<微电脑世界>> 1997。3
      

  12.   

    上面的太长了,你们没用过MOXA的驱动程序吗?你们通讯的实时性也用不到消息级吧。如果你要,就给出分和你的EMAIL,那程序都放了3年了。
      

  13.   

    to hlb11:
       [email protected].
       如果给的程序调试通过,将为你另开一题,给出100分。
      

  14.   

    btw:
       app2001,WM_COMMNOTIFY消息好像是针对win31的,而win32下是直接对串口进行read/writefile的吧。
      

  15.   

    WaitCommEvent(hcon,&EvtMask,0);这个语句老是死等待事件出现,
    程序都没法中止了;
      

  16.   

    为什么我的Comstat结构的cbInQue值总为0.不管是写入(成功),还是读出。
      

  17.   

    to hlb11: 正等着你的程序。
      

  18.   

    to illcat:
       SetPortOpen(true);
    怎么查不到这个函数?自定义的?
    与m_bOpen一起标记端口是否再用?!
      

  19.   

    To BCB:比较关心异步通信的方法,不知能否谈的具体一点.另外至于你提到的死循环的问题,我是用开辟一个通信事件控制线程解决的.还有就是我发现大部分人都是用PostMessage这个函数.先开始我也用它,但发现程序根本没有反应,具体原因我忘记了(对不起,时间太久了)后来我改用SendMessage结果一切问题OK!尽管我也知道这两个函数的区别,但因为时间紧,没有过多考虑,不知现在那位能否解释一下该问题.
      

  20.   

    为什么不用多线程?你可以作一个控制通信事件的多线程,这样你就可以在其它线程和主线程中做你自己的工作了.另外我还想请教一个问题.由于我是在学VC不久就接触了串口编程的问题.所以还有问题到现在还是很糊涂,我想问一下,为什么你们都调用PostMessage函数而不用SendMessage这个函数.我记的当时编串口通信的时候开始也用了PostMessage,可一运行没什么反应.但是当我换成SendMessage后,一切OK!该线程和其它线程运行非常稳定.请问这是为什么?我也看过MSDN但还是找不出原因.
      

  21.   

    PostMessage是将消息放入消息列表中然后就退出来了,消息有没有被接受就不清楚了。:)SendMessage是发送消息并等待消息执行完毕。:)我写过PCTOPC,是使用MODEM的两台机子对连的,使用了,3个线程,主线程负责界面更新,一个线程负责发,一个线程负责收。:)
      

  22.   

    to all:没有过期。to BCB:不是死循环.
      

  23.   

    to hawk_yan:不是不使用多线程。我只是想搞清楚同步通信是如何一回事。而且在我发出到绶冲区的数据在ReadFile中读不出来,你能写一段程序(ReadFile)吗?我是同一串口收发。保证这个贴子在200分以上。
      

  24.   

    procedure TForm1.Button1Click(Sender: TObject);
    var
      CommID:Thandle;
      CommStateDCB:TDCB;
      ComState:TComStat;
      lpCommTimeOuts:COMMTIMEOUTS  ;
      dwBytesWritten,ReadBuffError:DWord;
    begin
    CommID := CreateFile( 'Com2',GENERIC_READ or GENERIC_WRITE,
                              0,nil,OPEN_EXISTING,0,0);
    GetCommState(CommID,CommStateDCB);//CommStateDCB:TDCB;
    CommStateDCB.BaudRate :=9600;
    CommStateDCB.Parity:=NOParity;
    CommStateDCB.ByteSize:=8;
    CommStateDCB.StopBits:=0;
    CommStateDCB.Flags:=0;
    SetCommState(CommID,CommStateDCB);
         lpCommTimeOuts.ReadIntervalTimeout:=MAXDWORD;
         lpCommTimeOuts.ReadTotalTimeoutMultiplier:=0;
         lpCommTimeOuts.ReadTotalTimeoutConstant:=0;
         lpCommTimeOuts.WriteTotalTimeoutMultiplier:=0;
         lpCommTimeOuts.WriteTotalTimeoutConstant:=0;
         SetCommTimeouts(CommID,lpCommTimeOuts);
       PurgeComm(CommID,PURGE_TXCLEAR);
       PurgeComm(CommID,PURGE_RXCLEAR);
       WriteFile(CommID,'aaaa',3,Dword(dwBytesWritten),nil);
       ClearCommError(CommID,ReadBuffError,@ComState);
       if ComState.cbInQue  > 0 Then //检查串口状态     ??为什么为0
         Showmessage('有数据');
    //   ReadFile(CommID,tempstr,ReadBuffLen,dwBytesWritten,nil);//从串口读取数据
       CloseHandle(CommID) ;
       //关闭串口
    end;
      

  25.   

    zoao() .不好意思.很久没来了,现在给你发过去,希望能帮上你忙!
      

  26.   

    to hlbl11:
        没有收到你的程序。给的成诺继续有效(另开一题)。
        请重发[email protected]:能写上你的oicq吗?  me 6082316