Для начала рассмотри, что такое UART:
UART (универсальный асинхронный приёмопередатчик) — одна из распространенных технологий передачи данных.
Асинхронный — означает, что интерфейс не использует синхросигнал для передачи данных. Частота передачи настраивается заранее и не меняется во время работы.
USART является более гибкий в настройки чем UART:
- Можно регулировать длину слова от 5 до 9 (в UART от 8 до 9).
- Возможна как асинхронная так и синхронная передача данных (в UART только асинхронная).
В нашем случаи мы будем использовать асинхронный режим работы.
Для приема и передачи данных USART использует следующие сигналы:
- Прием данных RxD (ножка PDO Atmega8)
- Передача данных TxD (ножка PD1 Atmega8)
- Синхронизация XCK (ножка PD4 Atmega8)
Для передачи и приема данных используется регистр UDR. При чтение будем обращаться к буферу приемника, при записи будем обращаться к буферу передатчика.
Для управлением работы с USART используются следующие регистры:
- UCSRA — содержит флаги состояния приема/передачи данных.
- UCSRB — определяет какие прерывания генерировать при наступление определенных событий, разрешает/запрещает передачу/прием.
- UCSRC — задает режим работы синхронный/асинхронный, определяет режим работы контроля данных (проверка на четность/не честность или отключено), количество стоп битов (1 или 2).
- UBRR — определяет скорость приема/передачи данных
Регистр UCSRA :
RXC — флаг завершения приема, устанавливается в 1 при наличие непрочитанных данных в буфере приемника UDR;
- TXC — флаг завершения передачи, устанавливается в 1 при передачи всех разрядов из передатчика UDR;
- UDRE — флаг опустошения регистра передатчика, устанавливается в 1 при пустом буфере передатчика UDR после передачи;
- FE — флаг ошибки кадрирования, устанавливается в 1 при обнаружение неправильного кадра, когда стоп бит равен 0.
- DOR — флаг переполнения регистра приемника, устанавливается в 1, когда байт данных принят, а предыдущий еще не прочитан из UDR;
- PE — флаг ошибки контроля четности, устанавливается в 1 при обнаружение ошибки контроля четности (если включена проверка);
- U2X — бит установки удвоенной скорости обмена, если установлена 1, то скорость передачи удваивается, данный бит используется только при асинхронном режиме работы;
- MPCM — бит мультипроцессорного обмена, если установлена 1, то контроллер аппаратно не принимает информацию, а только посылки с адресами, далее устанавливается бит завершения приема (или прерывание) и программа обрабатывает адрес, её ли это адрес. Отличие информации от адреса определяется с помощью 9-ого бита в режиме 9-и битового обмена.
Регистр UCSRB :
- RXCIE — бит разрешения прерывания по завершению приема, если установлена 1, то при установке флага RXC регистра UCSRA произойдет прерывание прием завершен;
- TXCIE — бит разрешения прерывания по завершению передачи, если установлена 1, то при установке флага TXC регистра UCSRA произойдет прерывание передача завершена;
- UDRIE — бит разрешения прерывания по опустошению регистра передатчика, если установлена 1, то при установке флага UDRE регистра UCSRA произойдет прерывание регистр данных пуст;
- RXEN — бит разрешения приема, при установки 1 разрешается работа приемника USART и включается вывод RXD;
- TXEN — бит разрешения передачи, при установки 1 разрешается работа передатчика USART и включается вывод TXD;
- UCSZ2 — бит формат посылок, данный бит совместно с битами UCSZ1 и UCSZ0 регистра UCSRC определяют количество бит данных в посылке.
- RXB8 — 9 разряд принимаемых данных при использование данного бита , данные необходимо считывать до считывание регистра UDR;
- TXB8 — 9 разряд передаваемых данных при использование данного бита, данные необходимо записывать до записи в регистр UDR.
Регистр UCSRC:
- URSEL — данный бит отвечает за выбор работа с регистром UCSRCили UBRR, при установке 1 мы работаем с регистром UCSRC, при 0 мы работаем с регистром UBRR;
- UMSEL — данным битом выбираем режим работы: асинхронный или синхронный, 1 — режим синхронный, 0 — режим асинхронный;
- UPM1, UPM0 — биты выбора режима проверки на четность/нечетность;
- USBS — данный бит отвечающий за количество стоп-битов в посылке: 1 — два стоп-бита, 0 — один стоп-бит;
- UCSZ1, UCSZ0 , UCSZ2(расположен в регистре UCSRB) — определяют количество бит данных в посылке;
- UCPOL — данный бит определяет полярность тактового сигнала, определяет по какому фронту принимать/передавать данные – по спадающему или по нарастающему.
Регистр UBRR отвечает за скорость обмена, и состоит из двух 8-и битных регистров — UBRRH и UBRRL
Скорость передачи данных исчисляются в бодах (количество передаваемых бит в секунду, причем в количество бит входят как данные так и стоп биты и другая информация).
Вычисляется следующим образом:
UBRR = ( fCK /( BAUD * 16 ) ) — 1 — если значение бита U2X = 0.
UBRR = ( fCK /( BAUD * 8 ) ) — 1 — если значение бита U2X =1.
где:
fCK — тактовая частота микроконтроллера в герцах;
BAUD — требуемая скорость в бодах;
UBRR — содержимое регистра UBRR.
В нашей программе мы будем использовать следующие настройки: асинхронный режим, скорость 9600 бод, 8 бит данных, 1 стоп-бит, без проверки четности.
Принимать наши данные будем через программу Terminal, которая бесплатно распространяется.
Переходник будем использовать следующий:
Наш программный код.
#define F_CPU 4000000 // Рабочая частота контроллера
#define BAUD 9600L // Скорость обмена данными
#define UBRRL_value (F_CPU/(BAUD*16))-1 //Согластно заданной скорости подсчитываем значение для регистра UBRR
#include <avr/io.h>
#include <util/delay.h>
void init_pin(void);
#define B_PB0 (PINB&(1<<PB0)) // считываем значение входа
#define B_PB1 (PINB&(1<<PB1)) // считываем значение входа
void init_USART() {
UBRRL = UBRRL_value; //Младшие 8 бит UBRRL_value
UBRRH = UBRRL_value >> 8; //Старшие 8 бит UBRRL_value
UCSRB |=(1<<TXEN); //Бит разрешения передачи
UCSRC |=(1<< URSEL)|(1<< UCSZ0)|(1<< UCSZ1); //Устанавливем формат 8 бит данных
}
void send_UART(char value) {
while(!( UCSRA & (1 << UDRE))); // Ожидаем когда очистится буфер передачи
UDR = value; // Помещаем данные в буфер, начинаем передачу
}
int main(void)
{
init_pin();
init_USART(); //инициализация USART в режиме 9600/8-N-1
send_UART(0x4F); //посылаем ASCII код знака ‘О’
send_UART(0x4B); //посылаем ASCII код знака ‘К’
send_UART(0x21); //посылаем ASCII код знака ‘!’
send_UART(0x0D); //переход в начало строки
send_UART(0x0A);//переход на новую строку
while(1)
{
if(B_PB0==0)// если кнопка нажата
{
send_UART(0x50); // символ ASCII буквы ‘P’
send_UART(0x42); //символ ASCII буквы ‘B‘
send_UART(0x30); //символ ASCII цифры ‘0’
send_UART(0x0D);
send_UART(0x0A);
_delay_ms(500);
}
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)
{
PORTB=0b00000011;//РВ0, PB1 с подтяжкой резистора к питанию.
DDRB= 0b00000000;//РВ0, PB1 input
}