7 years, 10 months ago.

Reading serial data gives irregular results

Hi,

I'm using LPC1768. I'm trying to build an IBIS data generator. I.e. I want to enter data serially and create IBIS data words to control an old flipdot matrix destination blind. I want the display to print a bus route number and a destination.

When reading in four digits for a line number I get strange results;

/*  Libraries and classes           */
#include "mbed.h"

/*  Preprocessor macros             */
/* Configure serial bus for IBIS communication */
#define IBUS_Baud       1200        //  IBIS bus: baud rate =   1200
#define IBUS_DataBits   7           //  IBIS bus: data bits =   7
#define IBUS_Parity     Even        //  IBIS bus: parity    =   even
#define IBUS_StopBits   2           //  IBIS bus: stop bits =   2

/* IBIS Commands */
#define ICMD_line       l           //  Line number =   l
#define ICMD_Dest       zA1         //  Destination =   zA1

/* Display layout configuration codes */
#define ICNF_start      .           //  start layout config =   .
#define ICNF_space      A           //  space 1 pixel       =   A
#define ICNF_upcenter   E           //  align upper center  =   E
#define ICNF_lowcenter  F           //  align lower center  =   F
#define ICNF_fontthin   8           //  thin font           =   8
#define ICNF_fontfat    6           //  fat font            =   6

/* checksum calc starts with ASCII <DEL> = 127 = 0x7F */
#define ICRC_start      0x7F        //  ASCII DE    =   0x7F

/*  Serial ports                    */
Serial  usbPC( P0_2, P0_3);         //  USB serial comm PC
                                    //      USBTX   =   P0_2 
                                    //      USBRX   =   P0_3 
/*  Global variables                */
char cLijn[4];

/*  Main program                    */
int main()
{
    while (1)
    {
        usbPC.printf("\n\r--== stel IBIS data samen ==--\n\r");
        usbPC.printf("Geef lijnnummer (1-4 cijfers):\n\r");
        for( int i = 0; i < 4; i++)
        {
            cLijn[ i] = '0';
            char cA;
            cA = usbPC.getc();
            if( cA >= '0')
            {
                if( cA <= '9')
                {
                    cLijn[ i] = cA;
                }   //  endif
            }   //  endif
            
        }   //  endfor    

        usbPC.printf("\n\rLijnnummer:\n\r");
        for( int i = 0; i < 4; i++)
        {
            usbPC.putc( i + '0');
            usbPC.printf(" = ");
            usbPC.putc( cLijn[ i]);
            usbPC.printf("\n");
        }   //  endfor    
    }   //  endwhile
}   //  endmain

I try to read in individual characters using getc and putc.

But somehow, after the second or 3rd iteration of this program, the values in cLijn[] start shifting. How can I reliably read 4 characters off the serial bus, terminated by a CR or LF?

For code formatting use <<code>> and <</code>> on seperate lines. And can you include a copy of your serial terminal what is shifting exactly?

posted by Erik - 23 Jan 2017

I enter 0172<CR> and the program returns 0, 1, 7, 2. Next iteration I enter 0170<CR> and the program returns <blank>, 0, 1, 7. Third iteration: IN: 0170<CR>, out comes 0, blank, 0, 1 or 0, 0, 1, 7. I tried my terminal program to send <CR>, <LF>, or both. No avail.

posted by Marout Yasuo Sluijter-Borms 24 Jan 2017

1 Answer

7 years, 10 months ago.

Why are you sending new lines / carriage returns anyway? Your program does not seem to expect them:

You only read data in:

for( int i = 0; i < 4; i++)
        {
            cLijn[ i] = '0';
            char cA;
            cA = usbPC.getc();
            if( cA >= '0')
            {
                if( cA <= '9')
                {
                    cLijn[ i] = cA;
                }   //  endif
            }   //  endif
            
        }   //  endfor    

Here you do 4 getcs: the four numbers. This will be processed, but if you send <CR> back, this will stay in the buffer of your MCU until the next time the loop is run. It will retrieve this CR from the buffer, your code tells it to throw it out, but it does continue to the next value.

So you need to make sure it properly handles unexpected characters, and ignores them, or restarts reading, instead of leaving it empty.

Accepted Answer

Should I be better off using a scanf() call?

posted by Marout Yasuo Sluijter-Borms 24 Jan 2017

Probably, although it depends a bit on how much your input is guaranteed, do you need to handle stupid users? In general scanf isn't a bad idea i think.

posted by Erik - 24 Jan 2017

I ended up doing following:

    int count;
    char cA;
    while( true)
    {
        usbPC.printf("\n\r--== stel IBIS data samen ==--\n\r");
        usbPC.printf("Geef lijnnummer (1-4 cijfers):\n\r");
        
        cA = '0';
        count = 0;

        while( true)
        {
            cA = usbPC.getc();
            if( cA >= '0')
            {
                if( cA <= '9')
                {
                    cLijn[ count] = cA;
                    count++;
                }   //  endif
            }   //  endif
            if( count == 4)
            {
                break;
            }   //  endif
        }   //  endwhile

That way, only ascii digits 0-9 get read. A bus route number is usually max 4 digits

posted by Marout Yasuo Sluijter-Borms 24 Jan 2017