Delphi4下的对串口的简单读取

goodyoung 2000-03-30 08:17:00
加精
单片机的输出信号通过RS232电平转换后,接
至PC机的COM2串口,如何实现Delphi4环境下
以查询方式读取串口数据?
我曾经试了ReadFile等函数,可是编译时总
说实参与形参类型不匹配。
各位高手能否给出完整的代码,谢谢!
...全文
1169 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
qzg 2001-10-20
  • 打赏
  • 举报
回复
我收藏一下,希望您别介意。
AdminBO 2001-02-16
  • 打赏
  • 举报
回复
You Use SpCOMM, download by VCl.VCLXX.com
aiirii 2000-07-02
  • 打赏
  • 举报
回复
我不赞成用mscomm,虽然容易,但要发布程序就麻烦了一点.其实就是用createfile,writfile,readfile,几个api而已.
eagleyin 2000-04-03
  • 打赏
  • 举报
回复
我这里有一个UNIT,比较简单,请用吧,希望能交个朋友:-) eagleyin@jlonline.com
格式有点乱,不过确实能用的。

///////////////
//
// (P) Eagle.Yin
// Serial port communication unit based on timers
//
// 1999/10/02 Mainframe was finished
// 1999/10/03 Add routine 'Get_Port_Config' for debug
// Add Input-Time-Out processing code
// 1999/10/07 Add error checking when read and write serial port
// Add routine 'Set_Port_TimeOut' and delete 'tmOut' parameters in 'Open_Port'
// Add routine 'Port_Error_Str' to get text description of port error
//
{---$define debugall}
{---$define debug}

unit SerialPort;

interface
uses
Windows, ExtCtrls;

const
tmInterval = 50; // timer interval is 50ms
const
E_NO_ERROR = 0; // port error codes
E_OPEN = 1;
E_GET_STATE = 2;
E_SET_STATE = 3;
E_GET_TMO = 4;
E_SET_TMO = 5;
E_TIMEOUT = 6;
E_READ = 7;
E_WRITE = 8;

const
InBufferSize= 1024; // size of input buffer
type
TInBuffer= array[0..InBufferSize-1] of byte; // input buffer

type
TReader = procedure( len:integer; var buf:TInBuffer ) of object; // data reader procedure
TWatcher = procedure( erCode:integer ) of object; // port exception watcher
type
TSerialPort = class( TObject )
private
hReader : TReader; // handle of data reader
hWatcher : TWatcher; // handle of watcher
tmReader : TTimer; // port monitor
tmOutCnt,
tmOutVal : integer; // time out value, tmOut = TIME_OUT(ms)/tmInterval(ms)
DataInFlag: boolean; // data flow in flag

procedure Monitor( Sender:TObject );
protected
hPort : THandle; // handle of serial port
public
procedure Set_Port_TimeOut( tmOut:integer );
function Open_Port( PortName:string; BaudRate, ByteSize, StopBits, Parity:integer ):integer;
procedure Close_Port;
function WriteData( num:integer; var buf ):integer;

function Get_Port_Config( var BaudRate, ByteSize, StopBits, Parity:integer ):boolean;

constructor Create( dReader:TReader; dWatcher:TWatcher );
destructor Destroy; override;
end;// TSerialPort

function Port_Error_Str( eCode:integer ):string;

implementation
uses
SysUtils, Dialogs;
//--------------------------------------------------------------------------------------------------
var
Err_Table : array[0..8] of string = ( // port error message table
'', // no error
'打开串行口失败',
'获取串行口状态失败',
'设置串行口状态失败',
'获取串行口超时失败',
'设置串行口超时失败',
'串行口无数据输入',
'读串行口错误',
'写串行口错误'
); // Error string table
function Port_Error_Str( eCode:integer ):string;
//
// This function return text description for port errors
// eCode : Port error code
// result: Text description for port error
//
begin
if ( eCode>=0 ) and ( eCode<=8 ) then
result := Err_Table[eCode] + '(' + inttostr( eCode ) + ')'
else
result := '未知串行口错误(' + inttostr( eCode ) + ')';
end;
//--------------------------------------------------------------------------------------------------
var
buf : TInBuffer; // input buffer for monitor

procedure TSerialPort.Monitor( Sender:TObject );
//
// This procedure is the 'OnTimer' event handler of 'tmReader', it reads data from serial port and
// call 'hReader' if necessary, it also counts timeouts, if timeout occured, it will call the error
// handler 'hWatcher'
//
var
eCode : dword;
cStat : COMSTAT;
numRead : dword;
begin
// manipulate serial port
eCode := 0;
ClearCommError( hPort, eCode, @cStat );
repeat
numRead :=0;
if not ReadFile( hPort, buf, sizeof( buf ), numRead, nil ) then
begin
if Assigned( hWatcher ) then // call read-error handler
hWatcher( E_READ );
exit;
end;{ if }

// count timeout counter
DataInFlag := numRead >0; // set data flow in flag
if DataInFlag then // reset time out counter if data in
tmOutCnt := 0;
inc( tmOutCnt );
if tmOutCnt>=tmOutVal then // timeout occured
begin
tmOutCnt := 0; // reset time out counter
if Assigned( hWatcher ) then
hWatcher( E_TIMEOUT );
end;{ if }

// pass data to reader
if Assigned( hReader ) then
hReader( numRead, buf );
until ( numRead<sizeof( buf ) );
end;
//--------------------------------------------------------------------------------------------------
procedure TSerialPort.Set_Port_TimeOut( tmOut:integer );
//
// This procedure set port timeout value and reset the timeout counter
// tmOut : Port timeout value, in milliseconds
//
begin
tmOutVal := tmOut div tmInterval;
tmOutCnt := 0;
end;

function TSerialPort.Open_Port( PortName:string; BaudRate, ByteSize, StopBits, Parity:integer ):integer;
//
// Open and config serial port and activate the monitor timer
//
function OpenPort:integer;
begin
hPort := INVALID_HANDLE_VALUE; // init port handle
hPort := CreateFile( pchar( PortName ), // port name
GENERIC_READ or GENERIC_WRITE, // access mode
0, // share mode
nil, // security attributes
OPEN_EXISTING, // how to create
0, // file attributes
0 ); // template file

if hPort = INVALID_HANDLE_VALUE then
result := E_OPEN
else
result := E_NO_ERROR;

{$ifdef debug}
if result<>E_NO_ERROR then
ShowMessage( 'Can not open port:' + PortName );
{$endif}
end;

function ConfigPort:integer;
var
commDCB : DCB;
commTMO : TCOMMTIMEOUTS;
begin
if not GetCommState( hPort, CommDCB ) then // can't get port state
begin
result := E_GET_STATE;
CloseHandle( hPort );
hPort := INVALID_HANDLE_VALUE;
{$ifdef debug}
ShowMessage( 'Can not get port state:' + PortName );
{$endif}
exit;
end;{ if }

commDCB.BaudRate := BaudRate; // setup port device control block
commDCB.ByteSize := ByteSize;
commDCB.StopBits := StopBits;
commDCB.Parity := Parity;

if not SetCommState( hPort, commDCB ) then // can't set port state
begin
result := E_SET_STATE;
CloseHandle( hPort );
hPort := INVALID_HANDLE_VALUE;
{$ifdef debug}
ShowMessage( 'Can not set port state:' + PortName );
{$endif}
exit;
end;{ if }

if not GetCommTimeOuts( hPort, commTMO ) then // can't get port time outs
begin
result := E_GET_TMO;
CloseHandle( hPort );
hPort := INVALID_HANDLE_VALUE;
{$ifdef debug}
ShowMessage( 'Can not get port timeouts:' + PortName );
{$endif}
exit;
end;{ if }

with commTMO do // setup port time outs
begin
ReadIntervalTimeOut:=MAXDWORD;
ReadTotalTimeOutMultiplier:=0;
ReadTotalTimeOutConstant:=0;
end;{ with }

if not SetCommTimeOuts( hPort, commTMO ) then // can't set port time outs
begin
result := E_SET_TMO;
CloseHandle( hPort );
hPort := INVALID_HANDLE_VALUE;
{$ifdef debug}
ShowMessage( 'Can not set port timeouts:' + PortName );
{$endif}
exit;
end;{ if }

result := E_NO_ERROR; // default result
end;
begin
result := OpenPort; // open port
if result<>E_NO_ERROR then
exit;

result := ConfigPort; // config port
if result<>E_NO_ERROR then
exit;

PurgeComm( hPort, PURGE_TXABORT + PURGE_RXABORT + PURGE_TXCLEAR + PURGE_RXCLEAR );
tmReader.Enabled := True; // init monitor timer
end;

procedure TSerialPort.Close_Port;
//
// Close port and deactivate the monitor timer
//
begin
if hPort<>INVALID_HANDLE_VALUE then
begin
tmReader.Enabled := False; // disable monitor timer

PurgeComm( hPort, PURGE_TXABORT + PURGE_RXABORT + PURGE_TXCLEAR + PURGE_RXCLEAR );
CloseHandle( hPort ); // close port
hPort := INVALID_HANDLE_VALUE;
end;{ if }
end;

function TSerialPort.WriteData( num:integer; var buf ):integer;
var
eCode : dword;
cStat : COMSTAT;
begin
eCode := 0;
ClearCommError( hPort, eCode, @cStat );
result := 0;
if not WriteFile( hPort, buf,num, dword( result ), nil ) then
begin
if Assigned( hWatcher ) then // call write error handler
hWatcher( E_WRITE );
end;{ if }
end;

function TSerialPort.Get_Port_Config( var BaudRate, ByteSize, StopBits, Parity:integer ):boolean;
//
// Get current port configuration
//
var
commDCB : DCB;
begin
result := ( hPort<>INVALID_HANDLE_VALUE );
if result then
begin
result := GetCommState( hPort, commDCB );
if result then
begin
BaudRate := commDCB.BaudRate;
ByteSize := commDCB.ByteSize;
StopBits := commDCB.StopBits;
Parity := commDCB.Parity;
end;{ if }
end;{ if }
end;
//--------------------------------------------------------------------------------------------------
constructor TSerialPort.Create( dReader:TReader; dWatcher:TWatcher );
begin
inherited Create;

hPort := INVALID_HANDLE_VALUE; // init port handle
hReader := dReader; // init event handler
hWatcher := dWatcher; // init watcher handler

tmOutVal := 5*1000; // default time out value is 5s
DataInFlag := True;

tmReader := TTimer.Create( nil ); // init timer
with tmReader do
begin
Enabled := False;
Interval := tmInterval;
OnTimer := Monitor;
end;{ with }
end;

destructor TSerialPort.Destroy;
begin
hWatcher := nil; // disable event handler
hReader := nil;
Close_Port; // close serial port
tmReader.Destroy; // destroy monitor reader

inherited;
end;

end.
zyb 2000-03-31
  • 打赏
  • 举报
回复
有一个ActiveX控件MSComm.ocx很不错的,使用简单、灵活!
它的读取:
var s : string ;
s := MSComm1.Input ;
Yangyang 2000-03-30
  • 打赏
  • 举报
回复
ReadFile( FHandle, DataPtr^, nToRead, nRead, nil );
FHandle 为串口句柄,DataPtr^为串口缓存......,其余的参数可见帮助。
Firing_Sky 2000-03-30
  • 打赏
  • 举报
回复
1.用M$的MSComm控件
2.用CreateFile打开串口,ReadFile来读,这里有一段我用C Builder写的程序中的一段函数,你看看

bool ReceiveByteFromComDev(double TimeReceiveDelay, unsigned char* ByteBuf, HANDLE hCom)
{
unsigned long dwNumRead ;
unsigned long dwNumtoRead ;
unsigned char TempCommRead[3];
GetCommTimeouts(hCom,&MyCommTimeouts);
MyCommTimeouts.ReadIntervalTimeout = TimeReceiveDelay;
MyCommTimeouts.ReadTotalTimeoutMultiplier = 1;
MyCommTimeouts.ReadTotalTimeoutConstant = TimeReceiveDelay;
SetCommTimeouts(hCom ,&MyCommTimeouts );
dwNumtoRead = 1 ;
BOOL Fcom=ReadFile(hCom,&TempCommRead,dwNumtoRead ,&dwNumRead,NULL);
if (Fcom && dwNumRead!= 0) {*ByteBuf = TempCommRead[0] ;return true;}
else return false;
}

5,386

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧