Site icon Меандр — занимательная электроника

Работа с интерфейсом UART в микроконтроллерах AVR

Очень часто требуется связать микроконтроллер с компьютером. Проще всего для этого использовать интерфейс UART. В этой статье постараюсь подробно рассказать что это за интерфейс и как с ним работать.

Интерфейс UART имеет две сигнальные линии – RxD и TxD. RxD – линия приёма данных, а TxD – передачи. Чтобы подключить микроконтроллер к компьютеру нужен какой-нибудь переходник, о котором я расскажу позже, а сейчас покажу как подключить этот самый переходник к микроконтроллеру. Подключается он по такой схеме:

Как видно, всё очень просто. Земли переходника и микроконтроллера объединяются, а сигнальные линии соединяются крест-накрест, то есть RxD микроконтроллера на TxD переходника, а RxD переходника на TxD микроконтроллера, поскольку RxD – линия приёма, а TxD – передачи.

 

Переходники.

Как я и говорил, расскажу немного о переходниках. Существуют переходники USB<->UART и RS232<->UART. Соответственно первые подключаются к компу через USB порт, а вторые – через RS232 aka COM порт. Переходник  RS232<->UART можно собрать на специальной микросхеме, самая известная из них – MAX232. Вот схема такого переходника:

Также есть микросхема MAX3232. Это аналог MAX232, только выходные уровни у неё не 5В, а 3,3В. Ещё можно собрать такой переходник на 2-х транзисторах.

Переходник USB<->UART можно собрать на микроконтроллере, а можно на специальных микросхемах вроде FT232RL или PL-2303. Также в качестве такого переходника можно использовать датакабель от старых Сименсов.

 

Как проверить переходник?

Проверяется переходник очень просто. Нужно соединить выводы RxD и TxD и попробовать послать байт из терминальной программы на компьютере. Он должен тут же придти обратно.

В качестве терминальной программы я использую Terminal(скачать её можно в конце статьи). Итак, запустим терминалку и попробуем проверить переходник.

Для начала в графе “COM port” выберем порт, выберем скорость (я предпочитаю 9600) и нажмём “Connect”. Теперь мы подключились к порту и попробуем что-нибудь отправить. Как видно, мой переходник отлично работает и переданные байты возвращаются.

 

Подключаем микроконтроллер.

Переходник собран и работает и теперь мы попробуем написать простенькую программку для микроконтроллера, которая будет просто отправлять символ в порт.

Для начала разберемся с инициализацией. Вот код инициализации:

.equ Clock = 8000000

.equ BaudRate = 9600

.equ UBRR_Value = Clock/(16*BaudRate)-1

;======================================================

ldi r16,low(UBRR_Value)

out UBRRL,r16; Устанавливаем скорость

ldi r16,high(UBRR_Value)

out UBRRH,r16

;======================================================

ldi r16, (1<<RXEN)|(1<<TXEN); Подключаем приёмник и

out UCSRB,r16; передатчик.

;—————————————————–

ldi r16, (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1)

out UCSRC, r16; 8 бит данных, 1 стоп бит

 

Разберём этот код по порядку. Сначала мы определяем скорость, с которой нам нужно работать и тактовую частоту микроконтроллера. Тактовую обязательно нужно указать правильно, иначе вместо наших байтов в терминалку посыпется мусор всякий. Также, при работе с UART, нужно использовать как можно более стабильный тактовый генератор. Лучше всего внешнй кварц. После этого, вычисляется значение, которое нужно подгрузить в регистры, задающие скорость – UBRRL и UBRRH (младший и старший байты соответственно). После того, как скорость настроена, включается передатчик и приёмник записью единиц в биты RXEN и TXEN в регистре UCSRB. Давайте подробно рассмотрим значение других нужных нам битов этого регистра.

  • RXCIE, TXCIE и UDRIE – биты, разрешающие прерывания по приему байта, окончанию передачи байта и пустом регистре UDR соответственно. Установкой их в 1 разрешаем прерывания.
  • RXEN, TXEN – как я уже сказал, биты, включающие приёмник и передатчик соответственно. Установкой в 1 включаем приёмник или передатчик.

Остальные бты используются крайне редко и мы их рассматривать не будем. Теперь рассмотрим значение некоторых битов оставшихся двух регистров – UCSRA и UCSRC. Начнём с UCSRA:

  • TXC, RXC и UDRE – флаги прерываний по окончанию передачи, приёма и по опустошению регистра данных.
  • U2X – если записать в этот бит 1, то скорость UART удвоится.
  • UPE – флаг ошибки чётности. При ошибке он выставится в 1.

Теперь UCSRC. Тут нас интересуют лишь биты, задающие размер одного байта – UCSZ0 и UCSZ1. Для стандартной посылки 8 бит, нужно записать в них единицы.

Для прима и передачи данных по UART’у в микроконтроллере есть регистр UDR. Он двойной, то есть, чтобы отправить данные нужно их побайтно записать в этот регистр, а чтобы принять – дождаться окончания приёма и просто считать их из этого же регистра.

Итак, напишем программку, которая будет в цикле посылать буковку i в порт. Сразу приведу её текст:

;Пример работы с интерфейсом UART.
;Автор lpa
;http://radioelektr.ru
;======================================================

.include “m16def.inc”; Используем Мегу16

;======================================================

.equ Clock = 8000000
.equ BaudRate = 9600
.equ UBRR_Value = Clock/(16*BaudRate)-1

;======================================================

ldi r16,low(UBRR_Value)
out UBRRL,r16; Устанавливаем скорость

ldi r16,high(UBRR_Value)
out UBRRH,r16

;======================================================

ldi r16, (1<<RXEN)|(1<<TXEN); Подключаем приёмник и
out UCSRB,r16; передатчик.

;—————————————————–

ldi r16, (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1)
out UCSRC, r16; 8 бит данных, 1 стоп бит

;—————————————————–

Main:

sbis UCSRA,UDRE
rjmp pc-1; Ожидание готовности передатчика

ldi r16,’i’; Отправка байта
out UDR,r16

rjmp main; Зацикливаемся

;======================================================

В начале идёт процедура инициализации, а потом в цикле командой sbis мы проверяем, не опустошился ли регистр данных. Если UDR готов, мы посылаем байт в порт.

Как  и говорил, в микроконтроллерах AVR есть три прерывания,  которые относятся к этому интерфейсу – по приёму байта, по окончанию передачи и по опустошению регистра данных. Так что байт можно отправлять в прерывании по опустошению регистра данных. Немного перепишем программку, и она будет выглядеть так:

;Пример работы с интерфейсом UART.
;Автор lpa
;http://radioelektr.ru
;======================================================

.include “m16def.inc”; Используем Мегу16

;======================================================

.equ Clock = 8000000
.equ BaudRate = 9600
.equ UBRR_Value = Clock/(16*BaudRate)-1

;======================================================

.ORG $000
rjmp RST
.ORG $002
reti
.ORG $004
reti
.ORG $006
reti
.ORG $008
reti
.ORG $00A
reti
.ORG $00C
reti
.ORG $00E
reti
.ORG $010
reti
.ORG $012
reti
.ORG $014
reti
.ORG $016
reti
.ORG $018
rjmp Send_Byte
.ORG $01A
reti
.ORG $01C
reti
.ORG $01E
reti
.ORG $020
reti
.ORG $022
reti
.ORG $024
reti
.ORG $026
reti
.ORG $028
reti

.ORG INT_VECTORS_SIZE

;======================================================

Send_Byte:; Обработчик прерывания

ldi r16,’i’; Отправка байта
out UDR,r16

RETI

;======================================================

Rst:

ldi r16,low(RAMend)
out SPL,r16

ldi r16,high(RAMend)
out SPH,r16; Инит стека

;————————————————

ldi r16,low(UBRR_Value)
out UBRRL,r16; Устанавливаем скорость

ldi r16,high(UBRR_Value)
out UBRRH,r16

;======================================================

ldi r16, (1<<RXEN)|(1<<TXEN)|(1<<UDRIE); Подключаем приёмник и
out UCSRB,r16; передатчик.

;—————————————————–

ldi r16, (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1)
out UCSRC, r16; 8 бит данных, 1 стоп бит

SEI; Разрешаем прерывания

;—————————————————–

Main:

rjmp main; Зацикливаемся

;======================================================

Как видно, здесь в главном цикле никаких действий не производится, а байт отправляется в прерывании. Кстати, принимать бат тоже очень удобно в прерывании  по приёму байта.

Также интерфейс UART очень удобно использовать при отладке программ. К примеру, если нужно понять, проходит ли контроллер определённый кусок кода или нет. Для эт ого в нужном месте нужно просто отправить байт и из терминальной программы судить прорабатывает контроллер этот кусок кода или нет. Когда нужно узнать, что находится в определённом регистре, тоже можно слить содержимое регистра в порт.

 

radioelektr.ru

Exit mobile version