Serial Communication Under DOS

Keywords: DOS, serial communication, RS 232, ASCII

Who should read this tutorial?

    For communication with external devices, PCs today have a lot of different ports that one can use (serial, parallel, USB). Unfortunatelly, there are not many books describing how to use them. As more external devices are being made available to the consumer (e.g. digital camera and scanners) it is ever more important to have a good understanding of how to connect the devices to a PC and program the ports. This tutorial will assist the reader in serial port programming.
    For this tutorial it is assumed that the reader:

   - wants to interface some device with a PC;
   - has some DOS experience;
   - has some C programming experience;
   - has a device which allows serial control (by receiving some ASCII characters).

    After reading this tutorial and downloading the .zip file, you should be able to establish a serial communication between a PC and an external device, or between two PCs. The estimated time to do this is about 1 day.

Motivation and Audience

   - Why serial communication?
   - What is RS 232?
   - What are the logic levels in serial communication?
   - Are there more serial communication protocols, or just RS232? Which are others?
   - What I really need (I just want to try) for a serial communication?
   - Do I really need to be an expert programmer to set up a serial communication, or these things are not so complicated?
   - What I need is just a practical approach of serial communication and some sheared code to set it up.

    In comparison with parallel communication, serial communication has some certain advantages:
   - serial communication doesn't need as many wires as parallel transmission,
   - in serial communication, the cables can be longer than the ones used in parallel transmission,
   - because of voltage levels used in serial communication the serial transmission is offering better protection against perturbations.

    RS 232 is a standart in serial communication. An 8 bit word is transmitting one after other. The first bit sent is LSB. Some other bits are attachet to the useful bits. These bits are: START BIT, STOP BIT and some parity bits. The START BIT is the first bit sent. Then the useful package of bits are following (LSB first). The last bit sent is STOP BIT. In RS 232 standard an "1" is transmitted as -3 to -25 volts and "0" as +3 to +25 volts.
Some other standard for serial communication are RS 422, RS 423, RS 485.
         To establish a serial communication you can connect to PC some external devices like:





  a DSP Board,

  



  a Microcontroller System (for a Brushless DC Motor)

  



  a Pan Tilt Head (PTH)

  









But, the easiest way to establish a serial communication is using two PCs. To connect two PCs all what you need is a serial cable and a null modem.





  serial cables,

  



  null modem,



  

   To buy a serial cable or a null modem you can try Radio Shack or Jameco. If you don't exactly know what is a "null modem" don't worry. Once you have the serial cable and the null modem (see pictures above) everything should be ok. More than that, you will see that you do not need to be an expert programer to set up a serial communication. The next thing you need is a Turbo C compiler. Turbo C compiler which can be free downloaded. Download Turbo C compiler (following the link) and instal it in "c:\borlandc". After that, create a folder at your C drive, name it scon and download in the "scon" folder serial.zip file. Unpack the .zip file in your folder. After unpacking you should see in the folder following files: ibmcom1b.c , Ibmcom1b.obj, Ibmcom3.c, Ibmcom3.h, ibmcom3.obj, Scon1_1.c, which is the program you may need to modify and re-compile, Scon1_1.exe , the .exe file for source file and Scon1_1.obj - the object file. Connect two PCs using a serial cable and null modem. To set up the connection (to make sure that everything is OK) use can use Hyperterminal . Install Hyperterminal and open it on both PCs.





























Click on "Yes". A new window will open.

Give any name to your connection and press OK after. A new window will open.

Press again OK and another window will open.



Choose here a value for "Bit per second" field (for example 34800). For "Flow control field" choose "None". After establishing serial communication (now you are sure that because of hardware point of view, everything is OK), close Hyperterminal program from one PC and compile scon1_1.c (which is in serial.zip file). The first step to compile the .c file is to open a DOS window (see picture below).



Than you have to go into scon folder. To do this tupe "cd\" and press "ENTER". Now type "cd scon" to go into scon folder. To open the .c file type "tc scon1_1.c". To compile the .c file, first close Turbo C compiler and (in DOS window) type "c:\borlandc\bin\bcc -ml scon1_1.c ibmcom3.obj". The program should run in an infinite loop (wairting for receiving characters) until you will press a key. The try to type some characters from other PC. Because the program will select numbers and commas from characters you send, try to type numbers.

DOS Turbo C code

    Note: download serial.zip from here rather than cutting and pasting from below. This program is useful to receive ASCII characters (the program will select from all received characters just numbers) from serial port, converting into numbers and displaying on the screen.

     /*
FILE: c:\c_work\scon\scon1_1.c WORKS!!!!!!!
AUTH: R.STANCIU

DESC: scon1_1.c reads and the serial port, convert the incoming character into integers and prints the integers to screen. The source (the device which is sending the characters to serial port) is Newton board.
DATE: 02/02/02 18:18 - scon1_1.c
STAT: 1.1: Use ibmcom3.obj
           1.2: Use the success of c:\c_work\pt1_4.c
           Note: Compiling will require the ibmcom3.obj, ibmcom3.h
           1.3: The file is reading the serial port (source for serial port is Newton board) and the incoming characters are converted in integers
           1.4: IMPORTANT!!!! this version is working properly if Newton board is sending only one coordinate (x or y).
REFS: pt1_4.c which was modified
NOTE: Compile with "c:\borlandc\bin\bcc -ml scon1_1.c ibmcom3.obj"
*/


/* Defines required for serial i/o */
#define COM_PORT 1       /* serial port number */
#define SPEED 38400L       /* baud rate = 38400 */
#define CR 0x0d
#define LF 0x0a
#define ESC 0x1b
#define BEEP 0x07

#include< stdio.h >
#include< ctype.h >       /* required for the isalnum function */
#include< stdlib.h >
#include< conio.h >
#include< math.h >
#include< dos.h >
#include "ibmcom3.h"       /* for serial */

/* Prototypes */
void comm_setting(void);       /* Set com port */
void close_com(void);       /* Close com port */

int main(void) {

int k, x, i;
/* defining parameters for serial port part */
unsigned char charFromNewton;
char buffer[80];
char o[10];

printf("1. Setting for serial port\n");
comm_setting();       /* initializing communication */
printf("Serial port initialized\n");

k=0;
printf("Entering while loop...\n");
while(1) {

/* Read a char from serial port. If a key is pressed close serial port and abort communication*/
do {
charFromNewton = com_rx();       /* Note: 0X7F is "DEL" char. Receive data from com_port */
if(kbhit()) {                    /* If a key is hit then gracefully exit by closing the port first*/
  close_com();        /*Close serial port*/
  printf("Bye!\n");
  exit(0);
                }
      }

while( !isalnum(charFromNewton) && (charFromNewton != 0x20) && (charFromNewton != 0x2C) );
/* 0x20 ASCII for space and 0x2C is ASCII for comma */

if( isalnum(charFromNewton) ){      /* check if the income character is a number (remember that it can be a number a comma or a space)*/
  o[k] = charFromNewton;            /* if I have a number (character type) I will keep it in a char type matrix*/
  k++;
  if ( k ==3 )                        /* If I received three of ASCII characters (which represent numbers) then I will procede to convert them into integers*/
      k=0;
  x = atoi(o);                        /* here take place the conversion from character string to integers*/
  printf("\nx=%d \n", x);       /* print to screen the omtained integer*/
}

else k=0;
}         /* end of while motion loop */
printf("while loop finished... kill serial port\n");

/* Finished with serial port so close it */
close_com();

printf("Exiting program\n");
return (0);
}       /* end of MAIN */

/**************************************************************************/
void comm_setting(void)
{
  int dummy;
  dummy = com_install(COM_PORT);
  if ( dummy != 0 )
    {
    switch (dummy)
    {
      case 1 : printf("Invaid port number\n"); break;
      case 2 : printf("No UART fot specified port\n"); break;
      case 3 : printf("Drivers already installed\n"); break;
      default : printf("Err #%d\n", dummy); break;
    }
    exit(1);
  }      com_raise_dtr();
com_set_speed(SPEED);
com_set_parity(COM_NONE, STOP_BIT_1);
}

/**************************************************************************/
void close_com(void)
{   com_lower_dtr();   com_deinstall(); }

Code Description

    The program part which is reading serial port is placed in an infinite loop (while(1)). For those which not very familiar with Turbo C syntax, isalnum is defined in ctype.h and allows to check if income character is a number or a letter.

The statements:

    do {
    charFromNewton = com_rx();
    if(kbhit()) {
        close_com();
        printf("Bye!\n");
        exit(0);
                }

        }

use function com_rx();to read serial port. This function is placed in a loop to force the program to read serial port until a character is received. In the same time, program is testing is any key is pressed (if(kbhit())). If any key is pressed the program will call close_com(); function to close the serial port.
After a character is received, the program will check if the income character is a number, a space or a comma (the DSP board I use for serial communcation sent me both numbers and commas). The statement which check this is

while( !isalnum(charFromNewton) && (charFromNewton != 0x20) && (charFromNewton != 0x2C) );

Note: This checking was important for my application. It might not be important for you so you can remove it.

The following part of code is what I used to convert a group of characters to an integer.

if( isalnum(charFromNewton) ){
o[k] = charFromNewton;
k++;
if ( k ==3 )
k=0;
x = atoi(o);
printf("\nx=%d \n", x);
}


First of all I check if incoming character is a number (remember it can also be a comma or a space). The instruction which is checking if indeed the character is a number is if( isalnum(charFromNewton) ). If indeed the character is ASCII code for a number, then I inscribe it into a character matrix
o[k] = charFromNewton;. Basically I am "waiting" to receive three characters (ASCII code for numbers). To count this I am using a variable k. Once I already received three characters, I use atoi function to convert the string formed with these three caracters into an integer (e.g. the string formed using characters 1,2,3 will be 123 as an integer). If the character I received is not ASCII code for a number, the program will continue to "read" the serial port until another cahracter is received.


Final Words

     As you can see, this program is not so complicated. Connecting together two PC's and try to receive some ASCII characters using this program should be enough easy to perform even for people who are not "expert programmers". Normally, you should not have any problem setting up such a communication.
Anyway, if there are any problems, please do not hesitate to email me.