一、VC编程实现串口通信软件
首先,我们来大概的回忆一下单片机的串口通信。
8051单片机的串行接口由数据缓冲寄存器SBUF、移位寄存器、串行控制寄存器SCON组成。8051单片机的串行接口是一个可编程的全双工通信接口,通过软件编程可以作为通用异步接收和发送器使用,也可作为同步移位寄存器,还可实现多机通信。其帖格式有8位、10位和11位,通过T1或T2设置各种波特率。
1.1 串行口工作原理
在发送和接收数据前,先对串行口进行初始化设置,要明确串行口的工作方式、波特率等。
1.发送数据
发送数据,由累加器A送入发送缓冲寄存器SBUF,在发送控制器控制下组成帧结构,并自动以串行方式从TXD输出,每发送完一帧TI置位,可以通过中断方式或查询方式来了解数据的发送情况。值得注意的是TI只能用软件复位。
2.接收数据
单片机每接收完一帧数据,RI置位,通过中断或查询方式来了解数据的接收情况,然后用MOV A,SBUF指令,将接收缓冲寄存器(SBUF)的值送累加器A。RI与TI一样,也只能用软件复位。
1.2串行口工作方式
8051单片机通过编程可选择4种串行通信工作方式。
1.方式0
在方式0下,串行口用作同步移位寄存器,以8位数据为1帧,先发送或接收最低位,每个机器周期发送或接收1位,其波特率为fosc/12。串行数据由RXD端输入或输出,同步移位脉冲由TXD端送出。方式0数据发送与接收是无起始位和停止位,先发送或接收最低位,数据格式为:
— D0 D1 D2 D3 D4 D5 D6 D7
2.方式1
在方式1下,串行口为10位通用异步接口,数据格式为:
—— 0 D0 D1 D2 D3 D4 D5 D6 D7 1 ——
发送数据:当执行MOV SBUF,A指令,CPU将1字节的数据写入发送缓冲寄存器SBUF,数据从引脚TXD端输出,当发送完1帧数据后,TI标志置1,可用中断或查询方式来了解数据发送情况,TI只有通过软件复位。
接收数据:接收时,先使REN置1,使串行口处于允许接收状态,RI标志为0,串行口采样到RXD由1到0时,确认是起始位0,就开始接收1帧数据。当停止位到来时,RB8位置1,同时,中断标志位RI也置1,用中断或查询方式,通知CPU从SBUF取走接收到的数据。
3.方式2和方式3
方式2和方式3均为11位异步通信方式,只是波特率的设置方法不同,数据格式为:
— 0 D0 D1 D2 D3 D4 D5 D6 D7 D8 1 ——
发送数据:发送前,先要根据能信协议由软件设置TB8,然后将要发送的数据写入SBUF即可启动发送器。
接收数据:接收时,先使REN置1,使串行口处于允许接收状态,RI标志为0。在满足这个条件的前提下,再根据SM2的状态和所接收到的RB8的状态,才能决定此串行口在信息到来后是否会使RI置1。如果置1,在中断方式下将申请中断,接收数据。
当SM2=0时,不管RB8为0还是为1,RI都置1,此串行口将接收发来的信息。
当SM2=1,且RB8为1时,表示在多机能信情况下,接收的信息为地址帧,此时RI置1。串行口将接收发来的地址。
当SM2=1,且RB8为0时,表示接收到的信息为数据帧,便不是发给本从机的,此时RI不置1,因而SBUF中所接收的数据帧将丢失。
4.多机通信
在方式2和方式3下,有一个专门用于多机通信的功能,这一功能使它可以方便地应用于集散分布系统中,这种系统采用一台主机和多台从机之间通信。多机通信的实现,主要靠主、从机之间正确地设置与判断多机通信控制位SM2和发送或接收的第9位数据位。
在硬件上,所有从机的TXD接主机的RXD,所有从机的RXD接主机的TXD。在编程序前,首先要给从机地址编号,如分别为00H、01H、02H等,主机设置在工作方式2或方式3,TB8=1,从机初始化时设置SM2=1,处于方式2或方式3的允许接收状态。主机与从机通信前,主机先发送一个地址字节(地址字节和数据字节可用第9位数据位来区别,第9位为1表示发送的是地址)给从机,从机接收到主机发来的信息时,第9位RB8若为1,则置位中断标志位RI,并在中断后判断主机送来的地址与本机是否相同,若相同,则被寻址的从机设置成SM2=0,准备接收即将从主机送来的数据帧,未被选中的从机保持SM2=1的状态。
当主机发送数据时,应置TB8为0,此时,虽各从机处于接收状态,但由于TB8=0,所以只有SM2=0的从机才接收数据,其余从机保持SM2=1状态。
1.3 串行口控制
串行口控制与串行口控制寄存器SCON、电源控制寄存器PCON、串行口发送/接收缓冲区SBUF中断允许寄存器IE、中断优先级、定时控制寄存器TCON及方式控制寄存器TDOM有关。
1.串行控制寄存器SCON
SCON是一个可位寻址的专用寄存器,地址为98H,用于串行数据通信的控制,位功能如下:
SM0 SM1 SM2 REN TB8 RB8 TI RI
SM0、SM1:串行口工作方式选择位。工作方式的选择如表8.1所示下。
表8.1 串行口工作方式
SM0 SM1 工作方式 功能 波特率
0 0 0 同步移位寄存器 FOSC/12
0 1 1 8位格式 2SMOD/32×T1溢出率
1 0 2 9位格式 FOSC/32 或FOSC/64
1 1 3 9位格式 2SMOD/32×T1溢出率
SM2:多机通信控制位。
在方式2或方式3下,如果SM2=1,当RB8=1(RB8为收到的第9位数据),接收数据送SBUF,并产生中断请求(RI=1),否则丢失8位数据。
在方式2或方式3下,如果SM2=0,无论RB8=0或1,接收数据装入SBUF,并产生中断(RI=1)。
在方式1下,如果SM2=1,则只有接收到有效的停止位时,才激活RI;如果SM2=0,接收一帧数据,停止位进处RB8,数据进入SBUF,才激活RI。
在方式0下,SM2只能为0。
REN:允许接收位。由软件置位或清0。REN=1,允许接收;REN=0,禁止接收。
TB8:发送数据位。在方式2或方式3下,将要发送的第9位数据放在TB8中。可根据需要由软件置位或复位。在多机通信中,TB8=0表示主机发送的是数据,TB8=1表示主机发送的是地址。
RB8:接收数据位。方式0不使用这位。方式1下,如果SM2=0,RB8的内容是接收到的停止位。在方式2或方式3下,存放接收到的第9位数据。
TI:发送中断标志位。在方式0下,发送完第8位数据时,TI=1。在其它方式下,开始发送停止位时,TI=1。在任何工作方式下TI必须由软件清0。
RI:接收中断标志位。在方式0下,接收完第8位数据时,RI=1。在其它方式下,接收到停止位时,RI=1。在任何工作方式下RI也必须由软件清0。
2.串行口波特率设置
串行口波特率设置与串行口工作方式及定时控制寄存器TCON、方式控制寄存器TDOM及电源控制寄存器有关。
(1).T溢出率的计算
在串行通信方式1和方式3下,使用定时器T作为波特率发生器。T可以工作于方式0、方式1和方式2,由于定时器方式2是具有自动重装功能的8位定时器,因此常选用它。
溢出周期=(12/fosc)*(256--X) ;式中X为定时器初值,fosc为晶振频率。
溢出率=1/溢出周期
(2).波特率的计算
(1)方式0和方式2的波特率
方式0的波特率=fosc/12
方式2的波特率=(2SMOD/64)×fosc
(2)方式1和方式3的波特率
方式1和方式3的波特率=2SMOD×fosc/[32×12(256-X)]
(3).波特率的设置
TMOD:工作在方式2
PCON:只有工作在方式1、2、3时,如果PCON的SMOD为高电平,则通信整度加倍。
SMOD — — —
计算定时器初值:定时器初值是由波特率=2SMOD×fosc/[32×12(256-X)]计算得到。
中断设置:
SETB ES ;开串行中断
SETB EA ;中断启动
串行中断优先级由中断优先控制寄存器IP中的PS决定。
二、VC编程实现串口通信软件
好,串口通信的基本概念和通信规则我们已经大概的有一个了解了,相信大家都已经熟记在心了。下面,我们开始编写上位机了。先让我们来了解一下串口通信上位机编写的方法有哪些以及要用到哪些技术,其实到现在为止我自己也是一窍不通,也没有具体的书参考,先我们还是这样画葫芦画下去吧,本人对VC的研究也不是很透彻,还得去学好C++,不过一步一步慢慢来吧,告诉自己坚持到底,要坚持到底!
方法一:使用VC++提供的串行通信控件MSComm 首先,在对话框中创建通信控件,若Control工具栏中缺少该控件,可通过菜单Project --> Add to Project --> Components and Control插入即可,再将该控件从工具箱中拉到对话框中。此时,你只需要关心控件提供的对 Windows 通讯驱动程序的 API 函数的接口。换句话说,只需要设置和监视MSComm控件的属性和事件。
---- 在ClassWizard中为新创建的通信控件定义成员对象(CMSComm m_Serial),通过该对象便可以对串口属性进行设置,MSComm 控件共有27个属性,这里只介绍其中几个常用属性:
---- CommPort 设置并返回通讯端口号,缺省为COM1。
---- Settings 以字符串的形式设置并返回波特率、奇偶校验、数据位、停止位。
---- PortOpen 设置并返回通讯端口的状态,也可以打开和关闭端口。
---- Input 从接收缓冲区返回和删除字符。
---- Output 向发送缓冲区写一个字符串。
---- InputLen 设置每次Input读入的字符个数,缺省值为0,表明读取接收缓冲 区中的全部内容。
---- InBufferCount 返回接收缓冲区中已接收到的字符数,将其置0可以清除接收缓 冲区。
---- InputMode 定义Input属性获取数据的方式(为0:文本方式;为1:二进制方式)。
---- RThreshold 和 SThreshold 属性,表示在 OnComm 事件发生之前,接收缓冲区或发送缓冲区中可以接收的字符数。
---- 以下是通过设置控件属性对串口进行初始化的实例:
BOOL CSampleDlg:: PortOpen(){BOOL m_Opened; ...... m_Serial.SetCommPort(2); // 指定串口号 m_Serial.SetSettings("4800,N,8,1"); // 通信参数设置 m_Serial.SetInBufferSize(1024); // 指定接收缓冲区大小 m_Serial.SetInBufferCount(0); // 清空接收缓冲区 m_Serial.InputMode(1); // 设置数据获取方式 m_Serial.SetInputLen(0); // 设置读取方式 m_Opened=m_Serail.SetPortOpen(1); // 打开指定的串口 return m_Opened; }
---- 打开所需串口后,需要考虑串口通信的时机。在接收或发送数据过程中,可能需要监视并响应一些事件和错误,所以事件驱动是处理串行端口交互作用的一种非常有效的方法。使用 OnComm 事件和 CommEvent 属性捕捉并检查通讯事件和错误的值。发生通讯事件或错误时,将触发 OnComm 事件,CommEvent 属性的值将被改变,应用程序检查 CommEvent 属性值并作出相应的反应。在程序中用ClassWizard为CMSComm控件添加OnComm消息处理函数:
void CSampleDlg::OnComm(){ ...... switch(m_Serial.GetCommEvent()) { case 2: // 串行口数据接收,处理; }}
---- 方法二:在单线程中实现自定义的串口通信类
---- 控件简单易用,但由于必须拿到对话框中使用,在一些需要在线程中实现通信的应用场合,控件的使用显得捉襟见肘。此时,若能够按不同需要定制灵活的串口通信类将弥补控件的不足,以下将介绍如何在单线程中建立自定义的通信类。
---- 该通信类CSimpleComm需手动加入头文件与源文件,其基类为CObject,大致建立步骤如下:
---- (1) 打开串口,获取串口资源句柄
---- 通信程序从CreateFile处指定串口设备及相关的操作属性。再返回一个句柄,该句柄将被用于后续的通信操作,并贯穿整个通信过程。CreateFile()函数中有几个值得注意的参数设置:串口共享方式应设为0,串口为不可共享设备;创建方式必须为OPEN_EXISTING,即打开已有的串口。对于dwFlagAndAttribute参数,对串口有意义的值是FILE_FLAG_OVERLAPPED,该标志表明串口采用异步通信模式,可进行重叠操作;若值为NULL,则为同步通信方式,在同步方式下,应用程序将始终控制程序流,直到程序结束,若遭遇通信故障等因素,将导致应用程序的永久等待,所以一般多采用异步通信。
---- (2)串口设置
---- 串口打开后,其属性被设置为默认值,根据具体需要,通过调用GetCommState(hComm,&dcb)读取当前串口设备控制块DCB(Device Control Block)设置,修改后通过SetCommState(hComm,&dcb)将其写入。再需注意异步读写的超时控制设置, 通过COMMTIMEOUTS结构设置超时,调用SetCommTimeouts(hComm,&timeouts)将结果写入。以下是温度监控程序中串口初始化成员函数:
BOOL CSimpleComm::Open( ) { DCB dcb;m_hIDComDev=CreateFile( "COM2", GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVE RLAPPED, NULL ); // 打开串口,异步操作if( m_hIDComDev == NULL ) return( FALSE );dcb.DCBlength = sizeof( DCB );GetCommState( m_hIDComDev, &dcb ); // 获得端口默认设置dcb.BaudRate=CBR_4800;dcb.ByteSize=8;dcb.Parity= NOPARITY;dcb.StopBits=(BYTE) ONESTOPBIT; ...... }
---- (3)串口读写操作
---- 主要运用ReadFile()与WriteFile()API函数,若为异步通信方式,两函数中最后一个参数为指向OVERLAPPED结构的非空指针,在读写函数返回值为FALSE的情况下,调用GetLastError()函数,返回值为ERROR_IO_PENDING,表明I/O操作悬挂,即操作转入后台继续执行。此时,可以用WaitForSingleObject()来等待结束信号并设置最长等待时间,举例如下:
BOOL bReadStatus; bReadStatus = ReadFile( m_hIDComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead ); if(!bReadStatus) { if(GetLastError()==ERROR_IO_PENDING) { WaitForSingleObject(m_OverlappedRead.hEvent,1000); return ((int)dwBytesRead); } return(0); } return ((int)dwBytesRead);
---- 定义全局变量m_Serial作为新建通信类CSimpleComm的对象,通过调用类的成员函数即可实现所需串行通信功能。与方法一相比,方法二赋予串行通信程序设计较大的灵活性,端口的读写可选择较简单的查询式,或通过设置与外设数据发送时间间隔TimeCycle相同的定时器:SetTimer(1,TimeCycle,NULL),进行定时读取或发送。
CSampleView:: OnTimer(UINT nIDEvent) { char InputData[30]; m_Serial.ReadData(InputData,30); // 数据处理 }
---- 若对端口数据的响应时间要求较严格,可采用事件驱动I/O读写,Windows定义了9种串口通信事件,较常用的有:
---- EV_RXCHAR: 接收到一个字节,并放入输入缓冲区。
---- EV_TXEMPTY: 输出缓冲区中的最后一个字符发送出去。
---- EV_RXFLAG: 接收到事件字符(DCB结构中EvtChar成员),放入输入缓冲区。
---- 在用SetCommMask()指定了有用的事件后,应用程序可调用WaitCommEvent()来等待事件的发生。SetCommMask(hComm,0)可使WaitCommEvent()中止。
---- 方法三 多线程下实现串行通信
---- 方法一,二适用于单线程通信。在很多工业控制系统中,常通过扩展串口连接多个外设,各外设发送数据的重复频率不同,要求后台实时无差错捕捉,采集,处理,记录各端口数据,这就需要在自定义的串行通信类中创建端口监视线程,以便在指定的事件发生时向相关的窗口发送通知消息。
---- 线程的基本概念可详见VC++参考书目,Windows内部的抢先调度程序在活动的线程之间分配CPU时间,Win 32 区分两种不同类型的线程,一种是用户界面线程UI(User Interface Thread),它包含消息循环或消息泵,用于处理接收到的消息;另一种是工作线程(Work Thread),它没有消息循环,用于执行后台任务。用于监视串口事件的线程即为工作线程。
---- 多线程通信类的编写在端口的配置,连接部分与单线程通信类相同,在端口配置完毕后,最重要的是根据实际情况,建立多线程之间的同步对象,如信号灯,临界区,事件等,相关细节可参考VC++ 中的同步类。
---- 一切就绪后即可启动工作线程:
CWinThrea *CommThread = AfxBeginThread(CommWatchThread, // 线程函数名 (LPVOID) m_pTTYInfo, // 传递的参数 THREAD_PRIORITY_ABOVE_NORMAL, // 设置线程优先级 (UINT) 0, // 最大堆栈大小 (DWORD) CREATE_SUSPENDED , // 创建标志 (LPSECURITY_ATTRIBUTES) NULL); // 安全性标志
---- 同时,在串口事件监视线程中:
if(WaitCommEvent(pTTYInfo->idComDev,&dwEvtMask,NULL)) { if((dwEvtMask & pTTYInfo->dwEvtMask )== pTTYInfo->dwEvtMask) { WaitForSingleObject(pTTYInfo->hPostEvent,0xFFFFFFFF); ResetEvent(pTTYInfo->hPostEvent); // 置同步事件对象为非信号态 ::PostMessage(CSampleView,ID_COM1_DATA,0,0); // 发送通知消息 } }
---- 用PostMessage()向指定窗口的消息队列发送通知消息,相应地,需要在该窗口建立消息与成员函数间的映射,用ON_MESSAGE将消息与成员函数名关联。
BEGIN_MESSAGE_MAP(CSampleView, CView) //{{AFX_MSG_MAP(CSampleView)ON_MESSAGE(ID_COM1_DATA, OnProcessCom1Data) ON_MESSAGE(ID_COM2_DATA, OnProcessCom2Data) .....//}}AFX_MSG_MAPEND_MESSAGE_MAP()
---- 然后在各成员函数中完成对各串口数据的接收处理,但必须保证在下一次监测到有数据到来之前,能够完成所有的中间处理工作。否则将造成数据的捕捉错误。
---- 多线程的实现可以使得各端口独立,准确地实现串行通信,使串口通信具有更广泛的灵活性与严格性,且充分利用了CPU时间。但在具体的实时监控系统中如何协调多个线程,线程之间以何种方式实现同步也是在多线程串行通信程序实现的难点。
MSComm控件的属性
(必须要熟悉的几个——CommPort:设置并返回通信端口号;Setting:以字符串的形式设置并返回数据传输速率、奇偶校验、数据比特、停止比特;PortOpen:设置并返回通信端口的状态,也可以打开和关闭端口;Input:从接收缓冲区返回和删除字符;Output:向传输缓冲区定一个字符串)
1)CommPort属性
void SetCommPort(short nNewValue); short GetCommPort();
这一属性设置并返回连接的串行端口号,Windows将会利用该串口和外界通信。在设计时,nNewValue可以设置成从1~16的任何数(默认值为1)。但是如果用PortOpen属性打开一个并不存在的端口时,MSComm控件会产生错误68(设备无效)。
注意:必须在打开端口之前设置CommPort属性。
2)Settings属性
void Settings(LPCTSTR lpszNewValue); String GetSettings();
该属性用于设置并返回数据传输速率、奇偶校验、数据比特、停止比特参数。当端口打开时,如果value非法,则MSComm控件产生错误380(非法属性值)。其中lpszNewValue用字符串表示,由四个设置值组成,有如下的组成格式:
“BBBB,P,D,S”
BBBB为数据传输速率,P为奇偶校验,D为数据比特,S为停止比特。Value的默认值是:“9600,N,8,1”,数据传输速率合法值可以是110、300、600、1200、2400、4800、9600、14400、19200、28800、38400、56000、57600、115200、12800、25600。
奇偶校验值可以是设置为下表的任一值。
设定值描述
E偶校验(EVEN)
M标号校验(MARK)
N无校验(NONE)
O奇校验(ODD)
S空格校验(SPACE)
数据比特数可以是4、5、6、7、8。
停止比特数可以是1、1.5、2。
注意:只有当通信的双方的Settings属性值都一样时,通信连接才能生效。
3)Handshaking属性
这一属性用于设置或者返回硬件握手协议,也就是PC和通信设备之间为了控制流速而设定的内部协议。属性值可以设置为下表中的任一个。
设定值值描述
ComNone0默认值,无握手协议
comXOnXOff 1XON/XOFF握手
ComRTS 2RTS/CTS握手
comRtsXOnXOff3 RTS/CTS和XON/XOFF握手皆可
4)RThreshold属性
void SetRThreshold(short nNewValue); short GetRThreshold();
在MSComm控件设置CommEvent属性为comEvReceive并产生OnComm之前,RThreshold属性设置并返回的要接收的字符数。这里nNewValue是short型参数,说明在产生OnComm事件之前要接收的字符数。
当接收字符后,若RThreshold属性设置为0(默认值)则不会产生OnComm事件。否则,该属性为一阈值,当接收缓冲区内字节个数达到或超过该值后就会产生OnComm事件,例如,设置RThreshold为1,接收缓冲区收到每一个字符都会使MSComm控件产生OnComm事件。
5)CTSHolding属性
void SetCTSHolding(BOOL bNewValue); BOOL GetCTSHolding();
其属性设定值如下表所示。
设定值功能描述
TRUECTS线为高电平
FALSECTS线为低电平
该属性确定是否可通过查询CTS线的状态发送数据。CTS是调制解调器发送到相连计算机的信号,指示传输可以进行。该属性在设计时无效,在运行时为只读。
如果CTS线为低电平(CTSHolding =
FALSE)并且超时时,MSComm控件设置CommEvent属性为comEventCTSTO(Clear To Send
Timeout)并产生OnComm事伯。CTS线用于RTS/CTS硬件握手。如果需要确定CTS线的状态,CTSHolding属性给出一种手工查询方法。
6)SThreshold属性
void SetSThreshold(short nNewValue); short GetSThreshold();
MSComm控件设置CommEvent属性为comEvSend并产生OnComm事件之前,设置并返回传输缓冲区中允许的最小字符数。这里nNewValue是short型数据,代表在OnComm事件产生之前在传输缓冲区中的最小字符数。
若设置Sthreshold属性为0(默认值),数据传输事件不会产生OnComm事件。若设置Sthreshold属性为0,当传输缓冲区完全空时,MSComm控件产生OnComm事件。如果在传输缓冲区的字符数小于value,CommEvent属性设置为comEvSend,并产生OnComm事件。comEvSend事件仅当字符数与Sthreshold交叉时被激活一次。例如,如果Sthreshold等于5,仅当在输出队列中字符数从5降到4时,comEvSend才发生。如果在输出队列中从没有比Sthreshold多的字符,comEvSend事件将绝不会发生。
7)InputMode属性
void SetInputMode(long nNewValue); long GetInputMode();
访属性用于设置或者返回传输数据的类型。其取值和基本含义如下表所示。
设定值值描述
ComInputModeText(缺省)0通过Input属性以文本方式取回数据
ComInputModeBinary1通过Input属性以二进制方式取回数据
8)InputLen属性
void SetInputLen(short nNewValue); short GetInputLen ();
该属性用于设置并返回Input属性从接收缓冲区读取的字符数。nNewValue是short型数值,说明Input属性从接收缓冲区中读取的字符数。
InputLen属性的默认值是0。当设置InputLen为0时,使用Input将使MSComm控件读取接收缓冲区中全部的内容。若接收缓冲区中InputLen字符无效,Input属性返回一个零长度字符串(“”)。在使用Input前,用户可以选择检查InBufferCount属性来确定缓冲区中是否已有需要数目的字符。该属性在从输出格式为定长数据的机器读取数据时非常有用。
9)InBuffersize属性
void SetBufferSize(short nNewValue); short GetInBufferSize();
InBuffersize属性用于设置或返回输入缓冲区的大小,默认值为1024字节。
10)InBufferCount属性
void SetInBufferCount(short nNewValue); short
GetInBufferCount();
InBufferCount属性用于返回输入缓冲区内的等待读取的字节个数,可以通过该属性值为0来清除接收缓冲区。
11)Input属性
VARIANT GetInput();
Input属性表示从接收缓冲区移走一串字符,将缓冲区中收到的数据读入变量。属性值为VARIAN型变量。该属性在端口未打开时不可用,在运行时是只读的。
注意:当InputMode属性值
为0时(文本模式),变量中含String型数据。当InputMode属性值为1(二进制模式),变量中含Byte型数组数据。
12)PortOpen属性
void SetPortOpen(BOOL bNewValue); BOOL GetPortOpen();
PortOpen属性用于打开或者关闭端口。如果bNewValue设为TRUE,可以打开端口;设为FALSE时可以关闭端口。
一般情况下在程序开始时打开端口,在程序结束时关闭端口。当应用程序终止时,MSComm控件将自动关闭串
口。在打开端口前,确定CommPort属性调协为正确的端口号。而且,用户的串口设备必须支持Settings属性中的设置。如果硬件设备不支持Settings属性中的一些设置,则硬件工作或许不正确。
13)OutBuffersize属性
void SetOutBufferSize(short nNewValue);
OutBuffersize属性用于设置或者返回发送缓冲区的大小,值为整形表达式,表示传输缓冲区的字节数,默认值为512字节。对发送缓冲区设置得越大,应用程序可以使用的内存就越小。然而,如果发送缓冲区太小,缓冲区将会溢出,除非使用握手协议。
14)OutBufferCounter属性
void SetOutBufferSize(short nNewValue); short
GetOutBufferSize();
OutBufferCounter属性用于返回发送缓冲区内等待发送的字节数,可以通过设置该属性为0来清空发送缓冲区。
15)Output属性
void SetOutput(const VARIANT & newValue);
Output属性用于向发送缓冲区写数据流。属性为VARIANT变量。该属性在端口未打开时不可用,在运行时只是写的。
注意:Output属性可以发送文本数据或二进制数据。传输文本数据时,应该将字符型数据放入VARIANT变量中;传输二进制数据(即按字节传送)时,应将字节型数据放入VARIANT型变量中。如果通常给应用程序发送ANSI字符串,可以以文本方式发送。如果数据包含了内嵌控制字符、NULL字符等,必须将其作为二进制传递过去。
16)CommEvent属性
short GetCommEvent();
如果在通信过程中发生错误或事件,将会引发OnComm事件并且改变其属性值。CommEvent属性值反映错误或者事件类型,通信的设计中可以根据该属性值执行同的操作。该属性在端口未打开时不可用,在运行时是只读的。通信错误及通信事件的设定值分别如下两表所示。
通信错误设定值
设定值值描述
comEventBreak 1001接收到中断信号
comEventCTSTO1002CTS超时
comEventDSRTO1003DSR超时
comEventFrame1004帧错误,硬件检测到一个帧出错,双方设置的格式不一致时,就会引发此错误
comEventOverrun1006端口超速。一个字符没有在下一个字符到达之前被硬件读取,该字符丢失
comEventCDTO 1007数据检测超时
comEventRxOver1008接收缓冲区溢出
comEventRxParity1009奇偶校验错误
comEventTxFull1010传输缓冲区溢出,表明输出缓冲区已满,不能再将字符输出到缓冲区
comEventDCB1011检索端口、设备控制块(DCB)时的意外错误
通信事件设定值
设定值值描述
comEvSend1发送事件。发送缓冲区的内容少于SThreshold指定的值
comEvReceive2接收事件。接收缓冲区内字符数达到RThreshold值,该事件在缓冲区内数据被移走前将持续产生,利用此事件可编写接收数据的过程
comEvCTS3CTS线变化
comEvDSR4DSR线变化
comEvCD5CD线变化
comEvRing6振铃检测
comEvEOF7文件结束。接收数据中出现文件结束(ASCII 码26)字符
17)DTREnable属性
void SetDTREnable(BOOL bNewValue); BOOL GetDTREnable();
DTREnable属性确定在通信时是否使用DTR线有效,DTR是计算机发送到调制解调器的信号,表明计算机在等待数据传输。
18)RTSEnable属性
void SetRTSEnable(BOOL bNewValue); BOOL GetRTSEnable();
RTSEnable属性确定是否使用RTS线有效。一般情况下,由计算机发送RTS信号到连接的调制解调器,请求允许发送数据。
19)EOFEnable属性
void SetEOFEnable(BOOL bNewValue); BOOL GetEOFEnable();
EOFEnable属性确定在输入过程中MSComm控件是否寻找文件结尾(EOF)字符。如果找到EOF字符,将停止输入并激活OnComm事件,此时CommEvent属性设置为comEvEOF,这里bNewValue为布尔表达式,确定当找到EOF字符时,OnComm事件是否被激活。当bNewValue的设置值TRUE时,EOF字符找到时OnComm事件被激活。否则当VALUE值设为
FALSE(默认)时,EOF字符找到时OnComm事件不被激活。
注意:当EOFEnable属性设置为FALSE时,OnComm控件将不在输入流中寻找EOF字符。
20)CDHolding属性
void SetCDHolding(BOOL bNewValue); BOOL GetCDHolding();
通过查询CD线的状态确定当前是否有传输。CD是从调制解调器发送到相连计算机的一个信号,指示调制解调器正在联机。该属性在设计时无效,在运行时为只读。属性的设置值为:当bNewValue为TRUE时,CD线为高电平;当bNewValue为FALSE时,CD线为低电平。注意当CD线为高电平(CDHolding=TRUE)且超时时,MSComm控件设置CommEvent属性为comEventCDTO(CD超时错误),并产生OnComm事件。
注意:在主机应用程序中捕获一个丢失的传输是特别重要的,例如一个公告板,因为呼叫者可以随时挂起(放弃传输)。CD也被称为Receive
Line Signal Detect(RLSD)。
21)DSRHolding属性
void SetDSRHolding(BOOL bNewValue); BOOL GetDSRHolding();
确定DSR线的状态。DSR信号由调制解调器发送到相连计算机,指示作好操作准备。该属性在设计时无效,在运行时为只读。DSRHolding属性返回为TRUE时,表示DSR线高,返回FALSE时,表示DSR线低。当DSR线为高电平时(DSRHolding=TRUE)超时时,MSComm控件设置CommEvent属性为comEventDSRTO(数据准备超时)并产生OnComm事件。当为DTE(Data
Terminal Equipment)机器写DSR/DTR握手例程时该属性是分有用的。