rs232串口通讯模块 - Delphi编程
應(yīng)為工作需要自己編寫的RS232通訊模塊,該模塊已經(jīng)編寫了蠻久,在實(shí)際使用中可能有沒(méi)有考慮和不完善的地方。
| 正在裝載數(shù)據(jù)…… |
//=================================================================================
//如果使用該模塊請(qǐng)保留該注釋,如果被修改或編輯請(qǐng)將修改后的代碼發(fā)送一份給我
//編寫:戴琪英
//E_Mail:qiyingdai@163.com
//2000-09-01
//=================================================================================
unit R232Comm;
interface
uses
Windows,SysUtils;
const
INITR12COMM_SUCCESS=0;
INITR12COMM_FAILURE=-1;
var
bSendFinish:boolean=True;//發(fā)送完標(biāo)志
iRecvLen:DWORD=0;
RecvBuff,TempBuff:PChar;
SendCommand,RecvCommand:String;//發(fā)送和接收到的命令
RecvFinish:BOOL=False;
RecvBuffInit:BOOL=False;
SendCommandSuccess:BOOL; //切換臺(tái)命令被成功發(fā)送標(biāo)志
functionInitR12CommDev(comNo:PChar):String;//初始化切換臺(tái)串口,返回狀態(tài)字符
procedure SwitchR12(WriteBuffer:PChar);//對(duì)切換臺(tái)進(jìn)行切換函數(shù)
procedure SwitchR12Byte(WriteBuffer:Byte);
procedure CommSendNotify;//串口接收到字符事件響應(yīng)過(guò)程
procedure CommRecvNotify; //串口發(fā)送緩沖區(qū)空事件響應(yīng)過(guò)程
procedure CommWatchThread(var lpdwParam:DWORD);//通信口監(jiān)視線程
functionConInfo :String;
implementation
var
//comMask,comBuf,ComState:Integer;
dcb:_DCB; //DCB結(jié)構(gòu)用于配置串口,程序中涉及各域含義如下:
//DWORD DCBlength :DCB結(jié)構(gòu)大小
//DWORD BaudRate :波特率
//DWORD fBinary: 1 二進(jìn)制模式
//DWORD fParity: 1 進(jìn)行奇偶校驗(yàn)
//BYTEByteSize: 字符位數(shù) 4~8
//BYTEParity:奇偶校驗(yàn)位 0-4分別表示無(wú)、奇、偶、傳號(hào)、空號(hào)校驗(yàn)
//BYTEStopBits: 停止位數(shù) 0-2分別表示 1、1.5、2個(gè)停止位
//WORDXonLim :XON 閾值
//WORDXoffLimXOFF 閾值
//charXonChar: XON 字符
//charXoffChar: XOFF 字符
//charEvtChar:事件字符
comStat:_COMSTAT; //COMSTAT結(jié)構(gòu)用于存放有關(guān)通信設(shè)備的當(dāng)前信息
//程序中涉及各域含義如下:
//cbInQue :接收緩沖區(qū)中字符個(gè)數(shù)
//cbOutQue:發(fā)送緩沖區(qū)中字符個(gè)數(shù)
dwErrorFlag:LongWord;
hCommDev,comThreadHwnd:Thandle;//通信串口句柄和通信監(jiān)視線程句柄
comMask,comBuf,comState:BOOL;
read_os,write_os:_OVERLAPPED;//OVERLAPPED 結(jié)構(gòu),用于異步操作的Win32函數(shù)中
//程序中涉及各域含義如下:
//DWORD Interval 保留給操作系統(tǒng)使用
//DWORD IntervalHigh 保留給操作系統(tǒng)使用
//DOWDhEvent 當(dāng)I/O操作完成時(shí)被設(shè)置為有信號(hào)狀態(tài)
//的事件;當(dāng)調(diào)用ReadFile和WriteFile函數(shù)之前,調(diào)
//用進(jìn)程設(shè)置該事件
postRecvEvent,postSendEvent:Thandle;//發(fā)送緩沖區(qū)空和接收到字符事件句柄
dwThreadID1:DWORD; //通信監(jiān)視線程ID號(hào)
///串口初始化函數(shù)
//該函數(shù)主要完成串口初始化設(shè)置和通信線程的啟動(dòng)
//入口參數(shù):串口號(hào)
//返回值;初始化是否成功的狀態(tài)字符
functionInitR12CommDev(comNo:PChar) :String;
begin
///打開(kāi)串口
hCommDev:=CreateFile(comNo,//串口好
GENERIC_READ or GENERIC_WRITE,//對(duì)串口以讀寫方式打開(kāi)
0,
nil,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED,//允許重疊操作
0
);
if hCommDev=INVALID_HANDLE_VALUE then
InitR12CommDev:='切換臺(tái)通訊端口初始化失敗.'
else
InitR12CommDev:='切換臺(tái)通訊端口初始化成功.';
comMask:=SetCommMask(hCommDev,EV_RXFLAG);//設(shè)置事件掩碼
//comBuf:=SetupComm(hCommDev,4096,4096);//設(shè)置接收和發(fā)送緩沖區(qū)大小皆為4096字節(jié)
comBuf:=SetupComm(hCommDev,1,1);//設(shè)置接收和發(fā)送緩沖區(qū)大小皆為4096字節(jié)
ifcomBuf=False then
InitR12CommDev:='切換臺(tái)通訊端口初始化失敗.'
else
begin
InitR12CommDev:='切換臺(tái)通訊端口初始化成功.';
//清空緩沖區(qū)
PurgeComm(hCommDev,PURGE_TXABORT or PURGE_RXABORT or
PURGE_TXCLEAR or PURGE_RXCLEAR ) ;
end;
//以下對(duì)串口進(jìn)行配置
dcb.DCBlength:=sizeof(_DCB);
comState:=GetCommState(hCOmmDev,dcb);//得到缺省設(shè)置
ifcomState=False then
InitR12CommDev:='切換臺(tái)通訊端口初始化失敗.'
else
InitR12CommDev:='切換臺(tái)通訊端口初始化成功.';
dcb.BaudRate:=9600;//波特率 9600
dcb.ByteSize:=8;//7;//數(shù)據(jù)長(zhǎng)度7位
dcb.Parity:=NOPARITY;//ODDPARITY; //校驗(yàn)方式 奇校驗(yàn)
dcb.StopBits:=ONESTOPBIT; //停止位 1 位
dcb.Flags := 0;// Enable fBinary
dcb.Flags := dcb.Flags or 2;// Enable parity check
dcb.XonChar:= chr($00) ;
dcb.XoffChar:= chr($00) ;
dcb.XonLim:= 100 ;
dcb.XoffLim:= 100 ;
dcb.EvtChar := Char($ff);
comState:=SetCommState(hCommDev,dcb);//設(shè)置串口
if comState=False then
InitR12CommDev:='切換臺(tái)通訊端口初始化失敗.'
else
InitR12CommDev:='切換臺(tái)通訊端口初始化成功.';
//設(shè)置通信接收到字符事件句柄
postRecvEvent:=CreateEvent(NIL,
TRUE,//手工重置事件
TRUE, //初始化為有信號(hào)狀態(tài)
NIL
);
//設(shè)置讀異步I/O操作事件句柄
read_os.hEvent:=CreateEvent(NIL,
TRUE,//手工重置事件
FALSE, //初始化為無(wú)信號(hào)狀態(tài)
NIL
);
//設(shè)置發(fā)送緩沖區(qū)空事件句柄
postSendEvent:=CreateEvent(NIL,
TRUE,//手工重置事件
TRUE, //初始化為有信號(hào)狀態(tài)
NIL);
//設(shè)置寫異步I/O操作事件句柄
write_os.hEvent:=CreateEvent(NIL,
TRUE,//手工重置事件
FALSE,//初始化為無(wú)信號(hào)狀態(tài)
NIL);
//創(chuàng)建通信監(jiān)視線程
comThreadHwnd:=CreateThread(NIL,
0,
@CommWatchThread, //通信線程函數(shù)的地址
nil,
0,//創(chuàng)建后立即運(yùn)行
dwThreadID1);//通信線程ID號(hào)
if comThreadHwnd=INVALID_HANDLE_VALUEthen
InitR12CommDev:='INITR12COMM_FAILURE'
else
InitR12CommDev:='切換臺(tái)通訊端口初始化成功.';
end;
///切換臺(tái)切換控制函數(shù)
///輸入?yún)?shù);切換命令字符串
procedure SwitchR12(WriteBuffer:PChar);
var
dwWriteByte,TxCount:DWORD;
bl:BOOL;
dwError:DWORD;
begin
//WriteBuffer:=chr($0D)+'03A00';
TxCount:=StrLen(WriteBuffer);
if bSendFinish=True then//發(fā)送緩沖區(qū)空發(fā)送
begin
dwWriteByte:=0;
bSendFinish:=False;
bl:=WriteFile(hCommDev,Byte(WriteBuffer^),TxCount,dwWriteByte,@write_os);
if bl=True then
begin
bSendFinish:=True;
PurgeComm(hCommDev,PURGE_TXCLEAR );//如果發(fā)送完成,置緩沖區(qū)空標(biāo)志,并清空緩沖區(qū)
end;
if bl=False then
begin
dwError:=GetLastError();
if (dwError=ERROR_IO_PENDING) or (dwError=ERROR_IO_INCOMPLETE) then
begin
bl:=GetOverLappedResult(hCommDev,
write_os,dwWriteByte,TRUE);//如果未發(fā)送完命令字符
//等待發(fā)送完成
if bl=True then
begin
bSendFinish:=True;
PurgeComm(hCommDev,PURGE_TXCLEAR ); //發(fā)送完成 置緩沖區(qū)空標(biāo)志,并清空緩沖區(qū)
//Result:=True;
end;
end;
end;
end;
//Result:=True;
end;
procedure SwitchR12Byte(WriteBuffer:Byte);
var
dwWriteByte,TxCount:DWORD;
bl:BOOL;
dwError:DWORD;
begin
//WriteBuffer:=chr($0D)+'03A00';
TxCount:= 1 ;//StrLen(WriteBuffer);
if bSendFinish=True then//發(fā)送緩沖區(qū)空發(fā)送
begin
dwWriteByte:=0;
bSendFinish:=False;
bl:=WriteFile(hCommDev,WriteBuffer,TxCount,dwWriteByte,@write_os);
if bl=True then
begin
bSendFinish:=True;
PurgeComm(hCommDev,PURGE_TXCLEAR );//如果發(fā)送完成,置緩沖區(qū)空標(biāo)志,并清空緩沖區(qū)
end;
if bl=False then
begin
dwError:=GetLastError();
if (dwError=ERROR_IO_PENDING) or (dwError=ERROR_IO_INCOMPLETE) then
begin
bl:=GetOverLappedResult(hCommDev,
write_os,dwWriteByte,TRUE);//如果未發(fā)送完命令字符
//等待發(fā)送完成
if bl=True then
begin
bSendFinish:=True;
PurgeComm(hCommDev,PURGE_TXCLEAR ); //發(fā)送完成 置緩沖區(qū)空標(biāo)志,并清空緩沖區(qū)
//Result:=True;
end;
end;
end;
end;
//Result:=True;
end;
通信監(jiān)視線程
procedure CommWatchThread(var lpdwParam:DWORD);
var
dwTransfer,dwEvtMask,dwError:DWORD;
os:_OVERLAPPED;
bl:boolean;
begin
os.hEvent:=CreateEvent(nil,
TRUE,
FALSE,
NIL);
comMask:=SetCommMask(hCommDev,EV_RXCHAR or EV_TXEMPTY);//設(shè)置監(jiān)視的事件為接
//收到字符或發(fā)送緩沖區(qū)空
if comMask=True then
begin
while True do
begin
dwEvtMask:=0;
bl:=WaitCommEvent(hCommDev,dwEvtMask,@os); //查詢所監(jiān)視的通信事件是否
//已經(jīng)發(fā)生
if bl=False then
begin
dwError:=GetLastError();
if dwError=ERROR_IO_PENDING then
GetOverlappedResult(hCOmmDev,os,dwTransfer,TRUE);//若未監(jiān)測(cè)到通信事件
//則在此等待事件發(fā)生
end;
//有事件,進(jìn)行如下處理
if (dwEvtMask and EV_RXCHAR)=EV_RXCHAR then //判斷是否為接收到 字符事件
begin
WaitForSingleObject(postRecvEvent,$FFFFFFFF);//等待接收事件句柄為有
//信號(hào)狀態(tài)
ResetEvent(postRecvEvent); //置接收事件句柄為無(wú)信號(hào)狀態(tài),以免接收
//緩沖區(qū)被覆蓋
CommRecvNotify; //調(diào)用接收到字符處理函數(shù)
continue; //處理完接收字符,繼續(xù)監(jiān)測(cè)通信事件
end;
if (dwEvtMask and EV_TXEMPTY)=EV_TXEMPTY then //判斷是否為發(fā)送緩沖區(qū)空事件
begin
WaitForSingleObject(postSendEvent,$FFFFFFFF);//等待發(fā)送事件句柄為有
//信號(hào)狀態(tài)
ResetEvent(postSendEvent); //置發(fā)送事件句柄為無(wú)信號(hào)狀態(tài),,以免發(fā)送
//緩沖區(qū)被覆蓋
CommSendNotify; //調(diào)用發(fā)送緩沖區(qū)空處理函數(shù)
continue;//處理完,繼續(xù)監(jiān)測(cè)通信事件
end;
end;
end;
CloseHandle(os.hEvent);
end;
//發(fā)送緩沖區(qū)空處理過(guò)程
procedure CommSendNotify;
begin
SetEvent(postSendEvent);//置發(fā)送事件未有信號(hào)狀態(tài),以便進(jìn)行下一次發(fā)送
end;
///接收到字符處理函數(shù)
procedure CommRecvNotify;
var
RxCount,dwReadByte:DWORD;
inData :Byte;
begin
ClearCommError(hCommDev,dwErrorFlag,@ComStat);
RxCount:=ComStat.cbInQue; //獲取接收緩沖區(qū)的字符個(gè)數(shù)
if RxCount>0 then
begin
if not RecvBuffInit then
begin
StrCopy(RecvBuff,'');
RecvBuffInit:=True;
end;
StrCopy(TempBuff,'');
ReadFile(hCommDev,Byte(TempBuff^),RxCount,dwReadByte,@read_os);//讀字符存入
//臨時(shí)緩沖區(qū)中
iRecvLen:=iRecvLen+dwReadByte; //接收到字符個(gè)數(shù)統(tǒng)計(jì)
if iRecvLen >=1 then
begin
inData := Byte(TempBuff^);
if inData = $D9 then
begin
SendCommandSuccess:=True;//如果狀態(tài)一致,則置該標(biāo)志為真,標(biāo)志切換成功
end
else
begin
SendCommandSuccess:=False;//否則,置該標(biāo)志為假,表示切換失敗
end;
iRecvLen:=0;
StrCopy(RecvBuff,'');
RecvBuffInit:=False;
PurgeComm(hCommDev,PURGE_RXCLEAR ); //清空接收緩沖區(qū)
end
end;
SetEvent(postRecvEvent); //置接收事件句柄為有信號(hào)狀態(tài),以便接收新字符
end;
function ConInfo :String;
begin
ifSendCommandSuccess =True then
begin
Result := '切換器聯(lián)機(jī)監(jiān)測(cè)成功!';
end
else
begin
Result := '切換器聯(lián)機(jī)監(jiān)測(cè)失敗!';
end;
end;
{
procedure CommSendNotify;
begin
SetEvent(postSendEvent);//置發(fā)送事件未有信號(hào)狀態(tài),以便進(jìn)行下一次發(fā)送
end;
///接收到字符處理函數(shù)
{procedure CommRecvNotify;
var
RxCount,dwReadByte:DWORD;
inData :Byte;
begin
ClearCommError(hCommDev,dwErrorFlag,@ComStat);
RxCount:=ComStat.cbInQue; //獲取接收緩沖區(qū)的字符個(gè)數(shù)
if RxCount>0 then
begin
if not RecvBuffInit then
begin
StrCopy(RecvBuff,'');
RecvBuffInit:=True;
end;
StrCopy(TempBuff,'');
ReadFile(hCommDev,Byte(TempBuff^),RxCount,dwReadByte,@read_os);//讀字符存入
//ReadFile(hCommDev,Byte(TempBuff^),RxCount,dwReadByte,@read_os);//讀字符存入
//臨時(shí)緩沖區(qū)中
iRecvLen:=iRecvLen+dwReadByte; //接收到字符個(gè)數(shù)統(tǒng)計(jì)
{
if iRecvLen<13 then
begin
strcat(Recvbuff,TempBuff); //若接收到的切換臺(tái)狀態(tài)字符小于13個(gè),
//將臨時(shí)緩沖區(qū)中的字符拷貝到接收命令緩沖區(qū),準(zhǔn)備繼續(xù)讀
end
else
begin
strcat(Recvbuff,TempBuff);
RecvCommand:=RecvBuff;
//若接收到13個(gè)切換臺(tái)狀態(tài)字符進(jìn)行如下處理
if (RecvCommand[7]='P')
and(RecvCommand[8]=SendCommand[7])//比較讀入的切換臺(tái)端口狀態(tài)
and(RecvCommand[9]=SendCommand[8])//是否與切換指令中切換的端口
and (RecvCommand[10]=SendCommand[9])//一致
and (RecvCommand[11]=SendCommand[10])then
begin
SendCommandSuccess:=True;//如果狀態(tài)一致,則置該標(biāo)志為真,標(biāo)志切換成功
end
else
begin
SendCommandSuccess:=False;//否則,置該標(biāo)志為假,表示切換失敗
end;
iRecvLen:=0;
StrCopy(RecvBuff,'');
RecvBuffInit:=False;
PurgeComm(hCommDev,PURGE_RXCLEAR ); //清空接收緩沖區(qū)
end;
}
{
if iRecvLen >=1 then
begin
inData := Byte(TempBuff^);
if inData = $D9 then
begin
SendCommandSuccess:=True;//如果狀態(tài)一致,則置該標(biāo)志為真,標(biāo)志切換成功
end
else
begin
SendCommandSuccess:=False;//否則,置該標(biāo)志為假,表示切換失敗
end;
iRecvLen:=0;
StrCopy(RecvBuff,'');
RecvBuffInit:=False;
PurgeComm(hCommDev,PURGE_RXCLEAR ); //清空接收緩沖區(qū)
end
end;
SetEvent(postRecvEvent); //置接收事件句柄為有信號(hào)狀態(tài),以便接收新字符
end;
}
initialization
RecvBuff:=StrAlloc(50*sizeof(Char));
TempBuff:=StrAlloc(50*sizeof(Char));
Finalization
StrDispose(RecvBuff);
StrDispose(TempBuff);
CloseHandle(PostRecvEvent);
CloseHandle(read_os.hEvent);
CloseHandle(PostSendEvent);
CloseHandle(write_os.hEvent);
end.
總結(jié)
以上是生活随笔為你收集整理的rs232串口通讯模块 - Delphi编程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 进军餐饮行业,店铺该如何选址?
- 下一篇: 斐讯空气检测仪M1使用Easylink配