Skip to content

Instantly share code, notes, and snippets.

@adnbr
Last active September 22, 2022 07:01

Revisions

  1. adnbr revised this gist Apr 6, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions simple-usart-commands.c
    Original file line number Diff line number Diff line change
    @@ -76,7 +76,7 @@ void copy_command ()
    }
    }

    unsigned long parse_assignment (char input[16])
    unsigned long parse_assignment ()
    {
    char *pch;
    char cmdValue[16];
    @@ -100,7 +100,7 @@ void process_command()
    // Do the query action for S
    print_value('S', sensitivity);
    } else if (command_in[1] == '=') {
    sensitivity = parse_assignment(command_in);
    sensitivity = parse_assignment();
    }
    break;
    case 'M':
  2. adnbr created this gist May 7, 2012.
    160 changes: 160 additions & 0 deletions simple-usart-commands.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,160 @@
    /* Parsing simple USART commands
    * -----------------------------
    * For more information see
    * http://www.adnbr.co.uk/articles/parsing-simple-usart-commands
    *
    * 996 bytes - ATmega168 - 16MHz
    */

    #define F_CPU 16000000UL
    #define BAUD 19200
    #define BAUD_PRESCALE (((F_CPU / (BAUD * 16UL))) - 1)

    #define TRUE 1
    #define FALSE 0

    #define CHAR_NEWLINE '\n'
    #define CHAR_RETURN '\r'
    #define RETURN_NEWLINE "\r\n"

    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/atomic.h>
    #include <string.h>

    // The inputted commands are never going to be
    // more than 8 chars long. Volatile for the ISR.
    volatile unsigned char data_in[8];
    volatile unsigned char command_in[8];

    volatile unsigned char data_count;
    volatile unsigned char command_ready;

    // Variables to hold current settings
    unsigned int sensitivity = 223;

    void usart_putc (char send)
    {
    // Do nothing for a bit if there is already
    // data waiting in the hardware to be sent
    while ((UCSR0A & (1 << UDRE0)) == 0) {};
    UDR0 = send;
    }

    void usart_puts (const char *send)
    {
    // Cycle through each character individually
    while (*send) {
    usart_putc(*send++);
    }
    }

    void usart_ok()
    {
    usart_puts("OK\r\n");
    }

    void print_value (char *id, int *value)
    {
    char buffer[8];
    itoa(value, buffer, 10);
    usart_putc(id);
    usart_putc(':');
    usart_puts(buffer);
    usart_puts(RETURN_NEWLINE);
    }

    void copy_command ()
    {
    // The USART might interrupt this - don't let that happen!
    ATOMIC_BLOCK(ATOMIC_FORCEON) {
    // Copy the contents of data_in into command_in
    memcpy(command_in, data_in, 8);

    // Now clear data_in, the USART can reuse it now
    memset(data_in[0], 0, 8);
    }
    }

    unsigned long parse_assignment (char input[16])
    {
    char *pch;
    char cmdValue[16];
    // Find the position the equals sign is
    // in the string, keep a pointer to it
    pch = strchr(command_in, '=');
    // Copy everything after that point into
    // the buffer variable
    strcpy(cmdValue, pch+1);
    // Now turn this value into an integer and
    // return it to the caller.
    return atoi(cmdValue);
    }


    void process_command()
    {
    switch (command_in[0]) {
    case 'S':
    if (command_in[1] == '?') {
    // Do the query action for S
    print_value('S', sensitivity);
    } else if (command_in[1] == '=') {
    sensitivity = parse_assignment(command_in);
    }
    break;
    case 'M':
    if (command_in[1] == '?') {
    // Do the query action for M
    } else if (command_in[1] == '=') {
    // Do the set action for M
    }
    break;
    default:
    usart_puts("NOT RECOGNISED\r\n");
    break;
    }
    }

    int main(void)
    {
    // Turn on USART hardware (RX, TX)
    UCSR0B |= (1 << RXEN0) | (1 << TXEN0);
    // 8 bit char sizes
    UCSR0C |= (1 << UCSZ00) | (1 << UCSZ01);
    // Set baud rate
    UBRR0H = (BAUD_PRESCALE >> 8);
    UBRR0L = BAUD_PRESCALE;
    // Enable the USART Receive interrupt
    UCSR0B |= (1 << RXCIE0 );

    // Globally enable interrupts
    sei();

    while(1) {

    if (command_ready == TRUE) {
    copy_command();
    process_command();

    command_ready = FALSE;
    usart_ok();
    }

    }
    }

    ISR (USART_RX_vect)
    {
    // Get data from the USART in register
    data_in[data_count] = UDR0;

    // End of line!
    if (data_in[data_count] == '\n') {
    command_ready = TRUE;
    // Reset to 0, ready to go again
    data_count = 0;
    } else {
    data_count++;
    }
    }