删除吧!!! (300分)

  • 主题发起人 delphiroad
  • 开始时间
D

delphiroad

Unregistered / Unconfirmed
GUEST, unregistred user!
有一个喷墨机的控制通讯协议,其链路层的描述大致如下:

一、消息帧格式:
STX 帧序号 应用帧长度 应用消息帧 检验和
02h # LSB|MSB XXXX LSB|MSB
1 byte 1 byte 2 byte 2 to 1023 bytes 2 bytes

二、应答帧格式
ACK or NAK 帧序号
06h/15h #
1 byte 1 byte

三、消息帧发送过程:
retry_counter=0
帧序号加一
:送出消息帧
等待,在[maximum-valid-message-acknowledge-time]毫秒内有三个可能的结果:
1、如果出现超时:
Increment retry_counter
如果retry_counter等于[maxinmum-transmissions](最大重发次数),则:
Increment Message_Cancel_Err_Count
End(Transmission failed)
否则
回到“:送出消息帧”(即帧序号不变的情况下重发此帧)
2、获得应答帧,但帧序号与发出的消息帧不相等,则
Increment Ack_Err_Count
Increment retry_counter
如果retry_counter==[maxinmum-transmissions],则:
Increment Message_Cancel_Err_Count
End(Transmission failed)
否则
回到“:送出消息帧”(即帧序号不变的情况下重发此帧)
3、如果获得的应答帧正确(应答帧的序号与发出的消息帧一致),则
End(transmission succeeded).

四、帧接收过程:
1、首字符显示非帧(stx or ack),则其后的所有字节均舍弃,直到在
[minimum-inter-message-packet-delay-time]所规定的时间内再无字节接受为止;
然后继续侦听下一个帧的首字节。以此来保证在出现通讯错误或断开之后的重新同步。
2、校验和或长度无效,则舍弃并发送NAK应答。
3、合法的帧,将把帧序号和上次接收的帧序号比较:
相等:证明发送者并没收到ACK,Repeat_Err_Count加一,并再次应答,
但不再传递给应用层;
大一:ACK应答并传递给应用层;
其它值:证明有侦丢失了,TAC_Err_Count加一,ACK应答并传递给应用层。

五、传输冲突
如果主机(host)和喷墨机同时想发送消息帧,则喷墨机发出的消息帧优先。
是这样实现的:
host在发送消息帧的每个字节之前,先检测是否有接收的数据,
如果有,则放弃剩下的发送并在应答之后再重新发送整个帧。
喷墨机则在发送消息帧期间放弃所有接收到的字节。

以上协议用delphi非常非常的难以做到,但我又不懂汇编。我是用MsComm控件来作的,
在发送消息帧时如何即判断是否接收到了,又判断是否超时,在允许的情况下还要重发。
并且上面所提到的[maximum-valid-message-acknowledge-time]和
[minimum-inter-message-packet-delay-time]都是一个很小的值(如10ms)因此我觉得用
高级语言很难做到实时、准确,且太多的循环和线程均会导致效率低下,像我编的,发送
一个帧,10ms超时,最大5次重发,按理最多50ms之后就可以收到发送失败了,但是我足足
等了20多秒!请高手帮忙。
 
主要问题是什么,是在协议的实现上(这对于汇编和Delphi是一样的,且肯定Delphi更简单),
还是在性能上(这方面Delphi和汇编是有差异的)?

你把串口速率设大一点不行吗?
 
我觉得不是高级语言的效率问题, 而且根本不需要太多的循环和线程. 应该
有发送和接收2个线程就可以了, 循环也不应该有太多.
 
和速率等没关系,比如说帧发送,我的做法是:
在一个线程里用一个死循环不断的读串口的接收缓冲,如果有字节接收,则跳出死循环,
该线程随之结束。而在主线程中WaitSigleObject来等待读串口的线程,并且设有超时。
如果超时为10ms,最多重发5次的话,由于读串口的线程中是个循环,而主线程又要等待
该线程的结束,我不知到怎么回事,但就是慢的要死。把串口速率设大一点每次发送能
提高10秒钟吗?
 
》》在一个线程里用一个死循环不断的读串口的接收缓冲
用poll的方式太费资源,最好用中断方式。不过以现在机器的性能,可能影响不大。

》》如果超时为10ms,最多重发5次的话,由于读串口的线程中是个循环,而主线程又要等待
》》该线程的结束,我不知到怎么回事,但就是慢的要死。把串口速率设大一点每次发送能
》》提高10秒钟吗
提高几个毫秒(ms)即可,拿用得着10秒?或者把超时设得大一点,如1秒。
 
不要太多的循环,OK,我试过只有一个循环的,发送的时候我试过这种:
发送之后,进入一个循环,这个循环不断的判断两个标记:是否收到应答帧和是否超时的
标记。MsComm控件的OnComm事件中添加接受代码,当接受时将是否收到应答帧标记置为True
在OnTimer(超时计时器)事件中添加接受代码,当超时时将是否收超时标记置为True,
这样在循环中就可以进行相应的判断。但由于循环影响了Timer控件和MsComm的事件反应
,所以我又在循环中加入application.processmessage来让两个事件能反应,但效率依然
极低!

 
是不是你把超时设得太短了,10ms是很短的,而串口速率较慢。而且看你的意思似乎把10ms当成10s了,你把
超时改成10s,传输肯定不会有问题。
 
使用WaitForsingleObject函数进行等待,如果收全则将标志位置位,可以实现此功能。
 
我实现了,关键在于同步和异步!!用同步就可以了!
咳!怎么每次都是我自己解决的!!
版主看着办吧!
 
很简单的协议,用SPCOMM控件直接发数据就行了,给你几个常量
STX = $02;
ETX = $03;
ESC = $1B;
SYNC = $16;
 
多人接受答案了。
 
顶部