rs232串口通讯模块 - Delphi编程 [ http://www.99inf.net/SoftwareDev/Delphi/14966.htm ] ... rs232串口通讯模块 作者:佚名文章来源: 不详 点击数: <script language="javascript" src="/SoftwareDev/GetHits.asp?ArticleID=14966" ></script> 更新时间:2007-7-1

<script language="javascript" src="/AD/200707/4.js" ></script>

应为工作需要自己编写的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; //切换台命令被成功发送标志

functionInitR12CommDev(comNo:PChar):String;//初始化切换台串口,返回状态字符
procedure SwitchR12(WriteBuffer:PChar);//对切换台进行切换函数
procedure SwitchR12Byte(WriteBuffer:Byte);
procedure CommSendNotify;//串口接收到字符事件响应过程
procedure CommRecvNotify; //串口发送缓冲区空事件响应过程
procedure CommWatchThread(var lpdwParam:DWORD);//通信口监视线程
functionConInfo :String;

implementation
var
//comMask,comBuf,ComState:Integer;
dcb:_DCB; //DCB结构用于配置串口,程序中涉及各域含义如下:
//DWORD DCBlength :DCB结构大小
//DWORD BaudRate :波特率
//DWORD fBinary: 1 二进制模式
//DWORD fParity: 1 进行奇偶校验
//BYTEByteSize: 字符位数 4~8
//BYTEParity:奇偶校验位 0-4分别表示无、奇、偶、传号、空号校验
//BYTEStopBits: 停止位数 0-2分别表示 1、1.5、2个停止位
//WORDXonLim :XON 阈值
//WORDXoffLimXOFF 阈值
//charXonChar: XON 字符
//charXoffChar: XOFF 字符
//charEvtChar:事件字符
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 保留给操作系统使用
//DOWDhEvent 当I/O操作完成时被设置为有信号状态
//的事件;当调用ReadFile和WriteFile函数之前,调
//用进程设置该事件
postRecvEvent,postSendEvent:Thandle;//发送缓冲区空和接收到字符事件句柄
dwThreadID1:DWORD; //通信监视线程ID号

///串口初始化函数
//该函数主要完成串口初始化设置和通信线程的启动
//入口参数:串口号
//返回值;初始化是否成功的状态字符
functionInitR12CommDev(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字节
ifcomBuf=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);//得到缺省设置
ifcomState=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_VALUEthen
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
ifSendCommandSuccess =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.

...

rs232串口通讯模块 - Delphi编程相关推荐

  1. RS232串口通讯模块

    应为工作需要自己编写的RS232通讯模块,该模块已经编写了蛮久,在实际使用中可能有没有考虑和不完善的地方. //============================================ ...

  2. plc和pc串口通讯接线_PC与PLC的串口通信及编程实现

    35 PC 与 PLC 的串口通信及编程实现 黄植功 (广西师范大学物理与电子工程学院,广西  桂林  541004) 摘  要: 在自由口模式下,通信协议由用户自己的梯形图程序控制.用户可以使用梯形 ...

  3. 笔记本通过网口控制单片机_国产又推出笔记本:旋转屏,自带RS-232串口和网口,工程师专用...

    很多人可能认为笔记本电脑基本都是长一个样子的,然而实际上根据使用用途的不同还是有很明显的差异,比如主打玩游戏的游戏本一般采用16寸左右的大屏,整体厚重,性能突出:主打办公的笔记本则一般在13.3寸左右 ...

  4. 图解通信原理与案例分析-6:基于离散字符的RS232串口数字通信--收发双方独立预设置同步时钟

    前言: RS-232标准接口是计算机常用的串行通信接口标准之一,虽然比较简单与成熟,但对于理解通信原理的基本流程和框架.核心的概念有基础性帮助作用. 本文将从通信原理的角度,解析RS232串口通信过程 ...

  5. 程控电源CANoe上位机面板(CAN\ETH测试、RS232串口通信、编写设计思路)

    程控电源CANoe上位机面板 编写此面板的目的 编写思路 一.通讯方式 1.RS232串口连接 2.CANoe与RS232串口相关的函数 3.帧格式命令字 4.校验码 二.面板设计 1.所需文件说明 ...

  6. c语言接收rs232串口速率,C语言在RS232串行接口通信中的实现

    串口通信是一种广泛使用且实用的通信方式,介绍RS232串行通信的联结方式,研究利用c语言编程实现RS232串行通信的过程.结合实际应用,在约定双方串行通信协议的基础上,运用C语言开发的串行通信软件,实 ...

  7. RS232串口通讯的那些事

    串口通讯这件事,说简单吧,2 3 5 三根线搞明白了就ok.说复杂吧,这里边的段子就多了.俺刚参加工作时,主要的工作就是搞这个的.那几年,连接了上百种不同型号的设备. RS232串口通讯程序的开发 基 ...

  8. delphi编程模拟发送QQ2008消息!

    本文主要讲解的是delphi编程模拟发送QQ消息!即利用外部程序发送QQ消息,代码很少,其实原理就是,找到QQ消息输入框,然后利用sendmessage传送一个文本信息进去,再找到发送按钮,模拟点击按 ...

  9. UART0串口编程(六):串口(UART0)之UC/OS(二)UC/OS下的串口接收任务编程

    串口(UART0)之UC/OS(二) 一.串口接收数据在UC/OS设计中应注意的问题 1.    串口通信的数据接收过程: 1>  UART 接收FIFO接收到预定字节后触发中断 2>   ...

最新文章

  1. 《UG NX8.0中文版完全自学手册》一第1章 UG NX 8.0简介
  2. 关于AndroidSDK配置时的tools目录下找不到adb.exe的错误
  3. Eclipse上的项目分享到GitHub
  4. 网编编程必看书籍:unix网络编程
  5. 超全超实用的Javascript类库和jQuery插件大全之二:文字处理,表格和列表处理,实用......
  6. API接口调用里的QPS指什么?百度语音API里的QPS实例说明
  7. Diffie-Hellman密钥交换协议
  8. i.MX 系列CPU HAB漏洞SecureBoot漏洞
  9. 黑马12期 day73-EasyUI笔记(2017年7月11日16:23:45)
  10. VisualStudio.gitignore git 忽略
  11. Kubernetes API 与 Operator:不为人知的开发者战争
  12. VsCode从零开始配置一个属于自己的Vue开发环境
  13. Apollo使用ConfigBean装载配置
  14. 【数学逻辑思维】好玩的数独游戏(高难度版)——003
  15. 阿里巴巴python招聘_作为应届生,我在阿里巴巴的成功面试经历!
  16. vue2理论学习(全套教程,包含vuex、路由等)
  17. python调用OpenCV和IOSAutoTouch实现硬件级免越狱自动化
  18. java鬼混笔记:springboot 5、springboot的Scheduled定时器:fixedDelay和fixedRate区别
  19. ATAx=0与Ax=0同解
  20. The container name XXX is already in use by container

热门文章

  1. 高考之后,泪眼婆娑,爱很脆弱
  2. 初步探究Android App API接口测试--实战
  3. 风云三国2.4问鼎天下修改作弊大全
  4. 关于word页眉页脚的设置-页码不连续的问题
  5. 思岚科技邀你2017日本东京国际机器人展
  6. Kafka配置动态SASL_SCRAM认证
  7. 《调教命令行09》磁盘很廉价,放小电影最合适了
  8. 《夏目友人帐》第4季第13集--漫漫回家路
  9. 如何理解广义线性回归分析Logistic输出的OR值?
  10. siTOOLs Biotech中国总代理蓝景科信 riboPOOL植物通用核糖体RNA(rRNA)去除探针试剂盒——高效去除开花植物(被子植物)核糖体RNA