打印

请教懂上位机软件的专家们一个问题

[复制链接]
7337|40
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wzf3151|  楼主 | 2011-8-3 17:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我现在打算开发个上位机软件,利用232通信完成一些功能,我拟定的协议有点类似于modbus协议的RTU模式,一帧数据的起始和结束都是依赖空闲时间进行判断的,在单片机上我觉得还好弄点,但是在PC上就不知道怎么去处理这样的定时了。我看了VC的串口通信的一些方法,像采用CSerialPort类编程或者采用MSComm编程都不太容易对协议的精确实现,不知道用Windows API怎么样?我没有用过,是不是必须用Windows API?或者还有什么其它更好的编程手段?盼望专家给提点意见,谢谢!

===========
我上个项目作了个232通信的上位机软件,当时可能用的还是.net。我就是从微软官网上下载了个VS,然后就乱做一通,查着微软的网上MSDN做,最后就是能完成我想要的功能就行。但是这次我的协议设计稍微复杂点,并且想正规点,所以就看看大家有没有什么好的做法。

相关帖子

沙发
wzf3151|  楼主 | 2011-8-3 17:18 | 只看该作者
或者说,我想在PC上精确的实现MODBUS协议,我该怎么做,谁有例程让俺学习一下。

使用特权

评论回复
板凳
chengchenz| | 2011-8-3 17:32 | 只看该作者
不清楚需要多精准?
Windows上的应用程序很难做到很精准的时间来收发串口数据(秒级别的应当能做到),
线程/进程优先级、缓冲区、CPU负载等等因素都会影响到数据实际的收发时间。

使用特权

评论回复
地板
mohanwei| | 2011-8-3 17:47 | 只看该作者
搜“多媒体定时器”,精度能达到1ms,一般足够用了

使用特权

评论回复
5
wzf3151|  楼主 | 2011-8-3 22:21 | 只看该作者
不清楚需要多精准?
Windows上的应用程序很难做到很精准的时间来收发串口数据(秒级别的应当能做到),
线程/进程优先级、缓冲区、CPU负载等等因素都会影响到数据实际的收发时间。 ...
chengchenz 发表于 2011-8-3 17:32

要能实现modbus协议对数据起始的约定。要能实现检测出3倍的一个字节的时间没有数据接收。这个如果是在非常底层去实现肯定没有问题,可是,我得依赖微软给提供的一些接口啊,那些接口感觉不是能够很方便的实现协议中所提到的状态判断。当然可能一个主要因素是我对上位机软件的修炼不够,要是高手可能很快就能解决。
所以我到这里来向高手咨询咨询。

使用特权

评论回复
6
mmax| | 2011-8-3 23:07 | 只看该作者
只要在每次接收中断的时候,读取一次系统时钟(不是时间,是底层时钟计数值)。
比如用,QueryPerformanceCounter(),获得PC机器内部的时钟数值。
然后两次接收之间的时钟数值做减法来获取时间。

没做过,只是想法。

使用特权

评论回复
7
jrcsh| | 2011-8-4 01:43 | 只看该作者
定义个开始码和结束码不就行了

开始                                                                                    收工        
AA AA  AA    xx xx xx  x  x x x x x x x x xxxx x x x x x x x BB BB BB BB BB

使用特权

评论回复
8
chengchenz| | 2011-8-4 09:39 | 只看该作者
本帖最后由 chengchenz 于 2011-8-4 09:53 编辑
只要在每次接收中断的时候,读取一次系统时钟(不是时间,是底层时钟计数值)。
比如用,QueryPerformanceCounter(),获得PC机器内部的时钟数值。
然后两次接收之间的时钟数值做减法来获取时间。

没做过,只是想法 ...
mmax 发表于 2011-8-3 23:07

在API层,主要问题是,系统有时不会每收到一个字节就通知程序(缓冲区的问题),就算通知了,程序也有可能无法立即响应(CPU负载很重或有更高优先级的任务在处理),可能会将不超时的数据传输以为是超时。可以试一下,如果上述问题实际上不严重,你的想法可能可以实现。另外,可以试一下依赖SetCommTimeouts所设定的超时来做。这个文档或许对你有用.

http://www.robbayer.com/files/serial-win.pdf

4楼提到的多媒体定时器可以得到ms级的计数,也有一个函数可以设定一个ms级的Timer回调函数来完成指定任务,也可能试试。

使用特权

评论回复
9
chengchenz| | 2011-8-4 09:49 | 只看该作者
我觉得7楼的做法更常用更合理,既然上下位机程序都是自己做,就定个好做的协议吧。

使用特权

评论回复
10
yewuyi| | 2011-8-4 11:34 | 只看该作者
定义个开始码和结束码不就行了

开始                                                                                    收工        
AA AA  AA    xx xx xx  x  x x x x x x x x xxxx x x x x x x x BB BB BB ...
jrcsh 发表于 2011-8-4 01:43


如果协议就这么定的话,本身就有很多弊端,这也就意味着你的数据报文中出现AA 或者BB都将可能面临数据纠纷。


MODBUS本身是一个很好很成熟的协议,不建议自搞一套协议。

使用特权

评论回复
11
wzf3151|  楼主 | 2011-8-4 11:47 | 只看该作者
如果协议就这么定的话,本身就有很多弊端,这也就意味着你的数据报文中出现AA 或者BB都将可能面临数据纠纷。


MODBUS本身是一个很好很成熟的协议,不建议自搞一套协议。 ...
yewuyi 发表于 2011-8-4 11:34

还是没有好的解决办法,其实MODBUS的ASCII模式就是定义起始码和结束码的,但是ASCII传输模式我又嫌单片机做起来麻烦点。

我之前做的一个协议只定义了起始码,然后定义了数据长度,完全的自由主义,我现在想要回归正统啊!

使用特权

评论回复
12
yewuyi| | 2011-8-4 11:50 | 只看该作者
还是没有好的解决办法,其实MODBUS的ASCII模式就是定义起始码和结束码的,但是ASCII传输模式我又嫌单片机做起来麻烦点。

我之前做的一个协议只定义了起始码,然后定义了数据长度,完全的自由主义,我现在想要回归 ...
wzf3151 发表于 2011-8-4 11:47


谁说的?
MODBUS在ASCII和RTU下,结束都是通过时间判断的。

使用特权

评论回复
13
wzf3151|  楼主 | 2011-8-4 13:06 | 只看该作者
谁说的?
MODBUS在ASCII和RTU下,结束都是通过时间判断的。
yewuyi 发表于 2011-8-4 11:50

2.5.2.1 Modbus ASCII 报文帧
由发送设备将Modbus 报文构造为带有已知起始和结束标记的帧。这使设备可以在报文的开始
接收新帧,并且知道何时报文结束。不完整的报文必须能够被检测到而错误标志必须作为结果被设
置。
报文帧的地址域含有两个字符。
在 ASCII 模式, 报文用特殊的字符区分帧起始和帧结束。一个报文必须以一个‘冒号’ ( : )
(ASCII 十六进制3A )起始,以‘回车-换行’ (CR LF) 对(ASCII 十六进制0D 和0A) 结束。
报文中字符间的时间间隔可以达一秒。如果有更大的间隔,则接受设备认为发生了错误。
下图显示了一个典型的报文帧。
起始地址 功能 数据LRC 结束
1 字符
:
2字符2字符2字符2字符
CR,LF
0 到to 2x252字符
图 14: ASCII 报文帧

/////////////////上面摘自协议文本

使用特权

评论回复
14
yewuyi| | 2011-8-4 13:45 | 只看该作者
2.5.2.1 Modbus ASCII 报文帧
由发送设备将Modbus 报文构造为带有已知起始和结束标记的帧。这使设备可以在报文的开始
接收新帧,并且知道何时报文结束。不完整的报文必须能够被检测到而错误标志必须作为结果被设
置 ...
wzf3151 发表于 2011-8-4 13:06


接收方在确定报文是否结束时,是以发送结束后的一个停止时间为判断依据的,即使此时解析到的报文数据超过了报文中数据长度的规定,则报文会被继续接受,直到出现一个时间间隔满足停止时间的要求。

你贴出的这一段与以上的时间间隔并无矛盾吧!

使用特权

评论回复
15
ahgao| | 2011-8-4 14:10 | 只看该作者
虽然没有做过MODBUS,但是在PC WINDOWS上想精确知道(10ms级别)串口数据线空闲了多久是不可能的。

使用特权

评论回复
16
wzf3151|  楼主 | 2011-8-4 14:59 | 只看该作者
我贴出的那段说了,报文的起始和结尾由发送设备构造,接收端是对标志判断的,这个就是专门针对某些不能满足定时要求的。 15# yewuyi

使用特权

评论回复
17
yewuyi| | 2011-8-4 15:28 | 只看该作者
我贴出的那段说了,报文的起始和结尾由发送设备构造,接收端是对标志判断的,这个就是专门针对某些不能满足定时要求的。 15# yewuyi
wzf3151 发表于 2011-8-4 14:59


没见过 ,也没听说过,也从来没这么做过。

在MODBUS协议里面规定结束好像是不小于3.5个字符,但最大可到多少,并没有规定,你如果接收方对此结束时间响应不过来,可以加大到35个字符也没关系。

使用特权

评论回复
18
wzf3151|  楼主 | 2011-8-4 16:05 | 只看该作者
给你个协议文本,仔细看看ASCII模式,的确是两种方式的起始停止标志。我正在研究一个modbus例程,而且有win32的移植,我刚刚编译成功,好好研究研究。可以继续讨论

中文MODBUS协议.pdf

1.07 MB

使用特权

评论回复
19
hqgboy| | 2011-8-4 16:06 | 只看该作者
VC有精确的定时器。
1,多媒体定时器。
2,QueryPerformanceCounter


试试吧。

使用特权

评论回复
20
yewuyi| | 2011-8-4 16:26 | 只看该作者
给你个协议文本,仔细看看ASCII模式,的确是两种方式的起始停止标志。我正在研究一个modbus例程,而且有win32的移植,我刚刚编译成功,好好研究研究。可以继续讨论 ...
wzf3151 发表于 2011-8-4 16:05


:dizzy: ,晕倒,俺用MODBUS很多年了,还要你发一份协议学习?:L ,俺自己的电脑里面中英文的MODBUS协议都有。

俺虽然没有用过ASCII模式,但仔细想想,如果用所谓的0x3A做开始接受判断,以0X0d0a做结束接受判断的话,那么数据报文中显然不能出现任何的0X3A或者0X0D,0X0A的数据,否则接受将会出现异常。而且,根据通常的通信处理,一般是接受完一帧数据才会对该帧数据进行解析,接受一个字符就立即解析一个字符显然不是太好,这对稍大容量的数据通信速度将会产生阻塞作用,显然是有很多弊端的。
综上所述,个人认为即使在ASCII模式下,接收方也应以判断间隔时间超过一定阀值作为发送结束的标准,你所说的0X3A,0X0D0A应该在接受方根据间隔时间结束完一帧数据的接受后,用以对该帧数据进行功能解析时辅助所用,作用类似CRC校验码,如果接收方发现数据头不是0X3A,数据尾不是0X0D0A则视为收发错误,此时因为头尾地址确定,所以数据段内容即使出现这些字符也不会产生影响。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

150

主题

832

帖子

0

粉丝