Click to See Complete Forum and Search --> : Need Serial Comm Expert! Intercharacter delay problem


Randy C
April 24th, 1999, 12:27 PM
This is going to be a tough nut to crack. I built up multithreaded serial Comm drivers, using the model Allen Denver presented in his Multi Threaded MTTTY example, on the Microsoft Knowledge base. It works fine. but there are some instances where I need to talk to very primitive devices, and a delay is needed between characters that I write to the port. Interestingly, the baud rate does not make a significant difference. Anywhere from 57.6K baud down to 9600, I still need an intercharacter delay of at least 250 microseconds to make it work. This is where the problem comes in. The messages I need to send are 25 byte packets, and there are lots of them to complete a "download". So simply doing a "Sleep" between Write calls is no good. I don't know what the specification is, but as near as I can tell, Sleep(1) doesn't seem to resolve to less then 10 milliseconds at best. That makes the download take forever. I've tried brute forcing a delay between write calls, by doing the obviously horrendous practice of waiting in a loop, using the multimedia timeGetTime() call. That works better, since timeGetTime() does resolve to a millisecond, at least on Win 95. By keeping my application thread at a slightly lower than normal priority, and keeping the Write thread at HIGHEST_PRIORITY, this kludge works wiithout impacting the system too badly. But it still falls apart once I try to go below 3 milliseconds. At that point, the overlapped events seem to pile up, and garbage comes out of the port. Maybe Overlapped I/O was not a good idea for Writing, but it is needed for robust reading, and the portt can't be opened both ways at once.

This is nonsense. I have a DOS version of the same program I'm porting that easilly forces a 1 millisecond delay between writes to the COMM port. While my above kludge works, 3 milliseconds is overkill for intercharacter delay, and the performance is still only about 10% of the DOS version. With all the COMM port handshaking features built into the operating system, how is it that such a simple feature as character delay has been left out? Am I missing something? It really should be done at a low level. Using a scope, I can see that even a 1/4 millisecond (250 uS) delay would work. Yet the API provides no apparent way to tap into the many high frequency counters that must be available in your average machine running at hundreds of MegaHertz.

Can anyone think of a strategy for doing a character delay, at least down to (an actual millisecond)? I'm not afraid to get down to the interupt and driver level if I have to, but an off the shelf solution would be nice, even if I have to buy it.

Thanks









--Randy C
* * * Second star to the Right!

Gomez Addams
April 25th, 1999, 11:57 AM
Hans W. wrote a delay function that might be able to help.
It is in the misc section and is called Microsecond Delay.
Another possibility is to check intel's site at http://developer.intel.com
where they have app notes on how to use the high performance
counters and other curious things.

Randy C
April 26th, 1999, 01:10 AM
Thanks. I did look into it. Judging by the brute force approach of creating timed assembly loops, I can see this is not so easy. But one of the comments on that article mentioned the use of QueryPerformanceCounter() which looks like it might be helpful too. I wasn't able to find anything on that intel site though.

--Randy C
* * * Second star to the Right!

Dieter Fauth
April 26th, 1999, 02:23 AM
Hi Randy,
did you try to increase the number of stop bits? The Stop bits are nothing else than a pause between transmittions. For 9600 you'll get about 100 uS per bit whivh might not enough in your case, but give it a try. Default in the PC world is 1 stop bit, while other often use 2 stop bits. From my recal there a re some UART chips with up to 4 stop bits, I think the 16c550 only supports a max. of 3.
If this does not help you might consider to write your own comm port driver based on the DDK sources.

I guess the required delay is caused by slow interrupt proccessing or even polling mode in your slave devices. I assume you cannot change anything there.

Good luck,

Dieter Fauth :-)

Gomez Addams
April 26th, 1999, 01:13 PM
There is an article on this site in the misc section called 'High Resolution Timing'
that illustrates using QueryPerformanceCounter. Apparently the performance
counter is not available on all of the 'compatible' processors. There is an article
on the intel site at http://developer.intel.com/drg/pentiumII/appnotes/RDTSCPM1.HTM
about using the RDTSC instruction that might be helpful.

straight on til morning

Randy C
April 26th, 1999, 05:04 PM
Yes... actually, at 9600 baud, going to 2 stop bits solved the problem. But at higher speeds it does no good. The problem is that the device I'm talking to does have a high speed UART, but it is being polled instead of handled by an interupt when it is in the "program" mode. Fortunately, there is only one device like this I have to worry about, but it just burns me that my DOS version beats the 32 bit Windows version hands down. I've had some better success in the last few days re-aranging my loop to get a 1 ms delay with timeGetTime(), and the 1ms is at least tollerable. Trouble is, on NT timeGetTime() resloves to 5mS, and at that point, the download speed will be unbearably slow.

As I said though, an intercharacer delay is a very old problem, so before I attempt hacking low level drivers, let me see if someone has already invented this wheel. BTW... do you (or anyone) know exactly what Sleep(1) resolves too? I definatly seems a far cry from a millisecond.


--Randy C
* * * Second star to the Right!