We help IT Professionals succeed at work.

Auto detect Baud Rate

pneves asked
Medium Priority
Last Modified: 2008-03-06
I am looking for source code in C and/or assembly for PC under DOS, to automatically detect and set Serial-Communication parameters such as: BaudRate, Parity, DataBits and StopBits.
The idea is to connect any kind of equipment to the COM1: serial port of a PC and automatically detect these parameters whenever the equipment transmmits some bytes over the serial link.
Theoretically, it is possible to try and set the COM1 parameters to every possible combinations of (baudrate, parity,databits and stopbits) until no errors are detected!
I never tried this thoroughly because I never managed to automatically detect any error at all.
Any suggestions are welcome. An executable program would also be interesting (but not for 400 points)!
I suppose the DEC terminals VT220 can tackle this problem,
at least for baudrate...
Thanks in advance,
Paulo Neves
Watch Question

Most Valuable Expert 2014
Top Expert 2015

Is it known what bytes the the serial port will send?
(if not, it should be possible to send a series of 38.4 breaks
which looks like a peffectly valid 2400 baud 'A', and vice versa)
But I think I'd suggest an ioctl TIOCMGET, and watch TIOCM_SR in a fast loop
to see what the minimum pulse time is, quessing that represents a single bit
Most Valuable Expert 2014
Top Expert 2015



Thanks ozo!
The bytes that the serial port on the PC will receive are NOT known in advance. It will always be a numerical-control program source code though. Most of the bytes will be ASCCI, ISO or EIA codes of digits and of a few capital letters and Line feeds.
Possible Baud Rates are between 1200 and 19200, so 38400 is out!
The code is to be run on a PC with a 8250, 16450 or 16550 UART.
Code for the internal UART on the 8051 is not so interesting.
I am using Borland C 3.1 for DOS. I don't know what ioctl TIOCMGET and TIOCM_SR are :-(
On the second link you suggested, I suppose you mean "...autobaud" instead of "...autoload". I'll check these and tell you about them later.

try this http://www.iniaccess.net.au/pub/simtelnet/msdos/qbasic/qbbaud.zip

its in basic - but you could convert


Thanks Ronslow,
but the program you suggested -GetBaud- returns the current baud rate of either COM1 or COM2. What I want is completely different!
I want to attach a remote DTE to the serial port of a PC via a null-modem cable, run this program I am looking for (a kind of diagnosis program) on the PC, force the remote DTE to send some bytes over the serial link (usually some ASCII text) and have this diagnosis program on the PC to find out automatically which parameters (BaudRate, parity, data bits, stop bits) are being used by the remote DTE.
It does not need to be perfect but it could help me finding out these parameters. Something like this: for this parameter set (xxxx,x,x,x) the input looks like this "ksgksdf" for other set of parameters looks like that, and so on.
My problem is that, independently of the parameters I set my UART to, I have never been able to detect any errors at all. I suppose that if I use the wrong parameters I should be able to detect some errors such as "parity errors, overwrite, ..."...
Any suggestions?

If you set the UART to parity, you'll be able to detect errors. But you cannot use errors to differentiate between different speeds at no parity. And mostly, parity is not used.
Most Valuable Expert 2014
Top Expert 2015

Do you know enough about the expected input to know whether "ksgksdf" is a likely string?
As I said earlier, one message at one baud rate can look like a perfectly valid
different message at another baud rate.
Checking parity is just another way of seeing if the data you are seeing is among the set of expected data.
If you can now that, say, anything other than capital letters
digits and linefeeds
is invalid, and that there should be no more than 80 characters beween linefeeds,
you should be able to make a pretty good guess.
(how often does the equipment send data?)
You may also notice that certain wrong baud rate multiples may produce
data with certain recogniseable characteristics, this may also help your guess.


Thanks y96andha!
Unfortunately parity is used quite often on the machines I usually connect to the PC. (Most of them are old CNC machines with parameter-sets as strange as '4800,E,7,2'). The problem is that I usually do not have access to the operator's manual of these machines and just have to guess the parameters. Later I can show you the UART programming code that is NOT detecting parity errors, may be you could help then.

Thanks ozo (once again)!
I know almost exactly what the input looks like because I have access to this data by checking the CNC program on the CNC console, but, I cannot force it to be what I want because, usually the CNC editor will NOT allow me to make a program to look like a string of A's or anything similar. CNC programs have a very specific syntax and the rules must be followed, otherwise I won't be able to store the program and send it through the serial link.
Yes, one can assume that only digits, capital letters and LF are valid and that no more than 80 chars per line will ever be received.
The equipment sends data as often as I want. All I have to do is select a CNC program on the CNC memory and send it through the serial link as often as required.
I also read the file you pointed out on the second link you suggested but that code is only suitable for terminal handling on Unix machines. It didn't help much :-(
Thanks anyway.
Most Valuable Expert 2014
Top Expert 2015

Sorry I didn't pay enough attention to your OS,
I had gotten the impression you already knew how to set port speeds and test for errors.
Here are some examples of how to set the ports in DOS


I'd suggest trying different speeds and checking the input to see if it looks like a valid CNC program.
Or, if certain characters with one bit wide transitions are known
to occur regularly in CNC programs,
I might try using the fastest speed at which you can see those characters.

I guess at the programming level, all we can do is to guess a most likely configuaration, receive something, then check whether it seems to be the correct data, if not, change the settings and try again.  But this can cost several seconds so you will lose the first part of the data.  Maybe a the hardware level it is a quite easy job.

Do you use a modem to connect to the hosts?  If so, when connection the modem will automatically negotiate a baud rate and you need not worry about it.  The modem will tell you at what baud rate it is connected.


Thanks ozo,
I am currently inspecting your comments.

Thanks faster,
I am NOT using a modem! The PC and the "remote" equipment are close to each other. I can handle both machines and I said they are both DTE and are connected through a short null-modem cable.
I don't care if I miss part of the data. I just want the source to a dignosis program which could help me guessing the communication parameters being used by the "unknown" machine which is usually a CNC (Computerised Numerical Control).
What do you mean by an "easy job at the hardware level"? It is for this job I am offering 500 points!

Most Valuable Expert 2014
Top Expert 2015

Well, at the hardware level you don't need to keep trying different speeds,
but could look at the RD pin directly, interpreting it at
all possible baud rates simultaneously.
But you can sort of do this too, by starting at the highest possible rate,
and knowing what the data would look like when sent at a slow
speed and read at a higher one.
(you probably already have lots of samples of these)
If you can characterise them algorithmicly, say by frequency counts
of various characters or strings, then you should be able to
automatically infer the correct baud rate,
(and perhaps even translate what you see into what you would have
seen at the correct rate)


Thanks ozo,
"but could look at the RD pin directly, interpreting it at all possible baud rates simultaneously". How can I do this? I think this would be interesting and could effectively help me.
Your second suggestion may work fine if the other parameters are correctly set which is not the case, usually.
I still didn't check the links wou provided.

At the hardware level you just need to check the incoming signals, that is why a modem can automatically negotiate for the speed.
Most Valuable Expert 2014
Top Expert 2015

Modem speed negotiations usually means recognising the tones for
a particular protocol, then using that ptotocol to determine a speed based on the measured quality of the phone line...
On the DTE end, it usually depend on seeing a known sequence,
like "AT"

I don't see a way to look directly at the data pins in DOS,
the closest I thing I can see might be to set the speed about 16
times too fast and watching for a Break or Framing Error in the Line Status Register
and using their timeing to figure out what was being sent.

The other parameters may also give characteristicly recogniseable
patterns when they are wrong in known ways,
otherwise, you may just have to step through the possible setting
until you either recognise what looks like good data, or data
that looks wrong in a characteristic way.

It could get tricky if theres some data that your hardwars sends
that happens to look valid under two different settings.

When your CNC machines transmit data, does the data take up all the bandwidth? In other words, assuming the CNC machine was at 1200 baud, does the CNC machine send enough information to fuly utilise the baud rate?
If it does, or if you can arrange it so that that it does, then I think it is possible to simply check the rate of received characters at the PC end, e.g. CNC at 1200: sends data to PC. PC checks the rate at which characters are received. Is rate greater then would be possible at 300baud then baud rate must be greater than 300. And continue through the different baud rates.
After discovering suitable baud rate, go through Parity and Stop bit settings until the characters received are in allowable range, e.g. > '0' && < 'z' or whatever.

Don't know if this would work, but it is an idea...

Apparently the only solution is to test every possibility by the program and eliminate as mutch as possible. There are 90 possibilities.
5 speed * 3parity * 2 size(7/8bit) * 3 stopbits.
you don't told us about hardware/software flow control: Xon/Xoff/none. You may have to multiply by 3.

There are many informations on the input data you can use to eliminate things. Apprently you have letters that should never appear in the input. Build a 256 byte table holding a two state flag: forbidden/possible.
As soone as you get a forbidden character you can skip to the next port setting combination.

I bet you will get significant result with that straight forward method.

Now you wanted a smarter method.
It is possible if you know exactly what is the first character you should get in the input. Suppose your first character is 'A'.  
Set your port at maximum speed (19200) and 8 bit lenght. Inject 'A' at the different possible speed into the com port and save the outcome. You will have a signature giving you the speed. This signature is independent of the parity and stop bits setting. This is how ppl do here.

You should experiment how to infer about parity and stop bits once you have the appropriate speed by looking at two consecutive  byte input. I guess you need the correct speed then.

This should be fun to test.

Sorry I can't provide code, I don't have a DOS computer, nor Borland compiler. I don'tknow the call to set the ports parameters and how to get the read byte. I was told you have to fiddle with the bios interrupt calls.

Try this, with your own "int CheckChar( char, int);" function
to validate character & position pairs.

#include <stdio.h>
#include <bios.h>

void main(void)
  char data_bits[2]={_COM_CHR7,_COM_CHR8};
  char datac[2]={'7', '8'};
  char stop_bits[2]={_COM_STOP1, _COM_STOP2};
  char stopc[2]={'1', '2'};
  char parityc[3]={'n', 'e', 'o'};
  char baud_rate[4]={_COM_1200,_COM_2400,_COM_4800,_COM_9600};
  int  baudi[4]={1200, 2400, 4800, 9600};

  unsigned current_conf=0, max_conf=2*2*3*4, rem;
  unsigned ch, bit[16];
  int i, ok=0, cur_char=0;

       int data, stop, par, baud;
            ret=_bios_serialcom( _COM_INIT, 0, data | stop | par | baud );
       } while (!(ret & bit[5]));
       ret/=256; // look for an error
       if (ret >0)
            ch=_bios_serialcom( _COM_RECEIVE, 0, 0);
            ok=CheckChar(ch, cur_char);
            if (ok&&(cur_char>300))
              printf("\n>%4d, %c, %c, %c\n", baudi[baud],
                   parityc[par], stopc[stop], datac[data] );
       } while( ok );
  } while( !ok && (++current_conf<max_conf) );
  printf("Try again!\n");

   Best regards....

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.