Дуже часто потрібно зв’язати мікроконтролер з комп’ютером. Найпростіше для цього використовувати інтерфейс 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
;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
;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