api串口通信实例

我这里有一个示例程序,功能不是很强,但是学习串口API编程还是可以的:  
   
  unit   Unit1;  
   
  interface  
   
  uses  
      Windows,   Messages,   SysUtils,   Variants,   Classes,   Graphics,   Controls,   Forms,  
      Dialogs,   StdCtrls,   ComCtrls;  
   
  const  
      WM_COMMNOTIFY   =   WM_USER   +   100;   //   通讯 消息  
   
  type  
      TForm1   =   class(TForm)  
          StatusBar1:   TStatusBar;  
          Memo1:   TMemo;  
          Memo2:   TMemo;  
          Label1:   TLabel;  
          Label2:   TLabel;  
          GroupBox1:   TGroupBox;  
          Label3:   TLabel;  
          Label4:   TLabel;  
          Label5:   TLabel;  
          Label6:   TLabel;  
          ComboBox4:   TComboBox;  
          ComboBox3:   TComboBox;  
          ComboBox2:   TComboBox;  
          ComboBox1:   TComboBox;  
          Label7:   TLabel;  
          ComboBox5:   TComboBox;  
          btnOpenCom:   TButton;  
          btnSendData:   TButton;  
          btnReceiveData:   TButton;  
          btnCloseCom:   TButton;  
          procedure   btnOpenComClick(Sender:   TObject);  
          procedure   FormCreate(Sender:   TObject);  
          procedure   btnCloseComClick(Sender:   TObject);  
          procedure   btnSendDataClick(Sender:   TObject);  
          procedure   btnReceiveDataClick(Sender:   TObject);  
      private  
          {   Private   declarations   }  
          procedure   WMCOMMNOTIFY(var   Message   :TMessage);message   WM_COMMNOTIFY;  
      public  
          {   Public   declarations   }  
      end;  
   
  var  
      Form1:   TForm1;  
   
  implementation  
   
  {$R   *.dfm}  
   
  var  
      CommHandle:THandle;  
      PostEvent:THandle;  
      ReadOs   :   Toverlapped;  
      Connected:Boolean;  
      Receive   :Boolean;  
      ReceiveData   :   Dword;  
   
  procedure   AddToMemo(Str:PChar;Len:Dword);   //   接收的数据送入显示区Memo2  
  begin  
      //设置接收后的字符串为NULL终止  
      str[Len]:=#0;  
      Form1.Memo2.Text:=Form1.Memo2.Text+StrPas(str);  
  end;  
   
   
  procedure   CommWatch(Ptr:Pointer);stdcall;   //   通讯监视线程  
  var  
      dwEvtMask,dwTranser   :   Dword;  
      PostMsgFlag:   Boolean;  
      overlapped   :   Toverlapped;  
   
  begin  
      Receive   :=True;  
      FillChar(overlapped,SizeOf(overlapped),0);  
      overlapped.hEvent   :=CreateEvent(nil,True,False,nil);   //   创建重叠读事件对象  
      if   overlapped.hEvent=null   then  
      begin  
          MessageBox(0,'overlapped.Event   Create   Error   !','Notice',MB_OK);  
          Exit;  
      end;  
   
      //进入串口监视状态,直到全局变量Receive置为False停止  
      while(Receive)   do  
      begin  
          dwEvtMask:=0;  
          //   等待串口事件发生  
          if   not   WaitCommEvent(CommHandle,dwEvtMask,@overlapped)   then  
          begin  
              if   ERROR_IO_PENDING=GetLastError   then  
                  GetOverLappedResult(CommHandle,overlapped,dwTranser,True)  
              end;  
   
              //串口读事件发布消息    
              if   ((dwEvtMask   and   EV_RXCHAR)=EV_RXCHAR)   then  
              begin  
                  //   等待允许传递WM_COMMNOTIFY通讯消息  
                  WaitForSingleObject(Postevent,INFINITE);  
                  //   处理WM_COMMNOTIFY消息时不再发送WM_COMMNOTIFY消息  
                  ResetEvent(PostEvent);  
                  //   传递WM_COMMNOTIFY通讯消息,告知主线程调用读串口的过程  
                  PostMsgFlag:=PostMessage(Form1.Handle,WM_COMMNOTIFY,CommHandle,0);  
                  if   (not   PostMsgFlag)   then  
                  begin  
                      MessageBox(0,'PostMessage   Error   !','Notice',MB_OK);  
                      Exit;  
                  end;  
              end;  
          end;  
          CloseHandle(overlapped.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(CommHandle,ErrorFlag,@CommState)   then  
      begin  
          MessageBox(0,'ClearCommError   !','Notice',MB_OK);  
          PurgeComm(CommHandle,Purge_Rxabort   or   Purge_Rxclear);  
          Exit;  
      end;  
   
      if   CommState.cbInQue>0   then  
      begin  
          fillchar(InputBuffer,CommState.cbInQue,#0);  
          //   接收通讯数据  
          if   (not   ReadFile(   CommHandle,InputBuffer,CommState.cbInQue,  
                                    dwNumberOfBytesRead,@ReadOs   ))   then  
          begin  
              ErrorFlag   :=   GetLastError();  
              if   (ErrorFlag   <>   0)   and   (ErrorFlag   <>   ERROR_IO_PENDING)   then  
              begin  
                  MessageBox(0,'ReadFile   Error!','Notice',MB_OK);  
                  Receive   :=False;  
                  CloseHandle(ReadOs.hEvent);  
                  CloseHandle(PostEvent);  
                  CloseHandle(CommHandle);  
                  Exit;  
              end  
              else   begin  
                  WaitForSingleObject(CommHandle,INFINITE);   //   等待操作完成  
                  GetOverlappedResult(CommHandle,ReadOs,dwNumberOfBytesRead,False);  
              end;  
          end;  
          if   dwNumberOfBytesRead>0   then  
          begin  
              ReadOs.Offset   :=ReadOs.Offset+dwNumberOfBytesRead;  
              ReceiveData   :=   ReadOs.Offset;  
              //   处理接收的数据  
              AddToMemo(InputBuffer,dwNumberOfBytesRead);  
          end;  
      end;  
      //   允许发送下一个WM_COMMNOTIFY消息  
      SetEvent(PostEvent);  
  end;  
   
   
  procedure   TForm1.btnOpenComClick(Sender:   TObject);  
  var  
          CommTimeOut   :   TCOMMTIMEOUTS;  
          DCB   :   TDCB;  
   
  begin  
          StatusBar1.SimpleText   :=   '连接中...';  
   
          //发送消息的句柄  
          PostEvent:=CreateEvent(nil,True,True,nil);  
          if   PostEvent=null   then  
          begin  
                  MessageBox(0,'CreateEvent   Error!','Notice',MB_OK);  
                  StatusBar1.SimpleText   :=   '串口打开失败';  
                  Exit;  
          end;  
   
          //Overlapped   Read建立句柄  
          ReadOs.hEvent   :=CreateEvent(nil,true,False,nil);  
          if   ReadOs.hEvent=null   then  
          begin  
                  MessageBox(0,'CreateEvent   Error!','Notice',MB_OK);  
                  CloseHandle(PostEvent);  
                  StatusBar1.SimpleText   :=   '串口打开失败';  
                  Exit;  
          end;  
   
          //建立串口句柄  
          CommHandle   :=   CreateFile(PChar(ComboBox1.Text),GENERIC_WRITE   or   GENERIC_READ,  
                            0,nil,OPEN_EXISTING,FILE_FLAG_OVERLAPPED   or   FILE_ATTRIBUTE_NORMAL,0);  
   
          if   CommHandle   =   INVALID_HANDLE_VALUE   then  
          begin  
                  CloseHandle(PostEvent);  
                  CloseHandle(ReadOs.hEvent);  
                  MessageBox(0,'串口打开失败!','Notice',MB_OK);  
                  StatusBar1.SimpleText   :=   '串口打开失败';  
                  Exit;  
          end;  
          StatusBar1.SimpleText   :=   '已同 端口   '+   ComboBox1.Text   +   '   连接!';  
   
          //设置超时  
          CommTimeOut.ReadIntervalTimeout   :=   MAXDWORD;  
          CommTimeOut.ReadTotalTimeoutMultiplier   :=   0;  
          CommTimeOut.ReadTotalTimeoutConstant   :=   0;  
          SetCommTimeouts(CommHandle,   CommTimeOut);  
   
          //设置读写缓存  
          SetupComm(CommHandle,4096,1024);  
   
          //对串口进行指定配置  
          GetCommState(CommHandle,DCB);  
          DCB.BaudRate   :=   StrToInt(ComboBox2.Text);  
          DCB.ByteSize   :=   StrToInt(ComboBox3.Text);  
          DCB.Parity   :=   ComboBox4.ItemIndex;;  
          DCB.StopBits   :=   ComboBox5.ItemIndex;  
          Connected   :=   SetCommState(CommHandle,   DCB);  
   
          //关系串口的读事件  
          if   (not   SetCommMask(CommHandle,EV_RXCHAR))   then  
          begin  
              MessageBox(0,'SetCommMask   Error   !','Notice',MB_OK);  
              Exit;  
          end;  
   
          if   (Connected)   then  
          begin  
                  btnOpenCom.Enabled   :=False;  
          end  
          else   begin  
                  CloseHandle(CommHandle);  
                  StatusBar1.SimpleText   :=   '设置串口失败';  
          end;  
  end;  
   
  procedure   TForm1.FormCreate(Sender:   TObject);  
  begin  
          Connected:=False;  
          ComboBox1.ItemIndex:=0;  
          ComboBox2.ItemIndex:=0;  
          ComboBox3.ItemIndex:=4;  
          ComboBox4.ItemIndex:=0;  
          ComboBox5.ItemIndex:=0;              
  end;  

procedure   TForm1.btnCloseComClick(Sender:   TObject);  
  begin  
          if   not   Connected   then  
          begin  
                  StatusBar1.SimpleText   :=   '未打开串口';  
                  Exit;  
          end;  
          Receive   :=False;  
          //取消事件监视,此时监视线程中的WaitCommEvent将返回  
          SetCommMask(CommHandle,0);  
          //等待监视线程结束  
          WaitForSingleObject(PostEvent,INFINITE);  
            //关闭事件句柄  
          CloseHandle(PostEvent);  
          //停止发送和接收数据,并清除发送和接收缓冲区  
          PurgeComm(CommHandle,PURGE_TXABORT   or   PURGE_RXABORT   or   PURGE_TXCLEAR   or   PURGE_RXCLEAR);  
            //关闭其他的句柄  
          CloseHandle(ReadOs.hEvent);  
          CloseHandle(CommHandle);          
          btnOpenCom.Enabled   :=True;  
          Connected:=False;  
          StatusBar1.SimpleText   :=   '串口已经关闭';  
  end;  
   
  procedure   TForm1.btnSendDataClick(Sender:   TObject);  
  var  
          Str:String;  
          i:Integer;  
          writeoverlapped:TOverlapped;  
          ByteToWrite,BytesWritten,AllBytesWritten:DWORD;  
          ErrorCode,ErrorFlag:DWORD;  
          CommStat:COMSTAT;  
   
  begin  
          if   not   Connected   then  
          begin  
                  StatusBar1.SimpleText   :=   '未打开串口';  
                  Exit;  
          end;  
   
          if   (Memo1.GetTextLen=0)   then  
          begin  
                  StatusBar1.SimpleText   :=   '缓冲区为空';  
                  Exit;  
          end;  
   
          AllBytesWritten:=0;  
          for   i:=0   to   memo1.Lines.Count-1   do  
          begin  
                  Str:=memo1.Lines[i];  
                  ByteToWrite:=length(Str);  
                  if     ByteToWrite=0   then   continue;  
                  try  
                          StatusBar1.SimpleText   :=   '正在发送数据';  
                          //初始化一步读写结构  
                          FillChar(writeoverlapped,Sizeof(writeoverlapped),0);  
                            //避免贡献资源冲突  
                          writeoverlapped.hEvent:=CreateEvent(nil,True,False,nil);  
                          //发送数据  
                          if   not   WriteFile(Commhandle,Str[1],ByteToWrite,BytesWritten,@writeoverlapped)   then  
                          begin  
                                  ErrorCode:=GetLastError;  
                                  if   ErrorCode<>0   then  
                                  begin  
                                          if   ErrorCode=ERROR_IO_PENDING   then  
                                          begin  
                                                  StatusBar1.SimpleText   :=   '端口忙,正在等待...';  
                                                  while   not   GetOverlappedResult(Commhandle,writeoverlapped,BytesWritten,True)   do  
                                                  begin  
                                                          ErrorCode:=GetLastError;  
                                                          if   ErrorCode=ERROR_IO_PENDING   then  
                                                                  continue  
                                                          else   begin  
                                                                  ClearCommError(Commhandle,ErrorFlag,@CommStat);  
                                                                  showmessage('发送数据出错');  
                                                                  CloseHandle(WriteOverlapped.hEvent);  
                                                                  CloseHandle(Commhandle);  
                                                                  btnOpenCom.Enabled   :=True;  
                                                                  Exit;  
                                                          end;  
                                                    end;  
                                                    AllBytesWritten:=AllBytesWritten+BytesWritten;  
                                          end  
                                          else   begin  
                                                  ClearCommError(Commhandle,ErrorFlag,@CommStat);  
                                                  showmessage('发送数据出错');  
                                                  CloseHandle(WriteOverlapped.hEvent);  
                                                  Receive   :=False;  
                                                  CloseHandle(Commhandle);  
                                                  CloseHandle(PostEvent);  
                                                  btnOpenCom.Enabled   :=True;  
                                                  Exit;  
                                          end;  
                                  end;  
                          end;  
                  finally  
                          CloseHandle(writeoverlapped.hEvent);  
                  end;  
          end;  
          StatusBar1.SimpleText:='已经发送了Byte个数:'+IntToStr(ALLBytesWritten);  
  end;  
   
  procedure   TForm1.btnReceiveDataClick(Sender:   TObject);  
  var  
          com_thread:   Thandle;  
          ThreadID:DWORD;  
   
  begin  
          if   not   connected   then  
          begin  
                  StatusBar1.SimpleText   :=   '未打开串口';  
                  Exit;  
          end;  
   
          ReceiveData   :=0;  
          Memo2.Clear;  
          FillChar(ReadOs,SizeOf(ReadOs),0);  
          ReadOs.Offset   :=   0;  
          ReadOs.OffsetHigh   :=   0;  
   
          //   建立通信监视线程  
          Com_Thread:=CreateThread(nil,0,@CommWatch,nil,0,ThreadID);  
          if   (Com_Thread=0)   then  
                  MessageBox(Handle,'No   CreateThread!',nil,mb_OK);  
                   
          //设置DTR信号线  
          EscapeCommFunction(Commhandle,SETDTR);  
          StatusBar1.SimpleText   :=   '正在接收数据...';  
  end;  
   
  end.

MFC(Microsoft Foundation Class)是一种用于编写Windows应用程序的库,它提供了许多可以简化开发过程的类和函数。串口通信是一种用于在计算机和外部设备之间进行数据传输的通信方式,通过串口通信API可以实现在MFC应用程序中与串口设备进行通信。 要在MFC应用程序中使用串口通信API,首先需要包含头文件"afxwin.h"和"afxdisp.h",然后创建一个CWinApp派生类的应用程序对象,并在InitInstance函数中调用AfxEnableControlContainer函数以启用ActiveX控件支持。接下来,创建一个对话框或窗口来实现用户界面,并在该对话框或窗口的消息映射中处理串口通信的逻辑。 使用串口通信API实例涉及到打开、关闭串口、设置串口参数、读取和写入串口数据等操作。首先需要使用CreateFile函数打开串口,并通过DCB结构体设置串口的参数,包括波特率、数据位、停止位和校验位等。然后可以使用ReadFile和WriteFile函数来进行数据的读写操作。 在处理串口通信时,需要注意数据的接收和发送是异步进行的,需要通过事件或定时器来进行数据的处理和监控。可以使用WaitCommEvent函数等待串口事件的发生,并通过SetCommMask函数设置串口事件的掩码。此外,在使用串口通信API时还需要注意处理可能出现的错误和异常情况,例如串口设备被拔出、通信超时等。 总之,通过MFC的串口通信API可以实现在Windows应用程序中与串口设备进行稳定而高效的通信,为实现串口通信功能提供了便利的工具和接口。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值