这个是早期的版本,后期我做了很大的修动...仅做为学习参考用.
在做数据采集,及控制系统中,我建议大家自己用API写通讯类..不要使用SPCOMM,以及MSCOMM...在实际的应用中,自己写的通讯类在应用上会更加的灵活方便(^^当然写这个通讯类是比较费时的...)
在做数据采集时,可以自己很方便的加入CRC或者checksum校验方式..51以CRC8 /16为主......采用CRC可以使用数据传输更加的可靠..
unit MYCOMM;
{
This unit create by 李金浩
2004-3-12号23:26修正
QQ:67260745
E-Mail:LTSoft918@163.com
}
interface
uses
Forms, SysUtils, Windows, Messages, Dialogs, Controls, Classes, ToolWin, ComCtrls,
ExtCtrls, StdCtrls, Math;
//----------------
(*串口号*)
const
Com1=1;
Com2=2;
Com3=3;
Com4=4;
Com5=5;
Com6=6;
Com7=7;
Com8=8;
Com9=9;
Com10=10;
(*StopBit*)
sbit1=0;
sbit1_5=1;
sbit2=2;
(*modem 事件常量*)
MY_CTS=1; //The CTS (clear-to-send) signal is on.
MY_DSRL=2; //The DSR (data-set-ready) signal is on.
MY_RING=4; //The ring indicator signal is on.
MY_RLSD=8; //The RLSD (receive-line-signal-detect) signal is on.
(*处理消息*)
MY_ReadComm=WM_User+507;
Type
TMyComm=Class
public
(*关闭指定串口*)
//********************
Function CloseComm(Const Com:integer;const CloseAll:boolean=False):boolean;
(*打开指定串口*)
function OpenComm(Const COM:integer;
Const My_BandRate:DWORD=4800;
Const My_ByteSize:byte=8;
Const My_Parity:byte=NoParity;
Const My_StopBits:byte=0):Boolean;
//读串口函数集
Function ReadComm_string(Const Com:integer;var revcStr:string;const len:DWORD=0):boolean;//读取串口string
Function ReadComm_ByteArray(const Com:integer;var revcArray:array of byte;const len:DWORD=0):boolean;
Function ReadComm_Byte(Const Com:integer;var OneByte:byte):boolean;
//写串口口函数集
Function WriteComm_String(Const Com:integer;Const SendString:string):boolean;
Function WriteComm_ByteArray(Const Com:integer;const SendByte:array of byte;Buflong:DWORD):boolean;
Function WriteComm_Byte(Const Com:integer;const SendByte:byte):boolean;
//--------------
Function GetRXDsize(com:integer):integer; //得到RXD缓冲区数据长度
Function GetModemState(com:integer):DWord;//得到状态口的状态
procedure SetReadOFFByte(offByte:byte=$13);//设置接收停止结束符
Function IsReadOFFByte(RByte:byte):boolean;//判断接收的是不是停止结束符
procedure ClearRXD(com:integer);//清空RXD缓冲区内容
procedure ClearTXD(com:integer);//清空TXD缓冲区内容
procedure ClearComBuf(com:integer);//清空所有缓冲区
end;
//---------------------
var
MComm:TMycomm;//创建TMycomm实例
// myThread:TThread;
// Timer1:TTimer;
bOFFByte:byte;//接收结束byte
lpDCB:TDCB;
COMHandle:array[1..10] of Thandle; //文件句柄
ComOpenFlag:array[1..10] of boolean;//文件打开标识
rCommTimeouts:COMMTIMEOUTS;
bSuccessFlag:boolean;
ipError:Dword;
lpstat:PcomStat;
abSendBuf,abRecvBuf:array[1..1024] of byte;
nBytesWrite,nBytesRead:DWORD;//设置已写/读的数量
i:integer;
//---------
implementation
{***************************************************}
(*打开文件句柄 *)
(*默认格式如:MComm.OpenComm(com1,4800,8,NoParity,0)*)
{***************************************************}
function TMyComm.OpenComm(const COM:integer; //端口号
const My_BandRate:DWORD;//波特率
Const My_ByteSize:byte; //数据位
Const My_Parity:byte; //是否有奇偶校验
Const My_StopBits:byte):Boolean;//打开指定串口//打开指定串口
var //默认设置格式为:4800,8,N,1
comNum:string;
begin
//如果ComOpenFlag[COM]=false 表示未打开。。。则进行操作
if not ComOpenFlag[COM] then//if ComOpenFlag[COM]=false
begin
comNum:=format('Com%d',[com]);
(*第一。创键文件句柄*)
ComHandle[com]:=Createfile(pAnsiChar(comNum),
GENERIC_Read or GENERIC_Write,(*访问读写方式*)
0,(*不共享*)
nil,(*无安全属性指针*)
open_existing,(*创建方式*)
file_attribute_normal,0);
if ComHandle[com]=invalid_handle_value then
begin
// showmessage('com1打开错误!');
CloseComm(com); //调用关闭串口
result:=false;
exit;
end
else begin
result:=True;
ComOpenFlag[COM]:=true //表示打开过
end; // if ComHandle[com]=invalid_handle_value then
(*第二:设备com输入输出缓冲区*)
bSuccessFlag:=SetupComm(ComHandle[com],4096,4096);
if not bSuccessFlag then
begin
showmessage('设备com输入输出缓冲区错误!');
CloseComm(com);
result:=false;
exit;
end;
(*第三:取得默认DCB*)
bSuccessFlag:=GetCommstate(ComHandle[com],lpDcb);
if not bSuccessFlag then
begin
// showmessage('取得默认DCB错误!');
CloseCOMM(ComHandle[com]);
result:=false;
exit;
end;
(*第四,设置DCB*)
//4800,8,N,1
lpDCB.BaudRate:=My_BandRate;
lpDCB.ByteSize:=My_ByteSize;
lpDCB.Parity:=My_Parity;//N无奇偶校验
lpDCB.StopBits:=My_StopBits;//0,1,2===>1,1.5,2
bSuccessFlag:=SetCommstate(ComHandle[com],lpDCB);
if not bSuccessFlag then
begin
// showmessage('设置DCB错误!');
CloseCOMM(ComHandle[com]);
exit;
end;
ClearComBuf(Com);//清空所有缓冲区
ClearCommError(ComHandle[com],iperror,lpstat);
(*第六 设置TimeOut*)
rCommTimeouts.ReadIntervalTimeout:=0;
rCommTimeouts.ReadTotalTimeoutConstant:=250;
rCommTimeouts.ReadTotalTimeoutMultiplier:=0;
rCommTimeouts.WriteTotalTimeoutMultiplier:=0;
rCommTimeouts.WriteTotalTimeoutConstant:=250;
bSuccessFlag:=SetCommTimeOuts(ComHandle[com],rCommTimeouts);
//EV_RXCHAR A character was received and placed in the input buffer.
SetCommMask(comHandle[com],EV_RXCHAR
or EV_CTS
or EV_DSR
or EV_RING
or EV_RLSD); //设置接收消息
//------------------------------------------
if not bSuccessFlag then
begin
// showmessage('设置TimeOut出错!');
result:=false;
CloseCOMM(ComHandle[com]);
exit;
end;
end else begin
result:=false;
end;
end;
{**************************************************}
(*关闭文件句柄 *)
(*CloseAll:boolean默认为false;为True时关闭所有端口*)
{**************************************************}
Function TMyComm.CloseComm(Const Com:integer;const CloseAll:boolean):boolean;
var
cSucc:boolean;
i:integer;
begin
//关闭文件句柄
if not CloseAll then
begin
cSucc:=true;
if ComOpenFlag[COM] then //如果处于打开,就进行关闭处理
begin
cSucc:=CloseHandle(ComHandle[com]);
ComOpenFlag[COM]:=false;//设为false。表示已关闭
end;
result:=cSucc;
end else
begin
//关闭所有端口
for i:=1 to 10 do
begin
CloseHandle(ComHandle[i]);
end;
result:=True;;
end;
//----------------
end;
{******************************}
(* 读串口 ReadComm_string *)
(* 读取string *)
{******************************}
Function TMyComm.ReadComm_string(Const Com:integer;var revcStr:string;const len:DWORD=0):boolean;
var
SL:DWORD;
begin
//在读取前消空缓冲区
result:=True;
SL:=len;
//如果为len=0 则系统自动获取缓冲区长度
if len=0 then SL:=GetRxDSize(Com);
revcStr:='';
bSuccessFlag:=ReadFile(ComHandle[com],Pointer(revcStr)^,SL,nBytesRead,nil);
if (not bSuccessFlag) or (nBytesRead=0) then result:=false;
end;
{******************************}
(* 读取byte数组 *)
{******************************}
Function TMyComm.ReadComm_ByteArray(const Com:integer;
var revcArray:array of byte;
const len:DWORD=0):boolean;
var
i:integer;
SL:DWORD;
begin
result:=True;
SL:=len;
//如果为len=0 则系统自动获取缓冲区长度
if len=0 then SL:=GetRXDsize(ComHandle[com]);
if GetRXDsize(ComHandle[com])>high(revcArray) then//如果接缓冲区的数据大于数组就出错
begin
ClearRXD(ComHandle[com]);//出错时清空读取缓冲区
result:=false;
exit;
end;
//在读取前消空缓冲数组
for i:=low(revcArray) to high(revcArray) do
begin //清空读写数组,防止读取乱码
revcArray[i]:=byte(0);
end;
bSuccessFlag:=ReadFile(ComHandle[com],revcArray,SL,nBytesRead,nil);
if (not bSuccessFlag) or (nBytesRead=0) then result:=false;
end;
{******************************}
(* 读串口 ReadComm_Byte *)
(* 读取一个Byte *)
{******************************}
Function TMyComm.ReadComm_Byte(Const Com:integer;var OneByte:byte):boolean;
begin
result:=true;
if GetRXDSize(com)<=0 then
begin
result:=false;
exit;
end;
bSuccessFlag:=ReadFile(ComHandle[com],OneByte,1,nBytesRead,nil);
if (not bSuccessFlag) or (nBytesRead=0) then result:=false;
end;
{******************************}
(* 写串口WriteComm_String *)
{******************************}
Function TMyComm.WriteComm_String(Const Com:integer;Const SendString:string):boolean;
begin
result:=true;
PurgeComm(ComHandle[com],4);//清空TXD缓冲区内空
bSuccessFlag:=writeFile(ComHandle[com],pointer(SendString)^,length(sendString),nBytesWrite,nil);
if (not bSuccessFlag) or (nBytesWrite=0) then result:=false;
end;
{***************************}
(*写串口WriteComm_ByteArray*)
(*发送一个byte 数组 *)
{***************************}
Function TmyComm.WriteComm_ByteArray(Const Com:integer;const SendByte:array of byte;Buflong:DWORD):boolean;
begin
result:=true;
//----------------
ClearTXD(ComHandle[com]);//清空TXD缓冲区内空
bSuccessFlag:=writeFile(ComHandle[com],SendByte,Buflong,nBytesWrite,nil);
if (not bSuccessFlag) or (nBytesWrite=0) then result:=false;
end;
{***************************}
(* WriteComm_Byte *)
(* 写入一个byte *)
{***************************}
function TMyComm.WriteComm_Byte(const Com: integer;const SendByte:byte): boolean;
begin
result:=true;
//----------------
ClearTXD(ComHandle[com]);//清空TXD缓冲区内空
bSuccessFlag:=writeFile(ComHandle[com],SendByte,1,nBytesWrite,nil);
if (not bSuccessFlag) or (nBytesWrite=0) then result:=false;
end;
{**************************************}
(* 得到RXD缓冲区的数据长度 *)
{**************************************}
function TMyComm.GetRXDsize(com:integer): integer;
var
cs:TComstat;
begin
ClearCommError(ComHandle[com],iperror,@cs);
result:=cs.cbInQue
end;
{******************}
(* 清空RXD *)
{******************}
procedure TMyComm.ClearRXD(com: integer);
begin
PurgeComm(ComHandle[com],8);//清空RXD缓冲区内空
end;
{*************************************}
(* 清空所有缓冲区 *)
{*************************************}
procedure TMyComm.ClearComBuf(com:integer);
begin
//第五:通过PurgeComm清空指定通信口的输入输出缓冲区的所有字符
// PURGE_TXABORT = 1; { Kill the pending/current writes to the comm port. }
// PURGE_RXABORT = 2; { Kill the pending/current reads to the comm port. }
// PURGE_TXCLEAR = 4; { Kill the transmit queue if there. }
// PURGE_RXCLEAR = 8; { Kill the typeahead buffer if there. }
PurgeComm(ComHandle[com],1 or 2 or 4 or 8);
end;
{******************}
(* 清空TXD *)
{******************}
procedure TMyComm.ClearTXD(com: integer);
begin
PurgeComm(ComHandle[com],4);//清空TXD缓冲区内空
end;
{*******************************}
// 端口状态消息说明
// MS_CTS_ON //The CTS (clear-to-send) signal is on.
// MS_DSR_ON //The DSR (data-set-ready) signal is on.
// MS_RING_ON //The ring indicator signal is on.
// MS_RLSD_ON //The RLSD (receive-line-signal-detect) signal is on.
{*******************************}
function TMyComm.GetModemState(com: integer): DWord;
var
dwModemState:DWord;
begin
if GetCommModemStatus(ComHandle[com],dwModemState) then
result:=dwModemState
else
result:=0;//操作失败返回为0
end;
{************************************************}
{设置接收结束byte--->设置全局变量offByte }
{注:这里的接收结束byte不是DCB里XoffChar是自定义的}
{************************************************}
procedure TMyComm.SetReadOFFByte(offByte: byte);
begin
bOFFByte:=offByte
end;
{*****************************************}
{判断设置的结束byte--->读取全局变量offByte}
{*****************************************}
function TMyComm.IsReadOFFByte(RByte: byte): boolean;
begin
result:=RByte=bOFFByte
end;
initialization
MComm:= TMycomm.Create;
finalization
MComm.CloseComm(0,True);//关闭所有端口
MComm.Free;
end.