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多秒!请高手帮忙。
一、消息帧格式:
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多秒!请高手帮忙。