<%@Language=VBScript%> C++爱好者

 

Victor 控件使用方法详解 - TYbCommDevice

说明:
TYBComm32 是最早版本的串口控件, 提供访问串口的基本功能, 为兼容以前版本保留的, 建议新用户使用 TYbCommDevice 控件。

相关控件:
TYBComm32, TCommQueue, EComm32Error

继承关系:
 TObject
 └TPersistent
  └TComponent
   └TYbCustomCommDevice
    └TYbCommDevice

相关链接和演示程序
    二进制数据收发演示程序 (简单的二进制收发)
    文本收发演示程序 (简单的文本收发)
    用超时的方法实现数据包演示程序 (典型应用: 与单片机的通讯)
    用帧首尾和控制符实现的数据包演示程序 (适合大量数据传输)
    固定格式的数据包收发演示 (兼容以前版本控件的方式)
    文件收发演示程序


属性:
属性 描述
Active 打开/关闭串口、判断串口是否已经打开
定义:
    __property bool Active = { read = fGetActive, write = fSetActive };
在打开串口时用 try ... catch 可得到串口错误信息, 关于错误信息的详细描述:EComm32Error

try
{
  YbCommDevice1->Active = true; //打开串口
}
catch(Exception &e)
{
  ShowMessage(e.Message); //错误处理
}
PortNo

串口号, 整数, 1 对应 COM1, 2 对应 COM2, 3 对应 COM3 ... n 对应 COMn
定义:
    __property int PortNo = { read = fGetPort , write = fSetPort };

可通过这个属性改变操作的串口, 也可通过这个属性判断正在操作哪个串口。
改变这个属性的值, Active 属性会自动变为 false, 需要重新打开串口。

例如:
    YbCommDevice1->PortNo = 2; //使用 COM2

Baud

波特率, 整数, 可通过这个属性修改或得到当前读写的波特率。
定义:
    enum TBaudRate {
        br110,br300,br600,br1200,br2400,br4800,br9600,br14400,br19200,
        br38400,br56000,br57600,br115200,br128000,br256000
    };
    __property TBaudRate Baud = { read = fGetBaud , write = fSetBaud };

改变这个属性的值, Active 属性会自动变为 false, 需要重新打开串口。

例如:
    YbCommDevice1->Baud = TYbCommDevice::br57600; //设置波特率为 57600bps

Parity 奇偶校验, 可以通过此属性设置或得到当前串口数据的奇偶校验。
定义:
    enum TParity
    {
      ptNoParity  ,//无奇偶校验 (No parity)
      ptOddParity ,//奇校验 (Odd)
      ptEvenParity,//偶校验 (Even)
      ptMarkParity,//Mark 校验
    };
    __property TParity Parity = { read = fGetParity , write = fSetParity };

改变这个属性的值, Active 属性会自动变为 false, 需要重新打开串口。

在一般的通讯中, 这个属性的值都设置成 ptNoParity (无奇偶校验), 这个属性的默认值为 ptNoParity.

例如:
    YbCommDevice1->Parity = TYbCommDevice::ptNoParity;
ByteSize 数据位数, 可通过此属性设置或得到当前串口的数据位数。
定义:
    __property BYTE ByteSize = { read = fGetByteSize, write = fSetByteSize };

改变这个属性的值, Active 属性会自动变为 false, 需要重新打开串口。
支持的值: 4 到 8 之间的整数。

在一般的通讯中, 这个属性的值都设置成 8, 即 8 位的数据。这个属性的默认值为 8.

例如:
    YbCommDevice1->ByteSize = 8; //采用8位数据
StopBits 停止位, 可通过此属性设置或得到当前串口的停止位数。
定义:
    enum TStopBits
    {
      sbOneStopBit    ,//1 个停止位
      sbOne_5_StopBits,//1.5个停止位
      sbTwoStopBit    ,//2 个停止位
    };
    __property BYTE StopBits = { read = fGetStopBits, write = fSetStopBits };

改变这个属性的值, Active 属性会自动变为 false, 需要重新打开串口。

在一般的通讯中, 这个属性值都设置成 sbOneStopBit, 即 1 个停止位。这个属性的默认值为 sbOneStopBit.

例如:
    YbCommDevice1->StopBits = TYbCommDevice::sbOneStopBit; //设置成 1 个停止位
FlowControl

数据流控制 (Modem 与电脑之间的通讯握手协议)
定义:
    enum TFlowControl
    {
      fcNone ,//不启动 Modem 通讯协议
      fcRtsCts ,//采用硬件 RTS/CTS 协议
      fcXonXoff ,//采用软件 XON/XOFF 协议
      fcTranXonXoff ,//采用透明的 XON/XOFF 协议
      fcRtsCtsXonXoff,//同时采用 RTS/CTS 和 XON/XOFF 协议
    };
   __property TFlowControl FlowControl = { read = fGetFlCtrl, write = fSetFlCtrl };

如果没有 Modem, 一般设置为 fcNone (不启动 Modem 通讯协议)
如果使用 Modem, 必需设置一个通讯协议, 一般采用 RTS/CTS 协议, 也可以用 XON/XOFF 协议。

改变这个值, 需要调用 InitModem 方法之后才可生效, 请参考方法 InitModem 的说明。

例如:
    YbCommDevice1->FlowControl = TYbCommDevice::fcNone; //不启动通讯协议

AutoAnswer Modem 自动应答, 可设置或得到当前自动应答的状态。
定义:
    __property int AutoAnswer = { read = fGetAutAns, write = fSetAutAns };

这个属性的值取值范围: 0 到 255 之间的整数。
    0 表示不自动应答;
    1 到 255 之间的数表示电话响铃几次之后应答; 1 是响铃立即应答, 2 是响铃 2 次之后应答……

改变这个值, 需要调用 InitModem 方法之后才可生效, 请参考方法 InitModem 的说明。

例如:
    YbCommDevice1->AutoAnswer = 3; //电话响铃 3 声之后自动应答。
ModemStatus 调制解调器 (Modem) 状态 (只读属性)
定义:
    enum TModemStatusItem
    {
      msCtsOn , //清除发送 CTS (Clear To Send) 位有效;
      msDsrOn , //数据设备就绪 DSR (Data Set Ready) 位有效;
      msRingOn, //振铃指示 (Ring Indicator) 位有效;
      msRlsdOn, //数据载波检测 DCD (Data Carrier Detect) 或 RLSD (Receive Line Signal Detect) 位有效;
    };
    typedef Set<TModemStatusItem,msCtsOn,msRlsdOn>TModemStatus;
    __property TModemStatus ModemStatus = { read = fGetModemStatus };

其他状态 (DTR 和 RTS 等) 请参考 Handle 属性和 EscapeCommFunction 方法。

例如:
    if(YbCommDevice1->ModemStatus.Contains(TYbCommDevice::msRlsdOn))
       Label1->Caption = "Modem 拨号成功, 正在联机通讯状态";
    else
       Label1->Caption = "Modem 在待命状态, 可以输入 AT 指令";
DisableWrite 不允许写串口 (让 Write 方法无效)
定义:
    __property bool DisableWrite = { read = fGetDisableWrite, write = fSetDisableWrite};
如果 DisableWrite 属性为 true, 可禁止写串口, 但是 Command 方法仍然有效.

典型应用: 如果 Modem 正在数据通讯状态, 要想发送 "+++" 命令时, 必须在命令前、后各延时1秒钟, 此期间不允许写入串口任何其他数据。

例如:
    YbCommDevice1->DisableWrite = true; //不允许写串口数据
    YbCommDevice1->PurgeWrite(); //清空发送缓存, 扔掉缓存中所有正在写入的数据
    Sleep(1000); //延时一秒钟
    YbCommDevice1->Command("+++"); //写入命令"+++", 这是AT指令当中惟一不需要回车的命令, 也不允许有回车
    Sleep(1000); //延时一秒钟
    YbCommDevice1->Command("ATH0\r"); //写入挂机命令"ATH0", AT 命令需要用回车结束
    YbCommDevice1->DisableWrite = false; //允许写串口
InBufSize 串口读数据缓存的容量, 单位: 字节, 可以读出或修改这个值。
定义:
    __property long InBufSize = { read = fGetInBufSize , write = fSetInBufSize };

这个属性的默认值为 8192, 即 8kb 缓存。
OutBufSize 串口写数据缓存的容量, 单位: 字节, 可以读出或修改这个值。
定义:
    __property long OutBufSize = { read = fGetOutBufSize, write = fSetOutBufSize};

这个属性的默认值为 8192, 即 8kb 缓存。
HwInSize 在 Windows 串口驱动里面的读数据缓存容量, 单位: 字节, 可以读出或修改这个值。
定义:
    __property long HwInSize = { read = fGetHwInSize , write = fSetHwInSize };

这个属性的默认值为 1200 (字节)。
HwOutSize 在 Windows 串口驱动里面的写数据缓存容量, 单位: 字节, 可以读出或修改这个值。
定义:
    __property long HwOutSize = { read = fGetHwOutSize, write = fSetHwOutSize };

这个属性的默认值为 1200 (字节)。
QueueSize 如果启动了数据包协议, 这个属性表示缓存中可容纳的数据包个数, 默认值为 16
定义:
    __property long QueueSize = { read = fGetQSize, write = fSetQSize };
相关属性:
    UsePackage, PackageSize, FrameSettings
PackageSize 如果启动了数据包协议, 这个属性表示最大数据包的字节数, 如果要启动数据包, 这个属性必须正确的设置。
定义:
    __property long PackageSize = { read = fGetPkgSz, write = fSetPkgSz };
相关属性:
    QueueSize, UsePackage, FrameSettings
PackageType 如果启动了数据包协议, 这个属性指定数据包类型
enum TCommPackageType
{
    cptCompatiblePkg, //兼容以前版本 (用第一个成员是32位整数表示字节数的结构)
    cptFrameHeadTail, //用帧首尾和控制符的数据包 (帧首+带控制符的数据+帧尾)
    cptFrameTimeout , //用定义超时时间的方法判断数据包 (适合单片机的简单协议)
};
__property TCommPackageType PackageType = { read = fGetPkgType , write = fSetPkgType, default = cptCompatiblePkg };
PackageInterval 如果使用 PackageType = cptFrameTimeout 类型的数据包, 这个属性指定接收数据包的超时时间间隔, 单位: 毫秒
__property long PackageInterval = { read = fGetPkgInterval, write = fSetPkgInterval, default = 50 };
Handle 串口句柄。通过串口句柄, 可用 API 函数直接对串口操作.
定义:
    __property HANDLE Handle = { read = fGetHandle };
UsePackage 使用数据包协议。如果启动数据包协议, 可以用 ReadPackage 和 WritePackage 方法发送和接收数据包。
定义:
    __property bool UsePackage = { read = _bUsePackage, write = fSetUsePackage };
相关属性:
    QueueSize, PackageSize, FrameSettings
FrameSettings 规定数据包首、尾、和控制符。
定义:
    __property TYbCommFrameSettings *FrameSettings = { read = _FrameSettings, write = fSetFrameSettings };

例如:
    YbCommDevice1->FrameSettings->FrameHead = 0xdb; //数据包头
    YbCommDevice1->FrameSettings->FrameTail = 0xde; //数据包尾
    YbCommDevice1->FrameSettings->FrameCtrl = 0xdc; //数据控制符
InQueue 串口读缓存, 指向一个 FIFO 队列缓存, 由控件内部使用, 不要访问除 Count 之外的其他属性。
定义:
    __property TCommQueue *InQueue = { read = fGetInQueue };

可以通过 YbCommDevice1->InQueue->Count 来判断串口缓存收到数据的字节数, 这个属性是随着接收数据动态变化的。
OutQueue 串口写缓存, 指向一个 FIFO 队列缓存, 由控件内部使用, 不要访问除 Count 之外的其他属性。
定义:
    __property TCommQueue *OutQueue = { read = fGetOutQueue };

可以通过 YbCommDevice1->OutQueue->Count 来判断缓存中还剩多少字节未发送, 这个属性是随着发送数据动态变化的。
CommPort 串口控件内部使用的属性, 用于处理串口数据。
定义:
    __property TComm32 *CommPort = { read = _CommPort };
CommPackage 串口控件内部使用的属性, 用于处理数据包。
定义:
    __property TCommPackage *CommPackage = { read = _CommPackage };

方法:
方法 描述
Read 读串口 (接收数据)
定义:
    virtual long __fastcall Read(void far *s, long n);
参数:
    s: 读出数据存放的地址;
    n: 读出数据字节数。
返回值:
    实际读出的字节数。返回值有可能:
    ① 0: 没有读出数据;
    ② 实际读出的字节数, 这个数小于或等于参数 n 的值, 并且也小于或等于属性 InBufSize 的值。

例如:
char Buffer[8192]; //定义一个 8kb 缓存
int n = YbCommDevice1->Read(Buffer,8192); //收到 n 个字节, 接收的数据保存到 Buffer 里
Write 写串口 (发送数据)
定义:
    virtual long __fastcall Write(const void far *s, long n);
参数:
    s: 发送数据的地址
    n: 发送的字节数
返回值:
    实际发送的字节数。返回值有可能小于参数 n 的值, 原因是串口忙, 或者发送缓存不足以保存所有数据。

//--- 例(1), 发送简单数据类型: ---
char a[10];
AnsiString s;
short n;

YbCommDevice1->Write(a,10); //发送字符数组
YbCommDevice1->Write(s.c_str(),s.Length()); //发送字符串
YbCommDevice1->Write(&n,2); //发送一个 16 位的短整数, 先发送低位字节, 后发送高位字节

//--- 例(2), 发送结构: ---
#pragma pack(push,1) //用字节型对齐方式,下面的 TMyStruct 结构是 7 个字节, 否则 TMyStruct 结构是8个字节
typedef struct
{
  char  a; //字节型变量, 1 个字节
  short b; //短整数变量, 2 个字节
  long  c; //长整数变量, 4 个字节
} TMyStruct;
#pragma pack(pop)    //恢复原来的对齐方式

TMyStruct MyStruct;  //定义结构变量
YbCommDevice1->Write(&MyStruct,sizeof(TMyStruct));
Command 发送命令/字符串, 这个方法不受属性 DisableWrite 的控制。
定义:
    virtual long __fastcall Command(const char far *s);
参数:
    s: 以 '\0' 结束的字符串
返回值:
    实际发送的字节数。返回值有可能小于参数 n 的值, 原因是串口忙, 或者发送缓存不足以保存所有数据。

例如:
    YbCommDevice1->Command("ATDT12345678\r"); //通过 Modem 进行拨号, 采用双音频方式, 电话号码为 12345678

注意: 如果使用 AT 指令, 除了"+++"之外的指令都要用回车结束。
Command 方法只是简单的通过串口发送字符串, 并不是特殊的功能, 本例子程序用下面的方法同样可以实现:

    YbCommDevice1->Write("ATDT12345678\r",13); //发送 13 个字节的数据, 因为数据的内容为 AT 指令, 如果 Modem 为命令状态, 就会进行拨号, 号码为 12345678

通过属性 ModemStatus 可判断 Modem 的状态, 如果 MS_RLSD_ON 位有效, 为已经拨号成功, 收发数据的状态, 否则为命令状态, 所有写入串口的数据都认为是命令。
ReadPackage 读数据包 (接收数据包)

定义:
    virtual bool __fastcall ReadPackage(void *lpPkg);
    virtual unsigned long __fastcall ReadPackage(void *lpPkg, unsigned long BufSize);
前面的函数定义为 PackageType 为 cptCompatiblePkg 兼容以前版本的数据包接收函数。
后面的函数定义适用于所有其他情况的数据包接收, 这个函数可以接收任意类型和结构的数据。

参数:
    lpPkg: 收到的数据包存放的地址
    BufSize: 接收缓存的容量
返回值:
    实际收到的字节数(长整数), 可能的值:
        等于 0: 没收到数据包
        小于等于缓存容量的值: 收到数据包的字节数

相关属性:
    PackageType, PackageSize, QueueSize, UsePackage, FrameSettings

例:
    char Buf[1000];
    int n = YbCommDevice1->ReadPackage(Buf,1000);
WritePackage 写数据包 (发送数据包)

定义:
    virtual bool __fastcall WritePackage(void *lpPkg);
    virtual unsigned long __fastcall WritePackage(void *lpPkg, unsigned long nBytes);
前面的函数定义适用于 PackageType 为 cptCompatiblePkg 兼容以前版本的数据包发送函数。
后面的函数定义适用于所有其他情况的数据包发送, 这个函数可以发送任意类型和结构的数据。

参数:
    lpPkg: 要发送的数据包存放的地址
    nBytes: 要发送的数据包的字节数
返回值:
    实际发送的字节数(长整数), 可能的值:
        等于 0: 数据包不能发送 (缓存已满)
        等于参数 nBytes 的值: 发送成功
        小于参数 nBytes 的值(一般会等于属性 PackageSize): 原因是 nBytes 超过了属性 PackageSize 的值

相关属性:
    PackageType, PackageSize, QueueSize, UsePackage, FrameSettings
PurgeRead 清空读数据缓存 (扔掉读出的数据)
定义:
    virtual void __fastcall PurgeRead(bool bAbort=false);
参数:
    bAbort: 强制终止正在执行的接收动作, 默认值为 false
PurgeWrite

清空写数据缓存 (扔掉正在写的数据, 终止当前的写动作)
定义:
    virtual void __fastcall PurgeWrite(bool bAbort=false);
参数:
    bAbort: 强制终止正在执行的发送动作, 默认值为 false

SettingsDialog

显示串口设置对话框, 要求用户选择配置
    virtual bool __fastcall SettingsDialog(TComponent* AOwner, bool FActive=false);

参数:
    AOwner: 显示对话框的拥有者窗体, 一般用 this 即可;
    FActive: 是否确认选择的配置必须有效
      如果为 true, 选择的配置必须有效, 并且按确定按钮时, 会打开串口;
      如果为 false, 选择的配置不加验证, 按确定按钮时不打开串口;

返回值:
    true: 设置成功, 并且接受了设置;
    false: 设置失败, 或者取消了设置.

例: 打开串口, 如果打开失败, 就让用户选择配置, 如果选择配置成功, 打开串口, 否则退出程序。

try
{
    YbCommDevice1->Active = true;
}
catch(Exception &e)
{
    ShowMessage("YbCommDevice1: "+e.Message);
    if(!YbCommDevice1->SettingsDialog(this,true))
        Application->Terminate();
}

ResetModem 复位 Modem, Modem 恢复上电状态
定义:
    virtual void __fastcall ResetModem(void);

通过 Command("ATZ\r") 实现的。
InitModem 初始化 Modem, 使用 Modem 之前必须进行初始化
定义:
    virtual void __fastcall InitModem(void);

通过 AT 指令实现的, 初始化成功会从串口收到包含 "OK" 和回车换行的字符串。
通过 InitModem 设置电脑与 Modem 之间的通讯协议, 通常在打开串口时执行, 或者在 AfterOpen 事件里执行。
建议拨号方在拨号之前先执行 InitModem 来判断 Modem 是否联机, 应答方在打开串口时必须进行 InitModem。
EscapeCommFunction 控制串口状态
定义:
    virtual BOOL __fastcall EscapeCommFunction(DWORD dwFunc);
相关属性:
    ModemStatus
参数:
    dwFunc: 下列内容之一: CLRDTR,CLRRTS,SETDTR,SETRTS,SETXOFF,SETXON,SETBREAK,CLRBREAK
具体内容请参考 API 函数 EscapeCommFunction 的解释
TYbCommDevice 构造函数, 由系统自动调用, 或者通过 new 来调用。
定义:
    __fastcall TYbCommDevice(TComponent* Owner);
参数:
    Owner: 拥有者, 通常用 this.
~TYbCommDevice 析构函数, 由系统调用, 或者通过 delete 来调用。
定义:
    virtual __fastcall ~TYbCommDevice();
NewCommBusy protected 成员, 串口事件 OnCommNotify 的默认处理
定义:
    virtual void __fastcall NewCommBusy(TObject *Sender, int NotifyType);
参数:
    Sender: 产生事件的控件
    NotifyType: 是以下位或位的组合, 表示产生了相应的事件:
      EV_RXCHAR 收到数据
      EV_TXEMPTY 数据已经发送完毕
      EV_CTS 清除发送信号有变化 (CTS引脚电平有变化)
      EV_DSR 数据设备就绪状态有变化 (DSR引脚电平有变化)
      EV_RLSD 数据载波检测状态有变化 (DCD引脚电平有变化)
      EV_RING 有振铃信号
      EV_RXFLAG 收到可产生事件的字符, 可参考 API 函数 SetCommState
      EV_RX80FULL 接收缓存已经达到 80% 的容量, 如果是通过 Modem 等设备进行通讯, 要及时通知对方暂停发送
      EV_ERR 线路状态有错误, 包括 CE_FRAME, CE_OVERRUN 和 CE_RXPARITY.

以上事件均由默认的处理过程进行处理, 用户通常只需要处理 EV_RXCHAR 和 EV_TXEMPTY 事件。
NewCommNotify protected 成员, 串口事件 OnPackage 的默认处理
定义:
    virtual void __fastcall NewCommNotify(TObject *Sender, int NotifyType);
参数:
    Sender: 产生事件的控件
    NotifyType: 是以下位或位的组合, 表示产生了相应的事件:
      EV_RXCHAR 收到数据包
      EV_TXEMPTY 数据包已经发送完毕
NewAfterOpen

protected 成员, 当打开串口之后产生的事件的默认处理过程。
定义:
    virtual void __fastcall NewAfterOpen(TObject *Sender);
参数:
    Sender: 产生事件的控件。

NewBeforeClose protected 成员, 关闭串口之前产生的事件的默认处理过程。
定义:
    virtual void __fastcall NewBeforeClose(TObject *Sender);
参数:
    Sender: 产生事件的控件。

事件:
事件 描述
OnCommNotify 串口事件, 串口在数据传输过程中产生的事件。
定义:
    __property void __fastcall (__closure *OnCommNotify) (TObject *Sender, int NotifyType) =
         { read = lpCommBusyProc, write = lpCommBusyProc };
参数:
    Sender: 产生事件的控件
    NotifyType: 是以下位或位的组合, 表示产生了相应的事件:
      EV_RXCHAR 收到数据
      EV_TXEMPTY 数据已经发送完毕
      EV_CTS 清除发送信号有变化 (CTS引脚电平有变化)
      EV_DSR 数据设备就绪状态有变化 (DSR引脚电平有变化)
      EV_RLSD 数据载波检测状态有变化 (DCD引脚电平有变化)
      EV_RING 有振铃信号
      EV_RXFLAG 收到可产生事件的字符, 可参考 API 函数 SetCommState
      EV_RX80FULL 接收缓存已经达到 80% 的容量, 如果是通过 Modem 等设备进行通讯, 要及时通知对方暂停发送
      EV_ERR 线路状态有错误, 包括 CE_FRAME, CE_OVERRUN 和 CE_RXPARITY.

以上事件均由默认的处理过程进行处理, 用户通常只需要处理 EV_RXCHAR 和 EV_TXEMPTY 事件。
也可以不用事件, 通过定期查询来访问串口的数据, 毕竟要收满缓存或者把缓存数据发完需要比较长(相对而言)的时间。
这个事件在另外一个线程里, 没在主线程里。在这个事件里要尽可能的缩短处理时间, 不要在此事件中停留太久。
OnPackage 串口事件, 当启动数据包之后, 收到数据包或者数据包发送完毕产生的事件
定义:
    __property void __fastcall (__closure *OnPackage) (TObject *Sender, int NotifyType) =
        { read = lpUserCommNotify, write = lpUserCommNotify };
参数:
    Sender: 产生事件的控件
    NotifyType: 是以下位或位的组合, 表示产生了相应的事件:
      EV_RXCHAR 收到数据
      EV_TXEMPTY 数据已经发送完毕
这个事件在另外一个线程里, 没在主线程里。在这个事件里要尽可能的缩短处理时间, 不要在此事件中停留太久。
AfterOpen 在串口打开之后产生的事件, 在这个事件中可以作一些特殊处理, 比如初始化 Modem 等。
    __property void __fastcall (__closure *AfterOpen) (TObject *Sender)  =
         { read = lpAfterOpen, write = lpAfterOpen };
参数:
    Sender: 产生事件的控件
BeforeClose 在关闭串口之前产生的事件, 在这个事件中可以作一些在串口关闭之前必须执行的特殊的处理。
    __property void __fastcall (__closure *BeforeClose) (TObject *Sender) =
         { read = lpBeforeClose, write = lpBeforeClose };
参数:
    Sender: 产生事件的控件

返回目录

 

C++ 爱好者
-- Victor Chen 的个人主页
网址: http://www.cppfans.com/
Email: victor@cppfans.com
本站可以互相交换相关内容网站的链接
本站拒绝任何毫无相关的广告和链接