Интерфейс UART (Universal asynchronous receiver/transmitter, он же УАПП
- универсальный асинхронный приемопередатчик), несмотря на древность и простоту, все еще находит применение.
В его "семейство" входят протоколы RS-232, RS-422, RS-485 (вообще правильнее называть их, TIA/EIA, но RS как-то привычнее), по которым можно общаться с компьютерами или промышленным оборудованием.
AT-команды для всяких там модемов тоже посылаются по UART.
В одной из будущих статей мне понадобится передача данных на ПК, поэтому я решила не рассусоливать эту тему там, а выделить под нее отдельную статью.
Arduino хорош для начинающих и торопливых - программку для посылки символа или строки по UART можно написать буквально за минуту:
Но расплачиваться за это придется "толстыми" программами с неизвестным быстродействием и... потерей уважения более опытных радиолюбителей :)
Что ж, напишем такую программу на чистом C для AVR.
Для примера возьму ATmega328P, потому что она у меня есть на руках, для остальных AVR принцип примерно тот же, разве что названия регистров могут отличаться.
Далее будет вольный перевод даташита, если умеете читать по-английски, можете прокрутить :)
Формат данных UART
Данные по интерфейсу UART передаются в фреймах. Начинается сообщение с нулевого стартового бита, затем идет от 5 до 8 информационных бит, затем идет бит четности и единичный стоповый бит.
При передаче или приеме данные располагаются в регистре UDR0.
При работе в качестве буфера передачи UDR0 не может быть изменен, пока не установлен флаг UDRE0 в регистре UCSR0A.
После записи данных в буфер и включения передатчика, данные начнут последовательно выводиться на ножку TxD0.
Основные регистры настройки и мониторинга UART
UCSR0A
RXC0 - USART Receive Complete (прием завершен). Установлен, кода в буфере есть непрочитанные данные.
Может генерировать прерывание по приему.
TXC0 - USART Transmit Complete (передача завершена). Установлен, когда передача завершена и в UDR0 больше нет данных.
Может генерировать прерывание по передаче, при этом будет автоматически обнулен.
UDRE0 - USART Data Register Empty (регистр данных пуст). Равен единице, если UDR0 пуст и готов к получению новых данных.
Может генерировать прерывание по пустому буферу, при этом будет автоматически обнулен.
FE0 - Frame Error (ошибка фрейма). Равен единице, если стоповый бит в принятом сообщении оказался нулевым.
DOR0 - Data OverRun (ошибка переполнения). Равен единице, если буфер приема полон, а на подходе еще одно сообщение.
UPE0 - USART Parity Error (ошибка четности). Равен единице, если принятое сообщение не соответствует биту четности (не то число единиц, или бит пришел неправильный).
U2X0 - Double the USART Transmission Speed (удвоенная скорость передачи). Ускоряет скорость асинхронной передачи в 2 раза.
MPCM0 - Multi-processor Communication Mode (режим связи с несколькими процессорами). Включает, собственно, названный режим :)
В этом режиме сперва приходит байт с адресом, потом - байты с данными.
UCSR0B
RXCIE0 - RX Complete Interrupt Enable (включение прерывания по окончанию приема). Включает прерывание по флагу RXC0.
TXCIE0 - TX Complete Interrupt Enable (включение прерывания по окончанию передачи). Включает прерывание по флагу TXC0.
UDRIE0 - USART Data Register Empty Interrupt Enable (включение прерывания по пустому буферу). Включает прерывание по флагу UDRE0.
RXEN0 - Receiver Enable (включение приемника). Теперь пин RxD0 работает на прием данных.
TXEN0 - Transmitter Enable (включение передатчика). Теперь пин TxD0 работает на передачу данных.
UCSZ02 - Character Size (количество бит в сообщении). См. биты UCSZ0[1:0] в UCSR0C, в комбинации с которыми задает количество бит во фрейме.
RXB80 - Receive Data Bit 8 (бит 8 приема). Сюда принимается старший девятый бит, если установлен размер сообщения 9. Сперва нужно считать его, а потом уже остальные 8 битов в UDR0.
TXB80 - Transmit Data Bit 8 (бит 8 передачи). Отсюда отправляется старший девятый бит, если установлен размер сообщения 9. Сперва нужно записать его, а потом уже остальные 8 битов в UDR0.
UCSR0C
UMSEL0[1:0] - USART Mode Select (режим работы UART).
UPM0[1:0] - USART Parity Mode (режим проверки четности). Если проверка четности включена, и при приеме четность/нечетность нарушится, будет установлен флаг UPE0 в UCSR0A.
USBS0 - USART Stop Bit Select (выбор стоп-битов). Задает количество стоп-бит в передаваемом сообщении.
UCSZ0[0:1] - USART Character Size (количество бит в сообщении). В комбинации с UCSZ02 в UCSR0B задает количество бит во фрейме.
UCPOL0 - Clock Polarity (полярность тактов). В синхронном режиме работы задает, по фронту или спаду сохраняется/передается бит данных.
UBRR0L и UBRR0H
Baud Rate 0 Register Low and High - младший и старший регистры настройки скорости обмена.
В нормальном режиме работы скорость (BAUD, бодрейт) считается по формуле во втором столбце и зависит от частоты тактирования МК и значения в регистрах UBRR0H и UBRR0L.
По правой формуле можно посчитать значение UBBRn, старший байт полученного 16-битного числа помещается в UBRR0H, младший - в UBRR0L.
В ускоренном в 2 раза режиме вместо числа 16 в знаменателе подставляем 8.
Так, ну вроде все...
Теперь пример кода :)
Тут показана настройка UART (init_UART) и даны пара функций - для передачи без прерываний, просто с ожиданием, пока UDR не освободится (send_byte, send_buffer), и по прерыванию по опустошению UDR (send_buffer_by_interrupt).
В терминале все пишется... Программа стала весить в 3,5 раза меньше, а ведь в ней пишется сразу две строки :)
Для программирования и подключения МК или Arduino к компьютеру по USB нужен преобразователь интерфейса. Могу предложить вот такой:
Программ для общения по COM-порту много, в выборе может помочь обзорчик:
С недавнего времени решила немного больше писать об Arduino и микроконтроллерах AVR:
В будущем, надеюсь написать еще несколько статей об интерфейсе I2C, подключении RTC, LCD дисплея, шагового двигателя и прочей периферии.
Сперва будут статьи по Arduino, затем - по МК AVR, чтобы повышать сложность постепенно :)