044-UART. Применение в электронных проектах.

Автор: | 15.06.2010

ТитлРаз уж я буду использовать UART для связки устройств блога с Вашими проектами немного расскажу как он устроен и как им пользоваться.

Универсальный асинхронный приемопередатчик (UART) довольно старый и распространенный интерфейс. До недавнего времени разъем COM порта (тот-же UART только уровни напряжения другие) был обязательным атрибутом каждого компьютера. Теперь COM порт постепенно «отмирает» и если на «башнях» он еще не редкость, то на ноутбуках его уже нет и в помине. Но в виду простоты и популярности интерфейса подавляющее большинство микроконтроллеров имеет UART в составе своей периферии. И если персональный компьютер UART перестает удовлетворять из-за низкой скорости и невозможности расширения, то для микроконтроллеров интерфейс удобен и использование его будет продолжаться.
Раз UART есть во многих микроконтроллерах, значит мы его будем использовать как один из интерфейсов связи устройств блога с Вашими электронными устройствами.
Для начала немного теории работы интерфейса (без лишних подробностей). Для связи по интерфейсу UART используется две ножки контроллера  RXD – для приема сообщений (Receiver) и TXD – для передачи сообщений (Transmitter). UART — полнодуплексный интерфейс. Это значит, что приемник и передатчик работают независимо друг от друга. Более того, передатчик или приемник можно отдельно отключить, освободив ножку контроллера для других нужд. Передача (соответственно и прием) сообщений осуществляется фиксированными пакетами битов (такой пакет называют кадром). Кадр состоит из старт-бита (с него начинается каждый кадр), битов данных (может быть от 5 до 9 бит), бита проверки четности (проверка правильности передачи данных) и одного или двух стоп-битов (сигнал об окончании кадра).

Формат кадра UART

где:
IDLE — ожидание обмена — должна быть 1;
St — Старт-бит — всегда 0;
(n) — Биты данных — может быть от 5 до 9 бит;
P — Бит четности;
Sp — Стоп бит — всегда 1.

Если посылка содержит более одного байта, каждый следующий байт передается отдельным кадром. Передача (и прием) данных ведется на определенных фиксированных частотах (измеряется в Бод=бит/сек) от 600 до 128 000 Бод. Условием правильной работы порта есть задание одинаковых параметров, как для приемника, так и для передатчика (скорость, количество бит данных, бит четности, количество стоп битов).

Договоримся о формате кадра (настройках UART) для устройств блога:
Скорость передачи – 9600 (это в пределах килобайта в секунду);
Количество бит данных – 8 (наиболее удобно работать);
Бит четности – Even (производится проверка на четность);
Количество стоп-бит – 1;
В сокращенном варианте это выглядит так:
Baud Rate: 9600, 8 Data, 1 Stop, Even Parity

Еще UART может работать в синхронном режиме (для этого задействуется еще одна ножка контроллера) и поддерживать адресацию множества устройств. Но так как наши устройства несложны и нам не нужны данные функции, то рассматривать мы их не будем.

Если нужны дополнительные возможности, то полное описание UART есть в datasheet на микроконтроллер – обращайтесь к нему.

Для того чтобы устройство с блога начало работать с Вашим проектом через интерфейс UART нужно:
1 Подключить устройство блога к соответствующим ножкам микроконтроллера.
2 Настроить приемо-передатчик UART Вашего контроллера. Для этого в соответствующие порта ввода/вывода записать определенные значения.
3 Иметь (написать)  процедуры приема/передачи сообщений по UART в Вашей программе.

Теперь рассмотрим подробно каждый пункт:


1 СОЕДИНЕНИЕ УСТРОЙСТВ ПОСРЕДСТВОМ UART.

Тут все просто:
— если планируется и прием и передача — устройства соединяются по двум линиям — TX_устройства с RX_проекта и TX _проекта с RX_устройства (здесь и далее под «устройством» я буду понимать устройство с блога, а под «проектом» — Ваш электронный проект);
— если нужен только прием (например принимаются данные с клавиатуры) — TX_устройства с RX_проекта;
— если нужна только передача (например передаются данные на устройство отображения) — TX _проекта с RX_устройства.

Соединение устройств по UART


2 НАСТРОЙКА ПРИЕМО-ПЕРЕДАТЧИКА UART.

Как мы договорились выше, формат кадра для наших устройств:
Baud Rate: 9600, 8 Data, 1 Stop, Even Parity
Для работы в с этим форматом кадра нужно в разделе инициализации устройств в Вашей программе, записать соответствующие значения в нужные порта ввода/вывода контроллера. Для этого нужно открыть раздел USART datasheet’а на Ваш микроконтроллер и выбрать/вычислить необходимые значения. Но можно сделать все гораздо проще – использовать автоматические настройщики периферии – CodeWisard’ы.
Возьмем для примера микроконтроллер Attiny2313 (по аналогии можно настроить любой микроконтроллер) и настроим UART в разных языках программирования.

Для начала — Algorithm Builder.
Тут все предельно просто – создаем проект (Файл/Новый). Выбираем микроконтроллер и частоту задающего генератора в Опции/Опции проекта… (ATtiny2313, внутренний задающий генератор на 8МГц). В панели инструментов жмем кнопочку «S» — настройщик управляющих регистров» выбираем USART и в открывшемся окошке заполняем все как на картинке. Там все подписано и понятно.

Инициализация UART в Algorithm Builder

Жмем «ОК».  Готово – UART проинициализирован и готов к работе.
Если нужен только приемник или только передатчик ставим только нужную галочку – незадействованную ножку можно использовать как порт ввода-вывода.

Так как в программе будут разрешены прерывания, нужно перед инициализацией USART установить указатель стека на конец памяти («S»/Stack Pointer SP) и озаглавить вершину блока ключевым словом «Reset».


В ассемблере. Честно говоря, я не знаю, есть ли в асемблерах для AVR настройщики периферии, но даже если нет, простое решение использовать все тот же Algorithm Builder. В окошке настройки USART, в правой части, прописаны мнемокоманды (Operations), обеспечивающие выбранные характеристики. Перевести их в ассемблерный код не составит труда.

Инициализация UART в ассемблере

Переводим в ассемблерные команды.

;USART initialization
;Communication Parameters: 8 Data, 1 Stop, Even Parity
;USART Receiver: On
;USART Transmitter: On
;USART Mode: Asynchronous
;USART Baud Rate: 9600
 
uart_init:	LDI 	R16, $00
		OUT 	UBRRH,R16
		LDI 	R16, $33
		OUT 	UBRRL,R16
 		LDI 	R16,$26
		OUT 	UCSRC, R16
		LDI 	R16,$00
		OUT 	UCSRA, R16
		LDI 	R16,$98
		OUT 	UCSRB, R16

Готово!

С — в программе CodeVisionAVR. CodeVision содержит свой настройщик периферии (CodeWisard), еще похлеще чем у Algorithm Builder’а. Для генерации настроек UART, нажимаем на значок шестеренку (CodeWisardAVR) на панели инструментов. В открывшемся окошке сначала выбираем вкладку Chip в ней выбираем микроконтроллер и устанавливаем частоту, с которой будет работать задающий генератор. Далее выбираем и заполняем вкладку USART в соответствии с нужными характеристиками (если нужен только приемник или только передатчик ставим соответствующую галочку).

Инициализация UART в CodeVisionsAVR

// USART initialization
// Communication Parameters:
// 8 Data, 1 Stop, Even Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
 
UCSRA=0x00;
UCSRB=0x98;
UCSRC=0x26;
UBRRH=0x00;
UBRRL=0x33;

Сохраняем сгенерированный проект (File\Generate, Save and Exit) — готово. Создан проект со всеми нужными установками для UART. В проекте инициализируется и другая периферия (зачастую не нужная).  После создания проекта его можно подкорректировать – удалить все не нужное.


3 СОЗДАНИЕ ПРОЦЕДУР ОБРАБОТКИ СООБЩЕНИЙ UART.

Небольшое отступление.
Работу с UART можно организовать различными способами. Например:
— просто ожидать в теле программы когда придет сообщение, постоянно проверяя бит приема сообщения;
— разрешить прерывание и в теле прерывания обрабатывать сообщение;
— создать буфер куда по прерываниям будут загоняться сообщения, а уже в теле программы, «по свободе», считывать из буфера значения;
— еще куча вариантов – выбор за Вами.
Но, исходя из того, что сообщения от устройств, в большинстве своем, единичные (один байт) и не слишком часты (взять, к примеру, клавиатуру – пару нажатий в секунду, не больше), наилучшим вариантом, в плане экономии памяти и скорости обработки, будет обработка сообщения UART в теле прерывания. Под обработкой я понимаю чтение регистров, проверка на правильность приема и сохранение принятого байта в глобальной переменной (своего рода буфер в один байт). Если предполагаются несложные манипуляции с принятым байтом можно их тоже организовать в теле прерывания.

В дальнейшем я буду ориентироваться на такой алгоритм работы, если другой не будет более оправданным.

Algorithm Builder.
Прием данных осуществляется в процедуре обработки прерывания по окончании приема байта (кадра). Принятый байт записывается в глобальную переменную FromGCnDevice. В теле программы проверяется значение FromGCnDevice ели оно нулевое ничего не принято.

Прерывание приема байта

Если работа с принятым значением несложна можно это сделать прямо в теле обработки прерывания.  
Передача данных производиться без использования прерываний и буфера (аппаратно у UART передатчика существует буфер на 2 байта). Это значит, что комфортно будут передаваться только единичные байты (что мы и планируем делать). Если зарядить сразу строку данных, то микроконтроллер будет заниматься только этой строкой.

Передача байта по UART

Ассемблер.
Прием байта осуществляется в прерывании, результат остается в регистре r17 (если нужно сохраните в SRAM).

;Обработка прерывания по окончании приема байта
 
		PUSH	R16
		IN	R16,SREG
		PUSH	R16
 
		IN	R16,UCSRA	;Читаем статус из UCSRA
		IN	R17,UDR		;Читаем данные из UDR
		ANDI 	R16,$1C
		BREQ	_END		;Проверяем на ошибки
		CLR  	R17
 _END:
 					;в R17 находится принятый байт
		POP	R16
		OUT	SREG,R16
		POP	R16
		RETI

Передача байта

		LDI	R16,значение
		SBIS 	UCSRA,UDRE
		RJMP	PC-1 		; ждем готовности принять байт
 		OUT	UDR, R16	; шлем байт


С — в программе CodeVisionAVR.
Тут все просто CodeWizard вместе с инициализацией UART создает и процедуры для приема-передачи. Единственно что можно тут поковырять так это выкинуть буфер для приема (если разрешить прерывания по приему или передаче автоматически создается буфер). Если этот буфер не нужен процедура обработки прерывания приема байта и процедура передачи могут выглядеть так:

// Глобальная переменная - полученные даные от устройства
// Эсли FromGCnDevice==0 - ничего не получено
char FromGCnDevice;
 
// Обработка прерывания окончания приема байта
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status;
// Получаем байт статуса и данных
status=UCSRA;
FromGCnDevice=UDR;
// Если произошла ошибка при приеме байта то FromGCnDevice=0
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))!=0)FromGCnDevice=0;
}
 
// Процедура передачи байта
void ToGCnDevice (char c)
{
// Ждем окончания передачи предідущего байта
while ((UCSRA & DATA_REGISTER_EMPTY)==0);
// Передаем байт
UDR=c;
}


Во и все про UART. Этого должно хватить для того чтобы подключить устройство к Вашему проекту. По анологии приведенных примеров легко все можно проделать и для других микроконтроллеров АВР.
Ниже оставляю архивы  программ с примерами работы UART для ATtiny2313.
044-UART-CWAVR.zip [7.82 KB] - Пример проекта созданного автоматически CodeWisionsAVR
044-UART-AB.zip [5.11 KB] - Пример программы для работы с UART в Algorithm Builder


P.S. Я слабо знаю С и Asm, поэтому пинать и кидать тапками — разрешается! Мы все учимся.


Инициализируется

(Visited 2 126 times, 9 visits today)

There are 25 comments

Комментарии подгрузятся после небольшой паузы.