cpubbs论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

LabVIEW+单片机学习套件全套教程资料下载[免费]LabVIEW论坛精华列表贴USB0816数据采集卡《LabVIEW宝典》
LabWindows/CVI论坛精华贴NET0816以太网数据采集卡RC0210远程设备授权系统 关闭关停锁定打开设备 户外分布式数据采集
NET1624低速高精度以太网数据采集卡WIFI0824SD无线WIFI网络数据采集卡脱机运行 SD存储 小尺寸微型 串口采集远程采集 安卓 手持移动采集 纪录仪
查看: 1896|回复: 0

阶段总结:51与PC的多机通信[转]

[复制链接]
发表于 2004-12-15 09:37:42 | 显示全部楼层 |阅读模式
以前做的485总是纯粹的8位方式,因为很多前辈都栽倒在PC端上了,所以我就不尝试9位的方式了,失去了DOS这个乐园,windows的9位多机通信真是让人失色,但是8bit方式的缺点非常明显:每次主机发送指令后,所有终端都收到了,之后才判断是不是喊自己,被叫的从机发送执行数据也要带上机号,而且发送的时候,所有从机又收一遍,收完之后又废除。。。。。

我依然决定尝试9bit的方式,起码这样做从机有权听不到和自己不相干的信息,这倒不是因为从机很忙,而是因为这年头,事不关己高高挂,主管又没找我,我何必竖起耳朵装孙子。

我选择了VB6+MsComm,使用RTS作为收发切换,我一上来就发现只要在发送之后修改了RTS线的状态,通信肯定出问题,百思不得其解,因为我在Handshaking属性中设置成了comNone,纯正的三线制,根本不需要RTS来左右数据流握手呀,RTS在发送前设置为True,发送后延时转为接收设置成false,但是就是这样的变化就引起数据丢失,去掉多RTS的控制就正常,想不通就干脆不想了,我干脆将控制线换成了DTR,嘿嘿,这下子没事了,看来mscomm对RTS有一定的敏感性。只是不知道那么多大侠都使用的VB6+MsComm,为什么都声称自己使用RTS控制自如呢?而我却不得要领。

接下来,因为发送完机号之后应该发送数据,他们之间的差别在于多级通信位的不同(第九位),那么既然修改了MsComm的设置,就应该等机号数据完全发送结束之后再修改设置发送剩余的数据。于是我装模作样的这样写:
  While (MSComm1.OutBufferCount <> 0)  '等待发送数据流发送完成
    DoEvents
  Wend
结果我发现根本不起作用,因为即使一次发送几百字节,OutBufferCount的查询结果都是0,于是我改成:
   Public Transmit_OK As Boolean        ' 串行缓冲区数据发送完成标志

   在 MSComm1_OnComm()中加入:
   Select Case MSComm1.CommEvent
      Case comEvSend
          Transmit_OK = True
   End Select

   Transmit_OK = False
   MSComm1.SThreshold= 1          '发送缓冲区空的时候激发OnComm事件
   MSComm1.Output = Recs
   While (Transmit_OK = False)           '等待机号字节发送完成
     DoEvents
   Wend

这样总算差不多了,起码会等到缓冲区为空的时候通知发送结束。我在115200bps下按照每包32字节,共计发送了8192包数据给从机,都没出错,我以为没事了,可是,当我将波特率改为9600bps的时候,发现从机接收数据包的通过率跌落到了小于5%的地步!有这样的可能吗?高波特率正常但是低波特率却不能工作,我仔细检查后认为波特率设置没有错,问题被定位在了发送机号结束后,虽然得到了MsComm的通知事件,但最后一个字节毕竟没有在总线上发送完,所以接下来修改第九位多机通信位再发送命令数据就会出错,于是我将波特率压低到1200bps再试验,这下子热闹了,没有一个数据包被正常接收!据此判断,115200bps之所以好用,是因为检测到缓冲区空到数据完全在总线上发送结束之间的时间非常短,可以忽略不计,所以不会出错,而9600bps~1200bps就不同了,于是我就在检测到发送缓冲区为空之后,加入延时10ms,开始使用Timer来实现(PII之后的定时器精度为10ms,不再是55ms),再试验9600bps,基本成功,我继而测试2400bps,偶尔有不成功,加大延时为20ms在1200bps下仍然有不成功,不能再加大了,因为终端的超时时间设定是50ms,因为我在VB延时循环过程中使用了doevents,所以实际时延变得不确定,而且如果不加doevents,有时候程序会有不响应外部事件的问题,非常挠头,windows难道没有一个精确延时器吗?上网翻了一通,搞来了一各延时函数,总算基本满足我的要求了:

Public Declare Function GetTickCount Lib "kernel32" () As Long   '它传回Windows启动後到目前为止所经过的时间,传回值以微秒为单位?
   'delay (BUS_Comm_Byte_interval是延时时间,ms)
   Dim Begin_time As Long, End_time As Long
   Begin_time = GetTickCount()
   Do
      End_time = GetTickCount()
   Loop Until (End_time - Begin_time) >= BUS_Comm_Byte_interval

GetTickCount()函数被下载网站的版主描述成是返回us精度的,但是我测试是以ms为单位的,精度嘛就更不好说了,看来做纯PC开发的人不会象我们做单片机的这样会对时间精度负责的,不过这个函数肯定优于Timer控件,我体会还可以对付。这下子在延时20ms的时候,下位机没发生超时错误,而用Timer的时候就不确定。不过找个问题也让我猜测MsComm的发送机理,OnComm事件发生的时候,虽然表示缓冲区空了,似乎只有一个字节等待发送,但MsComm提供的串行缓冲区并非硬件的最终发送缓冲区,也就是说串口适配器16C550里面还有若干字节的FIFO,我们没法控制它不用FIFO,那么mscomm发送结束仅仅是将待发数据都转移到了16550的FIFO,这时候总线上还要持续发送多久我们是很难把握的,此时我们改变发送设置或者切换总线方向都是不可预知的。我眼下是蒙混过关了,但肯定尚有很多隐患,不知各位是如何考虑这个问题的。

MsComm中定义第九位多机通信位的方法如下,其中BUS_Comm_Baud是波特率:
MSComm1.Settings = Format(BUS_Comm_Baud) & ",M,8,1"    '第九位置1
MSComm1.Settings = Format(BUS_Comm_Baud) & ",S,8,1"    '第九位置0

总之,我感觉用VB+MSComm做多机通信似乎有很多不可预知的东西,特别是收发切换的时间控制问题,这个时间快了怕尚未发完就转入接收,慢了又影响网络效率,唉,一言难尽。

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|cpubbs论坛. ( 粤ICP备09171248号 )

GMT+8, 2025-4-5 14:12 , Processed in 0.425769 second(s), 6 queries , Gzip On, File On.

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表