日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

RS232串口通讯模块

發布時間:2023/12/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 RS232串口通讯模块 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

應為工作需要自己編寫的RS232通訊模塊,該模塊已經編寫了蠻久,在實際使用中可能有沒有考慮和不完善的地方。

//=================================================================================

//如果使用該模塊請保留該注釋,如果被修改或編輯請將修改后的代碼發送一份給我

//編寫:戴琪英

//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;//發送完標志
? iRecvLen:DWORD=0;
? RecvBuff,TempBuff:PChar;
? SendCommand,RecvCommand:String;//發送和接收到的命令
? RecvFinish:BOOL=False;
? RecvBuffInit:BOOL=False;
? SendCommandSuccess:BOOL; //切換臺命令被成功發送標志

function? InitR12CommDev(comNo:PChar):String;? //初始化切換臺串口,返回狀態字符
procedure SwitchR12(WriteBuffer:PChar);//對切換臺進行切換函數
procedure SwitchR12Byte(WriteBuffer:Byte);
procedure CommSendNotify;//串口接收到字符事件響應過程
procedure CommRecvNotify; //串口發送緩沖區空事件響應過程
procedure CommWatchThread(var lpdwParam:DWORD);//通信口監視線程
function? ConInfo :String;

implementation
var
? //comMask,comBuf,ComState:Integer;
? dcb:_DCB; //DCB結構用于配置串口,程序中涉及各域含義如下:
??????????? //DWORD DCBlength :DCB結構大小
??????????? //DWORD BaudRate :? 波特率
??????????? //DWORD fBinary? : 1 二進制模式
??????????? //DWORD fParity? : 1 進行奇偶校驗
??????????? //BYTE? ByteSize: 字符位數 4~8
??????????? //BYTE? Parity:?? 奇偶校驗位 0-4分別表示無、奇、偶、傳號、空號校驗
??????????? //BYTE? StopBits: 停止位數 0-2分別表示 1、1.5、2個停止位
??????????? //WORD? XonLim :XON 閾值
??????????? //WORD? XoffLim? XOFF 閾值
??????????? //char? XonChar: XON 字符
??????????? //char? XoffChar: XOFF 字符
??????????? //char? EvtChar:? 事件字符
? comStat:_COMSTAT; //COMSTAT結構用于存放有關通信設備的當前信息
??????????????????? //程序中涉及各域含義如下:
??????????????????? //cbInQue :接收緩沖區中字符個數
??????????????????? //cbOutQue:發送緩沖區中字符個數
? dwErrorFlag:LongWord;
? hCommDev,comThreadHwnd:Thandle;//通信串口句柄和通信監視線程句柄
? comMask,comBuf,comState:BOOL;
? read_os,write_os:_OVERLAPPED;? //OVERLAPPED 結構,用于異步操作的Win32函數中
??????????????????????????????? //程序中涉及各域含義如下:
??????????????????????????????? //DWORD Interval 保留給操作系統使用
??????????????????????????????? //DWORD IntervalHigh 保留給操作系統使用
??????????????????????????????? //DOWD? hEvent 當I/O操作完成時被設置為有信號狀態
??????????????????????????????? //的事件;當調用ReadFile和WriteFile函數之前,調
??????????????????????????????? //用進程設置該事件
? postRecvEvent,postSendEvent:Thandle;//發送緩沖區空和接收到字符事件句柄
? dwThreadID1:DWORD; //通信監視線程ID號

///串口初始化函數
//該函數主要完成串口初始化設置和通信線程的啟動
//入口參數:串口號
//返回值;初始化是否成功的狀態字符
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);//設置事件掩碼
?? //comBuf:=SetupComm(hCommDev,4096,4096);//設置接收和發送緩沖區大小皆為4096字節
?? comBuf:=SetupComm(hCommDev,1,1);//設置接收和發送緩沖區大小皆為4096字節
?? if? comBuf=False then
???????? InitR12CommDev:='切換臺通訊端口初始化失敗.'
?? else
????? begin
???????? InitR12CommDev:='切換臺通訊端口初始化成功.';
???????? //清空緩沖區
???????? PurgeComm(hCommDev,PURGE_TXABORT or PURGE_RXABORT or
????????????????????????????????????? PURGE_TXCLEAR or PURGE_RXCLEAR ) ;
????? end;

?? //以下對串口進行配置
?? dcb.DCBlength:=sizeof(_DCB);
?? comState:=GetCommState(hCOmmDev,dcb);? //得到缺省設置
?? if? comState=False then
???????? InitR12CommDev:='切換臺通訊端口初始化失敗.'
?? else
?????? InitR12CommDev:='切換臺通訊端口初始化成功.';
?? dcb.BaudRate:=9600;? //波特率 9600
?? dcb.ByteSize:=8;//7;? //數據長度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);? //設置串口
?? if comState=False then
???????? InitR12CommDev:='切換臺通訊端口初始化失敗.'
?? else
????? InitR12CommDev:='切換臺通訊端口初始化成功.';
???? //設置通信接收到字符事件句柄
?? postRecvEvent:=CreateEvent(NIL,
????????????????????????????? TRUE,//手工重置事件
????????????????????????????? TRUE, //初始化為有信號狀態
????????????????????????????? NIL
????????????????????????????? );
?? //設置讀異步I/O操作事件句柄
?? read_os.hEvent:=CreateEvent(NIL,
????????????????????????????? TRUE,//手工重置事件
????????????????????????????? FALSE, //初始化為無信號狀態
????????????????????????????? NIL
????????????????????????????? );
?? //設置發送緩沖區空事件句柄
?? postSendEvent:=CreateEvent(NIL,
????????????????????????????? TRUE,//手工重置事件
????????????????????????????? TRUE, //初始化為有信號狀態
????????????????????????????? NIL);
?? //設置寫異步I/O操作事件句柄
?? write_os.hEvent:=CreateEvent(NIL,
????????????????????????????? TRUE,//手工重置事件
????????????????????????????? FALSE,//初始化為無信號狀態
????????????????????????????? NIL);
?? //創建通信監視線程
?? comThreadHwnd:=CreateThread(NIL,
???????????????????????? 0,
???????????????????????? @CommWatchThread, //通信線程函數的地址
???????????????????????? nil,
???????????????????????? 0,?? //創建后立即運行
???????????????????????? dwThreadID1);//通信線程ID號
?? if comThreadHwnd=INVALID_HANDLE_VALUE? then
????? InitR12CommDev:='INITR12COMM_FAILURE'
?? else
????? InitR12CommDev:='切換臺通訊端口初始化成功.';
end;

///切換臺切換控制函數
///輸入參數;切換命令字符串
procedure SwitchR12(WriteBuffer:PChar);
var
?dwWriteByte,TxCount:DWORD;
?bl:BOOL;
?dwError:DWORD;

begin
???? //WriteBuffer:=chr($0D)+'03A00';
???? TxCount:=StrLen(WriteBuffer);
???? if bSendFinish=True then? //發送緩沖區空發送
???? 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 );//如果發送完成,置緩沖區空標志,并清空緩沖區
???????? 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);//如果未發送完命令字符
??????????????????????????????????????????????????? //等待發送完成
???????????? if bl=True then
???????????? begin
??????????????? bSendFinish:=True;
??????????????? PurgeComm(hCommDev,PURGE_TXCLEAR ); //發送完成 置緩沖區空標志,并清空緩沖區
??????????????? //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? //發送緩沖區空發送
???? begin
???????? dwWriteByte:=0;
???????? bSendFinish:=False;
???????? bl:=WriteFile(hCommDev,WriteBuffer,TxCount,dwWriteByte,@write_os);
???????? if bl=True then
???????? begin
????????? bSendFinish:=True;
????????? PurgeComm(hCommDev,PURGE_TXCLEAR );//如果發送完成,置緩沖區空標志,并清空緩沖區
???????? 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);//如果未發送完命令字符
??????????????????????????????????????????????????? //等待發送完成
???????????? if bl=True then
???????????? begin
??????????????? bSendFinish:=True;
??????????????? PurgeComm(hCommDev,PURGE_TXCLEAR ); //發送完成 置緩沖區空標志,并清空緩沖區
??????????????? //Result:=True;
???????????? end;
?????????? end;
???????? end;
???? end;
???? //Result:=True;
end;

通信監視線程
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);//設置監視的事件為接
??????????????????????????????????????????????????????? //收到字符或發送緩沖區空
??? if comMask=True then
??? begin
??????? while True do
??????? begin
?????????? dwEvtMask:=0;
?????????? bl:=WaitCommEvent(hCommDev,dwEvtMask,@os); //查詢所監視的通信事件是否
?????????????????????????????????????????????????????? //已經發生
?????????? if bl=False then
?????????? begin
???????????? dwError:=GetLastError();
???????????? if dwError=ERROR_IO_PENDING then
??????????????? GetOverlappedResult(hCOmmDev,os,dwTransfer,TRUE);//若未監測到通信事件
?????????????????????????????????????????? //則在此等待事件發生
?????????? end;
?????????? //有事件,進行如下處理
?????????? if (dwEvtMask and EV_RXCHAR)=EV_RXCHAR then //判斷是否為接收到 字符事件
?????????? begin
????????????? WaitForSingleObject(postRecvEvent,$FFFFFFFF);//等待接收事件句柄為有
????????????????????????????????????????????????????? //信號狀態
????????????? ResetEvent(postRecvEvent); //置接收事件句柄為無信號狀態,以免接收
??????????????????????????????????????? //緩沖區被覆蓋
????????????? CommRecvNotify; //調用接收到字符處理函數
????????????? continue; //處理完接收字符,繼續監測通信事件
?????????? end;
?????????? if (dwEvtMask and EV_TXEMPTY)=EV_TXEMPTY then //判斷是否為發送緩沖區空事件
?????????? begin
????????????? WaitForSingleObject(postSendEvent,$FFFFFFFF);//等待發送事件句柄為有
?????????????????????????????????????????????????????????? //信號狀態
????????????? ResetEvent(postSendEvent); //置發送事件句柄為無信號狀態,,以免發送
??????????????????????????????????????? //緩沖區被覆蓋
????????????? CommSendNotify; //調用發送緩沖區空處理函數
????????????? continue;//處理完,繼續監測通信事件
?????????? end;
??????? end;
??? end;
??? CloseHandle(os.hEvent);
end;

//發送緩沖區空處理過程
procedure CommSendNotify;
begin
??? SetEvent(postSendEvent);//置發送事件未有信號狀態,以便進行下一次發送
end;

///接收到字符處理函數
procedure CommRecvNotify;
var
???? RxCount,dwReadByte:DWORD;
???? inData :Byte;
begin
???? ClearCommError(hCommDev,dwErrorFlag,@ComStat);
???? RxCount:=ComStat.cbInQue; //獲取接收緩沖區的字符個數
???? 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);//讀字符存入
????????????????????????????????????????????????????????????????????? //臨時緩沖區中
?????? iRecvLen:=iRecvLen+dwReadByte; //接收到字符個數統計

?????? if iRecvLen >=1 then
?????? begin
??????????? inData := Byte(TempBuff^);
??????????? if inData = $D9 then
??????????? begin
???????????????? SendCommandSuccess:=True;? //如果狀態一致,則置該標志為真,標志切換成功
??????????? end
??????????? else
??????????? begin
???????????????? SendCommandSuccess:=False;//否則,置該標志為假,表示切換失敗
??????????? end;

??????????? iRecvLen:=0;
??????????? StrCopy(RecvBuff,'');
??????????? RecvBuffInit:=False;
??????????? PurgeComm(hCommDev,PURGE_RXCLEAR ); //清空接收緩沖區
?????? end
??? end;
???
??? SetEvent(postRecvEvent); //置接收事件句柄為有信號狀態,以便接收新字符

end;

function ConInfo :String;
begin
???? if? SendCommandSuccess =True then
???? begin
????????? Result := '切換器聯機監測成功!';
???? end
???? else
???? begin
????????? Result := '切換器聯機監測失敗!';
???? end;
end;

{
procedure CommSendNotify;
begin
??? SetEvent(postSendEvent);//置發送事件未有信號狀態,以便進行下一次發送
end;

///接收到字符處理函數
{procedure CommRecvNotify;
var
???? RxCount,dwReadByte:DWORD;
???? inData :Byte;
begin
???? ClearCommError(hCommDev,dwErrorFlag,@ComStat);
???? RxCount:=ComStat.cbInQue; //獲取接收緩沖區的字符個數
???? 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);//讀字符存入
????????????????????????????????????????????? //臨時緩沖區中
?????? iRecvLen:=iRecvLen+dwReadByte; //接收到字符個數統計
?????? {
?????? if iRecvLen<13 then
?????? begin
????????? strcat(Recvbuff,TempBuff); //若接收到的切換臺狀態字符小于13個,
????????????????????????? //將臨時緩沖區中的字符拷貝到接收命令緩沖區,準備繼續讀
?????? end
?????? else
?????? begin
???????? strcat(Recvbuff,TempBuff);
???????? RecvCommand:=RecvBuff;
???????? //若接收到13個切換臺狀態字符進行如下處理
???????? if (RecvCommand[7]='P')
??????????? and(RecvCommand[8]=SendCommand[7])???? //比較讀入的切換臺端口狀態
??????????? and? (RecvCommand[9]=SendCommand[8])?? //是否與切換指令中切換的端口
??????????? and (RecvCommand[10]=SendCommand[9])?? //一致
??????????? and (RecvCommand[11]=SendCommand[10])? then

???????? begin
??????????? SendCommandSuccess:=True;? //如果狀態一致,則置該標志為真,標志切換成功
???????? end
???????? else
???????? begin
?????????? SendCommandSuccess:=False;//否則,置該標志為假,表示切換失敗
???????? end;
???????? iRecvLen:=0;
???????? StrCopy(RecvBuff,'');
???????? RecvBuffInit:=False;
???????? PurgeComm(hCommDev,PURGE_RXCLEAR ); //清空接收緩沖區
?????? end;
?????? }
?????? {
?????? if iRecvLen >=1 then
?????? begin
??????????? inData := Byte(TempBuff^);
??????????? if inData = $D9 then
??????????? begin
???????????????? SendCommandSuccess:=True;? //如果狀態一致,則置該標志為真,標志切換成功

??????????? end
??????????? else
??????????? begin
???????????????? SendCommandSuccess:=False;//否則,置該標志為假,表示切換失敗
??????????? end;

??????????? iRecvLen:=0;
??????????? StrCopy(RecvBuff,'');
??????????? RecvBuffInit:=False;
??????????? PurgeComm(hCommDev,PURGE_RXCLEAR ); //清空接收緩沖區
?????? end
??? end;
???
??? SetEvent(postRecvEvent); //置接收事件句柄為有信號狀態,以便接收新字符

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.


?

轉載于:https://www.cnblogs.com/jimeper/archive/2006/03/01/340452.html

總結

以上是生活随笔為你收集整理的RS232串口通讯模块的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。