小菜求教关于串口通信 请教大哥们,在串口通信中的整个详细过程。请尽量详细点。什么缓冲区啊之类的 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 unit U_APISerialPort;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;const Wm_CommNotify = WM_User +12;type Tfrm_SerialPort = class(TForm) pnl1: TPanel; lbl_SerialPort: TLabel; cbb_SerialPort: TComboBox; btn_OpenSerialPort: TButton; btn_CloseSerialPort: TButton; pnl2: TPanel; lbl_RevData: TLabel; mem_RevData: TMemo; pnl3: TPanel; lbl_SendData: TLabel; mem_SendData: TMemo; pnl4: TPanel; btn_Send: TButton; btn_Close: TButton; btn_SaveToFile: TButton; procedure FormShow(Sender: TObject); procedure btn_OpenSerialPortClick(Sender: TObject); procedure btn_CloseSerialPortClick(Sender: TObject); procedure btn_CloseClick(Sender: TObject); procedure btn_SendClick(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormCreate(Sender: TObject); procedure btn_SaveToFileClick(Sender: TObject); private procedure CommInitialize; procedure MsgComm(var Msg:TMessage);Message Wm_CommNotify; function WriteStr(const Str:string):Boolean; { Private declarations } public { Public declarations } end; TComm=class(TThread) protected procedure Execute;override; end;var frm_SerialPort: Tfrm_SerialPort; g_Hcom,g_Post_Event:THandle; g_LpolW,g_LpolR:POverlapped; g_RXComm:TComm; g_bFlag :Boolean;implementation{$R *.dfm}procedure TComm.Execute;var l_dwEvtmask,l_dwOvres,l_dwbb:DWORD; l_bRXFinish:BOOL;begin while True do begin l_dwEvtmask := 0; l_bRXFinish := WaitCommEvent(g_Hcom,l_dwEvtmask,g_LpolR);//等待串口事件EV_RXCHAR if not l_bRXFinish then if GetLastError()= ERROR_IO_PENDING then//正在接受数据; begin l_dwbb:=WaitForSingleObject(g_LpolR^.hEvent,500);//等待500MS case l_dwbb of WAIT_OBJECT_0: l_bRXFinish:=GetOverlappedResult(g_Hcom,g_LpolR^,l_dwOvres,False); WAIT_TIMEOUT: l_bRXFinish:= False//定是益出 else l_bRXFinish := False; end; end else l_bRXFinish:=False; if l_bRXFinish then begin ResetEvent(g_Post_Event); //同步事件复位 PostMessage(frm_SerialPort.Handle,Wm_CommNotify,0,0); end; end;end;procedure Tfrm_SerialPort.FormShow(Sender: TObject);begin try btn_CloseSerialPort.Enabled := False; cbb_SerialPort.Clear; mem_RevData.Clear; mem_SendData.Clear; cbb_SerialPort.AddItem('',nil); cbb_SerialPort.AddItem('COM1',nil); cbb_SerialPort.AddItem('COM2',nil); cbb_SerialPort.AddItem('COM3',nil); cbb_SerialPort.AddItem('COM4',nil); except on e:Exception do ShowMessage(e.Message); end;end;procedure Tfrm_SerialPort.btn_OpenSerialPortClick(Sender: TObject);begin if cbb_SerialPort.Text ='' then begin MessageDlg('请选择COM口',mtWarning,[mbOK],0); end else begin btn_CloseSerialPort.Enabled := True; try CommInitialize; except on e:Exception do ShowMessage(e.Message); end; end;end;procedure Tfrm_SerialPort.btn_CloseSerialPortClick(Sender: TObject);begin btn_CloseSerialPort.Enabled := False;end;procedure Tfrm_SerialPort.btn_CloseClick(Sender: TObject);begin Self.Close;end;procedure Tfrm_SerialPort.CommInitialize;var l_Lpdcb:TDCB;begin g_Hcom:= CreateFile(PAnsiChar(cbb_SerialPort.Text),GENERIC_READ or GENERIC_WRITE,0,nil, OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0); g_bFlag := True; if g_Hcom <> invalid_handle_value then begin SetupComm(g_Hcom,4096,4096); GetCommState(g_Hcom,l_Lpdcb); l_Lpdcb.BaudRate := 9600; l_Lpdcb.StopBits :=0; l_Lpdcb.ByteSize :=8; l_Lpdcb.Parity :=0; SetCommState(g_Hcom,l_Lpdcb); SetCommMask(g_Hcom,EV_RXCHAR); end else ShowMessage('无法打开串口');end;function Tfrm_SerialPort.WriteStr(const Str: string): Boolean;var l_DwCharsWritten,l_DwRes:DWORD; l_S_DATA:string; l_BRes:Boolean;begin l_BRes :=False; l_S_DATA:=Str; if g_Hcom<>invalid_handle_value then begin l_DwCharsWritten :=0; l_BRes :=WriteFile(g_Hcom,PChar(l_S_DATA)^,Length(l_S_DATA),l_DwCharsWritten,g_LpolW); if not l_BRes then begin if GetLastError()=ERROR_IO_PENDING then begin l_DwRes :=WaitForSingleObject(g_LpolW^.hEvent,INFINITE); if l_DwRes=WAIT_OBJECT_0 then l_BRes :=GetOverlappedResult(g_Hcom,g_LpolW^,l_DwCharsWritten,False) else l_BRes:=True; end; end; end else Result := l_BRes;end;procedure Tfrm_SerialPort.MsgComm(var Msg: TMessage);var l_bclear:Boolean; l_coms :TComStat; l_dwcbNum,l_dwCbread,l_dwlpErrors:DWORD; l_s:string;begin l_bclear :=ClearCommError(g_Hcom,l_dwlpErrors,@l_coms); if l_bclear then begin l_dwcbNum :=l_coms.cbInQue;//获取接受缓冲区待接收字节数 SetLength(l_s,l_dwcbNum+1);//分配内存 ReadFile(g_Hcom,PChar(l_s)^,l_dwcbNum,l_dwCbread,g_LpolR);//读串口 SetLength(l_s,l_dwCbread);//分配 SetEvent(g_Post_Event);//同步事件置位 mem_RevData.Lines.Add(l_s); end; end;procedure Tfrm_SerialPort.btn_SendClick(Sender: TObject);var l_S_DATA:string;begin l_S_DATA :=mem_SendData.Text; if WriteStr(l_S_DATA) then ShowMessage('无法发送数据') else ShowMessage('发送成功');end;procedure Tfrm_SerialPort.FormDestroy(Sender: TObject);begin CloseHandle(g_LpolW^.hEvent); CloseHandle(g_LpolR^.hEvent); Dispose(g_LpolR); Dispose(g_LpolW); g_LpolW :=nil; g_LpolR :=nil; g_RXComm.Terminate; SetEvent(g_Post_Event); CloseHandle(g_Post_Event); CloseHandle(g_Hcom);end;procedure Tfrm_SerialPort.FormCreate(Sender: TObject);begin// CommInitialize; New(g_LpolW); New(g_LpolR); g_LpolW^.Internal :=0; g_LpolW^.InternalHigh :=0; g_LpolW^.Offset :=0; g_LpolW^.OffsetHigh :=0; g_LpolW^.hEvent :=CreateEvent(nil,True,False,nil); g_LpolR^.Internal :=0; g_LpolR^.InternalHigh :=0; g_LpolR^.Offset :=0; g_LpolR^.OffsetHigh :=0; g_LpolR^.hEvent :=CreateEvent(nil,True,False,nil); PurgeComm(g_Hcom,PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR); g_Post_Event:=CreateEvent(nil,True,True,nil); g_RXComm :=TComm.Create(False);end;procedure Tfrm_SerialPort.btn_SaveToFileClick(Sender: TObject);begin try if mem_RevData.Text =''then ShowMessage('接收数据不能为空!') else mem_RevData.Lines.SaveToFile('d:\receive.tex'); except end; end;end. 下载spcomm组件,自己看源代码 1楼的,是网上流行的一个经典写法。串口实际上也有很多写法,不过,实际上也就是几个API,弄懂机制就会变得简单。http://www.moon-soft.com/program/bbs/readelite515510.htm 请问DBExpress的StoredProcName属性时,不能出现数据库中的存储过程,是什么原因? 请教,想实现image控件拖拽到另外程序的窗口时,能得到该窗口的句柄? 原子函数的使用 工资有这么高吗,我怎么感觉不到啊?(生活在平均工资以下) 在线求解一些小问题 (转)Microsoft程序员测试题 进度条如何同步显示? 各位大吓!谁知道那里有用DELPHI语言做GSM MODEM 收发短信息实例?? C#转delphi求帮助(急) 过程与函数的调用约定 modem拨号,远程文件传输问题,急!!!!!!!!!! 如何判断是否存在连键盘上都按不出来的字符。
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
const
Wm_CommNotify = WM_User +12;
type
Tfrm_SerialPort = class(TForm)
pnl1: TPanel;
lbl_SerialPort: TLabel;
cbb_SerialPort: TComboBox;
btn_OpenSerialPort: TButton;
btn_CloseSerialPort: TButton;
pnl2: TPanel;
lbl_RevData: TLabel;
mem_RevData: TMemo;
pnl3: TPanel;
lbl_SendData: TLabel;
mem_SendData: TMemo;
pnl4: TPanel;
btn_Send: TButton;
btn_Close: TButton;
btn_SaveToFile: TButton;
procedure FormShow(Sender: TObject);
procedure btn_OpenSerialPortClick(Sender: TObject);
procedure btn_CloseSerialPortClick(Sender: TObject);
procedure btn_CloseClick(Sender: TObject);
procedure btn_SendClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure btn_SaveToFileClick(Sender: TObject);
private
procedure CommInitialize;
procedure MsgComm(var Msg:TMessage);Message Wm_CommNotify;
function WriteStr(const Str:string):Boolean;
{ Private declarations }
public
{ Public declarations }
end;
TComm=class(TThread)
protected
procedure Execute;override;
end;var
frm_SerialPort: Tfrm_SerialPort;
g_Hcom,g_Post_Event:THandle;
g_LpolW,g_LpolR:POverlapped;
g_RXComm:TComm;
g_bFlag :Boolean;implementation{$R *.dfm}
procedure TComm.Execute;
var
l_dwEvtmask,l_dwOvres,l_dwbb:DWORD;
l_bRXFinish:BOOL;
begin
while True do
begin
l_dwEvtmask := 0;
l_bRXFinish := WaitCommEvent(g_Hcom,l_dwEvtmask,g_LpolR);//等待串口事件EV_RXCHAR
if not l_bRXFinish then
if GetLastError()= ERROR_IO_PENDING then//正在接受数据;
begin
l_dwbb:=WaitForSingleObject(g_LpolR^.hEvent,500);//等待500MS
case l_dwbb of
WAIT_OBJECT_0: l_bRXFinish:=GetOverlappedResult(g_Hcom,g_LpolR^,l_dwOvres,False);
WAIT_TIMEOUT: l_bRXFinish:= False//定是益出
else
l_bRXFinish := False;
end;
end
else
l_bRXFinish:=False;
if l_bRXFinish then
begin
ResetEvent(g_Post_Event); //同步事件复位
PostMessage(frm_SerialPort.Handle,Wm_CommNotify,0,0);
end;
end;
end;procedure Tfrm_SerialPort.FormShow(Sender: TObject);
begin
try
btn_CloseSerialPort.Enabled := False;
cbb_SerialPort.Clear;
mem_RevData.Clear;
mem_SendData.Clear;
cbb_SerialPort.AddItem('',nil);
cbb_SerialPort.AddItem('COM1',nil);
cbb_SerialPort.AddItem('COM2',nil);
cbb_SerialPort.AddItem('COM3',nil);
cbb_SerialPort.AddItem('COM4',nil);
except on e:Exception do
ShowMessage(e.Message);
end;
end;procedure Tfrm_SerialPort.btn_OpenSerialPortClick(Sender: TObject);
begin
if cbb_SerialPort.Text ='' then
begin
MessageDlg('请选择COM口',mtWarning,[mbOK],0);
end
else
begin
btn_CloseSerialPort.Enabled := True;
try
CommInitialize;
except on e:Exception do
ShowMessage(e.Message);
end;
end;
end;procedure Tfrm_SerialPort.btn_CloseSerialPortClick(Sender: TObject);
begin
btn_CloseSerialPort.Enabled := False;
end;procedure Tfrm_SerialPort.btn_CloseClick(Sender: TObject);
begin
Self.Close;
end;procedure Tfrm_SerialPort.CommInitialize;
var
l_Lpdcb:TDCB;
begin
g_Hcom:= CreateFile(PAnsiChar(cbb_SerialPort.Text),GENERIC_READ or GENERIC_WRITE,0,nil,
OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
g_bFlag := True;
if g_Hcom <> invalid_handle_value then
begin
SetupComm(g_Hcom,4096,4096);
GetCommState(g_Hcom,l_Lpdcb);
l_Lpdcb.BaudRate := 9600;
l_Lpdcb.StopBits :=0;
l_Lpdcb.ByteSize :=8;
l_Lpdcb.Parity :=0;
SetCommState(g_Hcom,l_Lpdcb);
SetCommMask(g_Hcom,EV_RXCHAR);
end
else
ShowMessage('无法打开串口');
end;
function Tfrm_SerialPort.WriteStr(const Str: string): Boolean;
var
l_DwCharsWritten,l_DwRes:DWORD;
l_S_DATA:string;
l_BRes:Boolean;
begin
l_BRes :=False;
l_S_DATA:=Str;
if g_Hcom<>invalid_handle_value then
begin
l_DwCharsWritten :=0;
l_BRes :=WriteFile(g_Hcom,PChar(l_S_DATA)^,Length(l_S_DATA),l_DwCharsWritten,g_LpolW);
if not l_BRes then
begin
if GetLastError()=ERROR_IO_PENDING then
begin
l_DwRes :=WaitForSingleObject(g_LpolW^.hEvent,INFINITE);
if l_DwRes=WAIT_OBJECT_0 then
l_BRes :=GetOverlappedResult(g_Hcom,g_LpolW^,l_DwCharsWritten,False)
else
l_BRes:=True;
end;
end;
end
else
Result := l_BRes;
end;procedure Tfrm_SerialPort.MsgComm(var Msg: TMessage);
var
l_bclear:Boolean;
l_coms :TComStat;
l_dwcbNum,l_dwCbread,l_dwlpErrors:DWORD;
l_s:string;
begin
l_bclear :=ClearCommError(g_Hcom,l_dwlpErrors,@l_coms);
if l_bclear then
begin
l_dwcbNum :=l_coms.cbInQue;//获取接受缓冲区待接收字节数
SetLength(l_s,l_dwcbNum+1);//分配内存
ReadFile(g_Hcom,PChar(l_s)^,l_dwcbNum,l_dwCbread,g_LpolR);//读串口
SetLength(l_s,l_dwCbread);//分配
SetEvent(g_Post_Event);//同步事件置位
mem_RevData.Lines.Add(l_s);
end;
end;procedure Tfrm_SerialPort.btn_SendClick(Sender: TObject);
var
l_S_DATA:string;
begin
l_S_DATA :=mem_SendData.Text;
if WriteStr(l_S_DATA) then
ShowMessage('无法发送数据')
else
ShowMessage('发送成功');
end;procedure Tfrm_SerialPort.FormDestroy(Sender: TObject);
begin
CloseHandle(g_LpolW^.hEvent);
CloseHandle(g_LpolR^.hEvent);
Dispose(g_LpolR);
Dispose(g_LpolW);
g_LpolW :=nil;
g_LpolR :=nil;
g_RXComm.Terminate;
SetEvent(g_Post_Event);
CloseHandle(g_Post_Event);
CloseHandle(g_Hcom);
end;procedure Tfrm_SerialPort.FormCreate(Sender: TObject);
begin
// CommInitialize;
New(g_LpolW);
New(g_LpolR);
g_LpolW^.Internal :=0;
g_LpolW^.InternalHigh :=0;
g_LpolW^.Offset :=0;
g_LpolW^.OffsetHigh :=0;
g_LpolW^.hEvent :=CreateEvent(nil,True,False,nil);
g_LpolR^.Internal :=0;
g_LpolR^.InternalHigh :=0;
g_LpolR^.Offset :=0;
g_LpolR^.OffsetHigh :=0;
g_LpolR^.hEvent :=CreateEvent(nil,True,False,nil);
PurgeComm(g_Hcom,PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR);
g_Post_Event:=CreateEvent(nil,True,True,nil);
g_RXComm :=TComm.Create(False);
end;procedure Tfrm_SerialPort.btn_SaveToFileClick(Sender: TObject);
begin
try
if mem_RevData.Text =''then
ShowMessage('接收数据不能为空!')
else
mem_RevData.Lines.SaveToFile('d:\receive.tex');
except end;
end;end.
http://www.moon-soft.com/program/bbs/readelite515510.htm