Пишем программу для настройки UART в микроконтроллере Atmega8 на передачу данных, в среде программирования Atmel Studio.

Для начала рассмотри, что такое UART:

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

Асинхронный — означает, что интерфейс не использует синхросигнал для передачи данных.  Частота передачи настраивается заранее и не меняется во время работы.

USART является  более гибкий в настройки чем UART:

  1. Можно регулировать длину слова от 5 до 9 (в UART от 8 до 9).
  2. Возможна как асинхронная так и синхронная передача данных (в 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
}