这个是早期的版本,后期我做了很大的修动...仅做为学习参考用.
在做数据采集,及控制系统中,我建议大家自己用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.
|