| 應(yīng)為工作需要自己編寫的RS232通訊模塊,該模塊已經(jī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; //切換臺命令被成功發(fā)送標(biāo)志 function? InitR12CommDev(comNo:PChar):String;? //初始化切換臺串口,返回狀態(tài)字符 procedure SwitchR12(WriteBuffer:PChar);//對切換臺進(jìn)行切換函數(shù) procedure SwitchR12Byte(WriteBuffer:Byte); procedure CommSendNotify;//串口接收到字符事件響應(yīng)過程 procedure CommRecvNotify; //串口發(fā)送緩沖區(qū)空事件響應(yīng)過程 procedure CommWatchThread(var lpdwParam:DWORD);//通信口監(jiān)視線程 function? ConInfo :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)行奇偶校驗 ??????????? //BYTE? ByteSize: 字符位數(shù) 4~8 ??????????? //BYTE? Parity:?? 奇偶校驗位 0-4分別表示無、奇、偶、傳號、空號校驗 ??????????? //BYTE? StopBits: 停止位數(shù) 0-2分別表示 1、1.5、2個停止位 ??????????? //WORD? XonLim :XON 閾值 ??????????? //WORD? XoffLim? XOFF 閾值 ??????????? //char? XonChar: XON 字符 ??????????? //char? XoffChar: XOFF 字符 ??????????? //char? EvtChar:? 事件字符 ? comStat:_COMSTAT; //COMSTAT結(jié)構(gòu)用于存放有關(guān)通信設(shè)備的當(dāng)前信息 ??????????????????? //程序中涉及各域含義如下: ??????????????????? //cbInQue :接收緩沖區(qū)中字符個數(shù) ??????????????????? //cbOutQue:發(fā)送緩沖區(qū)中字符個數(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)使用 ??????????????????????????????? //DOWD? hEvent 當(dāng)I/O操作完成時被設(shè)置為有信號狀態(tài) ??????????????????????????????? //的事件;當(dāng)調(diào)用ReadFile和WriteFile函數(shù)之前,調(diào) ??????????????????????????????? //用進(jìn)程設(shè)置該事件 ? postRecvEvent,postSendEvent:Thandle;//發(fā)送緩沖區(qū)空和接收到字符事件句柄 ? dwThreadID1:DWORD; //通信監(jiān)視線程ID號 ///串口初始化函數(shù) //該函數(shù)主要完成串口初始化設(shè)置和通信線程的啟動 //入口參數(shù):串口號 //返回值;初始化是否成功的狀態(tài)字符 function? InitR12CommDev(comNo:PChar) :String; begin ?? ///打開串口 ?? hCommDev:=CreateFile(comNo,?? //串口好 ?????????????????????? GENERIC_READ or GENERIC_WRITE,//對串口以讀寫方式打開 ?????????????????????? 0, ?????????????????????? nil, ?????????????????????? OPEN_EXISTING, ?????????????????????? FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED,//允許重疊操作 ?????????????????????? 0 ?????????????????????? ); ?? if hCommDev=INVALID_HANDLE_VALUE then ??????? InitR12CommDev:='切換臺通訊端口初始化失敗.' ?? else ????? InitR12CommDev:='切換臺通訊端口初始化成功.'; ?? 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é) ?? if? comBuf=False then ???????? InitR12CommDev:='切換臺通訊端口初始化失敗.' ?? else ????? begin ???????? InitR12CommDev:='切換臺通訊端口初始化成功.'; ???????? //清空緩沖區(qū) ???????? PurgeComm(hCommDev,PURGE_TXABORT or PURGE_RXABORT or ????????????????????????????????????? PURGE_TXCLEAR or PURGE_RXCLEAR ) ; ????? end; ?? //以下對串口進(jìn)行配置 ?? dcb.DCBlength:=sizeof(_DCB); ?? comState:=GetCommState(hCOmmDev,dcb);? //得到缺省設(shè)置 ?? if? comState=False then ???????? InitR12CommDev:='切換臺通訊端口初始化失敗.' ?? else ?????? InitR12CommDev:='切換臺通訊端口初始化成功.'; ?? dcb.BaudRate:=9600;? //波特率 9600 ?? dcb.ByteSize:=8;//7;? //數(shù)據(jù)長度7位 ?? dcb.Parity:=NOPARITY;//ODDPARITY; //校驗方式 奇校驗 ?? 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:='切換臺通訊端口初始化失敗.' ?? else ????? InitR12CommDev:='切換臺通訊端口初始化成功.'; ???? //設(shè)置通信接收到字符事件句柄 ?? postRecvEvent:=CreateEvent(NIL, ????????????????????????????? TRUE,//手工重置事件 ????????????????????????????? TRUE, //初始化為有信號狀態(tài) ????????????????????????????? NIL ????????????????????????????? ); ?? //設(shè)置讀異步I/O操作事件句柄 ?? read_os.hEvent:=CreateEvent(NIL, ????????????????????????????? TRUE,//手工重置事件 ????????????????????????????? FALSE, //初始化為無信號狀態(tài) ????????????????????????????? NIL ????????????????????????????? ); ?? //設(shè)置發(fā)送緩沖區(qū)空事件句柄 ?? postSendEvent:=CreateEvent(NIL, ????????????????????????????? TRUE,//手工重置事件 ????????????????????????????? TRUE, //初始化為有信號狀態(tài) ????????????????????????????? NIL); ?? //設(shè)置寫異步I/O操作事件句柄 ?? write_os.hEvent:=CreateEvent(NIL, ????????????????????????????? TRUE,//手工重置事件 ????????????????????????????? FALSE,//初始化為無信號狀態(tài) ????????????????????????????? NIL); ?? //創(chuàng)建通信監(jiān)視線程 ?? comThreadHwnd:=CreateThread(NIL, ???????????????????????? 0, ???????????????????????? @CommWatchThread, //通信線程函數(shù)的地址 ???????????????????????? nil, ???????????????????????? 0,?? //創(chuàng)建后立即運行 ???????????????????????? dwThreadID1);//通信線程ID號 ?? if comThreadHwnd=INVALID_HANDLE_VALUE? then ????? InitR12CommDev:='INITR12COMM_FAILURE' ?? else ????? InitR12CommDev:='切換臺通訊端口初始化成功.'; end; ///切換臺切換控制函數(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)測到通信事件 ?????????????????????????????????????????? //則在此等待事件發(fā)生 ?????????? end; ?????????? //有事件,進(jìn)行如下處理 ?????????? if (dwEvtMask and EV_RXCHAR)=EV_RXCHAR then //判斷是否為接收到 字符事件 ?????????? begin ????????????? WaitForSingleObject(postRecvEvent,$FFFFFFFF);//等待接收事件句柄為有 ????????????????????????????????????????????????????? //信號狀態(tài) ????????????? ResetEvent(postRecvEvent); //置接收事件句柄為無信號狀態(tài),以免接收 ??????????????????????????????????????? //緩沖區(qū)被覆蓋 ????????????? CommRecvNotify; //調(diào)用接收到字符處理函數(shù) ????????????? continue; //處理完接收字符,繼續(xù)監(jiān)測通信事件 ?????????? end; ?????????? if (dwEvtMask and EV_TXEMPTY)=EV_TXEMPTY then //判斷是否為發(fā)送緩沖區(qū)空事件 ?????????? begin ????????????? WaitForSingleObject(postSendEvent,$FFFFFFFF);//等待發(fā)送事件句柄為有 ?????????????????????????????????????????????????????????? //信號狀態(tài) ????????????? ResetEvent(postSendEvent); //置發(fā)送事件句柄為無信號狀態(tài),,以免發(fā)送 ??????????????????????????????????????? //緩沖區(qū)被覆蓋 ????????????? CommSendNotify; //調(diào)用發(fā)送緩沖區(qū)空處理函數(shù) ????????????? continue;//處理完,繼續(xù)監(jiān)測通信事件 ?????????? end; ??????? end; ??? end; ??? CloseHandle(os.hEvent); end; //發(fā)送緩沖區(qū)空處理過程 procedure CommSendNotify; begin ??? SetEvent(postSendEvent);//置發(fā)送事件未有信號狀態(tài),以便進(jìn)行下一次發(fā)送 end; ///接收到字符處理函數(shù) procedure CommRecvNotify; var ???? RxCount,dwReadByte:DWORD; ???? inData :Byte; begin ???? ClearCommError(hCommDev,dwErrorFlag,@ComStat); ???? RxCount:=ComStat.cbInQue; //獲取接收緩沖區(qū)的字符個數(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);//讀字符存入 ????????????????????????????????????????????????????????????????????? //臨時緩沖區(qū)中 ?????? iRecvLen:=iRecvLen+dwReadByte; //接收到字符個數(shù)統(tǒng)計 ?????? 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); //置接收事件句柄為有信號狀態(tài),以便接收新字符 end; function ConInfo :String; begin ???? if? SendCommandSuccess =True then ???? begin ????????? Result := '切換器聯(lián)機(jī)監(jiān)測成功!'; ???? end ???? else ???? begin ????????? Result := '切換器聯(lián)機(jī)監(jiān)測失敗!'; ???? end; end; { procedure CommSendNotify; begin ??? SetEvent(postSendEvent);//置發(fā)送事件未有信號狀態(tài),以便進(jìn)行下一次發(fā)送 end; ///接收到字符處理函數(shù) {procedure CommRecvNotify; var ???? RxCount,dwReadByte:DWORD; ???? inData :Byte; begin ???? ClearCommError(hCommDev,dwErrorFlag,@ComStat); ???? RxCount:=ComStat.cbInQue; //獲取接收緩沖區(qū)的字符個數(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);//讀字符存入 ????????????????????????????????????????????? //臨時緩沖區(qū)中 ?????? iRecvLen:=iRecvLen+dwReadByte; //接收到字符個數(shù)統(tǒng)計 ?????? { ?????? if iRecvLen<13 then ?????? begin ????????? strcat(Recvbuff,TempBuff); //若接收到的切換臺狀態(tài)字符小于13個, ????????????????????????? //將臨時緩沖區(qū)中的字符拷貝到接收命令緩沖區(qū),準(zhǔn)備繼續(xù)讀 ?????? end ?????? else ?????? begin ???????? strcat(Recvbuff,TempBuff); ???????? RecvCommand:=RecvBuff; ???????? //若接收到13個切換臺狀態(tài)字符進(jìn)行如下處理 ???????? if (RecvCommand[7]='P') ??????????? and(RecvCommand[8]=SendCommand[7])???? //比較讀入的切換臺端口狀態(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); //置接收事件句柄為有信號狀態(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.
|