Источник: ATMega8
Протокол UART (Universal asynchronous receiver/transmitter) является одним из самых распространённых протоколов передачи данных между устройствами. Стандартный размер посылки при асинхронной передаче данных составляет 10 бит. Если по линии ничего не передаётся, то она находится в состоянии логической единицы. Передача начинается со стартового бита, который равен 0. Затем следуют 8 бит данных. Завершается передача стоп-битом, который равен 1.
На рисунке представлена передача байта 10000010
Для настройки и работы c UART в mega8 выделено 4 регистра:
1) Регистр управления UCSRB: разрешает/запрещает прерывания от UART, управляет функциями приёмопередатчика
2) Регистр состояния UCSRA
3) Регистр данных UDR - представляет собой 2 регистра, расположенных по одному адресу (1 регистр для передачи, 2 - для приёма данных)
4) Регистр UBRR отвечает за скорость передачи данных. Задаются значения младшего (UBBRL) и старшего (UBBRH) байтов регистра
5) Биты регистра UCSRC задают формат кадра
Регистр UCSRB
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|
RXCIE | TXCIE | UDRIE | RXEN | TXEN | CHR9 | RXB8 | TXB8 |
RXCIE=1 и прерывания разрешены (бит I=1 в регистре SREG) : прерывание по завершению приёма по UART разрешено
TXCIE=1 и прерывания разрешены (бит I=1 в регистре SREG) : прерывание по завершению передачи по UART разрешено
UDRIE=1 и прерывания разрешены (бит I=1 в регистре SREG) : прерывание по опустошению регистра данных UART разрешено
RXEN=1 : активация приёмника, вывод D0 становится входом UART.
TXEN=1 : активация передатчика, вывод D1 становится выходом UART.
CHR9=1 : длина передаваемой посылки с становится равной 11 бит (9 бит данных + старотовый бит + стоп-бит).
Регистр UCSRA
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|
RXC | TXC | UDRE | RXEN | FE | OR | - | - |
Регист UCSRA информирует о состоянии UART
RXC=1: принятое слово данных перемещено из сдвигового регистра в регистр UDR. После чтения регистра UDR бит RXC сбрасывается в 0
TXC=1: символ в сдвиговом регистре передан полностью (включая стоп-бит), и из регистра UDR не ожидается новый байт данных.
UDRE=1: содержимое регистра UDR передано в сдвиговый регистр, т.е приёмопередатчик готов к передаче нового байта. Только после этого в UDR можно записывать новое значение. В противном случае можно потерять байт, который находился в UDR в ожидании отправки в сдвиговый регистр. Бит UDRE сбрасывается при записи данных в регистр UDR. При включении питания бит UDRE устанавливается в лог. 1.
FE=1: ошибка кадрирования. Ошибка кадрирования происходит, если стоп-бит не равен лог.1
OR=1: один из символов, переданный в UDR из сдвигового регистра не был прочитан перед поступлением следующего символа.
Настройка скорости передачи данных по UART
Скорость передачи данных по UART рассчитывается по формуле
f=Ф/(16(UBRR+1))
Ф - тактовая частота микроконтроллера
UBRR - значение регистра UBRR (состоит из значений младшего и старшего байтов UBBRH+UBBRL)
Таблица готовых значений UBBR для заданной частоты и скорости передачи данных
Значения скоростей передачи на передающим и принимающем устройствах должны совпадать! Также совпадать должны форматы передающихся кадров.
Формат кадра задаётся в регистре UCSRC
UCSRC.0 | UCSRC.1 | UCSRC.2 | Формат кадра |
0 | 0 | 0 | Слово данных 5 бит |
1 | 0 | 0 | 6 бит |
0 | 1 | 0 | 7 бит |
1 | 1 | 0 | 8 бит (стоит по умолчанию) |
1 | 1 | 1 | 9 бит |
В качестве примера рассмотрим следующий код. Он инициализирует UART микроконтроллера ATMega8 на скорости 9600 бит/сек и передаёт на терминал сообщение "ATMega8 UART Ready!". Далее в бесконечном цикле ведётся обработка сигналов, поступающих от терминала - если приходит '1', то лампочка, подключённая к биту 0 порта B загорается, если приходит '2' - лампочка гаснет.
int i;
int lng;
char mystr[]="Atmega8 UART ready!";
char rc;
void lampOFF()
{
PORTB.0=0;
}
void lampON()
{
PORTB.0=1;
}
void initUART()
{
UCSRB|=(1<<3)|(1<<4);
UBRRH=0x00;
UBRRL=0x33;
}
void main(void)
{
DDRB.0=1;
initUART();
lng=strlen(mystr);
for (i=0; i < lng; i++) {
while ( !( UCSRA & (1<<5)) ) {}
UDR=mystr[i];
}
while (1)
{
if ((UCSRA & (1<<7)))
{
rc=UDR;
}
switch (rc)
{
case '1': lampON(); break;
case '2': lampOFF(); break;
}
}
}