Настраиваем UART/USART на передачу данных в ATmega8

В этом уроке разберём работу последовательного интерфейса USART микроконтроллера ATmega8 и настроим передачу данных со скоростью 9600 бод. В качестве примера микроконтроллер будет передавать текстовые сообщения на компьютер.

Что такое UART и USART

UART — универсальный асинхронный приёмопередатчик, используемый для последовательной передачи данных.

Асинхронный режим означает, что отдельный синхросигнал для передачи данных не используется. Скорость обмена заранее задаётся на передающей и принимающей стороне.

USART позволяет работать как в асинхронном, так и в синхронном режиме. В данном уроке будем использовать именно асинхронный режим.

Выводы USART микроконтроллера ATmega8

  • RXD — PD0: приём данных.
  • TXD — PD1: передача данных.
  • XCK — PD4: тактовый сигнал при работе USART в синхронном режиме.

Для приёма и передачи данных используется регистр UDR. При чтении регистра мы получаем данные из буфера приёмника, а при записи данные помещаются в буфер передатчика.

Основные регистры USART

  • UCSRA — содержит основные флаги состояния приёма и передачи данных.
  • UCSRB — разрешает приём и передачу, а также управляет прерываниями USART.
  • UCSRC — задаёт режим USART, количество бит данных, стоп-битов и режим контроля чётности.
  • UBRR — определяет скорость обмена данными.

Регистр UCSRA

Регистр UCSRA микроконтроллера ATmega8
Регистр UCSRA
  • RXC — флаг завершения приёма. Устанавливается, когда в буфере приёмника имеются непрочитанные данные.
  • TXC — флаг завершения передачи.
  • UDRE — показывает, что регистр передачи готов принять новые данные.
  • FE — флаг ошибки кадрирования.
  • DOR — флаг переполнения приёмника.
  • PE — флаг ошибки контроля чётности.
  • U2X — включает режим удвоенной скорости в асинхронном режиме.
  • MPCM — используется в режиме мультипроцессорного обмена.

Регистр UCSRB

Регистр UCSRB ATmega8
Регистр UCSRB
  • RXCIE — разрешение прерывания по завершению приёма.
  • TXCIE — разрешение прерывания по завершению передачи.
  • UDRIE — разрешение прерывания, когда регистр передачи пуст.
  • RXEN — разрешение работы приёмника.
  • TXEN — разрешение работы передатчика.
  • UCSZ2 — совместно с UCSZ1 и UCSZ0 задаёт количество бит данных.

Биты RXB8 и TXB8 используются для девятого разряда при работе в 9-битовом режиме.

Регистр UCSRC

Регистр UCSRC микроконтроллера ATmega8
Регистр UCSRC
  • URSEL — используется для выбора доступа к UCSRC или UBRRH.
  • UMSEL — выбор синхронного или асинхронного режима.
  • UPM1, UPM0 — задают режим проверки чётности.
  • USBS — выбирает один или два стоп-бита.
  • UCSZ1, UCSZ0 — совместно с UCSZ2 задают количество бит данных.
  • UCPOL — определяет полярность тактового сигнала в синхронном режиме.

Регистр UBRR и скорость передачи

Регистр UBRR задаёт скорость последовательного обмена и состоит из двух частей: UBRRH и UBRRL.

При U2X = 0 значение UBRR рассчитывается по формуле:

UBRR = ( fCK / ( BAUD × 16 ) ) - 1

При U2X = 1:

UBRR = ( fCK / ( BAUD × 8 ) ) - 1
fCK — тактовая частота микроконтроллера.

BAUD — требуемая скорость передачи.

UBRR — значение, которое необходимо записать в регистры UBRRH и UBRRL.

Настройки нашего примера

  • асинхронный режим;
  • скорость — 9600 бод;
  • 8 бит данных;
  • 1 стоп-бит;
  • контроль чётности отключён.

Полученные данные будем смотреть на компьютере через программу Terminal.

Для соединения микроконтроллера с компьютером используется USB-UART переходник.

USB UART переходник
USB-UART переходник

Программный код

#define F_CPU 4000000UL
#define BAUD 9600L

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


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


void init_pin(void);


/*
    Считываем состояние кнопок PB0 и PB1
*/
#define B_PB0 (PINB & (1 << PB0))
#define B_PB1 (PINB & (1 << PB1))


void init_USART(void)
{
    /*
        Младшие 8 бит UBRR
    */
    UBRRL = UBRRL_value;

    /*
        Старшие биты UBRR
    */
    UBRRH = UBRRL_value >> 8;

    /*
        Разрешаем передачу USART
    */
    UCSRB |= (1 << TXEN);

    /*
        8 бит данных,
        асинхронный режим,
        1 стоп-бит,
        без контроля чётности
    */
    UCSRC |= (1 << URSEL) |
             (1 << UCSZ0) |
             (1 << UCSZ1);
}


void send_UART(char value)
{
    /*
        Ждём освобождения
        регистра передачи
    */
    while (!(UCSRA & (1 << UDRE)))
    {
        ;
    }

    /*
        Записываем данные в UDR
        и запускаем передачу
    */
    UDR = value;
}


int main(void)
{
    init_pin();

    /*
        Инициализация USART:
        9600 бод, 8-N-1
    */
    init_USART();


    /*
        После запуска отправляем:
        OK!
    */

    send_UART(0x4F);   /* O */
    send_UART(0x4B);   /* K */
    send_UART(0x21);   /* ! */

    send_UART(0x0D);
    send_UART(0x0A);


    while (1)
    {

        /*
            Нажата кнопка PB0
        */
        if (B_PB0 == 0)
        {
            send_UART(0x50);   /* P */
            send_UART(0x42);   /* B */
            send_UART(0x30);   /* 0 */

            send_UART(0x0D);
            send_UART(0x0A);

            _delay_ms(500);
        }


        /*
            Нажата кнопка PB1
        */
        if (B_PB1 == 0)
        {
            send_UART('P');
            send_UART('B');
            send_UART('1');

            send_UART(0x0D);
            send_UART(0x0A);

            _delay_ms(500);
        }

    }
}


void init_pin(void)
{
    /*
        PB0 и PB1 — входы.
        Включаем внутренние
        подтягивающие резисторы.
    */
    PORTB = 0b00000011;

    DDRB = 0b00000000;
}

Как работает программа

После запуска микроконтроллер инициализирует USART и передаёт строку OK!.

При нажатии кнопки PB0 передаётся текст PB0.

При нажатии кнопки PB1 передаётся текст PB1.

Символы 0x0D и 0x0A используются для перехода на новую строку в терминальной программе.