Advertisement

02.14.2006 at 05:06AM PST, ID: 21735899
[x]
Attachment Details

Hardware Flow Control over RS232 (Serial) in DOS

Asked by john_ws in C Programming Language

Tags: control, flow, rs232, hardware, serial

I know the rules state that I'm not allowed to let you answer this question for me, since it's for school. But directing me in the right way would be more than helpful.

Basically I have a lab from last semester that is basic communication over serial using a defeated Null Modem Cable, but now we are given a full handshake cable (with CTS and RTS lines, etc) and must implement hardware flow control (and modify the old lab to allow this). What I know is that we must use CTS (Clear to Send), RTS (Request to Send), MCR (Modem Control Register), and MSR (Modem Status Register) to accomplish this.

It is surprisingly difficult to find examples in C (especially for DOS) of how exactly to do this. We were never actually taught this and it was one of those "research this on your own time" type of things.

If it helps, here is the code from last semester, just to give you an idea of what functions and includes we are using (conio.h, outportb(), inportb(), etc). WARNING: LONG CODE UP AHEAD!

====================================================

 /* Included Libraries */

#include <conio.h>
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/* Key Defines (ESC, F1, F2, F3, F4, F5) */

#define KEY_ESC       27
#define KEY_F1             59
#define KEY_F2             60
#define KEY_F3             61
#define KEY_F4             62
#define KEY_F5             63
#define KEY_F6            64
#define KEY_F7            65

/* Defines */

// COM1 0x3F8
// COM2 0x2F8
// COM3 0x3E8
// COM4 0x2E8

#define WALK_SIZE       80    /* Length of walking string   */
#define MAX_STRING      32    /* Max lengt of input strings */
#define BUFFER_SIZE       1024  /* Max buffer size for rx in  */

#define S_PORT             0x3f8 /* Serial port  */
#define INTMASK       0x21  /* Interrupt Mask */
#define INTVECT            0x0C  /* Interrupt Vector */

#define IER             ( S_PORT + 1 ) /* Interrupt Enable Register */
#define IIR             ( S_PORT + 2 ) /* Interrupt ID Register     */
#define LCR             ( S_PORT + 3 ) /* Line Control Register     */
#define MCR             ( S_PORT + 4 ) /* Modem Control Register    */
#define LSR             ( S_PORT + 5 ) /* Line Status Register      */
#define MSR             ( S_PORT + 6 ) /* Modem Status Register     */
#define DLAB_LOW       ( S_PORT + 0 ) /* DLAB Low Bit              */
#define DLAB_HIGH       ( S_PORT + 1 ) /* DLAB High Bit             */
#define DLAB             0x80  /* Divisor Latch Access Bit */

#define SBITS1             0x00  /* Stop Bits (1)       */
#define SBITS2             0x04  /* Stop Bits (2)       */

#define NBITS7             0x02  /* Data Bits (7)       */
#define NBITS8             0x03  /* Data Bits (8)       */

#define EVENPARITY       0x18  /* Parity Bits (EVEN)  */
#define NOPARITY       0x00  /* Parity Bits (NONE)  */
#define ODDPARITY       0x08  /* Parity Bits (ODD)   */
#define SPACEPARITY       0x38  /* Parity Bits (SPACE) */
#define MARKPARITY       0x28  /* Parity Bits (MARK)  */

#define BR37      0xC00       /* Baud Rate (37)      */
#define BR75      0x600       /* Baud Rate (75)      */
#define BR150     0x300       /* Baud Rate (150)     */
#define BR300         0x180       /* Baud Rate (300)     */
#define BR600         0xC0        /* Baud Rate (600)     */
#define BR1200         0x60        /* Baud Rate (1200)    */
#define BR2400         0x30        /* Baud Rate (2400)    */
#define BR4800         0x18        /* Baud Rate (4800)    */
#define BR9600         0x0C        /* Baud Rate (9600)    */
#define BR19200   0x06        /* Baud Rate (19200)   */
#define BR38400   0x03        /* Baud Rate (38400)   */
#define BR57600   0x02        /* Baud Rate (57600)   */
#define BR115200  0x01        /* Baud Rate (115200)  */

/* Start of Global Variables */

int             bufferpos,      /* Keep track of current buffer position. */
            currentbuf;

char             receivebuffer   [ BUFFER_SIZE ], /* Receive Buffer.        */
            argument       [ MAX_STRING ],       /* Command line arguments */
            setting        [ MAX_STRING ],  /* Left side of a=b arg.  */
            value              [ MAX_STRING ];  /* Right side of a=b arg. */

unsigned long int baudrate       = BR2400,       /* Default Baud value     */
              numbits        = NBITS8,       /* Default Data bit value */
              numstopbits       = SBITS1,        /* Default Stop bit value */
              parity      = ODDPARITY;       /* Default Parity value   */

/* Function Prototypes */

void interrupt rxchar ( void );
void interrupt ( * old_int ) ( );

void parse_string ( void );
void parse_params ( void );
void walk_pattern ( void );

/* Our Main */
int main ( int argc, char *argv[] )
{
      int i;
      char chartoprint, txchar;

      printf ( "\n" );

      /* If there is at least one arguments from the command line, *
       * and no more than 4, then let's parse them.                */
      if ( argc >= 2 && argc <= 5 )
      {
            for ( i=1; i < argc; i ++ )
            {
                  /* Copy each arg to "argument", and then first     *
                   * parse the string to get the setting and value.  *
                   * Then pass both to parse_params which takes care *
                   * of all the input parameters.                       */
                  strcpy ( argument, argv[i] );
                  parse_string ( );
                  parse_params ( );
            }
      }

      /* Otherwise, there are no parameters, or too many. So just use     *
       * default values.                                        */
      else
      {
            printf ( "\n" );
            printf ( "No parameters were entered.\n" );
            printf ( "Using default.\n\n" );
      }

      /* Print of the Hex values of all the Serial Port values */
      printf ( "Baud Rate:      0x%x\n", baudrate );
      printf ( "Parity:         0x%x\n", parity );
      printf ( "Stop Bits:      0x%x\n", numstopbits );
      printf ( "Number of Bits: 0x%x\n\n", numbits );

      disable ( ); /* Disable interrupts while we prepare the serial port. */

      /* Preparing the serial ports */
      outportb ( IER, 0x00 );

      old_int = getvect ( INTVECT );
        setvect ( INTVECT, rxchar );

      outportb ( LCR, DLAB );
      outportb ( DLAB_LOW, baudrate );
      outportb ( DLAB_HIGH, 0x00 );
      outportb ( LCR, numbits | parity | numstopbits );
      outportb ( IIR, 0xC7 );
      outportb ( MCR, 0x0B );
      outportb ( INTMASK, ( inportb ( INTMASK ) ) &0xEF );
      outportb ( IER, 0x01 );

      enable ( ); /* Renabling interrupts since we're done preparing */

      do
      {
            //rxchar (); /* Polling the serial ports for new characters */


            delay ( 10 );

            /* If the buffer position that has been read, does not    *
             * equal the current buffer position (of the available    *
             * read in buffer), then we have to read it in.           */
            if ( bufferpos != currentbuf )
            {
                  /* Get the character to print from the buffer */
                  chartoprint = receivebuffer [ currentbuf ];

                  /* Increase the buffer position */
                  currentbuf++;

                  /* If the position is over the buffer size, wrap around */
                  if ( currentbuf >= BUFFER_SIZE ) currentbuf = 0;

                  /* If the host has sent the F5 key, they are requesting *
                   * to clear our screen. So let's clear it.              */
                  if ( chartoprint == KEY_F5 ) system ( "cls" );

                  else printf ( "%c", chartoprint );

            }

            /* If there is a character being pressed on the keyboard .. */
            if ( kbhit ( ) )
            {
                  txchar = getch ( );

                  switch ( txchar )
                  {
                        case KEY_F1: walk_pattern (); break;
                        case KEY_F2: disable (); break;
                        case KEY_F3: enable (); break;
                        case KEY_F4: system ("cls"); break;
                        case KEY_ESC: break;

                        default: outportb(S_PORT, txchar);
                  }
            }
      } while ( txchar != KEY_ESC );

      outportb ( IER, 0 );
      outportb ( INTMASK, ( inportb ( INTMASK ) | 0x10 ) );
      setvect ( INTVECT, old_int );

      return 0;
}


/* Send 80 characters of our walking pattern. */
void walk_pattern ( )
{
      int thischar = 'A', i;

      for ( i = 0; i < WALK_SIZE; i ++ )
      {
            outportb ( S_PORT, thischar );
            thischar ++;
      }

      return;
}


/* Parse the args that were passed in from the command line
 * that were in the format setting=value. */
void parse_string ( )
{
      int counter1 = 0, counter2 = 0;

      while ( ( argument[counter1] != '=' ) && ( argument[counter1] != '\0' ) )
      {
            setting [counter1] = argument [counter1];
            counter1++;
      }

      setting [counter1] = '\0';
      counter1 ++;

      while ( argument [counter1] != '\0' )
      {
            value [counter2] = argument [counter1];
            counter1 ++;
            counter2 ++;
      }

      value [counter2] = '\0';
}


/* After we have parsed the paramters from the command line, we can
 * now get these values and place them in our serial port parameter
 * variables */
void parse_params ()
{
      long int baud_in,
             stop_in,
             parity_in,
             bytes_in;

      if ( !strcmp ( setting, "baud" ) )
      {
            baud_in = atoi(value);

            if ( baud_in == 37 ) baudrate = BR37;
            else if ( baud_in == 75    ) baudrate = BR75;
            else if ( baud_in == 150   ) baudrate = BR150;
            else if ( baud_in == 300   ) baudrate = BR300;
            else if ( baud_in == 600   ) baudrate = BR600;
            else if ( baud_in == 1200  ) baudrate = BR1200;
            else if ( baud_in == 2400  ) baudrate = BR2400;
            else if ( baud_in == 4800  ) baudrate = BR4800;
            else if ( baud_in == 9600  ) baudrate = BR9600;
            else if ( baud_in == 19200 ) baudrate = BR19200;
            else if ( baud_in == 38400 ) baudrate = BR38400;
            else baudrate = BR2400;
      }

      if ( !strcmp ( setting, "stop") )
      {
            stop_in = atoi ( value );
            if ( stop_in == 2 ) numstopbits = SBITS2;
            else numstopbits = SBITS1;
      }

      if ( !strcmp (setting, "bits") )
      {
            bytes_in = atoi ( value );
            if ( bytes_in == 7 ) numbits = NBITS7;
            else numbits = NBITS8;

      }
      if ( !strcmp(setting, "parity" ) )
      {
            if ( !strcmp ( value, "even" ) ) parity = EVENPARITY;
            else if ( !strcmp ( value, "none" ) ) parity = NOPARITY;
            else if ( !strcmp ( value, "space" ) ) parity = SPACEPARITY;
            else if ( !strcmp ( value, "mark"  ) ) parity = MARKPARITY;
            else parity = ODDPARITY;
      }
}

/* Polling the serial port for new available data */
void interrupt rxchar()
{
      int checkport = inportb ( LSR );

      while ( checkport & 1 )
      {
            if ( bufferpos >= BUFFER_SIZE ) bufferpos = 0;
            receivebuffer [bufferpos] = inportb ( S_PORT );
            bufferpos ++;
            outportb ( 0x20 , 0x20 );
            checkport = inportb ( LSR );
      }
}

====================================================


I know the parsing and stuff is pretty ugly (using global variables and all). This was actually modified from basic template we were given, so don't blame that on me :P

Basically all this does is allows you to enter certain baudrates and parity bits etc, if you want to. If you don't, it will use a default value. Then it will communicate with the other machine over COM1 using the Null Modem cable.

What I'm asking is what type of code would I have to add to implement hardware flow control? I am terrible with this communication stuff, so any examples or guides you can direct me to would be great.

Thank you.Start Free Trial
 
Loading Advertisement...
 
[+][-]02.14.2006 at 05:44AM PST, ID: 15950759

Often, when Experts are collaborating with members who have asked questions, they will request additional information about the problem. Askers respond with an author comment like this one.

Start your 7-day free trial to view this Author Comment or ask the Experts your question.

 
[+][-]02.14.2006 at 07:52AM PST, ID: 15951829

At Experts Exchange, members can ask their questions to thousands of technology professionals, also known as Experts. Experts compete and collaborate to answer those questions by leaving comments like this one.

Start your 7-day free trial to view this Expert Comment or ask the Experts your question.

 
[+][-]02.14.2006 at 08:27AM PST, ID: 15952264

Often, when Experts are collaborating with members who have asked questions, they will request additional information about the problem. Askers respond with an author comment like this one.

Start your 7-day free trial to view this Author Comment or ask the Experts your question.

 
[+][-]02.14.2006 at 09:49AM PST, ID: 15953030

At Experts Exchange, members can ask their questions to thousands of technology professionals, also known as Experts. Experts compete and collaborate to answer those questions by leaving comments like this one.

Start your 7-day free trial to view this Expert Comment or ask the Experts your question.

 
[+][-]02.14.2006 at 10:04AM PST, ID: 15953151

Often, when Experts are collaborating with members who have asked questions, they will request additional information about the problem. Askers respond with an author comment like this one.

Start your 7-day free trial to view this Author Comment or ask the Experts your question.

 
[+][-]02.14.2006 at 01:23PM PST, ID: 15954998

At Experts Exchange, members can ask their questions to thousands of technology professionals, also known as Experts. Experts compete and collaborate to answer those questions by leaving comments like this one.

Start your 7-day free trial to view this Expert Comment or ask the Experts your question.

 
[+][-]02.14.2006 at 01:48PM PST, ID: 15955292

View this solution now by starting your 7-day free trial. Setting up your free trial is quick, easy, and secure. We will return you to this solution, unlocked, when you're done.

 

About this solution

Zone: C Programming Language
Tags: control, flow, rs232, hardware, serial
Sign Up Now!
Solution Provided By: billtouch
Participating Experts: 3
Solution Grade: A
 
 
[+][-]02.14.2006 at 04:36PM PST, ID: 15956628

Often, when Experts are collaborating with members who have asked questions, they will request additional information about the problem. Askers respond with an author comment like this one.

Start your 7-day free trial to view this Author Comment or ask the Experts your question.

 
[+][-]02.15.2006 at 05:47AM PST, ID: 15960061

At Experts Exchange, members can ask their questions to thousands of technology professionals, also known as Experts. Experts compete and collaborate to answer those questions by leaving comments like this one.

Start your 7-day free trial to view this Expert Comment or ask the Experts your question.

 
[+][-]02.15.2006 at 05:52AM PST, ID: 15960101

At Experts Exchange, members can ask their questions to thousands of technology professionals, also known as Experts. Experts compete and collaborate to answer those questions by leaving comments like this one.

Start your 7-day free trial to view this Expert Comment or ask the Experts your question.

 
[+][-]02.15.2006 at 06:32AM PST, ID: 15960449

At Experts Exchange, members can ask their questions to thousands of technology professionals, also known as Experts. Experts compete and collaborate to answer those questions by leaving comments like this one.

Start your 7-day free trial to view this Expert Comment or ask the Experts your question.

 
[+][-]02.15.2006 at 07:57AM PST, ID: 15961363

At Experts Exchange, members can ask their questions to thousands of technology professionals, also known as Experts. Experts compete and collaborate to answer those questions by leaving comments like this one.

Start your 7-day free trial to view this Expert Comment or ask the Experts your question.

 
 
Loading Advertisement...
20080716-EE-VQP-32