我参考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.
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.
嗯,我再看看。麻烦你继续看一下读取部分嘛,呵呵
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;
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;
第一个的SetLength其实也自动实现了复制
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.