产品列表
PROUCTS LIST
新闻动态
NEWS
Delphi与多个AI仪表串口数据采集系统的实现
摘要:利用Delphi开发工业上位机控制系统软件已成为越来越多工控开发人员的选择,而怎么方便快速实现串口数据的采集成为问题的关键,本文着重讨论了Delphi6与Comport通信组件所实现的与多个AI仪表实时数据采集,同时对采集到的数据作相应的处理。
关键词:串口通信;Delphi6.0;Comport控件
1 引言
日前,随着现代信息技术的发展,计算机串口通信技术已日趋成熟。由于微机处理速度快、分析能力强、使用灵活等特点,而单独的二次仪表仅仅作为显示控制功能也不能满足生产的需要,更多是要采集和记录现场有用的数据,作为生产分析和存档,利用PC作为仪表功能拓展的上位机监控系统已在工业控制领域中被广泛采用。
PC机与仪表的串口通信可以采用语言编程实现,如Delphi、VC、VB等。Delphi是新一代面向对象的可视编程工具,它具有功能强大、简单易用、执行速度快和有丰富的第三方控件支持,使得开发过程变得如搭积木般简单易用,特别是对我们一些搞工控没有特别深厚编程基础的人使用。下位机仪表采用的是带485通信功能的九游J9中心AI系列仪表,因为九游J9中心的AI仪表所用的是AIBUS通讯协议,具有通信指令简单、通信速度快等特点,允许上位机指令读写仪表的数据,利用RS485总线功能可以实现多个仪表数据的串口通信。
用DelphiI实现串口通信,常用的方法有:使用控件,如Mscomm和Comport控件等;使用API函数对串口读写。使用API方法比较适合编写较为复杂的低层次通信程序,但缺点是编写串口通信程序较为复杂,需要掌握大量的通信和编程知识。而用串口控件,我们可以不理会它的内部机能,主要调用它的相关的属性和事件,就可以对串口实现各种操作,且编程简单、通常性强、可移植性好。在Delphi串口通信中我们选择用Comport控件,它直接编译在开发的工程文件里,不需要在运行的PC上另外安装控件。将Comport组件安装到DELPHI后可以看到多了一个Cportlib的组件页,Cportlib下面有多个组件,我们在这里主要应用的是Comport组件,对Comport控件的操作主要有:端口设置、打开端口、往端口写指令、读接收数据、关闭端口。
3 九游J9中心AIBUS通讯协议说明
AIBUS是厦门九游J9中心自动化科技有限公司为AI系列显示控制仪表开发的通讯协议,能用简单的指令实现强大的功能,AIBUS采用了16位的求和校正码,通讯可靠,支持4800、9600、19200等多种波特率,仪表允许连续写参数,写给定值或输出值,AI系列仪表使用异步串行通讯接口,接口电平符合RS232C或RS485标准中的规定。数据格式为1个起始位,8位数据,无校验位,1个或2个停止位。AI仪表采用多机通讯协议,采用RS485通讯接口,则可将32台的仪表同时连接在一个通讯接口上。AI仪表采用16进制数据格式来表示各种指令代码及数据。AI仪表软件通讯指令经过优化设计,标准的通讯指令只有两条,一条为读指令,一条为写指令,两条指令使得上位机软件编写容易,不过却能100%完整地对仪表进行操作;标准读和写指令分别如下:
读: 地址代号+52H(82)+要读的参数代号+0+0+校验码
写: 地址代号+43H(67)+要写的参数代号+写入数低字节+写入数高字节+校验码
地址代号:为了在一个通讯接口上连接多台AI仪表,需要给每台AI仪表编一个互不相同的通讯地址。AI仪表通讯协议规定,地址代号为两个相同的字节,数值为(仪表地址+80H)。例如:仪表参数Addr=10(16进制数为0AH,0A+80H=8AH),则该仪表的地址代号为:8AH 8AH
校验码:校验码采用16位求和校验方式,其中读指令的校验码计算方法为:要读参数的代号×256+82+ADDR
比如要读地址1的参数0的数据,就是0*256+82+1=83;转成十六制就是53 00;
如果是读OC的数据,就是十进制(C)*256+82+1= (十六制的)C53,校验码为53 0C;
写指令的校验码计算方法为以下公式做16位二进制加法计算得出的余数(溢出部分不处理):要写的参数代号×256+67+要写的参数值+ADDR
返回数据:无论是读还是写,仪表都返回以下10个字节数据,测量值PV+给定值SV+输出值MV及报警状态+所读/写参数值+校验码;其中PV、SV及所读参数值均各占2个字节,代表一个16位二进制有符号补码整数,低位字节在前,高位字节在后,整数无法表示小数点,要求用户在上位机处理;MV占一个字节,按8位有符号二进制数格式,数值范围-110~+110,状态位占一个字节,校验码占2个字节,共10个字节。
4 Comport控件与多个AI仪表通信的实现
4.1 硬件的组态
硬件组态主要由带串口的上位机PC、485转232转换器和AI仪表组成的485总线系统,AI仪表设置不同的通信地址,波特率设为9600。如下图:
总线结构 |
4.2 软件通信程序的实现
通过Comport控件与AI仪表实现通信是采用问答的方式进行的,所行我们在与多个仪表同时通信时应该采用轮询的通信方式。首先我们要在DELPHI里初始化串口,然后再用读写命令与每一个仪表轮询通信。通信结束后要关闭串口,释放串口资源。主要实现过程如下:
4.2.1 初始化串口并打开串口
选择好本次与AI通信的串口,该串口不能同时被其它程序引用,确定通信协议,如波特率、数据位、停止位和校验方式等属性,打开该串口。初始化可以在Comport的属性页里定义,也可以在程序运行时动态设置。属性页里的静态定义为:
BaudRate: br9600//定义波特率
DataBits:dbEight//8位数据位
Port: COM1//本例用串口1
StopBits:sbOneStopBit//1位停止位
…
其它属性可以参阅Comport的在线帮助文件。如果要在程序动态运行中修改设置串口参数,可以直接在程序中调用Comport的串口设置窗口函数:Comport. ShowSetupDialog。在弹出的设置窗口中设置串口属性。完成串口初始设置后就可心打开串口与AI通信,打开串口用如下命令:
Comport.open;//打开串口
4.2.2 数据转换函数
根据AI仪表的通信协议,上位机与AI通信时都是以十六进制的方式进行的,所以我们在程序里要做十六进制的格式转换,主要实现的函数如下:
function HexStrToStr(const S:string):string;
//16进制字符转换成字符串。 将要发送的十六进制格式字符转换成十六进制格式发送
var
t:Integer;
ts:string;
M,Code:Integer;
begin
t:=1;
Result:='';
while t<=Length(S) do
begin
while not (S[t] in ['0'..'9','A'..'F','a'..'f']) do
inc(t);
if (t+1>Length(S))or(not (S[t+1] in ['0'..'9','A'..'F','a'..'f'])) then
ts:='$'+S[t]
else
ts:='$'+S[t]+S[t+1];
Val(ts,M,Code);
if Code=0 then
Result:=Result+Chr(M);
inc(t,2);
end;
end;
function StrToHexStr(const S:string):string;
//字符串转换成16进制字符串,,将接收到的字符数转换成16进制数。
var
I:Integer;
begin
for I:=1 to Length(S) do
begin
if I=1 then
Result:=IntToHex(Ord(S[1]),2)
else Result:=Result+' '+IntToHex(Ord(S[I]),2);
end;
end;
function Hex2Dec(Hexs: string): string; //十六制转十制数
var
i,j: integer;
res,base: LongWord;
begin
res := 0;
for i:=1 to Length(Hexs) do
begin
base := 1;
for j:=1 to Length(Hexs)-i do
base := base * 16;
case Hexs[i] of
'0'..'9': res := res + (Ord(Hexs[i]) - Ord('0')) * base;
'a'..'f': res := res + (Ord(Hexs[i]) - Ord('a') + 10) * base;
'A'..'F': res := res + (Ord(Hexs[i]) - Ord('A') + 10) * base;
end;
end;
result := inttostr(res);
end;
4.2.3 送接收数据
上位机与多个AI通信,遵循一问一答的轮询方式进行,所读取到的数据是不含小数位的,所以我们要发送读取小数位的命令,同时也可以返回测量值。我们假定与四个AI仪表通过485总线通信的主程序实现如下:
procedure RXdata;
var
i:integer;
dot,dot2,dot3,dot4 :double;
obj:PAsync;
str,str2,a1,a2,a7,b1,b2,b7,c1,c2,c7,d1,d2,d7:string;
begin
InitAsync(obj);
try ///////////读*通道地址1的小数位和测量值
ComPort.WriteStrAsync(HexStrToStr('81 81 52 0C 0 0 53 0C'),obj);
ComPort.WaitForAsync(obj);
sleep(100);//发送命令后等待100MS,保证数据的完整性;
ComPort.ReadStr(Str, 20);//读取接收缓存区20个字节数;
comport.ClearBuffer(true,true);//清除发送区和接收区,准备下一个通道通信;
for I:=1 to Length(str) do//将接收到的数据作处理
begin
str2:=IntToHex(Ord(Str[i]),2) ;
if i= 1 then a1:= str2;//测量值的低位字节
if i= 2 then a2 :=str2;//测量值的高位字节
if i=7 then a7 := str2;//小数点的位数
end;
dot := Exp(ln(10)*(strtoint(hex2dec(a7))));
dot :=strtofloat(hex2dec(a2+a1))/dot;//高低位字节合并后转换成带小数点的十进制数;
//开始读第二通道地址二的数据,其它通道的方法以此一致。
ComPort.WriteStrAsync(HexStrToStr('82 82 52 0C 0 0 54 0C'),obj); //读地址0C的小数点;
ComPort.WaitForAsync(obj);
Sleep(100);
ComPort.ReadStr(Str, 20);
comport.ClearBuffer(true,true);
``````
//四通道全部读完,如果要读取更多地址的数据,也如此类推;
finally
DoneAsync(obj);
end;
end;
到此为止,对AI仪表的数据采集基本完成,把上面的过程放在delphi的一个定器时控件TIMMER里就可以实现自动采集了。如要在上位机操作AI仪表的其它参数,也可以参考AI仪表的通信协议对程序进行编写实现。
4.2.4 关闭串口
在系统开发中,应注意在不使用串口时及时关闭串口,释放系统资源,否则可能会影响系统的其它应用。关闭串口的代码如下:
Comport.close;
5 结论
实践证明,利用Comport控件在DELPHI中开发串口与下位机通信程序,具有灵活、方便、的特点。同时利用DELPHI中图表曲线和数据库的功能,可以采集实时生产中的数据生成实时曲线和历史曲线,方便对生产过程的分析存档。把相关的数据转存入数据库可以与企业的MIS系统整合,实现数据共享。
参考文献:
1.李庆亮.2006.SPCOMM控件在Delphi7.0串口通信中的应用.微计算机信息-嵌入式SOC. 22(5-2):8-10。
2.林枫,王月忠.2005.智能化锂离子电池管理系统的设计与实现.微计算机信息.(3):78-79。
3.范逸之,陈立元.2002.VB与RS-232串行通信控制.中国青年出版社,327-334。