您的当前位置:首页正文

使用VB中的MSComm控件实现串口通信

2021-11-12 来源:伴沃教育
使用VB中的MSComm控件实现RS-232串口通信

实验准备:需要准备一些与串口通信有关的设备,如(外置式)调制解调器、计算机串口与调制解调器的连接线、一根DTE到DTE的无调制解调器连接线(接法见本章有关习题的参考答案),在实验前检查计算机的两个串口是否能够正常工作。

实验环境:Windows 95/98操作系统,Microsoft VB 5.0以上程序设计环境。对例题中涉及调制解调器的内容,采用计算机与调制解调器连接的方式;对在例题中设计数据传输的内容,须事先将DTE到DTE的无调制解调器连接线的两端,分别插入Com1和Com2串口。

实验说明:

VB中的MSComm控件通过串行端口传输和接收数据,为应用程序提供串行通讯功能。MSComm控件提供下列两种处理通讯的方式:

(1)事件驱动(实时)方式,这是处理串行端口交互作用的一种非常有效的方法。在许多情

况下,在事件发生时需要得到通知,例如,在Carrier Detect(CD)或RequestToSend(RTS)线上一个字符到达或一个变化发生时。在这些清况下,可以利用MSComm控件的OnComm事件捕获并处理这些通讯事件。OnComm事件还可以检查和处理通讯错误。

(2)轮询方式,在程序的每个关键功能之后,可以通过检查CommEvent属性的值来查询

事件和错误。如果应用程序较小,并且是自保持的,这种方法可能是更可取的。例如,如果写一个简单的电话拨号程序,则没有必要对每接收一个字符都产生事件,因为唯一等待接收的字符是调制解调器的“OK”响应。

每个使用的MSComm控件都对应着一个串行端口。如果应用程序需要访问多个串行端口,必须使用多个MSComm控件。可以在Windows“控制面板”中改变端口地址和中断地址。

下面这个简单的例子采用了轮询方法演示了用调制解调器进行基本的串行通讯:

Private Sub Form_Load()

Dim Instring As String '保存输入子串的缓冲区 MSCOmm1.CommPort=3 '使用COM3。 MSComm1.Settings=\"2400,N,8,1\"

'2400波特率,无奇偶校验,8位数据位,一位停止位 MSComm1.InputLen=0 '当输入占用时,告诉控件读人整个缓冲区。 MSComm1.PortOpen=True '打开端口。 MSComm1.Output=\"AT\"+Chr$(13)

'将调制解调器的Attention命令送到调制解调器。

Do '等待数据返回到串行端口。 DoEvents

Loop Until MSComm1.InBufferCount>=2

Instring=MSComm1.Input '进行相应的处理,这里省略

'从串行端口读”OK“响应。

MSComm1.PortOpen=False End Sub

'关闭串行端口。

下面我们将讲述一下MSComm控件的所有属性,其中前5个是最基本的,必须首先掌握。

⑴MsComm控件属性

1) CommPort,设置并返回通讯端口号。语法为:

Object.CommPort[=value]

说明:value一为一个整型值,说明端口号。在设计时,va1ue可以设置成从1到16的任何数(缺省值为1)。但是如果用PortOpen属性打开一个并不存在的端口时,MSComm控件会产生错误68(设备无效)。

注意:必须在打开端口之前设置CommPort属性的值。

2) Settings,设置并返回波特率、奇偶校验、数据位、停止位参数。语法为:

0bject.Settings[=value]

说明:value一为字符串表达式,说明通讯端口的设置值。Value由四个设置值组成,其格式如下:

“BBBB,P,D,S”,其中:BBBB为波特率,P为奇偶校验,D为数据位数,S为停止位数。value的缺省值:”9600,N,8,1”

3) PortOpen,设置并返回通讯端口的状态(开或关)。在设计时无效。语法为:

object.PortOpen[=value]

说明:value一为布尔表达式,说明通讯端口的状态。value的取值为:

True——端口开,False一端口关

注意:设置PortOpen属性为True时打开端口。设置为False时关闭端口并清除接收和传输缓冲区。当应用程序终止时,MSComm控件自动关闭串行端口。

串行端口设备必须支持Settings属性当前的设置值。如果Settings属性包含硬件不支持的通讯设置值,那么硬件可能不会正常工作。

如果在端口打开之前,DTREnable或RTSEnable属性设置为True,当关闭端口时,该属性设置为False。否则,DTR和RTS线保持其先前的状态。

下例以波特率2400打开4号通讯端口,没有奇偶检查,7个数据位,1。5个停止位:

MSComm1.Settings=\"2400,n,7,1.5\" MSCOmm1.CommPort=4 MSComm1.PortOpen=True

4) Input,返回并删除接收缓冲区中的数据流。该属性在设计时无效,在运行时为只读。

语法为:

Object.Input

说明:InputLen属性确定被Input属性读取的字符数。设置InputLen为0,则Input属性读取缓冲区中全部的内容。

InputMode属性确定Input属性读取的数据类型。如果设置InputMode为comlnputModeText,则Input属性通过一个Variant返回文本数据。如果设置InputMode为comInputModeBinary,Input属性通过一个Variant.返回一二进制数据的数组。 例:这个例子说明如何从接收缓冲区读取数据:

Private Sub CmdReceive_Click()

Dim InString as String MSComm1.InputLen=0 '读取所有可用数据。 If MSComm1.InBufferCount Then '检查数据。

InString=MSComm1.Input ' 读入数据 End If End Sub

5) Output,往传输缓冲区写数据流。该属性在设计时无效,在运行时为只读。语法为:

object.Output[=value]

说明:value一为准备写到传输缓冲区中去的一个字符串。Output属性可以传输文本数据或二进制数据。用Output属性传输文本数据,必须定义一个包含一个字符串的Variant。发送二进制数据,必须传递一个包含字节数组的variant到Output属性。

一般情况下,如果发送一个ANSI字符串到应用程序,可以以文本数据的形式发送。如果发送包含嵌人控制字符、Null字符等等的数据,要以二进制形式发送。

例:这个例子说明如何将用户键人的每一个字符送到串行端口:

Private Sub Form_KeyPress(KeyAscii As lnteger)

Dim Buffer as Variant

MSCOmm1.CommPort=1 '设置并打开端口 MSComm1.PortOpen=True Buffer=Chr$(KeyAscii) MSCOmm1.Output=Buffer End Sub

6) Break,设置或清除中断信号的状态。该属性在设计时无效。

7) CDHolding,通过查询载波侦听CarrierDetect(CD)线的状态确定当前是否有传输。

CarrierDetect是从调制解调器发送到相联计算机的一个信号,指示调制解调器正在联机。该属性在设计时无效,在运行时为只读。

8) CommEvent,返回最近的通讯事件或错误。该属性在设计时无效,在运行时为只读。 9) CommID,返回一个说明通讯设备的句柄。该属性在设计时无效,在运行时为只读。

说明:该值与Windows API CreateFile函数返回的值一致。在WindowsAPI中调用任何通讯例程时使用该值。 10) CTSHolding,确定是否可通过查询ClearToSend(CTS)线的状态发送数据。C1ear To Send

是调制解调器发送到相联计算机的信号,指示传输可以进行。该属性在设计时无效,在运行时为只读。

11) DSRHolding,确定DataSetReady(DSR)线的状态。Data Set Ready信号由调制解调器

发送到相连计算机,指示作好操作准备。该属性在设计时无效,在运行时为只读。 12) DTREnable,确定在通讯时是否使DataTerminalReady(DTR)线有效。Data Terminal Ready

是计算机发送到调制解调器的信号,指示计算机在等待接受传输。 13) EOFEnable,EOFEnable属性确定在输入过程中MSComm控件是否寻找文件结尾(EOF)

字符。如果找到EOF字符,将停止输入并激活OnComm事件,此时commEvent属性设置为comEvEOF。

14) Handshaking,设置井返回硬件握手协议。语法为:

Object.Handshaking[=value] 说明:value一为整型表达式,说明握手约定。value的取值为: 常数 值 说明 comNone 0(缺省) 没有握手 comXOnXOff . 1(XON/XOFF) 握手 comRTS 2RTS/CTS 握手 (Request To Send/Clear To Send) comRTSXOnXOff 3 Request To Send 和 XON/XOFF皆可

Handshaking是指内部通讯协议,通过该协议,数据从硬件端口传输到接收缓冲区。当一个数据字符到达串行端口,通讯设备就把它移到接收缓冲区以使程序可以读它。如果没有接受缓冲区,程序需要直接从硬件读取每一个字符,这很可能会造成数据丢失,因为字符到达的速度可以非常快。

握手协议保证在缓冲区过载时数据不会丢失,缓冲区过载为数据到达端口太快而使通讯设备来不及将它移到接收缓冲区。

15) InBufferCount,返回接收缓冲区中等待的字符数。该属性在设计时无效。

说明:InBufferCount是指调制解调器已接收,并在接收缓冲区等待被取走的字符数。可以把InBufferCount属性设置为0来清除接收缓冲区。

16) InBufferSize,设置并返回接收缓冲区的字节数。

说明:InBufferSize是指整个接收缓冲区的大小。缺省值是1024字节。

注意:接收缓冲区越大则应用程序可用内存越小。但若接受缓冲区太小,若不使用握手协议。就可能有溢出的危险。一般的规律是,首先设置一个1024字节的缓冲区。如果出现溢出错误,则通过增加缓冲区的大小来控制应用程序的传输速率。

17) InputLen,设置并返回Input属性从接收缓冲区读取的字符数。

说明:InputLen属性的缺省值是0。设置InputLen为0时,使甩Input将使MSColnm控件读取接收缓冲区中全部的内容。

若接收缓冲区中InputLen字符无效,1nput。属性返回一个零长度字符串(\"\")。在使用Input前,用户可以选择检查InBuffereount属性来确定缓冲区中是否已有需要数目的字

符。该属性在从输出格式为定长数据的机器读取数据时非常有用。 例:这个例子说明如何读取25个数据字符:

Private CmdRead_Click()

Dim CommData as String

MSComm1.1nputLen=25 '确定一个25个字符的数据块。 CommData=MSComm1.Input '读数据。 End Sub

18) InputMode,设置或返回Input属性取回的数据的类型。

说明:InputMode属性确定Input属性如何取回数据。数据取回的格式或是字符串或是一数据组的二进制数据的数组。

若数据只用ANSI字符集,则用comInputModeText。对其它字符数据,如数据中有嵌入控制字符、Nulls等等,则使用comInputModeBinary。

19) NullDiscard,确定null字符是否从端口传送到接收缓冲区。

20) OutBufferrCount,返回在传输缓冲区中等待的字符数。也可以用它来清除传输缓冲区。

该属性在设计时无效。

说明:设置OutBufferCount属性为0可以清除传输缓冲区。

21) OutBufferSize,以字节的形式设置并返回传输缓冲区的大小。

说明:OutBufferSize指整个传输缓冲区的大小:缺省值是512字节。传输缓冲区设置的越大则应用程序可用内存越小。但若缓冲区太小,若不使用握手协议,就可能有溢出的危险。一般的规律是,首先设置一个512字节的缓冲区。如果出现溢出错误,则通过增加缓冲区的大小来控制应用程序的传输速率。

22) ParityReplace,当发生奇偶校验错误时,设置并返回替换数据流中一个非法字符的字符。

说明:缺省的情况是,Mscomm控件用问号(?)替换非法字符。如果设置parityRep1ace为一个空字符串(\"\"),则当奇偶校验错误出现时,字符替换无效。但onComm事件仍然产生,并且设置CommEvent。属性为comEventRXparity。

ParityReplace字符被用于面向字节的操作,它必须是单字节字符。可指定0到255之间的任何ANSI字符代码。

23) Rthreshold,在MSCoinm控件设置CommEvent属性为comEvReceive,并产生onComm

事件之前,设置并返回的要接收的字符数。

24) RTSEnable,确定是否使Requestrosend(RTS)线有效。一般情况下,由计算机发送

RequestToSend信号到联接的调制解调器,以请示允许发送数据。

25) Sthreshold,在MSComm控件设置。CommEvent属性为comEvSend并产生onComm事

件之前,设置并返回传输缓冲区中允许的最小字符数。

⑵事件

1) onComm,无论何时当CommEvent属性的值变化时,就产生onComm事件,它标志发

生了一个通讯事件或一个错误。 说明:CommEvent属性包含实际错误或产生onComm事件的编码。但是,当Rthresho1d或Sthreshold属性被设置为0时,则会分别使comEvReceive和comEvSend事件无效。

⑶使用轮询方式实现串口通信

工程名称:MSComm_Show1.vbp 发送窗体名称:MSComm_Send1.frm

接收窗体名称:MSComm_Receive_Polling.frm 控件及属性设置: 对象名称 MSComm_Send Label1 Label2 属性 Caption: MSComm_Send Caption:发送窗口 Caption: 请将发送内容写入文本框 Text1 MSComm1 Text: Text1 Macomm1 对象名称 MSComm_Receive_Polling Label1 Label2 属性 Caption: MSComm_Receive_Polling Caption:接收窗口 Caption: 接收到的文本将在文本框中显示 Text: 程序代码: '发送窗体程序

Private Sub Form_Load()

MSComm1.CommPort = 1 '使用COM1。

MSComm1.Settings = \"2400,N,8,1\"

'2400波特率,无奇偶校验,8位数据位,一位停止位 MSComm1.InputLen = 0 '当输入占用时,告诉控件读人整个缓冲区。 MSComm1.PortOpen = True '打开端口。

Mscomm_Receive_Polling.Show '显示轮询接收窗体,启动接收程序 End Sub

Private Sub Text1_KeyPress(KeyAscii As Integer)

MSComm1.Output = Chr$(KeyAscii) '发送用户从键盘上输入的字符 End Sub

Private Sub Form_Unload(Cancel As Integer) MSComm1.PortOpen = False '关闭串行端口 End Sub

'接收窗体程序

Private Sub Form_Load()

MSComm1.CommPort = 2 '使用COM2。 MSComm1.Settings = \"2400,N,8,1\" MSComm1.InputLen = 0 MSComm1.PortOpen = True End Sub

Private Sub Form_Click()

Text1.Text = MSComm1.Input '从串行端口读内容。

End Sub

Private Sub Form_Unload(Cancel As Integer) MSComm1.PortOpen = False End Sub

实验操作步骤:

1) 用发送窗体(MSComm_Send)作为启动对象,启动程序后,发送窗体和轮询接收窗体都

将出现在屏幕上;

2) 用鼠标将光标设置到发送窗体的文本框中,在文本框中输入字母或数字,观察接受窗口

的文本框有无变化;

3) 移动鼠标光标单击接收窗体,接收窗体由deactivate成为一个Activate状态,再观察接

收窗体的文本框有什么变化,请考虑一下程序执行的过程和轮询方式的工作原理。

⑷使用事件驱动(实时)方式实现串口通信

工程名称:MSComm_Show2.vbp 发送窗体名称:MSComm_Send2.frm

接收窗体名称:MSComm_Receive_Realtime.frm 控件及属性设置: 对象名称 MSComm_Send Label1 Label2 属性 Caption: MSComm_Send Caption:发送窗口 Caption: 请将发送内容写入文本框 Text1 MSComm1 Text: Text1 Macomm1 对象名称 MSComm_Receive_Polling Label1 Label2 属性 Caption: MSComm_Receive_Realtime Caption:接收窗口 Caption: 接收到的文本将在文本框中显示 Text: Rthreshold:1 程序代码: '发送窗体程序

Private Sub Form_Load()

MSComm1.CommPort = 1

MSComm1.Settings = \"2400,N,8,1\" MSComm1.InputLen = 0 MSComm1.PortOpen = True

Mscomm_Receive_Realtime.Show '显示实时接收窗体,启动接收程序 End Sub

Private Sub Text1_KeyPress(KeyAscii As Integer)

MSComm1.Output = Chr$(KeyAscii) '发送用户从键盘上输入的字符 End Sub

Private Sub Form_Unload(Cancel As Integer) MSComm1.PortOpen = False End Sub

'接收窗体程序

Private Sub Form_Load()

MSComm1.CommPort = 2 '使用COM2。

MSComm1.Settings = \"2400,N,8,1\" MSComm1.InputLen = 0 MSComm1.PortOpen = True

Mscomm_Receive_Reatime.Show '显示轮询接收窗体,启动接收程序 End Sub

Private Sub MSComm1_OnComm() On Error Resume Next

Text1.Text = Text1.Text + MSComm1.Input

'从串行端口实时读入到达的数据,并送文本窗口显示。

End Sub

Private Sub Form_Unload(Cancel As Integer) MSComm1.PortOpen = False End Sub

实验操作步骤:

1) 用发送窗体(MSComm_Send)作为启动对象,启动程序后,发送窗体和实时接收窗体都

将出现在屏幕上;

2) 用鼠标将光标设置到发送窗体的文本框中,在文本框中输入字母或数字,观察接受窗口

的文本框有无变化;

3) 请将接受窗体的MSComm1的Rthreshold属性改为5,重新启动程序,注意收发过程的

变化,请考虑一下程序执行的过程和实时方式的工作原理。

因篇幅问题不能全部显示,请点此查看更多更全内容