Настраиваем UART/USART на передачу данных в ATmega8
Что такое UART и USART
UART — универсальный асинхронный приёмопередатчик, используемый для последовательной передачи данных.
Асинхронный режим означает, что отдельный синхросигнал для передачи данных не используется. Скорость обмена заранее задаётся на передающей и принимающей стороне.
USART позволяет работать как в асинхронном, так и в синхронном режиме. В данном уроке будем использовать именно асинхронный режим.
Выводы USART микроконтроллера ATmega8
- RXD — PD0: приём данных.
- TXD — PD1: передача данных.
- XCK — PD4: тактовый сигнал при работе USART в синхронном режиме.
Для приёма и передачи данных используется регистр UDR. При чтении регистра мы получаем данные из буфера приёмника, а при записи данные помещаются в буфер передатчика.
Основные регистры USART
- UCSRA — содержит основные флаги состояния приёма и передачи данных.
- UCSRB — разрешает приём и передачу, а также управляет прерываниями USART.
- UCSRC — задаёт режим USART, количество бит данных, стоп-битов и режим контроля чётности.
- UBRR — определяет скорость обмена данными.
Регистр UCSRA
- RXC — флаг завершения приёма. Устанавливается, когда в буфере приёмника имеются непрочитанные данные.
- TXC — флаг завершения передачи.
- UDRE — показывает, что регистр передачи готов принять новые данные.
- FE — флаг ошибки кадрирования.
- DOR — флаг переполнения приёмника.
- PE — флаг ошибки контроля чётности.
- U2X — включает режим удвоенной скорости в асинхронном режиме.
- MPCM — используется в режиме мультипроцессорного обмена.
Регистр UCSRB
- RXCIE — разрешение прерывания по завершению приёма.
- TXCIE — разрешение прерывания по завершению передачи.
- UDRIE — разрешение прерывания, когда регистр передачи пуст.
- RXEN — разрешение работы приёмника.
- TXEN — разрешение работы передатчика.
- UCSZ2 — совместно с UCSZ1 и UCSZ0 задаёт количество бит данных.
Биты RXB8 и TXB8 используются для девятого разряда при работе в 9-битовом режиме.
Регистр UCSRC
- URSEL — используется для выбора доступа к UCSRC или UBRRH.
- UMSEL — выбор синхронного или асинхронного режима.
- UPM1, UPM0 — задают режим проверки чётности.
- USBS — выбирает один или два стоп-бита.
- UCSZ1, UCSZ0 — совместно с UCSZ2 задают количество бит данных.
- UCPOL — определяет полярность тактового сигнала в синхронном режиме.
Регистр UBRR и скорость передачи
Регистр UBRR задаёт скорость последовательного обмена и состоит из двух частей: UBRRH и UBRRL.
При U2X = 0 значение UBRR рассчитывается по формуле:
При U2X = 1:
BAUD — требуемая скорость передачи.
UBRR — значение, которое необходимо записать в регистры UBRRH и UBRRL.
Настройки нашего примера
- асинхронный режим;
- скорость — 9600 бод;
- 8 бит данных;
- 1 стоп-бит;
- контроль чётности отключён.
Полученные данные будем смотреть на компьютере через программу Terminal.
Для соединения микроконтроллера с компьютером используется 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;
}
Как работает программа
При нажатии кнопки PB0 передаётся текст PB0.
При нажатии кнопки PB1 передаётся текст PB1.
Символы 0x0D и 0x0A используются для перехода на новую строку в терминальной программе.