I'm using Atmel Studio with Atmega328P.

I'm trying to send the decimal number 876 continuously from the micro-controller. This was just to learn.

To send 876 I need two bytes which is:

0x036C = 00000011 01101100

So I manipulated a code and here is what I use now:

#include <avr/io.h>
#define F_CPU 16000000
#define USART_BAUDRATE 9600
#define UBRR_VALUE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

void USART0Init(void)
    // Set baud rate
    UBRR0H = (uint8_t)(UBRR_VALUE>>8);
    UBRR0L = (uint8_t)UBRR_VALUE;
    // Set frame format to 8 data bits, no parity, 1 stop bit
    UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00);
    //enable transmission and reception
    UCSR0B |= (1<<TXEN0);

int main (void)
    //Initialize USART0


        UDR0 = 0b00000011;
        UDR0 = 0b01101100;



The problem is at the receiving side the data comes as:

01101100 00000011 00000011 . . .

Here is the screen shot of the binary data at the receiving end: enter image description here

However it should be received correctly as two byte chunks 00000011 01101100.

And here you can see the problem of the data being received as uint16(not only 876 as desired): enter image description here

How can I fix this and receive the data properly as two bytes with correct order as 876?

  • you should wait until previous value was successfully transmitter and UDR0 is ready for next byte
    – KIIV
    Feb 22, 2017 at 14:00

3 Answers 3


The data sheet for the 328P - section 24.7.1 - contains an example of waiting for the transmission to complete before sending another byte.

When sending serial data, you determine the order of bytes and will need to reassembly in the correct order on receipt. You can use bit shift operators to move the bytes back into the correct location. If you send the most significant byte first (MSB) and then the least significant byte (LSB), putting them back into a 16 bit integer would look something like:

uint16_t result = (MSB << 8) | LSB;

  • i tried this works so far: UDR0 = 0b00000011; while(!(UCSR0A&(1<<UDRE0))){}; UDR0 = 0b01101100; while(!(UCSR0A&(1<<UDRE0))){};
    – floppy380
    Feb 22, 2017 at 14:19

Your code has a fundamental error: when you write "UDR0 = 0b00000011;", the CPU does not wait until the transmission is complete - that would be terribly wasteful, in terms of time. It just write to the transmit data buffer. Furthermore, if the transmission was not ongoing yet, that instruction also starts transmission (assuming the USART is properly initialized, as it is in your case). However, if a transmission is ongoing, and the data buffer is not empty, this write instruction might be either ignored or it might overwrite the data on the buffer.

Therefore, with your code, you're continuously writing two bytes (at a very high speed, because that loop would result in very few asm instructions), without checking if actually you can write to the transmit data buffer register. This will result in most of the bytes being "randomly" ignored, with some other being randomly picked and trasmitted.

Before sending any data, you must check if the data register is empty:

while ( !(UCSR0A & (1 << UDRE0)));
UDR0 = firstByte;
while ( !(UCSR0A & (1 << UDRE0)));
UDR0 = secondByte;

Where firstByte and secondByte are either the numeric values or two 8-bit variables.

Instead of the two "while" statements, you can use the built-in macro:

loop_until_bit_is_set(UCSR0A, UDRE0);

First, you want to determine what you are trying to send. Send data in binary form is rare.

Secondly, you want to wait for each transmission to send before starting the next one.

  • My goal is to learn to send 16bit unsigned data very fast way. I heard sending as bytes instead of strings is better for fast communication. What can I do for waiting between transmissions and how long? I dont know how to do that.
    – floppy380
    Feb 22, 2017 at 14:03
  • do you mean like this?: UDR0 = 0b00000011; while(!(UCSR0A&(1<<UDRE0))){}; UDR0 = 0b01101100; while(!(UCSR0A&(1<<UDRE0))){};
    – floppy380
    Feb 22, 2017 at 14:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.