问题描述:基本上这是一个手机用COM串口通讯的来电显示程序,但是现在就是程序运行后,SETCOMMSTATE失败,跟踪后发现READFILE与WRITEFILE失败。但是如果手动运行WINDOWS的超级终端,并与手机连接,断开后,在运行程序,就能在MEMO中显示来电了,解决不了啊。各位大哥们帮忙啊,这是我工作叫给我的第一个问题。我是个新手,就靠各位大哥了!!!(部分代码没写进去,估计各位大哥也应该想的出来)          
部分代码如下  
       procedure  TForm1.Button1Click(Sender:  TObject);  
var  
   lpdcb:  TDCB;  
   Ini:  TIniFile;  
   com:  string;  
   fdwattrsandflags:DWORD;  
begin  
   if  Opened  then  
       Exit;  
   Ini  :=  TIniFile.Create(apppath  +  'config.ini');  
 
   //    com:=Ini.ReadString('HW','Port','');  
   //    IF  com=''  Then  
   Com  :=  ComboBox1.Text;  
   ComboBox1.ItemIndex  :=  ComboBox1.Items.IndexOf(COM);  
       hCom  :=  CreateFile(Pchar(ComboBox1.Text),  generic_read  or  
       generic_write,  0,  nil,  open_existing,  
       file_attribute_normal  or  
       file_flag_overlapped,  0);                              
   if  hCom  =  INVALID_HANDLE_VALUE  then  
       begin  
           Ini.Free;  
           Exit;  
       end;  
 
   Opened  :=  True;  
       SetupComm(hCom,4096,4096);    
       PurgeComm(hCom,PURGE_RXCLEAR  );  
   GetCommState(hcom,  lpdcb);    
           lpdcb.baudrate  :=19200;  
   lpdcb.StopBits  :=  1;  
   lpdcb.ByteSize  :=  8;  
       lpdcb.Parity:=NoParity;  
   Setcommstate(hcom,  lpdcb);  
       
   SetcommMask(hcom,  EV_RXCHAR);    
   Ini.WriteString('HW',  'PORT',  ComboBox1.Text);  
   Ini.Free;  
   //SendCMD('AT+VCID=1');  
   SendCMD('AT+CLIP=1');  
end;  
 
 
constructor  TComThread.Create(Handle:  DWORD;  HWND:  DWORD);  
begin  
   FhCom  :=  Handle;  
   FHWND  :=  HWND;  
   FExit  :=  False;  
   post_event:=CreateEvent(nil,true,true,nil);    
     read_os.hEvent:=CreateEvent(NIL,TRUE,true,NIL);  
   write_os.hEvent:=CreateEvent(NIL,TRUE,true,NIL);  
   read_os.Offset:=0;  
   read_os.OffsetHigh:=0;  
   write_os.Offset:=0;  
   write_os.OffsetHigh:=0;  
   inherited  Create(False);  
   FreeOnTerminate  :=  True;  
end;  
 
 
procedure  TComThread.Execute;            
var  
   dwEvtMask:  Dword;  
   Wait:  Boolean;  
begin  
   fillchar(lpol,  sizeof(toverlapped),  0);  
   while  True  do  
       begin  
           dwEvtMask  :=  0;  
           Wait  :=  WaitCommEvent(Fhcom,  dwevtmask,  nil);    
           if  Wait  then  
               begin  
                   waitforsingleobject(post_event,  infinite);    
                   resetevent(post_event);    
                   PostMessage(FHWND,  WM_COMMNOTIFY,  0,  0);    
               end  
           else  
               Exit;  
       end;  
end;  
 
 
procedure  TForm1.SendCMD(CMD:  string);  
var  
   Buffer:  array[0..127]  of  char;  
   cbNum:  DWORD;  
begin  
   Fillchar(Buffer,  128,  0);  
   CMD  :=  CMD  +  #$0D#$0A;  
   StrCopy(@Buffer,  Pchar(CMD));  
   fillchar(lpol,  sizeof(toverlapped),  0);  
   ComThread  :=  TComThread.Create(hCom,  Handle);  
   WriteFile(hCom,  Buffer,  Length(CMD),  cbNum,  @lpol);  
end;  
 
 
procedure  TForm1.MsgComProcess(var  Message:  Tmessage);  
var  
   Clear:  Boolean;  
   Coms:  Tcomstat;  
   cbNum,  ReadNumber,  lpErrors:  DWORD;  
   Read_Buffer:  array[1..100]  of  char;  
   iPos,  Pos2:  Integer;  
   Num:  Pchar;  
   tmpstr:  string;  
begin  
   Clear  :=  Clearcommerror(hcom,  lpErrors,  @Coms);  
   if  Clear  then                                            
       begin  
           cbNum  :=  Coms.cbInQue;  
           FillChar(Read_Buffer,  100,  0);  
           Sleep(100);  
           ReadFile(hCom,  Read_Buffer,  cbNum,  ReadNumber,  @lpol;  
 SetEvent(Post_Event);      
       end;  

解决方案 »

  1.   

    代码太多,懒的看。。给你个用API打开串口的例子,自己看看吧。
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, ExtCtrls;type
      TForm1 = class(TForm)
        rdCOM: TRadioGroup;
        Label1: TLabel;
        Label2: TLabel;
        btnOpenPort: TButton;
        btnEnd: TButton;
        spCD: TShape;
        spDSR: TShape;
        spCTS: TShape;
        Label3: TLabel;
        Label4: TLabel;
        spRI: TShape;
        Timer1: TTimer;
        procedure btnOpenPortClick(Sender: TObject);
        procedure btnEndClick(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
      private
        { Private declarations }
        DTRState:Boolean;
        RTSState:Boolean;
        DOValue:DWORD;
      public
        { Public declarations }
        procedure OpenComm;  //打开通信端口
      end;var
      Form1: TForm1;
      hComm: THandle;implementation{$R *.DFM}//以下是打开通信端口的程序
    procedure TForm1.btnOpenPortClick(Sender: TObject);begin
    //若通信端口已打开,则不需要再打开
      if (hComm<>0) then begin
        ShowMessage('通信端口已打开!不需再开!');
        exit;
      end;
      OpenComm; //打开通信端口的子程序
      //先将DTR/RTS的电压降成低电压
      EscapeCommFunction( hComm, CLRDTR); //将DTR降为低电压
      EscapeCommFunction( hComm, CLRRTS); //将RTS降为低电压
    end;//以下是打开通信端口的实际程序代码,采用API
    procedure TForm1.OpenComm;
    var
      cc:TCOMMCONFIG; //定义通信组态变量
      Temp:string;
    begin
      // 选择所要打开的COM
      Temp:='COM'+inttostr(rdcom.ItemIndex+1);
      // 以Create函数打开COM
      hComm:=CreateFile(PChar(Temp), GENERIC_READ or GENERIC_WRITE,
           0, nil, OPEN_EXISTING, 0, 0);
      // 判断COM 是否顺利打开
      if (hComm = INVALID_HANDLE_VALUE) then begin
        MessageBox (0, '打开通信端口错误!!','',MB_OK);
        exit;
      end;
      //以下设置通信端口的参数
      GetCommState(hComm,cc.dcb);    // 得知目前COM 的状态
      cc.dcb.BaudRate:=CBR_9600;     // 设置波特率为9600
      cc.dcb.ByteSize:=8;            // 字节为 8 bit
      cc.dcb.Parity:=NOPARITY;       // Parity 为 None
      cc.dcb.StopBits:=ONESTOPBIT;   // 1 个Stop bit
      //若分别控制DTR、RTS,必须不能激活HandShaking
      cc.dcb.Flags:=1;  //此动作可关闭HandShaking等设置
      //以下将通信端口参数写入实际硬件
      if not SetCommState(hComm, cc.dcb) then begin // 设置COM 的状态
        MessageBox (0, '通信端口设置错误!!!','',MB_OK);
        CloseHandle(hComm);
        exit;
      end;
    end;//以下是结束按钮的动作
    procedure TForm1.btnEndClick(Sender: TObject);
    begin
       SetCommMask(hcomm,$0); //取消所有的事件设定
       CloseHandle(hComm);    //关闭通信端口
       close;                 //结束程序
    end;//窗体建立时的初值设定
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      RTSState:=False; //预设是低电压
      DTRState:=False; //预设是低电压
    end;procedure TForm1.Timer1Timer(Sender: TObject);
      var
        lStatus:DWORD;  //输入线路状态变量
    begin
      if (hComm =0) then exit ;
      if GetCommModemStatus(hComm,lStatus) then
       begin
         //检查CTS状态
         if ( lStatus and MS_CTS_ON )= MS_CTS_ON then
           spCTS.Brush.Color :=clRed
         else spCTS.Brush.Color :=clWhite;
         //检查DSR状态
         if ( lStatus and MS_DSR_ON )=MS_DSR_ON then
           spDSR.Brush.Color :=clRed
         else spDSR.Brush.Color :=clWhite;
         //检查RI状态
         if ( lStatus and MS_RING_ON )=MS_RING_ON then
           spRI.Brush.Color :=clRed
         else spRI.Brush.Color :=clWhite;
         //检查CD状态
         if ( lStatus and MS_RLSD_ON )=MS_RLSD_ON then
           spCD.Brush.Color :=clRed
         else spCD.Brush.Color :=clWhite;
       end;
    end;end.
      

  2.   

    例子二,
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, ExtCtrls;type
      TForm1 = class(TForm)
        rdCOM: TRadioGroup;
        Label1: TLabel;
        Label2: TLabel;
        btnOpenPort: TButton;
        btnEnd: TButton;
        spDTR: TShape;
        spRTS: TShape;
        btnDTR: TButton;
        btnRTS: TButton;
        procedure btnOpenPortClick(Sender: TObject);
        procedure btnEndClick(Sender: TObject);
        procedure btnDTRClick(Sender: TObject);
        procedure btnRTSClick(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
        DTRState:Boolean;
        RTSState:Boolean;
        DOValue:DWORD;
      public
        { Public declarations }
        procedure OpenComm;  //打开通信端口
      end;var
      Form1: TForm1;
      hComm: THandle;implementation{$R *.DFM}//以下是打开通信端口的程序
    procedure TForm1.btnOpenPortClick(Sender: TObject);begin
    //若通信端口已打开,则不需要再打开
      if (hComm<>0) then begin
        Messagedlg('通信端口已打开,不需再开',mtError,[mbOK],0);
        exit;
      end;
      OpenComm; //打开通信端口的子程序
      //先将DTR/RTS的电压降成低电压
      EscapeCommFunction( hComm, CLRDTR); //将DTR降为低电压
      EscapeCommFunction( hComm, CLRRTS); //将RTS降为低电压
    end;//以下是打开通信端口的实际程序代码,采用API
    procedure TForm1.OpenComm;
    var
      cc:TCOMMCONFIG; //定义通信组态变量
      Temp:string;
    begin
      // 选择所要打开的COM
      Temp:='COM'+inttostr(rdcom.ItemIndex+1);
      // 以Create函数打开COM
      hComm:=CreateFile(PChar(Temp), GENERIC_READ or GENERIC_WRITE,
           0, nil, OPEN_EXISTING, 0, 0);
      // 判断COM 是否顺利打开
      if (hComm = INVALID_HANDLE_VALUE) then begin
        Messagedlg('打开通信端口错误!!',mtError,[mbOK],0);
        exit;
      end;
      //以下设置通信端口的参数
      GetCommState(hComm,cc.dcb);    // 得知目前COM 的状态
      cc.dcb.BaudRate:=CBR_9600;     // 设置波特率为9600
      cc.dcb.ByteSize:=8;            // 字节为 8 bit
      cc.dcb.Parity:=NOPARITY;       // Parity 为 None
      cc.dcb.StopBits:=ONESTOPBIT;   // 1 个Stop bit
      //若分别控制DTR、RTS,必须不能激活HandShaking
      cc.dcb.Flags:=1;  //此动作可关闭HandShaking等设置
      //以下将通信端口参数写入实际硬件
      if not SetCommState(hComm, cc.dcb) then begin // 设置COM 的状态
        MessageBox (0, '通信端口设置错误!!!','',MB_OK);
        CloseHandle(hComm);
        exit;
      end;
    end;//以下是结束按钮的动作
    procedure TForm1.btnEndClick(Sender: TObject);
    begin
       CloseHandle(hComm);    //关闭通信端口
       close;                 //结束程序
    end;//以下是控制DTR状态的按钮程序
    procedure TForm1.btnDTRClick(Sender: TObject);
    begin
        //若通信端口未打开,则不作动作,并跳出
        if (hComm=0) then begin
           Messagedlg('通信端口未打开!!',mtError,[mbOK],0);
           exit;
        end;
        //判断DTRState值,输出状态后,将原值作转态
        if DTRState then
          begin
           DOValue:=CLRDTR; //设置DTR为低电压
           EscapeCommFunction( hComm, DOValue );//输出DTR状态
           spDTR.Brush.Color:=clWhite; //变更灯号的颜色
          end
        else
          begin
           DOValue:=SETDTR; //设置DTR为高电压
           EscapeCommFunction( hComm, DOValue );//输出DTR的状态
           spDTR.Brush.Color:=clRed; //变更灯号的颜色
          end;
        DTRState:=(not DTRState); //将DTRState转态
    end;//以下是控制RTS状态的按钮程序
    procedure TForm1.btnRTSClick(Sender: TObject);
    begin
        //若通信端口未打开,则不作动作,并跳出
        if (hComm=0) then begin
           Messagedlg('通信端口未打开!!',mtError,[mbOK],0);
           exit;
        end;
        //判断RTSState值,输出状态后,将原值作转态
        if RTSState then
          begin
           DOValue:=CLRRTS; //设置RTS为低电压
           EscapeCommFunction( hComm, DOValue );//输出RTS状态
           spRTS.Brush.Color:=$FFFFFF;//变更灯号
          end
        else
          begin
           DOValue:=SETRTS; //设置RTS为高电压
           EscapeCommFunction( hComm, DOValue );//输出RTS状态
           spRTS.Brush.Color:=$00FF00;//变更灯号
          end;
        RTSState:=(not RTSState); //将RTSState转态
    end;//窗体建立时的初值设置
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      RTSState:=False; //默认是低电压
      DTRState:=False; //默认是低电压
    end;
    end.
      

  3.   

    主要的设置我知道,但是就是不成功啊,发送AT+CLIP=1,在READ_BUFFER中读到的只是两个AT+CLIP=1,没OK,也没EROOR,弄不懂
      

  4.   

    还有,要是我用你的CREATEFILE打开端口,就是把通讯方式改为0,那么程序就没响应了