我参考SPCOMM原码改写的程序,打算执行AT指令中的“AT”命令,在进行写入的时候却碰到了问题,请高手指教!(不要让我用控件啊)
PS:因为之前有一个类似的问题http://expert.csdn.net/Expert/topic/2845/2845423.xml?temp=.1941034,所以这个问题会和另外一个问题一起给分(共100分)
unit formMain;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  TForm1 = class(TForm)
    GroupBox1: TGroupBox;
    btRunAT: TButton;
    mem1: TMemo;
    procedure btRunATClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
    function OpenSetupCom(var iComName : Integer) : THandle;
    function WriteCom(var hComF : Thandle ; pInput : PChar) : Boolean;
    function ReadCom(var hComF : Thandle ) : String;
    function CloseCom(var hComF : THandle) : Boolean;var
  Form1: TForm1;
  hCom : THandle;implementation{$R *.dfm}//打开串口设备,并进行设置
function OpenSetupCom(var iComName : Integer) : THandle;
var
  pComName : PChar;
  hComF : Thandle;
  dcb : TDcb;
  TimeOuts : TCommTimeOuts;
begin
  pComName := PChar('COM'+IntToStr(iComName));
//打开串口,并将句柄赋值给hComF
  hComF := CreateFile(
      pComName,
      GENERIC_READ or GENERIC_WRITE,
      0,
      nil,
      OPEN_EXISTING,
      FILE_ATTRIBUTE_NORMAL ,
      0
    );
//如果创建成功,则开始设置
  if hComF = INVALID_HANDLE_VALUE then
  begin
    MessageBox(0,PChar('Notice:COM'+IntToStr(iComName)+'设备异常,请检查!'),'Notice',MB_OK);
    exit;
  end
  else
  begin
//通过GetCommState函数填充设备控制块DCB
    GetCommState(hComF,dcb);
//通过调用SetCommState函数配置串行口的波特率、数据位、停止位和校验位
    dcb.BaudRate  := 9600;
    dcb.ByteSize  := 8;
    dcb.StopBits  := 1;
    dcb.Parity    := 0;
    SetCommState(hComF,dcb);
//设置读写缓冲
    SetupComm(hComF,4096,4096);
// 设置超时
    TimeOuts.ReadIntervalTimeout:=100;
    TimeOuts.ReadTotalTimeoutMultiplier:=1;
    TimeOuts.ReadTotalTimeoutConstant:=500;
    TimeOuts.WriteTotalTimeoutMultiplier:=1;
    TimeOuts.WriteTotalTimeoutConstant:=100;
    SetCommTimeouts(hCom,TimeOuts);
  end;
//返回创建串口设备的句柄
  Result := hComF;
end;//写串口设备
function WriteCom(var hComF : Thandle ; pInput : PChar) : Boolean;
var
  dwWhereToStartWriting   : Dword;   //从何处开始写入
  dwNumberOfBytesToWrite  : Dword;   //共需写入字符数
  dwNumberOfBytesWritten  : Dword;   //已经写入字符数
  bWriteResult : Boolean;
begin
//初始化
  dwWhereToStartWriting := 0;
  dwNumberOfBytesToWrite := StrLen(pInput);
  dwNumberOfBytesWritten := 0;
//开始写入
  repeat
    bWriteResult := WriteFile(
        hComF,                                        //写入句柄
        pInput[dwWhereToStartWriting],                //写入字符
        dwNumberOfBytesToWrite,                       //写入字符总长
        dwNumberOfBytesWritten,                       //已写入字符数
        nil                                           //结构指针
      );
//  dwNumberOfBytesToWrite := dwNumberOfBytesToWrite - dwNumberOfBytesWritten
    Dec( dwNumberOfBytesToWrite, dwNumberOfBytesWritten );
//  dwWhereToStartWriting := dwWhereToStartWriting + dwNumberOfBytesWritten
    Inc( dwWhereToStartWriting, dwNumberOfBytesWritten );
  until (dwNumberOfBytesToWrite <= 0);  Result := bWriteResult;
end;//读串口设备
function ReadCom(var hComF : Thandle ) : String;
var
  pOutput : PChar;
  dwNumberOfBytesToRead : Dword;
  dwNumberOfBytesRead : Dword;
//  bReadResult : Boolean;
begin
  dwNumberOfBytesToRead := 4096;
  dwNumberOfBytesRead := 0;
//  bReadResult := ReadFile(
  ReadFile(
      hComF,
      pOutput,
      dwNumberOfBytesToRead,
      dwNumberOfBytesRead,
      nil
    );
  Result := pOutput;
end;//关闭串口设备
function CloseCom(var hComF : THandle) : Boolean;
begin
  Result := CloseHandle(hComF);
end;procedure TForm1.btRunATClick(Sender: TObject);
var
  iComPort : Integer;
  pInput : PChar;
  sOutput : String;
//  bWriteResult : Boolean;
//  bCloseCom : Boolean;
begin
  iComPort := 1;  hCom := OpenSetupCom(iComPort);
  if hCom = INVALID_HANDLE_VALUE then
  begin
    mem1.Lines.Add('Open Com1 Failure!');
    exit;
  end
  else
  begin
    mem1.Lines.Add('Open Com1 Ok!'+'   串口句柄为:'+IntToStr(hCom));
//生成AT命令
    pInput := PChar('AT'+chr(13));
//向COM口设备写入命令
    if WriteCom(hCom,pInput) then
    begin
      sleep(1000);
//从COM口设备读取数据
      sOutput := ReadCom(hCom);
      mem1.Lines.Add('运行结果为:'+sOutput);
      sleep(100);
    end
    else
    begin
      MessageBox(0,'Notice:写入异常!','Notice',MB_OK);
      exit;
    end;
//关闭串口
    CloseCom(hCom);
    mem1.Lines.Add('Close Com1 OK');
  end;
end;end.

解决方案 »

  1.   

    TO:aiirii(ari-爱的眼睛) 
      嗯,我再看看。麻烦你继续看一下读取部分嘛,呵呵 
      
      

  2.   

    function ReadCom(const hComF : Thandle ) : String;
    var
      dwNumberOfBytesToRead : Dword;
      dwNumberOfBytesRead : Dword;
    //  bReadResult : Boolean;
    begin
      dwNumberOfBytesToRead := 4096;
      dwNumberOfBytesRead := 0;
      SetLength(Result,dwNumberOfBytesToRead);
      ReadFile(
          hComF,
          Result[1],
          dwNumberOfBytesToRead,
          dwNumberOfBytesRead,
          nil
        );
      SetLength(Result,dwNumberOfBytesRead);
    end;
      

  3.   

    Sorry想当然了
    function ReadCom(const hComF : Thandle ) : String;
    var
      dwNumberOfBytesToRead : Dword;
      dwNumberOfBytesRead : Dword;
      S:String;
    begin
      dwNumberOfBytesToRead := 4096;
      dwNumberOfBytesRead := 0;
      SetLength(S,dwNumberOfBytesToRead);
      ReadFile(
          hComF,
          S[1],
          dwNumberOfBytesToRead,
          dwNumberOfBytesRead,
          nil
        );
      if dwNumberOfBytesRead>0 then
      begin
        SetLength(Result,dwNumberOfBytesRead);
        move(S[1],Result[1],dwNumberOfBytesRead);
      end;
    end;
      

  4.   

    现在测试了一下上面两个都可以
    第一个的SetLength其实也自动实现了复制
      

  5.   

    以下是我重新写的程序源码:(上面的注释是我个人理解,还请各位大大指教)
    unit FormMain;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;const
    //  MAXCOMNUM = 2 ;  //设置最大支持串口数目
      WM_RECEIVEDATA = WM_USER + 1;type
      TForm1 = class(TForm)
        GroupBox1: TGroupBox;
        GroupBox2: TGroupBox;
        memResult: TMemo;
        btOpenCom: TButton;
        btStartListen: TButton;
        btRunAt: TButton;
        btStopListen: TButton;
        btCloseCom: TButton;
        edATCommand: TEdit;
        procedure btOpenComClick(Sender: TObject);
        procedure btStartListenClick(Sender: TObject);
        procedure btRunAtClick(Sender: TObject);
        procedure btCloseComClick(Sender: TObject);
      private
        { Private declarations }
        procedure proWM_ReceiveData(var Msg : TMessage ) ; message WM_RECEIVEDATA;
      public
        { Public declarations }
      end;  thrRead = Class(TThread)
      protected
        procedure Execute ; Override;
      public
        constructor Create;
      end;
      
    //串口-初始化
      function ComInitial(var iComName : Integer ) : THandle;
    //串口-读取
      function ComRead(var hComF : THandle ) : String;
    //串口-写入
      function ComWrite(var hComF : THandle ; pWrite : PChar ) : Boolean;
    //串口-关闭
      function ComClose(var hComF : THandle ) : Boolean;
      
    var
      Form1   : TForm1;
      hComAll : THandle;
      hEvent  : THandle;implementation{$R *.dfm}//////////////////////////////////////////////////////////////////////
    //串口操作
    //////////////////////////////////////////////////////////////////////function ComInitial(var iComName : Integer ) : THandle;
    var
      pComName  : PChar;
      hComF     : THandle;
      dcb       : TDcb;
      TimeOuts  : TCommTimeOuts;
    begin
    //缺省返回句柄
      Result := INVALID_HANDLE_VALUE;
    //打开串口名
      pComName := PChar('COM'+IntToStr(iComName));
    //打开串口,并将句柄赋值给hComF
      hComF := CreateFile(
          pComName,
          GENERIC_READ or GENERIC_WRITE,
          0,
          nil,
          OPEN_EXISTING,
          FILE_ATTRIBUTE_NORMAL ,
          0
        );
    //如果创建成功,则开始设置
      if hComF = INVALID_HANDLE_VALUE then
      begin
        MessageBox(0,PChar('Notice:COM'+IntToStr(iComName)+'设备异常,请检查!'),'Notice',MB_OK);
        Exit;
      end
      else
      begin
    //通过GetCommState函数填充设备控制块DCB
        GetCommState(hComF,dcb);
    //通过调用SetCommState函数配置串行口的波特率、数据位、停止位和校验位
        dcb.BaudRate  := 9600;
        dcb.ByteSize  := 8;
        dcb.StopBits  := 1;
        dcb.Parity    := 0;
        SetCommState(hComF,dcb);
    //设置读写缓冲
        SetupComm(hComF,4096,4096);
    // 设置超时
        TimeOuts.ReadIntervalTimeout          :=100;
        TimeOuts.ReadTotalTimeoutMultiplier   :=1;
        TimeOuts.ReadTotalTimeoutConstant     :=500;
        TimeOuts.WriteTotalTimeoutMultiplier  :=1;
        TimeOuts.WriteTotalTimeoutConstant    :=100;
        SetCommTimeouts(hComF,TimeOuts);
      end;//指定串行口事件为接收到字符;
      setcommMask(hComF,EV_RXCHAR);//返回创建串口设备的句柄
      Result := hComF;
    end;function ComRead(var hComF : THandle ) : String;
    var
      dwNumberOfBytesToRead : Dword;
      dwNumberOfBytesRead : Dword;
      S:String;
    begin
      dwNumberOfBytesToRead := 4096;
      dwNumberOfBytesRead := 0;
      SetLength(S,dwNumberOfBytesToRead);
      ReadFile(
          hComF,
          S[1],
          dwNumberOfBytesToRead,
          dwNumberOfBytesRead,
          nil
        );
      if dwNumberOfBytesRead>0 then
      begin
        SetLength(Result,dwNumberOfBytesRead);
        move(S[1],Result[1],dwNumberOfBytesRead);
      end;
    end;function ComWrite(var hComF : THandle ; pWrite : PChar ) : Boolean;
    var
      dwWhereToStartWriting   : Dword;      //从何处开始写入
      dwNumberOfBytesToWrite  : Dword;      //共需写入字符数
      dwNumberOfBytesWritten  : Dword;      //已经写入字符数
      bWriteResult            : Boolean;    //读取结果
    begin
    //初始化
      dwWhereToStartWriting := 0;
      dwNumberOfBytesToWrite := StrLen(pWrite);
      dwNumberOfBytesWritten := 0;
    //开始写入
      repeat
        bWriteResult := WriteFile(
            hComF,                                        //写入句柄
            pWrite[dwWhereToStartWriting],                //写入字符
            dwNumberOfBytesToWrite,                       //写入字符总长
            dwNumberOfBytesWritten,                       //已写入字符数
            nil                                           //结构指针
          );
    //  dwNumberOfBytesToWrite := dwNumberOfBytesToWrite - dwNumberOfBytesWritten
        Dec( dwNumberOfBytesToWrite, dwNumberOfBytesWritten );
    //  dwWhereToStartWriting := dwWhereToStartWriting + dwNumberOfBytesWritten
        Inc( dwWhereToStartWriting, dwNumberOfBytesWritten );
      until (dwNumberOfBytesToWrite <= 0);  Result := bWriteResult;
    end;function ComClose(var hComF : THandle ) : Boolean;
    begin
      Result := CloseHandle(hComF);
    end;//////////////////////////////////////////////////////////////////////
    //读线程操作
    //////////////////////////////////////////////////////////////////////procedure thrRead.Execute;
    var
      dwEventMask : Dword;
      bWait       : Boolean;
    begin
      dwEventMask := 0;
      
      while not Terminated do
      begin
        bWait := WaitCommEvent(hComAll , dwEventMask , nil);
    //    if ( dwEventMask and EV_RXCHAR ) = EV_RXCHAR then
        if bWait then
        begin
        //等待同步事件置位;
          WaitForSingleObject(hEvent , Infinite);
        //同步事件复位;
          ResetEvent(hEvent);
        //向主进程发送消息;
          PostMessage(Form1.Handle , WM_RECEIVEDATA , 0 , 0);
        end;
      end;
    end;constructor thrRead.Create;
    begin
      FreeOnTerminate := TRUE;
      inherited Create(FALSE);
    end;//////////////////////////////////////////////////////////////////////
    //主进程
    //////////////////////////////////////////////////////////////////////procedure TForm1.proWM_ReceiveData(var Msg : TMessage ) ;
    var
      ComStat : PComStat;
      dwErrorFlags : DWORD;
      sReadResult              : string;    //读取结果
    begin
        sReadResult := '';    GetMem(ComStat , SizeOf(TComStat));    ClearCommError(hComAll , dwErrorFlags , ComStat);    if dwErrorFlags > 0 then
        begin
          PurgeComm(hComAll , PURGE_RXABORT and PURGE_RXCLEAR);
        end;    if ComStat.cbInQue > 0 then
          sReadResult := ComRead(hComAll);    memResult.Lines.Add('Listen result :' + sReadResult);    SetEvent(hEvent);
    end;//打开并设置串口
    procedure TForm1.btOpenComClick(Sender: TObject);
    var
      iComNo : integer;
    begin
      iComNo := 1;
      hComAll := ComInitial(iComNo);
      if hComAll = INVALID_HANDLE_VALUE then
      begin
        memResult.Lines.Add('Open COM'+IntToStr(iComNo)+' ERROR!');
        Exit;
      end
      else
      begin
        memResult.Lines.Add('Open COM'+IntToStr(iComNo)+' OK!');
      end;
    end;//开始监听
    procedure TForm1.btStartListenClick(Sender: TObject);
    begin
      hEvent := CreateEvent(nil , True , False , nil);
      thrRead.Create;
      memResult.Lines.Add('COM Listen thread create OK!');
    end;//执行AT指令
    procedure TForm1.btRunAtClick(Sender: TObject);
    var
      pATCommand : PChar;
    begin
    //生成AT指令
      pATCommand := PChar(edATCommand.Text + Chr(13));
      if ComWrite(hComAll , pATCommand) then
      begin
        memResult.Lines.Add('AT Command Write OK!');
      end
      else
      begin
        memResult.Lines.Add('AT Command Write Error!');
        Exit;
      end;
    end;//关闭串口
    procedure TForm1.btCloseComClick(Sender: TObject);
    begin
      ComClose(hComAll);
    end;end.