1

I am working on a project where I need to communicate from an AVR microcontroller to an rs232 device via UART and a TTL level converter. I am using a serial callback to get the characters from the serial port, and checking for a carriage return/new line, then also checking the most recent character in the buffer for carriage return/new line. The data from the rs232 device is coming in the format of 26 lines seperated by carriage return AND line feed comprised of ASCII characters. The entire 26 lines is sent approximately every .7 seconds. I am trying to fill a 2D array with the 26 lines. However, I am now getting a what I should in the receive buffer. Here is my code so far:

    volatile uint8_t rxrs_buffer[26][12] = {
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        };

    static void serialrs_rx_cb(const struct usart_async_descriptor *const io_descriptor)

{

    //counters
    uint8_t ch, count;

    //read a character
    count = io_read(&SERIALRS232.io, &ch, 1);

    //check if we are receiving
    if (serialrs_receiving == 0)
    {
        //check for new line or carriage return
        if (ch != 10 && ch != 13)
        {
            if (rxrs_buffer[row-1][column-1] != 10 && rxrs_buffer[row-1][column-1] != 13)
            {           //set receiving flag
            serialrs_receiving = 1;

            //reset byte counter
            serialrs_bytes_received_counter = 0;

            //start filling the rx buffer
            rxrs_buffer[row][column] = ch;

            //increment the byte counter and column
            serialrs_bytes_received_counter += count;
            column++;
            }

        }
    }
    else
    {
        //continue filling the buffer
        rxrs_buffer[row][column] = ch;

        //increment the byte counter and column
        serialrs_bytes_received_counter += count;
        column++;

        //check for new line or carriage return
        if (ch == 10 || ch == 13)
        {   
            if (rxrs_buffer[row-1][column-1] != 10 && rxrs_buffer[row-1][column-1] != 13)
            {
            //continue filling the buffer
            rxrs_buffer[row][column] = ch;

            //increment the byte counter
            serialrs_bytes_received_counter += count;

            //increment the line counter and reset column
            row++;
            column = 0;

            if (row == 26)
                {
                    //set the completion flag
                    serialrs_complete = 1;

                    //total bytes
                    totalrs_bytes = serialrs_bytes_received_counter - 2;

                    row = 0;
                }   
            }

        }

        //check for buffer overflow
        if (serialrs_bytes_received_counter >= SERIALRS_BUFFER_SIZE)
        {
            //reset buffer counter
            serialrs_bytes_received_counter = 0;
        }
    }
}

The issue is my 2D buffer array is not filling up correctly. I am getting rows that start with two line feeds, then some that work perfectly and end in a carriage return line feed, only to find the next row starts with two carriage returns or line feeds? Any suggestions at all would help

  • 1
    A) `row-1` and `column-1` can cause your program to attempt to read at index -1. B) Nothing prevents `column` from incrementing past 11. C) The array initializer could be written as `{{0}}`. – user3386109 May 06 '20 at 21:30
  • 1
    You should also be paying attention to whether you get serial buffer overruns. If the data arrives faster than you are reading it out of the buffer, you can get all kinds of lost in the spew. Does the protocol include any kind of start or end of frame indicator? Perhaps two eol pairs? – jwdonahue May 06 '20 at 21:35
  • This is the serial output from the rs232 on Termite: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 10 -2 50 -6 10 -8 100 250 10 -2 50 -1 0 0 83 1 There does not seem to be any end of frame indicator, just the eol pair at the end of each line (not shown here). I am just trying to keep track of line and terminate when the 26th line sends its final eol character. Is there a way to check for a eol pair? – Coding Is Difficult May 06 '20 at 22:09
  • *"I am getting rows that start with two line feeds, ... the next row starts with two carriage returns or line feeds"* -- The lexical scan for CR or LF should take precedence because those are the EOL indicators. Hence the `if (serialrs_receiving == 0)` and `if (ch == 10 || ch == 13)` logic in your code is nested backwards. BTW use of [magic numbers](https://stackoverflow.com/questions/47882/what-is-a-magic-number-and-why-is-it-bad) such as 10 and 13 is poor coding. – sawdust May 06 '20 at 23:16
  • The easiest way is a simple state machine. The initial `state` is WAITING_FOR_CR. When you find a carriage return don't put it in the array, but change the `state` to EXPECTING_LF. When you receive a line feed, check the `state`. If it's EXPECTING_LF, then you've got a CR/LF pair. If it's WAITING_FOR_CR, then you got a linefeed that wasn't preceded by a carriage return. And if you receive a regular character when the `state` is EXPECTING_LF, then you got a carriage return that wasn't followed by a linefeed. – user3386109 May 06 '20 at 23:20
  • Another option is to accept both LF and CR in pairs (this way or the other) or all alone as line separators. Additionally, allow empty lines. This will simplify your state machine and enable you to feed contents generated by Unix or (old) MacOS systems. – the busybee May 07 '20 at 11:06

0 Answers0