zoukankan      html  css  js  c++  java
  • 串口编程

    这是串口编程的第三篇, 也是最后一篇.
    为客户开发一个程序, 是个机加工工厂, 他们有个量测仪器, 能将量测值通过串口打印机打印出来, 工人拿着这个纸条, 再加工中心上输入量测值. 在机床上输入东西比较麻烦, 也容易出错, 需要做些改造, 因为量测设备的操作系统是一个嵌入式系统, 也没有源码, 无法直接修改量测软件. 我给的方案如下:  
    方案:加一个PC机, 抓取串口打印机接收的数据, 提起其中的量测值, 然后将量测值以文件的形式发送到加工中心上.
    现场条件不允许安装.Net Framework, 所以我选择使用Delphi开发串口程序, 通讯用额是Turbo Power的 TApdComPort 组件,该组件功能非常强大. 但我感觉做为类库, 在编程接口上有些地方反人类, 瑕不掩瑜吧.  

    =============================
    TApdComPort 相关资料
    =============================
    本文主要参考:
    TApdComPort 使用说明,  http://blog.csdn.net/hanxiaoran1022/article/details/3453255
    最重要的资料是源码, TApdComPort 的核心代码在 AdPort.pas 中.
    官方的Faq 必须要学习, Reference文档名副其实, 仅做reference用吧.
    http://tpapro.sourceforge.net/Faq.html
    http://tpapro.sourceforge.net/docs/APRO_ReferenceGuide.pdf

     
    -----------------------------
    基本属性, 必须在串口打开之前设置
    -----------------------------
    **********
    1》ComNumber属性
      ComNumber:设置或返回串口号,值为 1、2时分别设置coml、com2。ComNumber并不验证串口号的有效性。当打开串口时,Windows驱动程序将决定串口号是否有效,如果无效,则出错。  
    **********
    2》Baud属性
    Baud属性决定端口使用的波特率。
    通常可接受的波特率值包括:300、1200、2400、4800、9600、19200、38400、57600、115200。
    当波特率被改变时,如果端口已打开,线路参数立即更新。把Baud属性传递给通信驱动程序之前,Baud不校验所赋予的值,驱动程序可能拒绝这个值,并将导致一个异常。异常:ENotSupported.
    **********
    3》StopBits属性
    决定端口的停止位的个数,可接受的值为1和2。如果DataBits等于5,一个请求2个停止位被解释为一个请求1.5个停止位。
    当改变StopBits属性时,如果端口已打开,线路参数立即更新。在把StopBit属性传递给通信驱动程序之前,StopBits不校验所赋予的值, 驱动程序可能拒绝这个值,并将导致一个异常。异常:EBadArgument、EBadHandle。
    **********
    4》DataBits属性
    决定端口的数据位的个数。可接受值是:5、6、7、8。
    当改变DataBits属性时,如果端口已打开,线路参数立即更新。把DataBit属性传递给通信驱动程序之前,DataBits不校验所赋予的值,驱 动程序可能拒绝这个值,并将导致一个异常。异常:ENotSupported.
    **********
    5》Parity属性
    决定端口的奇偶校验模式。
    当Parity被改变时,如果端口已打开,线路参数立即更新。把Parity属性传递给通信驱动程序之前,Parity不校验所赋予的值,驱动程序可能拒 绝这个值,并将导致一个异常。异常:EBadHandle、ENotSupported.
    **********


    -----------------------------
    其它控制属性
    -----------------------------
    1》AutoOpen:决定端口是否按要求自动打开。当然我总是禁掉AutoOpen, 另外PromptForPort也禁掉
    **********
    2》Open属性:决定是否打开端口,是否用当前端口的所有属性初始化该端口。控件发送或接收字符前,Open必须设定为True. 将Open属性设为True后, 并不表示串口就被打开了, 串口真正打开后, 会触发OnOpen事件, 关闭也类似.
    **********
    3》OutPut属性:向输出缓冲区中写入数据,在设计时无效,运行时只读。
    **********
    4》流控设置, 初始化COM时, 可设置如下流控参数
        ApdComPort.HWFlowOptions
        ApdComPort.SWFlowOptions
        ApdComPort.XOffChar
        ApdComPort.XOnChar
    设计时和运行时, 可通过设置DTR属性为True, 表示高电平, DTR为False, 为低电平; 但如要进行切换高低电平, 中间必须要sleep一下. CTS属性类似.   
         

    -----------------------------
    捕获底层的log, 这在抓取串口数据时非常有用
    -----------------------------
    TApdComPort能捕获到一些底层的信息, 并可将这些数据自动记录到对应的log文件中, 需要作的是开启Logging功能, 与Logging相关的还有Tracing, 但Tracing抓出的信息不如Logging全, 所以我仅仅使用Logging功能.

    --初始化Logging设置
    procedure TDataModule1.InitLogSettings(ApdComPort: TApdComPort);
    begin
        ApdComPort.LogAllHex:=True;
        ApdComPort.LogName:=ExtractFilePath(Application.ExeName)+'_COM.log' ;
        ApdComPort.Logging:=tlOn ;
    end;

    --我写了个FlushLog(), 看看写法, 就能体会到 ApdComPort 反人类之处了.  
    procedure TDataModule1.FlushLog(ApdComPort: TApdComPort);
    begin
        ApdComPort.Logging:=tlAppend; //save to file then ture off Logging
        ApdComPort.Logging:=tlOn;     //at last turn on Logging  
    end;

    另外, 可以使用AddStringToLog(), 将任意字符串写到Log文件中, 当然串口必须先打开.    


    -----------------------------
    发送数据
    -----------------------------
    PutString()和PutChar(),PutBlock()可以发送, 也可以通过设定OutPut属性来写.


    -----------------------------
    接收数据, 都是以事件的方式接收数据
    -----------------------------
    1. OnTriggerAvail事件介绍, 我认为这个方法最好用了.
    一旦有数据接收到, 就会触发OnTriggerAvail事件, 代码一般为,
    procedure TForm_Main.ApdComPort_1BTriggerAvail(CP: TObject; Count: Word);
    var
       I : Word;
    begin
         for I := 1 to Count do
             globalString := globalString + ApdComPort_1B.GetChar;
    end;

    2.OnTriggerData事件, 有时候需要判断是否接收到指定的数据, DataTrigger提供了一个简单的方式
    增加 DataTrigger 后, 当TApdComPort接受到指定的字符串后, 即触发OnTriggerData事件, 我们可以在这个事件中针对不同的dataTriggerHandle做不同的处理.
    //创建dataTrigger 的handle(WORD类)
    connectDataHandle=ApdComPort_1B.AddDataTrigger('connect server', true)
    disconnectDataHandle=ApdComPort_1B.AddDataTrigger('disconnect server', true)

    //在OnTriggerData事件, 判断 TriggerHandle, 是等于 connectDataHandle还是 disconnectDataHandle, 做相应的处理
    procedure TForm_Main.ApdComPort_1BTriggerData(CP: TObject;
      TriggerHandle: Word);
    begin
      //比较TriggerHandle和connectDataHandle/disconnectDataHandle值, 做进一步处理
    end;

    3. DataTrigger是一个简单的data match trigger, 要实现更复杂的匹配条件, 可以使用TApdDataPacket组件, 它可以设置起始字符串, 结束字符串等匹配条件, 一旦接受到满足条件的数据, 会触发OnPacket事件
    -----------------------------
    为 TApdComPort 增加 TimerTrigger
    -----------------------------
    增加 TimerTrigger, 需要两步, 第一步先获取handle, 第2步设定timer的interval
    //创建timerTrigger 的handle
    timerHandle:= ApdComPort_1B.AddTimerTrigger;
    ApdComPort_1B.SetTimerTrigger(timerHandle, 100, True); //interval为100,并启用这个trigger


    4. 删除方法RemoveTrigger(), 参数是triggerHandle.


    -----------------------------
    ApdComport, ApdSLController, ApdStatuslight配合使用
    -----------------------------
    ApdSLController是Statuslight的管理器, 可以为8个不同的信号事件配置各自的statuslight(显示红绿灯). 在将ApdSLController和指定的ApdComport组件绑定, 就可以通过这8个 statuslight来反映ApdComport的状态.

  • 相关阅读:
    和阿文一起学H5-文字云制作
    uml与数据库设计
    设计模式——面向对象设计原则
    koajs框架解决的问题
    mongodb
    javascript 获取select选中text,2种方法
    带参数跳转
    express表单提交和参数接收4种方式
    ejs模版的4种输出方式
    nodejs事件
  • 原文地址:https://www.cnblogs.com/harrychinese/p/RS232_Programming.html
Copyright © 2011-2022 走看看