注意:访问本站需要Cookie和JavaScript支持!请设置您的浏览器! 打开购物车 查看留言付款方式联系我们
初中电子 单片机教材一 单片机教材二
搜索上次看见的商品或文章:
商品名、介绍 文章名、内容
首页 电子入门 学单片机 免费资源 下载中心 商品列表 象棋在线 在线绘图 加盟五一 加入收藏 设为首页
本站推荐:
VB开发Windows环境下的串行通信程序
文章长度[20996] 加入时间[2006/7/1] 更新时间[2024/10/15 5:36:56] 级别[3] [评论] [收藏]
VB开发Windows环境下的串行通信程序
发布时间:2004-7-14
  随着Windows在国内的普及,特别是Windows95的推出,越来越多的微机用户转向了Windows操作系统。不过Windows应用软件的开发对于一般工程技术领域的技术人员来说并非易事,不但Windows的消息循环机制不易理解,而且要开发一个功能强、界面美观的应用软件,其编程和调试的工作量是非常大的。许多并非搞软件出身的工程技术人员对Windows编程望而生畏。然而使用微软的VisualBasic来开发这些方面的Windows应用软件就十分方便,一般工程技术人员易于掌握,设计软件界面非常方便,编程工作量相对较小,只需进行主要应用功能的编程和少量界面控制的编程。本文介绍了笔者使用VB在串行通信编程方面的一些收获,由于在报刊杂志上对Windows下串行通信编程的介绍多为用MicrosoftC++或BorlandC++,故笔者愿意就VB在该方面的应用与大家探讨。对于采用了RS-232接口进行串行通信的计算机测控系统软件的开发,具有一定的参考价值。

  在该系统中使用了80C31单片机作为下位机采集惯性敏感部件的测量数据,经过一定的预处理后通过RS-232串行口将数据传送给上位PC机。在PC机上Windows环境下运行检测软件,接受串行口传来的数据,进行数据处理、显示、存盘等。数据处理结果以表格形式打印输出。 在VB3.0中,有许多专业厂商提供用户定制的控件(Customcontrol),这些控件以.VBX为后缀,其中MSCOMM.VBX即是用于串行通信的控件。对于VB3.0,启动后该控件就包含于控件工具箱(toolbox)内,否则可以通过File|AddFile将该控件加入控件工具箱。然后就可以利用该控件进行串行通信的程序设计。 

下面举一个简单的例子,说明了如何进行串行通信的程序设计,该程序在Windows95环境下,使用VB3.0已经实现:

1.先建立一个项目文件,其控件如下表所示:

2.代码如下:

SubForm_Load()

comm1.CommPort=1‘使用串行口1

’波特率9600,偶校验,8个数据位,1个停止位。

comm1.Settings=“9600,E,8,1”

当使用Comm1.Input时,每次从接收缓冲区取一个字节。

comm1.InputLen=1

timer1.interval=20‘定时器的中断间隔为20ms,用于更新显示时间。

EndSub

SubcmdComm_Click()

Dimechoch%‘命令变量

Staticmaxf01&,maxf02&,minf01&,minf02&‘最大值,最小值

OnErrorResumeNext‘简单的错误处理

maxf01&=maxf02&=0‘初始化变量

minf01&=32767

minf02&=32767

label2.Caption=comm1.Settings‘显示串行口的设置。

Ifcmdcomm.Caption=“通信”Then‘若当前命令按扭的提示为“通信”则开始发送和

cmdcomm.Caption=“停止”‘接受数据,并将命令按扭提示改为“停止”,以

cmdexit.Enabled=False‘允许停止通信。使退出命令在通信中失效。

IfNotcomm1.PortOpenThen‘若串行口没有打开,则打开串行口

comm1.PortOpen=True

EndIf

Ifcomm1.PortOpenThen

Ifecho.Text<>“”Then‘若命令输入框不空,则将其转换为十六进制数值

echoch%=Val(“&H”+echo.Text)

Else

echoch%=&HF0‘否则确省命令为F0H

EndIf

comm1.Output=Chr(echoch%)‘向串行口写入一字节命令,由WINDOWS自

EndIf‘动将命令发出

label3.Caption=Hex(echoch%)‘显示刚发出的命令

DoWhilecomm1.PortOpen

Ifcomm1.InBufferCount>0Then‘若comm1.InBufferCount>0表示接受缓冲

ch$=comm1.Input‘区有数据,并读出一个字符,

IfAsc(ch$)=echoch%Then‘若与发出的命令相同,则退出当前循环

ExitDo‘进入下一循环

EndIf

Else

comm1.Output=Chr(echoch%)‘否则继续向下位机发命令,通知下位机

EndIf‘送数据

dummy=DoEvents()‘让系统处理其他消息

Loop

‘下位机接受到正确的命令,并回发命令正确时,进入下面循环

i=1

DoWhilecomm1.PortOpen

Ifcomm1.InBufferCount>5Then

ch$=comm1.Input

DoWhileAsc(ch$)<>echoch%‘以命令字节同步测试数据

ch$=comm1.Input

Loop

ch1$=comm1.Input‘从WINDOWS串行数据接受缓冲区读测试数据

ch2$=comm1.Input

ch3$=comm1.Input

ch4$=comm1.Input

newf01&=CLng(CLng(Asc(ch2$))*16*16+Asc(ch1$))‘合并为一个整数

newf02&=CLng(CLng(Asc(ch4$))*16*16+Asc(ch3$))

ifnewf01&>maxf01&Then‘判断最大值,最小值

maxf01&=newf01&

EndIf

Ifnewf01&
minf01&=newf01&

EndIf

Ifnewf02&>maxf02&Then

maxf02&=newf02&

EndIf

Ifnewf02&
minf02&=newf02&

EndIf

labf01.Caption=Str(newf01&)‘显示数据

labf02.Caption=Str(newf02&)

labmaxf01.Caption=Str(maxf01&)

labminf01.Caption=Str(minf01&)

labmaxf02.Caption=Str(maxf02&)

labminf02.Caption=Str(minf02&)

Else

comm1.Output=Chr(echoch%)

EndIf

dummy=DoEvents()

Loop

Else‘在通讯过程中,按下cmdCOMM按钮则停止通信,发出停止测试

cmdcomm.Caption=“通信”‘命令,关闭串行口,使退出按钮有效。 comm1.Output=Chr(&H5F)

comm1.PortOpen=False

cmdexit.Enabled=True

EndIf

EndSub

SubcmdExit_Click()

Ifcomm1.PortOpenThen‘确认关闭串行口

comm1.PortOpen=False

EndIf

End‘终止整个程序

EndSub

SubTimer1_Timer()‘更新显示时间

Iflabtime.Caption<>Time&Then

labtime.Caption=Time$

EndIf

EndSub

3.程序说明:

a.上述程序的通信协议为:波特率9600,偶校验,8个数据位,1个停止位。由上位机发送开始测试命令,下位机接收到命令后每隔500ms向上位机发送检测到的数据。每次发送5个字节,第一个字节为下位机接受到的命令,第二三字节为16Byte的值,第四五字节为16Byte的值。上位机循环接受并处理和显示数据;

b.由于在控制软件中,串行通讯发送和接受的数据多为十六进制,故在命令输入时为十六进制数,在程序中通过echoch%=Val(“&H”+echo.Text)将输入的echo.Text转换为十六进制数,并赋给变量echoch%。而在通过串行口发送时comm1.Output要求接受字符型变量,故通过语句comm1.Output=Chr(echoch%)实现;

c.接受数据时,每次要判断第一个字节是否为发出的命令,只有是后面4个字节才为正确的数据,否则查看下一字节。通过设置COMM1.InputLen=1来实现每次从接受缓冲区内读取一个字节;

d.当退出程序时,一定要关闭串行口,通过comm1.PortOpen=False完成;

e.如果需要上位机定时查询下位机,可以将串行通讯在定时器Timer1-Timer事件中进行;

f.要实现完善的功能,必须进一步改善程序,甚至要用到WindowsAPI、OLE等,上述程序只是一个简单的例子;

上面介绍了笔者在使用VB开发Windows环境下测控软件的一点收获,笔者使用上述原理开发了一个界面友好、功能全面、使用方便的卫星控制系统惯性敏感部件检测软件,实际使用效果良好,提高了工作效率,甚至实现了测试和数据处理的自动化。 


WIN95



Visual Basic5.0( 以 下 简 称VB) 以 其 简 单 易 学、32 位 面 向 对 象 的 程 序 设 计 等 特 点, 倍 受 广 大 计 算 机 开 发 者 的 青 睐, 已 广 泛 地 应 用 于 各 个 领 域; 在 实 时 监 测 系 统 中 串 行 端 口 通 信 是 一 项 基 础 功 能, 因 此 我 们 使 用VB5 编 写 了 实 时 水 库 水 文 自 动 监 测 系 统 的 后 台 机 软 件。 本 文 就Windows 95 环 境 中 采 用VB5 设 计 串 行 端 口 通 信 程 序 进 行 讨 论 并 给 出 实 例。

   一 般 用VB 开 发 串 行 通 信 程 序 有 两 种 方 法: 一 是 利 用Windows 的 通 信API 函 数; 另 一 种 是 采 用VB 标 准 控 件Mscomm 来 实 现。

Windows 95 的 通 信API
   Windows 95 中 的 串 口 通 信API 函 数 不 同 于Windows3.x 中 的OpenComm、CloseComm、ReadComm、WriteComm, 而 是 采 用 硬 件 与 文 件 通 用 的 函 数CreateFile、ReadFile、WriteFile、CloseHandle, 该 类 函 数 更 具 有 一 般 性, 并 且 可 以 用EscapeCommFunction 函 数 实 现 底 层 硬 件 操 作, 比 如:SETXOFF、 CLRDTR 等。
   利 用API 编 写 串 口 通 信 程 序 较 为 复 杂, 需 要 掌 握 大 量 通 信 知 识, 其 优 点 是 可 实 现 的 功 能 更 丰 富、 应 用 面 更 广 泛, 更 适 合 于 编 写 较 为 复 杂 的 低 层 次 通 信 程 序。 采 用 这 种 方 法 编 写 串 行 端 口 通 信 程 序 一 般 可 分 为 以 下 几 个 过 程:

   1. 初 始 化 串 行 端 口

   首 先 用CreateFile 函 数 打 开 指 定 串 口, 置 参 数 中 访 问 类 型 为GENERIC_READ |GENERIC_WRITE、 共 享 模 式 为0、 创 建 标 志 为OPEN_EXISTING、 模 板 句 柄 为NULL。

   2. 配 置 串 口

   Windows 95 的 串 口 配 置 比Windows 3.x 较 为 复 杂, 但 其 功 能 更 强 大, 对 一 般 程 序 可 使 用CommConfigDialog 函 数 以 对 话 框 方 式 设 置 波 特 率、 数 据 位、 奇 偶 校 验、 停 止 位 和 流 控 制 方 式, 并 且 可 以 恢 复 缺 省 值。

   3. 超 时 控 制

   为 了 防 止 意 外 情 况 使 串 口 读 写 无 休 止 地 等 待,Windows 95 提 供 了 超 时 设 置, 这 是 由COMMTIMEOUTS 结 构 定 义 的, 通 过 调 用GetCcommTimeOuts 函 数 获 得 当 前 的 设 置, 用SetCommTimeOuts 函 数 来 完 成 设 置。

   4. 数 据 传 输

   读 写 串 行 端 口 与 读 写 文 件 采 用 的 函 数 相 同, 即ReadFile、WriteFile, 读 写 操 作 可 分 四 种 方 式: 查 询 方 式、 同 步I/O、 异 步( 后 台)I/O 和 事 件 驱 动I/O。

   5. 关 闭 串 口

   程 序 的 终 止 可 以 自 动 关 闭 串 口, 也 可 用 函 数CloseHandle(), 以 便 释 放 所 独 占 资 源。

VB 通 信 控 件Mscomm
   Mscomm 控 件 提 供 了 功 能 完 善 的 串 口 数 据 的 发 送 和 接 收 功 能,Mscomm 控 件 具 有 两 种 处 理 方 式: 1 事 件 驱 动 方 式: 由Mscomm 控 件 的OnComm 事 件 捕 获 并 处 理 通 信 错 误 及 事 件;2 查 询 方 式: 通 过 检 查CommEvent 属 性 的 值 来 判 断 事 件 和 错 误。
   Mscomm 控 件 的 通 信 功 能 实 现, 实 际 上 是 调 用 了API 函 数, 而API 函 数 是 由Comm.drv 解 释 并 传 给 设 备 驱 动 程 序 执 行 的, 对 于VB 程 序 开 发 者 只 需 知 道Mscomm 控 件 的 属 性 和 事 件 的 用 法 即 可 以 实 现 串 口 的 操 作。

   以 下 是Mscomm 控 件 的 主 要 属 性 和 方 法:

   1)CommPort: 设 置 或 返 回 串 行 端 口 号, 其 取 值 范 围 为1 ~99, 缺 省 为1。

   2) Setting 设 置 或 返 回 串 行 端 口 的 波 特 率、 奇 偶 校 验 位、 数 据 位 数、 停 止 位。 如:Mscomm.Setting=“9600,N,8,1”。

   3)PortOpen: 打 开 或 关 闭 串 行 端 口, 格 式 为:Mscomm.PortOpen={TRUE|FALSE}。

   4) InBufferSize: 设 置 或 返 回 接 收 缓 冲 区 的 大 小, 缺 省 为1024 字 节。

   5) InBufferCount: 返 回 接 收 缓 冲 区 内 的 等 待 读 取 的 字 节 个 数, 可 通 过 设 置 该 属 性 为0 来 清 除 接 收 缓 冲 区。

   6) RThreshold: 该 属 性 为 一 阀 值, 它 确 定 当 接 收 缓 冲 区 内 字 节 个 数 达 到 或 超 过 该 值 后 就 产 生 代 码 为MSCOMM_EV_RECEIVE 的OnComm 事 件。

   7) InputLen: 设 置 或 返 回 接 收 缓 冲 区 内 用Input 读 入 的 个 数。 若 取0, 则INPUT 读 取 整 个 缓 冲 区 的 内 容。

   8) Input: 该 属 性 表 示 从 接 收 缓 冲 区 移 走 一 串 字 符。

   9) OutBufferSize: 设 置 或 返 回 发 送 缓 冲 区, 缺 省 为512 字 节。

   10) OutBufferCounter: 返 回 发 送 缓 冲 区 内 等 待 发 送 的 字 符 数, 可 用 来 清 空 缓 冲 区。

   11) Output: 向 发 送 缓 冲 区 传 送 一 字 符 串。

   12) EOFEnable: 若 置TRUE, 则 当 输 入 中 出 现EOF, 就 停 止 输 入 并 产 生OnComm 事 件。

   如 果 在 通 信 过 程 中 发 生 错 误 或 事 件, 就 会 引 发OnComm 事 件 并 且 改 变 属 性 值, 由CommEvent 属 性 代 码 反 映 错 误 类 型, 在 通 信 程 序 的 设 计 中 可 根 据 该 属 性 值 来 执 行 不 同 的 操 作, 以 下 是 部 分 属 性 常 数 值 及 其 含 义:

   1)ComEvSend: 其 值 为1, 发 送 缓 冲 区 的 内 容 少 于SThreshold 指 定 的 值。

   2) ComEvReceive: 其 值 为2, 接 收 缓 冲 区 内 字 符 数 达 到 RThreshold 值, 该 事 件 在 缓 冲 区 中 数 据 被 移 走 前 将 持 续 产 生。

   3) ComEventFrame: 其 值 为1004, 硬 件 检 测 到 帧 错 误。

   4) ComEventRxOver: 其 值 为1008, 接 收 缓 冲 区 溢 出。

   5) ComEventTxFull: 其 值 为1010, 发 送 缓 冲 区 溢 出。

   6) ComEventRxParity: 其 值 为1009, 奇 偶 校 验。

   7) ComEvEOF: 其 值 为7, 接 收 数 据 中 出 现 文 件 结 束(ASCII 码 为 26) 字 符。

程 序 样 例
   采 用Mscomm 控 件 实 现 串 口 通 信 时, 首 先 添 加 一Mscomm 控 件 到 窗 体 中, 该 控 件 一 般 不 在 通 用 工 具 窗 口 中, 而 是 需 通 过 菜 单 项“ 工 程(P) → 部 件(O)” 进 入 选 择 窗 口, 在 控 件tab 页 中 选 取Microsoft Comm Control 5.0 , 此 时 工 具 窗 口 中 出 现Mscomm 图 标, 即 可 被 使 用。
   以 下 是 事 件 驱 动 方 式 的 接 收 程 序 的 主 要 部 分: Private Sub getdatafromserial_Click()

   CommonDialog1.InitDir = “c:\temp"

   CommonDialog1.ShowSave

   mainfrm.MSComm1.CommPort=1

   hfile = FreeFile

   ’ 打 开 存 储 接 收 数 据 的 文 件

   Open CommonDialog1.filename For Output As #hfile

   ’ 设 接 收 缓 冲 区 的 大 小, 可 按 量 确 定

   mainfrm.MSComm1.InBufferSize = 4096

   If Not mainfrm.MSComm1.PortOpen Then ’ 打 开 串 口

  -- mainfrm.MSComm1.PortOpen = True

   End If

   If Err Then

   MsgBox “Communcation port cannot be opened!!"

   ’ 清 接 收 缓 冲 区

   mainfrm.MSComm1.InBufferCount = 0

   ’ 设 一 次 读 入 的 长 度, 可 根 据 数 据 格 式 设 置

   mainfrm.MSComm1.InputLen = 77

   ’ 设 置 接 收 事 件 触 发 的 阀 值

   mainfrm.MSComm1.RThreshold = 77

   counter = Timer + 10

   Do


If Timer > counter Then

mainfrm.Label1.Caption = “ 正 在 通 信......"

mainfrm.Label1.Refresh

counter = Timer + 10

End If

DoEvents

Loop

End Sub


   以 下 为 事 件 处 理 子 程 序,flag 为 一 静 态 变 量 记 录 读 取 次 数, 以 便 改 变 接 收 数 据 的 长 度, 读 者 可 根 据 实 际 需 要 添 加 其 它 处 理 内 容:


Private Sub MSComm1_OnComm()

Select Case MSComm1.CommEvent

Case comEvReceive

If flag > 246 Then

MSComm1.InputLen = 0: MSComm1.RThreshold = 32

End If

buffer = MSComm1.Input

temp = buffer

Print #hfile, temp

counter = Timer + 10

Do While Timer > counter

Do Events

Loop

flag = flag + 1

Case comEvEOF

EVMsg $ = “ 检 测 到 文 件 结 尾!!!"

Case comFrame

ERMsg $ = “ 帧 出 错!!!"

Case comRxParity

ERMsg $ = “ 奇 偶 错!!!"

End Select

If Len(EVMsg $) Then

Text1.Text = “Status: " & EVMsg $

ElseIf Len(ERMsg $) Then

Text1.Text = “Status: " & ERMsg $

Beep

Ret = MsgBox(ERMsg $, 1, “Click Cancel to

quit, OK to ignore.")

MSComm1.PortOpen = False

End If

End Sub


vb开发通信软件
一、PC串行通信程序机制
常用的PC串行通信程序大多利用BIOSINT14H中断,以查询I/O方式完成异步串行通信。

Windows系统提供中断方式驱动的串行通信驱动程序COMM.DRV。通信程序无需直接对串行端口进行操作,而是通过驱动程序这一编程接口进行间接操作。

Windows操作系统中,串行通信采用“事件通知”方式,支持数据按块传送。进行通信时,Windows开辟一个用户定义的输入输出缓冲区,每接收一个字符就产生一个低级硬件中断,串行驱动程序立即取得控制权,并将字符放入输入数据缓冲区,然后将控制权返还正在运行的应用程序。如果输入数据缓冲区满了,驱动程序用当前定义的流控制机制通知发送方停止发送数据。发送数据也采用类似的处理方式,应用程序将需要发送的数据放入输出数据缓冲区,串口每发送一个字符就产生一个低级硬件中断。

二、PC串行口远程通信的硬件配置

串行通信数据链中,计算机一端称为DTE,即数据终端设备;调制解调器一端称为DCE,即数据通信设备。PC串行通信的硬件连接方式分为零Modem连接和Modem连接。

零Modem连接即直接用调制解调器电缆将两台设备连接起来,Modem连接则通过DCE(Modem)将两台PC连接起来。

零Modem连接用于距离15m内两台DTE或DCE设备之间的连接。而Modem连接则通过电话网或专线用于长距离的通信。

TXD和RXD信号线用于计算机和Modem间传输数据信息;RTS从计算机端发送信号到Modem,表示希望把数据传给Modem,若Modem能接收这个数据,它将发送CTS信号给计算机;DTR从计算机端发送信号到Modem,表示计算机已作好通信准备,Modem将DTR信号作为初始化自己的信号,然后给计算机回送数据设置就绪信号DSR;当本地Modem接收到远地Modem的呼叫,则发送RING信号给计算机;Modem应答呼叫后,发送数据载波检测DCD信号到计算机,表示已建立连接。

Modem的工作状态分为命令状态和在线状态。处于命令状态时,Modem对串口发送的信息进行解释,可通过PC串口向Modem发送AT命令对其进行初始化、设置和操作。

例如,初始化命令为:“ATQOV1WOSOΚ1&C1&D2&YO&WO”,其含义为:

QO:返回结果码;

V1:以字符形式显示结果码;

WO:不返回协商进程结果码;

SOΚ1:振铃一次,即应答;

&C1:追踪数据载波信号CD;

&D2当DTR从开到关时,Modem挂机进入命令状态;

&YO:Modem上电时重新调出用户方案;

&WO:将以上设置存为动态设置用户方案0;

一旦本地Modem与远地Modem建立连接,Modem即处于在线状态,可进行数据传输。此时,Modem不响应AT命令,直接传送所收到的数据。

三、Modem连接远程通信软件的编制

通信过程中大部分的工作由串行通信驱动软件承担。

本文软件的运行环境为AST+4/66d,Hayes公司的ACCURA144+FAX144Modem,Windows3.2,VB3.0专业版。VB3.0专业版中提供了一个MSCOMM.VBX通信控件。它使用户能很方便地通过对控件属性的设置、检测,访问串行通信驱动程序的大多数特性,而不必考虑其实现细节。该控件为“事件驱动”,只响应“OnComm”事件,该事件可对已发生的事件或错误进行处理,与CommEvent属性紧密相关。

通信软件、通信驱动软件和Modem之间的通信关系

以下程序实现了通信的基本过程。包括初始化串口和Modem,上位机拨号呼叫下位机,下位机应答并开始定时传输数据,挂机停止传输等功能。

VB3.0编制的通信软件清单如下:

上位机控件清单:

控件名称 属性

Form1Form1Caption ″上位机通信″

MsComm comm1

CommandButton1CallCaption ″拨号″

CommandButton2hangCaption ″挂机″

CommandButton3ExitCaption ″退出″

下位机控件清单

控件名称 属性

Form1Form1Caption ″下位机通信″

MsComm comm1

CommandButton1hangCaption ″挂机″

CommandButton2ExitCaption ″退出″

Timer1Timer1Interval 3000

Text(i)Text(i)

1.串口初始化、设置程序

在程序初始化时,先对串口初始化。因为使用RTS/CTS握手信号的硬件设备只有RTS信号置为高才能接收数据,所以需将MSCOMM通信控件的RTSenable属性设为TRUE。由于Modem在处于命令状态时,通过串口发送的命令以及命令结果均会回显在输入缓冲区中,因此在进入在线状态前,禁止产生EV-RECEIVE事件,避免数据误处理。

由于Windows是多任务系统,在进行数据收发循环处理时,应调用DOEVENTS事件,将控制权交还系统,允许Windows执行其他任务。但应注意,在处理OnComm事件时小心使用DOEVENTS,避免系统又产生OnComm事件,造成嵌套,出现堆栈溢出错误。

Sub Form-Load()

comm1.CommportΚ1′COM1口通信

comm1.SettingsΚ″9600,N,8,1″′波特率9600,无校验,8位数据位1位停止位

comm1.OutBufferSizeΚOUTPACK′设置输出缓冲区大小

comm1.InBufferSizeΚINPACK′设置输入缓冲区大小

comm1.InputLenΚ1′每次从输入缓冲区中取一个字符

comm1.RTSenableΚ-1′RTS信号为高

comm1.RthresholdΚ0′不产生MSCOMM-EV-RECEIVE事件

comm1.PortOpenΚ-1′打开串口

cdΚcomm1.CDHolding′取载波检测信号线原始状态

comm1.outputΚ″ATQOV1WOSOΚ1&C1&D2&YOWO″′初始化Modem

Do DoEventsLoopUntilcomm1.OutBufferCountΚ0

End Sub

2.上位机拨号呼叫下位机

SubCallcom-Click()

Comm1.OutPutΚ″ATDT″&Phonnum$&chr$(13)′向Modem发拨号命令

Do DoEventsLoopUntilcomm1.OutBufferCountΚ0

End Sub

3.下位机Modem应答,连通后开始定时传输数据

下位机检测CD,判断是否连通:

Sub Comm1-OnComm()

Select Casecomm1.CommEvent

Case5 ′MSCOMM-EV-CD

Timer1.EnabledΚ-1′启动定时器

End Select

End Sub

VB传送定长字符串,数据接收处理相对简单。但在发送实时数据时,若将数据转换成定长字符串,这样会大大降低传输效率。在接收端,通知程序从输入缓冲区中取字符有两种方法:一是用轮询方法循环判断InBufferCount是否为0;另外就是利用Rthreshold属性触发“OnComm”事件及“CommEvent”属性中EV-RECEIVE事件。当Rthreshold的值不为0时,允许产生EV-RECEIVE事件。该属性设置和返回在通信控件设定CommEvent特性为接收和产生OnComm事件之前要接收的字符数。VB传送变长字符串时,接收端的Rthreshold值要作相应的改变,以确保接收数据及时准确。

下位机定时发送字符串“strin3$ΚFormat$(Len(strin1$),″0000″)&chr$(8)&strin2$”。strin1$为当前字符串,strin2$为上一字符串。上位机根据接收strin3$中Len(strin1$),相应改变RthresholdΚLen(strin1$)+4。这样,通过提前发送字符串长度,改变Rthreshold值可实现发送变长数据。

Windows串行通信驱动程序的事件驱动特性仍有不稳定的缺陷。如InputLenΚ0时,有可能取出不完整的数据。为保证可靠,采取降低处理速率的方法,保证下位机发送的数据流完整地进入输入缓冲区。设InputLenΚ1,即每次从缓冲区中取一个字符。也可采用轮询方法,定时检测输入缓冲区。下位机定时发送数据:

Sub Timer1-Timer()

If comm1.CDHoldingΙΛcdThen

str1$-text1(i).Text

strin2$Κstrin1$′上一字符串

strin1$Κstr1$′当前字符串

strin3$ΚFormat$(Len(strin1$),″0000″)&chr$(8)&strin2$

′传送当前字符串长度,以及上一字符串内容

com m1.OutPutΚstrin3$

Do DoEventsLoopUntilcomm1.OutBufferCountΚ0

Else

Timer1.EnabledΚ0

End If

End Sub

上位机检测CD状态,判断是否连通、并接收处理数据。

Sub Comm1-OnComm()

Select Case comm1.CommEvent

Case5 ′MSCOMM-EV-CD检测CD状态,判断是否连通

comm1.InBufferCountΚ0′清输入缓冲区

comm1.RThresholdΚ4′当输入缓冲区中有五个字符,

Case2′MSCOMM-EV-RECEIVE产生EV-RECEIVE事件,接收处理数据

Do DoEvents

Ifcomm1.InBufferCountThen′循环从缓冲区中取数据

str1$Κstr1$+comm1.Input

Else

Exit Do

End If

Loop

len2Κ1en1′当前字符串长度

len1ΚVa1(Left$(str1$,5))′即将发送的字符串长度

comm1.RThresholdΚlen1+4

strin$ΚRight$(str1$,len2)′数据处理

……

End Select

str1$Κ″″

End Sub

4.根据设置的AT命令“&D2”,当置DTR信号为低时,Modem挂机进入命令状态。也可通过串口输出““+++ATH”+chr$(13)”字符串挂机。

Sub Hang-click()

If comm1.CDHoldingΙΛcdThen′检测CD,判断是否挂机

comm1.DTRenableΚ0

comm1.DTRenableΚ-1′置DTR信号为高,为下一次通信准备

End If

End Sub

5.退出程序时,一定要关闭串口

Sub Exitcomm()

comm1.PortOpenΚfalse

End

End Sub

四、Windows通信机制和VB3.0通信控件潜在缺陷

在通信软件编制过程中,我们发现Windows下通信机制采用的“事件驱动”在实际运行中不稳定。如在文件传输过程中,误码和数据丢失的情况时有发生;若串口波特率过高,会产生无法通信或在通信过程中随机挂机的情况。这主要是由于Windows本身通信机制和通信线路介质及质量的影响。为保证数据传输稳定可靠,可采用通信协议如XModem-CRC或YModem。在MSCOMM.VBX通信控件中,Rthreshold属性值大小与输入缓冲区InBufferSize大小有关,当Rthreshold值较接近InBufferSize值时,有可能不产生EV-RECEIVE事件,为保证产生该事件,可将InBufferSize值取得较大



使用VB开发Windows环境下的串行通信程序 
  随着Windows在国内的普及,特别是Windows95的推出,越来越多的微机用户转向了Windows操作系统。不过Windows应用软件的开发对于一般工程技术领域的技术人员来说并非易事,不但Windows的消息循环机制不易理解,而且要开发一个功能强、界面美观的应用软件,其编程和调试的工作量是非常大的。许多并非搞软件出身的工程技术人员对Windows编程望而生畏。然而使用微软的VisualBasic来开发这些方面的Windows应用软件就十分方便,一般工程技术人员易于掌握,设计软件界面非常方便,编程工作量相对较小,只需进行主要应用功能的编程和少量界面控制的编程。本文介绍了笔者使用VB在串行通信编程方面的一些收获,由于在报刊杂志上对Windows下串行通信编程的介绍多为用MicrosoftC++或BorlandC++,故笔者愿意就VB在该方面的应用与大家探讨。对于采用了RS-232接口进行串行通信的计算机测控系统软件的开发,具有一定的参考价值。

  在该系统中使用了80C31单片机作为下位机采集惯性敏感部件的测量数据,经过一定的预处理后通过RS-232串行口将数据传送给上位PC机。在PC机上Windows环境下运行检测软件,接受串行口传来的数据,进行数据处理、显示、存盘等。数据处理结果以表格形式打印输出。

  在VB3.0中,有许多专业厂商提供用户定制的控件(Customcontrol),这些控件以.VBX为后缀,其中MSCOMM.VBX即是用于串行通信的控件。对于VB3.0,启动后该控件就包含于控件工具箱(toolbox)内,否则可以通过File|AddFile将该控件加入控件工具箱。然后就可以利用该控件进行串行通信的程序设计。

下面举一个简单的例子,说明了如何进行串行通信的程序设计,该程序在Windows95环境下,使用VB3.0已经实现:

1.先建立一个项目文件,其控件如下表所示:

2.代码如下:

SubForm_Load()

comm1.CommPort=1‘使用串行口1

"波特率9600,偶校验,8个数据位,1个停止位。

comm1.Settings=“9600,E,8,1”

当使用Comm1.Input时,每次从接收缓冲区取一个字节。

comm1.InputLen=1

timer1.interval=20‘定时器的中断间隔为20ms,用于更新显示时间。

EndSub

SubcmdComm_Click()

Dimechoch%‘命令变量

Staticmaxf01&,maxf02&,minf01&,minf02&‘最大值,最小值

OnErrorResumeNext‘简单的错误处理

maxf01&=maxf02&=0‘初始化变量

minf01&=32767

minf02&=32767

label2.Caption=comm1.Settings‘显示串行口的设置。

Ifcmdcomm.Caption=“通信”Then‘若当前命令按扭的提示为“通信”则开始发送和

cmdcomm.Caption=“停止”‘接受数据,并将命令按扭提示改为“停止”,以

cmdexit.Enabled=False‘允许停止通信。使退出命令在通信中失效。

IfNotcomm1.PortOpenThen‘若串行口没有打开,则打开串行口

comm1.PortOpen=True

EndIf

Ifcomm1.PortOpenThen

Ifecho.Text<>“”Then‘若命令输入框不空,则将其转换为十六进制数值

echoch%=Val(“&H”+echo.Text)

Else

echoch%=&HF0‘否则确省命令为F0H

EndIf

comm1.Output=Chr(echoch%)‘向串行口写入一字节命令,由WINDOWS自

EndIf‘动将命令发出

label3.Caption=Hex(echoch%)‘显示刚发出的命令

DoWhilecomm1.PortOpen

Ifcomm1.InBufferCount>0Then‘若comm1.InBufferCount>0表示接受缓冲

ch$=comm1.Input‘区有数据,并读出一个字符,

IfAsc(ch$)=echoch%Then‘若与发出的命令相同,则退出当前循环

ExitDo‘进入下一循环

EndIf

Else

comm1.Output=Chr(echoch%)‘否则继续向下位机发命令,通知下位机

EndIf‘送数据

dummy=DoEvents()‘让系统处理其他消息

Loop

‘下位机接受到正确的命令,并回发命令正确时,进入下面循环

i=1

DoWhilecomm1.PortOpen

Ifcomm1.InBufferCount>5Then

ch$=comm1.Input

DoWhileAsc(ch$)<>echoch%‘以命令字节同步测试数据

ch$=comm1.Input

Loop

ch1$=comm1.Input‘从WINDOWS串行数据接受缓冲区读测试数据

ch2$=comm1.Input

ch3$=comm1.Input

ch4$=comm1.Input

newf01&=CLng(CLng(Asc(ch2$))*16*16+Asc(ch1$))‘合并为一个整数

newf02&=CLng(CLng(Asc(ch4$))*16*16+Asc(ch3$))

ifnewf01&>maxf01&Then‘判断最大值,最小值

maxf01&=newf01&

EndIf

Ifnewf01&
minf01&=newf01&

EndIf

Ifnewf02&>maxf02&Then

maxf02&=newf02&

EndIf

Ifnewf02&
minf02&=newf02&

EndIf

labf01.Caption=Str(newf01&)‘显示数据

labf02.Caption=Str(newf02&)

labmaxf01.Caption=Str(maxf01&)

labminf01.Caption=Str(minf01&)

labmaxf02.Caption=Str(maxf02&)

labminf02.Caption=Str(minf02&)

Else

comm1.Output=Chr(echoch%)

EndIf

dummy=DoEvents()

Loop

Else‘在通讯过程中,按下cmdCOMM按钮则停止通信,发出停止测试

cmdcomm.Caption=“通信”‘命令,关闭串行口,使退出按钮有效。

comm1.Output=Chr(&H5F)

comm1.PortOpen=False

cmdexit.Enabled=True

EndIf

EndSub

SubcmdExit_Click()

Ifcomm1.PortOpenThen‘确认关闭串行口

comm1.PortOpen=False

EndIf

End‘终止整个程序

EndSub

SubTimer1_Timer()‘更新显示时间

Iflabtime.Caption<>Time&Then

labtime.Caption=Time$

EndIf

EndSub

3.程序说明:

  a.上述程序的通信协议为:波特率9600,偶校验,8个数据位,1个停止位。由上位机发送开始测试命令,下位机接收到命令后每隔500ms向上位机发送检测到的数据。每次发送5个字节,第一个字节为下位机接受到的命令,第二三字节为16Byte的值,第四五字节为16Byte的值。上位机循环接受并处理和显示数据;

  b.由于在控制软件中,串行通讯发送和接受的数据多为十六进制,故在命令输入时为十六进制数,在程序中通过echoch%=Val(“&H”+echo.Text)将输入的echo.Text转换为十六进制数,并赋给变量echoch%。而在通过串行口发送时comm1.Output要求接受字符型变量,故通过语句comm1.Output=Chr(echoch%)实现;

  c.接受数据时,每次要判断第一个字节是否为发出的命令,只有是后面4个字节才为正确的数据,否则查看下一字节。通过设置COMM1.InputLen=1来实现每次从接受缓冲区内读取一个字节;

  d.当退出程序时,一定要关闭串行口,通过comm1.PortOpen=False完成;

  e.如果需要上位机定时查询下位机,可以将串行通讯在定时器Timer1-Timer事件中进行;

  f.要实现完善的功能,必须进一步改善程序,甚至要用到WindowsAPI、OLE等,上述程序只是一个简单的例子;

  上面介绍了笔者在使用VB开发Windows环境下测控软件的一点收获,笔者使用上述原理开发了一个界面友好、功能全面、使用方便的卫星控制系统惯性敏感部件检测软件,实际使用效果良好,提高了工作效率,甚至实现了测试和数据处理的自动化。




1、 本站不保证以上观点正确,就算是本站原创作品,本站也不保证内容正确。
2、如果您拥有本文版权,并且不想在本站转载,请书面通知本站立即删除并且向您公开道歉! 以上可能是本站收集或者转载的文章,本站可能没有文章中的元件或产品,如果您需要类似的商品请 点这里查看商品列表!
本站协议 | 版权信息 |  关于我们 |  本站地图 |  营业执照 |  发票说明 |  付款方式 |  联系方式
深圳市宝安区西乡五壹电子商行——粤ICP备16073394号-1;地址:深圳西乡河西四坊183号;邮编:518102
E-mail:51dz$163.com($改为@);Tel:(0755)27947428
工作时间:9:30-12:00和13:30-17:30和18:30-20:30,无人接听时可以再打手机13537585389