中国石凳联盟 登录注册

【原创】再论串口通讯

rockage··2 回复·383 浏览

发表回复

串口通讯是众多接口里面最简单同时也是用得最广泛的,下面只讲使用,不讲原理(原理也并不复杂),
用VB的例子来说一下在PC机里是怎么进行串口通讯的。

一. 初始化
首先引用一个串口控件MSComm,打开VB的工程-部件-添加一个MicroSoft Comm Control 6.0,
拖到界面上, 初始化一般放在Form_Load处,如下:

Private Sub Form_Load()
MSComm1.CommPort = CommPort
通讯端口,就是指COM几

MSComm1.InputMode = comInputModeBinary
comInputModeBinary用二进制传输,可选为comInputModeText以传送纯文本

MSComm1.Settings = "9600,N,8,1"
含义是9600bps/s 波特率,无校验,数据位8,停止位1(这个设置可以参考与PC通讯的设备的说明书,设置错误将无法通讯)

MSComm1.RThreshold = 0
含义是不触发串口控件的OnComm事件,在接收方面,可以选择两种方法,一种是事件驱动,一种是轮寻法,等一下再详细介绍。

End Sub


二. 发送
发送使用MScomm的Output方法,首先定义一个发送变量数组SendBuf

Dim SendBuf() As Byte (当然如果只发一个字节,那么可以不用数组)

发送低于255的数据,很简单:
SendBuf(0) = 255
MSComm1.Output = SendBuf

发送高于255的数据,要将数据切分:
Dim L as Long, LS as String
L=64188
LS=HeX(L) 先将L换算成16进制数,65535则是“FABC”

SendBuf(0)=Val(Mid(LS,1,2)) 第一个字节FA
SendBuf(1)=Val(Mid(LS,3,2)) 第一个字节BC

然后使用Output方法发送:
MSComm1.Output = SendBuf

发纯文本相对简单些,例如:
MSComm1.Output = "I Love You Stoneren.com"

二. 接收
接收有两种模式,首先介绍事件驱动模式,在数据量不是很大,通讯要求不是很高的地方可以使用,特点是非常方便。首先在初始化的时候就要对MSComm1.RThreshold属性进行设置,例如:MSComm1.RThreshold = 10,表示当缓冲区里有10个字节的数据时,自动触发OnComm事件,双击界面上的MSComm控件,其实MSCOMM控件就只有一个事件,就是OnComm,双击进去就是了,例如:

Private Sub MSComm1_OnComm()

Dim ReciveBuf As Variant 定义一个变体变量以获取数据

ReciveBuf = MSComm1.Input 使用Input方法接收数据

这时候,MSComm的缓冲区被清空,数据被保存在ReciveBuf 里了,
我们可以用一个简单的循环来显示数据内容:
Dim I as integer
For I = 0 to Ubound(ReciveBuf)
debug.Print ReciveBuf(I)
Next I
就这么简单
End Sub

还有一种模式是轮寻模式,轮寻模式一般用在那些通讯很频繁并且对实时效率要求比较高的地方,同样的,在初始化的时候对MSComm1.RThreshold属性进行设置,轮寻模式需要屏蔽掉MSComm自身的OnComm事件,所以要把RThreshold设为0,表示无论缓冲区有多少数据都不触发OnComm事件:

MSComm1.RThreshold=0

接收的时候,完全由你自由掌握,你需要密切留意缓冲区大小,方法是监控InBufferCount属性,给个例子:

Dim K As Long

K = 0
Do
DoEvents
K = K + 1
Loop Until MSComm1.InBufferCount = 19 Or K = 10000
ReciveBuf = MSComm1.Input

上面的程序一直不断地监视InBufferCount属性,当它达到了需要的字节数(19)之后,退出Loop,当然,这是一个比较危险的循环,假如一直收不到19个数据,那么这是一个死循环,所以还需要设置一个K,当K值很大的时候,即便收不到19个数据也退出这个Loop,之后ReciveBuf = MSComm1.Input,接收的时候和事件驱动的时候是一模一样的。

关于接收文本:
文本很简单,初始化的时候MSComm1.InputMode = comInputModeText以传送纯文本,
接收的时候使用标准的String,例如:
Dim S As String
S=MSComm1.Input

备注:
1. MSComm1.Input 方法用于接收,它将自动清空缓冲区
2. 有些特殊情况,比如通讯错误的时候要及时清空缓冲区,不一定非要去Input一下,可以使用:
MSComm1.InBufferCount = 0 清空接收缓冲区
MSComm1.OutBufferCount = 0 清空发送缓冲区

Written By OldSheep 0609111501
点赞0 收藏
有点明白了
Being a devil is the same as being a human. We should be kind. If we are kind, we are not a devil, we are a hybrid.
点赞0 收藏

汗,有个地方说错了,发送大于255的数的时候,是有一点补充的:

如3902这个数,16进制是F3E,实际是由0F 和 3E构成的,而绝对不能拆分为F3和E(F30E就变成了62222),

所以在碰到这种16进制数位数为奇数的时候,前面要手工补0,

Dim L as Long, LS as string

L=3902

LS=Hex(L)

If Len(LS) MOD 2 = 1 then LS = "0" LS

另外,将一个16进制字符串转换为“数”的时候,需要在前面加“H”

SendBuf(0)=Val("H" Mid(LS,1,2)) 第一个字节0F
SendBuf(1)=Val("H" Mid(LS,3,2)) 第一个字节3E

------------------------------

再补充一点,从设备端接收小于255的数,直接接收过来就行了,如果碰到大于255的数,则需要转换,比如接收到上面那个数F3E,那么

ReciveBuf会产生两个字节,第一个是F,第二个是E。

F(15)是高8位,乘上它最低位的权256,也就是 15 * 256 = 3840

3E(62)是低8位,乘上它最低位的权1,也就是 62 * 1 = 62

再将结果相加3840 + 62 = 3902,

举例:

1. 单字节的数,也就是 Recive(0) ,也就是什么也不做

2. 双字节的数: Recive(1) * 256 + Recive(0)

3. 三字节的数: Recive(2) * 65536 + Recive(1) * 256 + Recive(0)

-----------------------------

权是怎么算出来的呢, 方法:

字节N 的权 = 256 的 N-1 次方,比如:

第一个字节的 权= 256 的 1-1 = 0次方 等于 1

第二个字节的 权= 256 的 2-1 =1次方 等于 256

第三个字节的 权= 256 的 3-1 =2次方 等于 65526

依此类推...
点赞0 收藏
发表回复
发表回复