51系列单片机片内支持其与上位机的多机通讯,也即是一个上位机可以控制多个下位机(由单片机组成)分时协同工作。这个功能的实现主要依赖于51单片机中存在从上位机接收地址还是接收数据的标志位SM2。51单片机有三种通讯模式,由SCON寄存器控制,SCON寄存器结构如下
SCON D7 D6 D5 D4 D3 D2 D1 D0
SM0 SM1 SM2 REN TB8 RB8 TI RI
(1).SM0、SM1:串行口工作方式控制位。
SM0,SM1 工作方式
00 方式0
01 方式1
10 方式2
11 方式3
(2).SM2:多机通信控制位。
多机通信是工作于方式2和方式3,SM2位主要用于方式2和方式3.接收状态,当串行口工作于方式2或3,以及SM2=1时,只有当接收到第9位数据(RB8)为1时,才把接 收到的前8位数据送入SBUF,且置位RI发出中断申请,否则会将接受到的数据放弃.当SM2=0时,就不管第位数据是0还是1,都难得数据送入SBUF,并发出中断申请.
工作于方式0时,SM2必须为0.
(3).REN:允许接收位。
REN用于控制数据接收的允许和禁止,REN=1时,允许接收,REN=0时,禁止接收。
(4).TB8:发送接收数据位8。
在方式2和方式3中,TB8是要发送的——即第9位数据位。在多机通信中同样亦要传输这一位,并且它代表传输的地址还是数据,TB8=0为数据,TB8=1时为地址。
(5).RB8:接收数据位8。
在方式2和方式3中,RB8存放接收到的第9位数据,用以识别接收到的数据特征。
6).TI:发送中断标志位。
可寻址标志位。方式0时,发送完第8位数据后,由硬件置位,其它方式下,在发送或停止位之前由硬件置位,因此,TI=1表示帧发送结束,TI可由软件清“0”。
(7).RI:接收中断标志位。
注:
1.实现原理
只有工作在2,3模式,单片机才具有多机通信能力,此时SM2=1时,只有当接收到第9位数据(RB8)为1时,才把接收到的前8位数据送入SBUF,且置位RI发出中断申请,否则会将接受到的数据放弃。当SM2=0时,就不管第位数据是0还是1,都难得数据送入SBUF,并发出中断申请。这样就可以实现多机通信。为什么?假设所有下位机初始时都将SM2置为1,那么它们只能接收被标志为地址的数据。上位机先发送地址数据,然后所有单片机同时接收到该数据送进各自的SBUF,那么我们就可以在单片机程序中进行对该数据的判断,看看它是否就是本机的地址,如果是,那么就将SM2清零,等待上位机发送数据(这里不是地址数据,它们的区别在于第9位是1还是0,若为1,我们定义为地址数据,为0,我们定义为数据),而其他单片机因为接收到的地址数据都与自己预置的不同,所以不将SM2清零,那么他们就接收不到下一个周期单片机发送过来的数据(不是地址数据),继续等待他的地址数据的到来。
2.VB如何发送第9位数据
这是一个艰苦的过程,对于我来说,PC机与单片机的通信搞过,但是多机通讯还是大姑娘上花轿——头一回。所以在网上找了许多资料,也在机上测试了许多次,终于让我找到了答案,现在我要记录下来:
VB代码及注解
//在PWM-4DA中的相关代码,实际运行有效
Public Function Send(ByRef MSComm As MSComm, ByVal moduleAddress As Byte, ByVal channelAddress As Byte, ByVal channelData As Byte)
Dim buffer(0) As Byte '存储发送的数据
MSComm.CommPort = 3 '设置COM1为串口发送端口
MSComm.NullDiscard = False
MSComm.PortOpen = True '打开串口
MSComm.Settings = "9600,M,8,1" '11位串行通讯模式,发送地址模式(Mark,表示标志为地址数据,发送的时候会自动将第9位置1)
buffer(0) = moduleAddress //先发送通道地址,注意其数据的第九位是1,(地址位标识,用于单片机识别)
MSComm.Output = buffer //输出数据,如果buffer的数组长度为N,那么这一句程序会以相同的方式连续发送N个数据
Delay (5) '至少延时2毫秒,推荐5毫秒 //数据传输以及单片机的判断需要一定的时间,这个延时对通讯的质量是有保证的
MSComm.Settings = "9600,S,8,1" //(Space,即空白,第九位为0,现在发送的已经不是地址数据了,而是确实需要的有用的数据)
buffer(0) = channelAddress //通道数据地址
MSComm.Output = buffer
Delay (5) '至少延时2毫秒,推荐5毫秒
buffer(0) = channelData //通道数据 注:我这里发了两个非地址数据
MSComm.Output = buffer
Delay (5) '至少延时2毫秒,推荐5毫秒
MSComm.PortOpen = False
Send = "OK"
End Function
Public Sub Delay(msec As Long)
On Error Resume Next
Dim tstart As Single
tstart = Timer
While (Timer - tstart) < (msec / 1000)
DoEvents
Wend
End Sub
对VB发送第九位数据的总结:即是对不同发送模式的控制,在代码中表现在对MSCOMM.SETTINGS = "9600,M,8,1" OR "9600,S,8,1" 的设置
3.在单片机端如何发送第九位数据(这个部分在项目PWM-4DA中没有用到,这里只是一些理论上的知识,没有去亲身实践)
假设那个上位机是一个51系列的单片机,那么这时我们就要解决在单片机端如何发送第九位数据,我们注意到在SCON控制寄存器中有个TB8位,这个位就是控制发的地址还是数据的控制位,当TB8为1时,发送的是地址数据,当TB8=0时,发送的是数据.它的发送是跟随在SBUF=?之后的.有时间可以试试.这对用一个单片机作主控是相当有用的.