• 技术文章

    Delphi与多个AI仪表串口数据采集系统的实现

    2012-06-29 09:58:02  来源:冼业雄
    1 引言智能温控仪 

        日前,随着现代信息技术的发展,计算机串口通信技术已日趋成熟。由于微机处理速度快、分析能力强、使用灵活等特点,而单独的二次仪表仅仅作为显示控制功能也不能满足生产的需要,更多是要采集和记录现场有用的数据,作为生产分析和存档,利用PC作为仪表功能拓展的上位机监控系统已在工业控制领域中被广泛采用。
    PC机与仪表的串口通信可以采用高级语言编程实现,如Delphi、VC、VB等。Delphi是新一代面向对象的可视编程工具,它具有功能强大、简单易用、执行速度快和有丰富的第三方控件支持,使得开发过程变得如搭积木般简单易用,特别是对我们一些搞工控没有特别深厚编程基础的人使用。下位机仪表采用的是带485通信功能的宇电AI系列仪表,因为宇电的AI仪表所用的是AIBUS通讯协议,具有通信指令简单、通信速度快等特点,允许上位机指令读写仪表的数据,利用RS485总线功能可以实现多个仪表数据的串口通信。

    2 Comport串口通信组件简介

        用DelphiI实现串口通信,常用的方法有:使用控件,如Mscomm和Comport控件等;使用API函数对串口读写。使用API方法比较适合编写较为复杂的低层次通信程序,但缺点是编写串口通信程序较为复杂,需要掌握大量的通信和编程知识。而用串口控件,我们可以不理会它的内部机能,主要调用它的相关的属性和事件,就可以对串口实现各种操作,且编程简单、通常性强、可移植性好。在Delphi串口通信中我们选择用Comport控件,它直接编译在开发的工程文件里,不需要在运行的PC上另外安装控件。将Comport组件安装到DELPHI后可以看到多了一个Cportlib的组件页,Cportlib下面有多个组件,我们在这里主要应用的是Comport组件,对Comport控件的操作主要有:端口设置、打开端口、往端口写指令、读接收数据、关闭端口。

    3 宇电AIBUS通讯协议说明

     

    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。


    留言
    林经理
    谷瀑服务条款》《隐私政策