Serial Control Interface

Hi All,

Can anyone help? I have the bellow code which does work except that in process_received_byte instead of looking for single charaters (“L”) on the RX and sending the correct response ("&L0202") I want to look for the the correct command string ("@L\n") and then send the correct response ("&L0202") only if the correct command string is in the RX buffer.

#include <avr/io.h>
#include <pololu/orangutan.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <pololu\OrangutanSerial\OrangutanSerial.h>


// receive_buffer: A ring buffer that we will use to receive bytes on PD0/RXD.
// The OrangutanSerial library will put received bytes in to
// the buffer starting at the beginning (receiveBuffer[0]).
// After the buffer has been filled, the library will automatically
// start over at the beginning.
char receive_buffer[32];
 
// receive_buffer_position: This variable will keep track of which bytes in the receive buffer
// we have already processed.  It is the offset (0-31) of the next byte
// in the buffer to process.
unsigned char receive_buffer_position = 0;
 
// send_buffer: A buffer for sending bytes on PD1/TXD.
char send_buffer[32];
 
// wait_for_sending_to_finish:  Waits for the bytes in the send buffer to
// finish transmitting on PD1/TXD.  We must call this before modifying
// send_buffer or trying to send more bytes, because otherwise we could
// corrupt an existing transmission.
void wait_for_sending_to_finish()
{
    while(!serial_send_buffer_empty());
}
 
// process_received_byte: Responds to a byte that has been received on
// PD0/RXD.  If you are writing your own serial program, you can
// replace all the code in this function with your own custom behaviors.
void process_received_byte (char byte)
{
	
switch(byte)

    {
			// LRU Response full command = @L\n
		case 'L':
				
			wait_for_sending_to_finish();
                                         memcpy_P(send_buffer, PSTR("&L0202\n"), 11);
                                          serial_send(send_buffer, 11);

		break;
    }
}
 
void check_for_new_bytes_received()
{
    while(serial_get_received_bytes() != receive_buffer_position)
    {
        // Process the new byte that has just been received.
        process_received_byte(receive_buffer[receive_buffer_position]);
 
        // Increment receive_buffer_position, but wrap around when it gets to
        // the end of the buffer. 
        if (receive_buffer_position == sizeof(receive_buffer)-1)
        {
            receive_buffer_position = 0;
        }
        else
        {
            receive_buffer_position++;
        }
    }
}

void USART_Init(void) 
{ 
	// Set the baud rate to 1200 bits per second.  Each byte takes ten bit
	// times, so you can get at most 120 bytes per second at this speed.

		serial_set_baud_rate(1200);
	
	//Set data frame format:

	//Set control register UCSR0C: 

   //   Register  Async/sync  7 Databits  Even Parity 1 stop bit
		UCSR0C = (0<<UMSEL00)|(2<<UCSZ00)|(2<<UPM00)|(0<<USBS0);
    

	//Set control register UCSR0B:

   //Enable Transmitter and Receiver

      //Register    En-TX      En-RX
		UCSR0B = (1<<RXEN0)|(1<<TXEN0); // |(1<<RXCIE0)|(1<<TXCIE0)|(1<<UDRIE0)|(1<<UCSZ02); 
} 

int main()
{

	//Initialize the USART: Set Baud Rate and Frame Format

	USART_Init();
 
    // Start receiving bytes in the ring buffer.

    //serial_receive_ring(receive_buffer, sizeof(receive_buffer));
	serial_receive(receive_buffer, sizeof(receive_buffer));
 
    while(1)
    {
        // Deal with any new bytes received.
        check_for_new_bytes_received();
 
    }
}

Hello, Dave.

I deleted the duplicate post that you made in the Software & Microcontrollers forum. Please use code tags to format your code in the future.

In general, the way I usually handle processing of multi-byte commands is that I add a few global variables to keep track of the state of the serial protocol, and the process_received_byte function uses those variables to correctly interpret the bytes it receives.

For example, you could add these two global variables:

// A buffer to hold all bytes received since the last \n was received.
static char lineBuffer[80];

// The number of characters received that are sitting in the line buffer but have not been processed yet.
static char lineBufferPosition = 0;

Your process_byte function would be in charge of updating these variables. When it receives a ‘\n’ it would call a function named process_line to process the entire line that was received. In this function, you could check the contents of the line buffer and compare it to “@L”.

–David

Thanks for your reply David it was most helpfull but can you give me an example of implementing the buffer?

Sure. Here is an untested and incomplete example but you should be able to follow it, understand it, and then implement it yourself in your program:

// A buffer to hold all bytes received since the last \n was received.
static char lineBuffer[80];

// The number of characters received that are sitting in the line buffer but have not been processed yet.
static char lineBufferPosition = 0;

// This gets called whenever a newline '\n' is received on the serial port.
void process_received_line()
{
    if (lineBufferPosition == 2 && lineBuffer[0] == '@' && lineBuffer[1] == 'L')
    {
        // We received command "@L".
        // Send response &L0202 after waiting for all previous transmissions to finish.
        wait_for_sending_to_finish();
        memcpy_P(send_buffer, PSTR("&L0202\n"), 7);
        serial_send(send_buffer, 7);
    }
}

// This gets called whenever a new byte is received on the serial port.
void process_received_byte(char b)
{
    if(b == '\n')
    {
        process_received_line();
        lineBufferPosition = 0;
    }
    else if (lineBufferPosition < sizeof(lineBuffer))
    {
        lineBuffer[lineBufferPosition++] = b;
    }
}