王朝网络
分享
 
 
 

RS232串口通讯模块

王朝delphi·作者佚名  2006-01-10
宽屏版  字体: |||超大  

应为工作需要自己编写的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.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有