§ Функции для работы

#include <avr/io.h>
#include <util/delay.h>

// Рабочая частота контроллера (F_CPU) 16 мгц
// Скорость обмена данными
#define BAUD 9600L

// Согласно заданной скорости подсчитываем значение для регистра UBRR
#define UBRRL_value ((F_CPU / (BAUD * 16)) - 1)

// Инициализация USART в режиме 9600/8-N-1
void UART_init() {

    // 16 бит UBRR
    UBRR0L  = UBRRL_value;
    UBRR0H  = UBRRL_value >> 8;

    // TXEN разрешить передачу и RXEN0 прием
    UCSR0B |= (1 << TXEN0) | (1 << RXEN0);

    // Устанавливаем формат 8 бит данных
    UCSR0C |= (1 << UMSEL01) | (1 << UCSZ01 ) | (1 << UCSZ00);
}

void UART_put(unsigned char value) {

    // Ожидаем когда очистится буфер передачи
    while (!( UCSR0A & (1 << UDRE0)));

    // Помещаем данные в буфер, начинаем передачу
    UDR0 = value;
}

unsigned char UART_get(){

    while ((UCSR0A & (1 << RXC0)) == 0);
    return UDR0;
}

// Вывод строки
void UART_print(const char* s) {

    int i = 0;
    while (s[i]) UART_put(s[i++]);
}

// Печатать байт в виде HEX
void UART_pbyte(unsigned char b) {

    int h = (b & 0xf0) >> 4;
    int l = b & 0x0f;

    UART_put(h + (h < 10 ? '0' : '7'));
    UART_put(l + (l < 10 ? '0' : '7'));
}

int main(void) {

    UART_init();
    while (1) {
        send_UART( UART_get() );
    }
}

§ Настройка портов

stty -F /dev/ttyACM0 cs8 9600 ignbrk -brkint -icrnl -imaxbel -opost -onlcr \
     -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts
echo "Hello World" > /dev/ttyACM0