叮
叮叮当当
Unregistered / Unconfirmed
GUEST, unregistred user!
我是搞工控的,写串口通信程序几年了,但是一直没能解决这个问题。<br><br>搞过工控的朋友应该知道,在422多机通讯时(一台计算机与多台单片机通讯),需要使用串行口的RTS来控制数据的发送。网络中的某台机器需要发送数据时,先把RTS打开,数据发送完毕后,关闭RTS,同一时刻只能有一台机器打开RTS发送数据,否则就会造成发送冲突。<br><br>因此需要在发送前打开RTS,这是很简单的,因为程序知道何时开始发送数据,但是在发送完后要及时关闭RTS,这却很难做到,因为Windows下的串行通信,好像都是把要发送的数据塞到Windows的串口缓冲区里面,Windows的驱动程序会自动完成缓冲区内数据的发送,具体什么时候完全发完,就不得而知了。<br><br>我用过很多串行通信控件,它们一般都有个发送缓冲区空的事件(比如TMS Async32控件是OnTxEmpty()),但是当这些事件触发时,只不过是发送缓冲区空了,可能串行口还在把最后的数据一位一位地移出呢,数据并没有真正的发送完毕,如果这时关闭RTS,就会造成最后一些数据无法正确发出,目标机器就会遗漏这些数据。我采取的做法是在发送函数返回后,或者发送缓冲区空事件中,人为延迟一段时间,再关闭RTS。这样虽然可以勉强过关,但发送的数据长度和波特率不同,就会造成所需的延迟时间不同,这很难准确计算。更糟糕的是,Windows的运行速度、程序的优先级似乎都会对一批数据的发送时间造成影响,靠估算最后数据的发出时间,实在很渺茫。因此我需要一个也许是底层的方法,来得到数据真正发送完毕的通知。<br><br>其实串口内部有一个移位寄存器,通过端口操作对这个寄存器的状态进行判断,就能知道数据有没有发送完毕。以前在DOS下用汇编语言进行串口编程的时候,发送和接收缓存由应用程序自己实现,每次只发送和接收1个字节,就是通过判断这个移位寄存器的状态来保证当1个字节完整发送完毕之后才再发送剩余的字节。现在Windows完全接管了对硬件的直接控制权,自行实现串口硬件的发送和接收操作,和访问这个移位寄存器都成了不可能的事。。