Can I code default serial port in Arduino Mega (USART0, I assume) in pure C? I mean to set up it and configure directly by ATmega's registers?

I'm asking because I'm trying to do it and I have a problem. Below is code which I use and Arduino doesn't transfer anything...

#include <avr/io.h>

#define F_CPU 16000000
#define BAUD_RATE 9600 

void setup() {


void loop() {


void UART_Init(unsigned char ubrr)
   UBRR0H = (unsigned char)(ubrr >> 8);
   UBRR0L = (unsigned char)ubrr;
   UCSR0B = (1<<RXEN0) | (1<<TXEN0);
   UCSR0C = (1<<USBS0) | (1<<UCSZ00);

 void UART_Transmit(unsigned char data)
    while(!(UCSR0A & (1<<UDRE0)))
    UDR0 = data;

That code I created following the datasheet for ATmega 2560. It has been compiled and programmed but doesn't work at all...

Please give me any advice. It's important for me use just C code in that case.

  • 1
    You forgot the semicolon after while(!(UCSR0A & (1<<UDRE0))). Jun 11, 2017 at 10:22
  • 1
    About it compiling with a missing ';': The reason it did is because it is still syntactically correct C. Indenting the "UDR0 = data;" statement should make it clear why.
    – JRobert
    Jun 11, 2017 at 15:42

2 Answers 2


I suggest to use existing code and copy that or use that.

This is the Arduino HardwareSerial : HardwareSerial.cpp
You can find more code at avrfreaks.net. Click on "Projects", search for "uart" and "usart" and try to find code that is compatible with the ATmega2560. Some projects have buffers and many functions, others are very simple.

The result might not be compatible with other Arduino code (for example with interrupts). Why do you not want to use the Arduino Serial library ?


I tried your program on an Uno, and it worked as expected once I fixed three problems:

  • Removed #define F_CPU 16000000. This is not a big issue, but it fixes a warning about that constant being already defined by the Arduino environment.
  • Added the UCSZ01 bit to UCSR0C in order to work in 8-bit mode instead of the uncommon 6-bit mode.
  • Added the semicolon after while(!(UCSR0A & (1<<UDRE0))).

Note also that there is no point in loading UBRR0 in two steps. You can just UBRR0 = ubrr and trust the compiler to do the right thing.

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.