1

i am sending 4 bytes of data from my Pc serially to my atmega16. i use UART. one technique is to use the functoins given in datasheet but they block rest of the code as they use polling. so i am using a while loop. but i am unable to understand the structure of the code when the while loop starts.. please help me in this. thnx

#include <avr/io.h>
#define FOSC 1843200// Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1

void UART_Init( unsigned int ubrr)
{
/* Set baud rate */
UBRRH = (unsigned char)(ubrr>>8);
UBRRL = (unsigned char)ubrr;
/* Enable receiver and transmitter */
UCSRB = (1<<RXEN);
/* Set frame format: 8data, 2stop bit */
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}

int main( void )
{   
int i = 0;
unsigned char my_data [4];

UART_Init ( MYUBRR );

while (1)
{   
    if (UCSRA & (1<<RXC)) 
    {
        my_data[i] = UDR;
    }
    i++;

    if (i == 3)
    {
        /*my next code here and once thats done, its again in uart receive mode*/
    i = 0;
    }
}
}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
M T
  • 161
  • 1
  • 2
  • 13
  • 2
    You should increase `i` onside the `if`-statement, otherwise it will be increased all the time in the loop and the code inside `if (i == 3)` will be executed every fourth loop, always, and not when you read four bytes. – Some programmer dude May 24 '12 at 05:11

2 Answers2

2

I've taken the while loop and put comments next to them so hopefully you understand it :)

while (1)
{   
    if (UCSRA & (1<<RXC)) //If Usart control and status register A and Receive complete flag are true (Comparing the register with the value of RXC, which is a bit in the register)
    {
        my_data[i] = UDR; //Read Usart Data Register, which is 1 byte
        i++; //Like Joachim Pileborg said, this should be in the if statement
    }

    if (i == 3) //If received your 4 bytes.
    {
        /*my next code here and once thats done, its again in uart receive mode*/
        //Do something with the data
        i = 0;
    }
}

I hope it is clear now! btw: you are also constantly polling for data now, so this is not any different then what you had I think.

Davey
  • 447
  • 2
  • 7
  • 27
1

If you don't want to use blocking polling you need to do interrupt driven handling of incoming data. Basically, you'd write an RX-Complete-ISR with your code in it:

    my_data[i] = UDR; //Read Usart Data Register, which is 1 byte
    i++; //Like Joachim Pileborg said, this should be in the if statement

(Naturally, you will need to turn on interrupts in general (sei();) and the USART receive complete interrupt before this can receive any data.)

Then, in your main loop, you can perform other tasks and check via

if (i == 3) //If received your 4 bytes.
{
    /*my next code here and once thats done, its again in uart receive mode*/
    //Do something with the data
    i = 0;
}

If your ISR has received all the bytes.

You may need to pay attention to some synchronization issues, like declaring i as volatile, but that's how it's done in the most performant way.

JimmyB
  • 12,101
  • 2
  • 28
  • 44