14. Протокол RS-232 и Bascom



Автор: WildCat

Протокол RS-232

На сегодняшний день RS-232 - устоявшийся протокол связи. Удивительно, что стандарт, описанный еще в далеких 60-х широко распространен и по сей день. Однако, формально название RS-232 не принадлежит к описанию стандарта.
Американская компания Electronis Industries Association разрабатывала способ соединения больших серверных машин с периферией, например терминалами. Разработка называлась "рекомендованный стандарт" ("recommened standard"), а число 232 было не более чем номером разработки. Гораздо позже она стала официальным стандартом EIA-232. В 1991 году была описана последняя версия протокола, EIA-232E. Однако наибольшее распространение получило всё же название RS-232, поэтому и мы будем применять его здесь.
RS-232 - это протокол последовательного обмена. По нему информация передается последовательно, бит за битом. Сам стандарт описывает два логических уровня:

- напряжение от -25 вольт до -3 вольт передает логическую единицу (1)
- напряжение от +3 вольт до +25 вольт передает логический ноль (0)



Как показано на рисунке, интервал от -3 до +3 вольт не определен. Но на практике это обычно не так. В большинстве случаев напряжение выше 2.5 вольт интерпретируется как логический ноль, все что ниже него - как логическая единица.
Электрические характеристики протокола достаточно суровы - все выходы должны выдерживать короткое замыкание, а все входы должны работать как триггер Шмитта. Это делает стандартный RS-232 порт ПК гораздо менее уязвимым, чем например, параллельный порт с его TTL уровнями.
RS-232 - асинхронный протокол. Это означает что тактовые импульсы не разделены с данными. Обе стороны должны знать скорость обмена данными (baud-rate) перед началом передачи. В оригинальной версии описывалась скорость в 20 000 бит в секунду. Сейчас используются скорости до 1 мегабита в секунду.
Этот стандарт описывает полностью аппаратный механизм "рукопожатия" (handshaking), используя несколько линий передачи данных. Мы воспользуемся тремя самыми важными:

- RxD: прием данных, пин порта 2
- TxD: передача данных, пин порта 3
- Gnd: земля, пин порта 5

Под портом мы имеем в виду стандартный коннектор DB9-M (папа) на вашем компьютере.

UART

UART расшифровывается как Universal Asynchronous Receiver Transmitter (универсальный асинхронный приемник-передатчик). Это оборудование на концах линии RS-232. В ПК или любом другом компьютере это чип на материнской плате под управлением центрального процессора. В контроллерах AVR это небольшая область кристалла, выделенная специально для этих целей. В AT90S2313 UART подключен к лапкам 2 (RxD) и 3 (TxD). Поскольку эти выводы являются портами ввода/вывода общего назначения, вам придется пожертвовать ими, если вам нужен UART.
UART берет на себя функции приема и передачи данных. При приеме он сам решает, когда опрашивать пин входа, чтобы определить, прислали ли 0 или 1. Когда прием байта завершен, он может сгенерировать прерывание, чтобы контроллер считал байт из входного буфера. При передаче UART считывает байт из выходного буфера и отсылает биты с нужной задержкой, согласно скорости обмена. Если выходной буфер пуст, UART также может сгенерировать прерывание, сообщив программе, что при необходимости можно отправить очередной байт.
Во встроенном в AVR UART используются стандартные логические уровни 0 и +5 вольт. Поэтому для согласования со стандартом RS-232 нужно использовать конвертер уровней типа MAX232:



Этот чип подгоняет уровни до нужного напряжения и инвертирует их. В MAX232 встроен инвертор и удвоитель напряжения, что позволяет получить -9 и +9 вольт, что достаточно для корректной работы.
Pin-to-pin совместимые аналоги этого чипа доступны у всех крупных производителей электроники.
Прочитайте даташит! Обычно емкости используемых конденсаторов меняются от 100 нанофарад до 10 микрофарад.



Вот собранный преобразователь на чипе National Semiconductor DS14C232CM:



Если как следует присмотреться, сверху можно разглядеть переменный резистор на 10 кОм. Он подключен к выходу -9 вольт. Это удобно, если вам нужно получить отрицательное напряжение например, для регулировки контрастности графического дисплея.

MAX232 на коленке

Далеко не всегда нужен чип-конвертер. Очень часто можно обойтись простым конвертером из двух тразисторов:



Конечно, это не полноценный конвертор, только инвертор уровней. Но он нормально работает с портами в ПК и ноутбуках (если такие монстры еще остались).
Напряжение с третьей лапки AT90S2313 инвертируется левым транзистором. Напряжение на выводе 2 (TxD) разъема DB-9 будет примерно между 0 и +5 вольт. Вывод 3 будет реагировать на напряжение от -9 до +9 вольт. Диод на базе правого транзистора ограничивает отрицательное напряжение -9 вольт примерно до -0.7 вольт. Уровень +9 вольт откроет транзистор, установив на 3 лапке контроллера (RxD) уровень в 0 вольт.

Еще проще!

Если вы хотите передавать данные только в направлении от контроллера к ПК, вы можете убрать правый транзистор
Учтите: эта схема попирает все стандарты RS-232. Она будет работать в большинстве случаев, но обязательно проверьте, как работает ваше оборудование, особенно на больших скоростях (выше 9600 бод).

Из AT90S2313 в COM-порт

Очень простая схема, для примера, будет выглядеть так:



В ней всего лишь контроллер, конвертер уровней и ЖКИ индикатор.

Скорость обмена RS-232

Скорость обмена в RS-232 определяется вашими настройками, но так же зависит от тактовой частоты микроконтроллера. Не все тактовые частоты дадут вам точную скорость обмена. Откроем вкладку Communications в настройках:



Здесь нужно обратить внимание на поле Error. Оно показывает отклонение внутренней скорости UART от выбранной вами в списке. Так например, для тактовой частоты 4 МГц и скорости 9600 бод, ошибка столь мала, что вы не заметите ошибок передачи. Но для высоких скоростей значение отклонения космически возрастает:



Естественно, столь высокий процент ошибок приведет к сбоям в передаче.
Если тактовая частота контроллера кратна скорости обмена, процент ошибок будет нулевым. Приведем пример.
Допустим, вы хотите подключить ваш контроллер к компьютеру на скорости 115 200 бод. Тогда отлично подойдет тактовая частота 11.0592 МГц, потому что если поделить 11 059 200 на 115 200, получим 96, а это целое число:



Еще одна "красивая" тактовая частота - 3.6864 МГц вместо 4 МГц. В магазинах вы можете поискать кварцы на следующие частоты, которые дадут вам 0% ошибок при скорости 115 200:
1.843.200
3.686,400
5.068,800
5.529,600
11.059.200
12.902,400
14.745,600
Так что отправляясь в следующий раз на барахолку, не забудьте взять калькулятор, он вам может пригодиться!

Чтение и запись в RS-232

Сперва выберите нужную вам скорость обмена в настройках компилятора (Options/Compiler/Communication) или используйте директиву

$Baud = 9600
Запись в RS-232 не сложнее, чем использование команды Print, а точнее, такая же точно:
Dim Name as String * 12
Dim Age as Integer

Name = "John"
Age = 36

Print "Name: " ; Name ; " Age: " ; Age
Этот код выведет в терминал "Name: John Age: 36"
Как обычно, используется оператор Print. Он может содержать набор строк и переменных, разделенных точкой с запятой ( ; ). Нестроковые переменные будут отформатированы перед выводом.
Чтение из RS-232:
Input "Name: " , Name
Опять же, употребление оператора Input такое же, как и у Print. Но обратите внимание, что Input использует запятую ( , ) в качестве разделителя, в то время как Lcd и Print - точку с запятой!

Полная программа для проверки RS-232 может быть такой:
rs-232-test.bas
$regfile = "2313def.dat"
$crystal = 4000000
$baud = 9600

Config Pind.6 = Output

Dim Firstnumber As Integer
Dim Secondnumber As Integer
Dim Sum As Integer

Do
  Set Portd.6
  Firstnumber = 0
  Secondnumber = 0
  Input "Enter first number : " , Firstnumber
  Input "Enter second number: " , Secondnumber
  Sum = Firstnumber + Secondnumber
  Print "Sum: " ; Sum
  Reset Portd.6
  Waitms 100
Loop

End
Скомпилируем её и прошьем контроллер. Затем откроем окно терминала (Tools/Terminal emulator). Эта программа позволит вам отсылать набранные символы в COM-порт ПК и принимать символы от контроллера.
Перед работой необходимо указать терминалу, что вы используете скорость 9600 и подключили устройство к нужному порту (например, COM1). Откроем окно настроек:



Сбросим наш AT90S2313, программа попросит ввести нас два числа и вернет их сумму:



Заметили ли вы, что все, что вы набираете после приглашения "Enter..." появляется в терминале? Bascom автоматически включает функцию эха. Но это не всегда хорошо, например, если вы хотите использовать другую программу для работы с контроллером, и она не может обрабатывать символы эха. Тогда используем директиву для его отключения:
Echo Off
В Bascom есть еще другие операторы ввода, Inputhex и Inputbin:
Dim Code as Byte
Inputhex "Type two-character hex-code: " , Code
Такой пример позволит вам ввести шестнадцатеричные коды, например, "A9" для десятичного числа 169.
Заметьте, что Inputhex не проверяет входную строку на наличие только символов 0-9 и A-F. Однако она урезает строку до 2 символов.
Inputbin может пригодиться, если вам нужно ввести коды, которые нельзя представить в виде ASCII символов. Например, если вы хотите передать 16-битный параметр:
Dim Tuneval as Word
Inputbin Tuneval
Этот код считает два байта из UART и положит их в переменную Tuneval. Количество считываемых битов зависит от типа используемой переменной. Запомните, что передачу нужно начинать всегда с младшего бита!
Давайте представим, что некий параметр Tuneword в ПК, который вы хотите передать, равен 12320 в десятичной системе. Это 3020 в шестнадцатеричной или 0011 0000 0010 0000 в двоичной.

Попробуем следующую программу:
Dim Tuneval as Word

Do
  Print "Enter bin-code: "
  Inputbin Tuneval
Loop

End
Теперь в терминале введите сначала пробел (ASCII код 20h), затем 0 (ASCII код 30h). Собственно, ничего не произойдет, но вы будете морально удовлетворены, что в памяти контроллера будут лежать введенные значения.

Чтение одного символа.
Иногда вам нужно только узнать, есть ли какой-нибудь символ в буфере UART. Тогда вы можете использовать команду Inkey:
Dim Testchar as Byte

Testchar = 0

While Testchar = 0
  Testchar = Inkey
Wend
Программа будет зациклена до тех пор, пока в буфере не появится какой-нибудь символ. Вы можете добавить в цикл какой-нибудь счетчик или даже таймер тайм-аута передачи. Возможно, такой код вам понравится больше:
Dim Testchar as Byte

Do
Loop until Inkey <> 0
Также вы можете использовать команды Waitkey и Ischarwaiting:
Dim Wtchar as Byte
Wtchar = Waitkey
Этот фрагмент заставит программу ждать, пока не введут какой-нибудь символ. Минус его в том, что здесь нельзя ввести проверку тайм-аута, и ваша программа может остаться в этой стадии навсегда!
Поэтому рассмотрим еще один пример:
Do
Loop until Ischarwaiting = 1
Он зациклит программу, пока не появится какой-нибудь символ в буфере. Затем его можно будет прочитать через Input или Inkey. Естественно, внутри цикла можно реализовать проверку тайм-аута.

Программный UART

Большинство контроллеров AVR имеют аппаратный UART на выводах 2 и 3. Но иногда вам может потребоваться использовать их с другой целью.
Bascom предоставляет возможность ПРОГРАММНОЙ реализации UART. Конечно, это значительно увеличит размер программы, но позволит вам самостоятельно назначить нужные выводы портов под него.
Лапки контроллера назначаются следующим образом:
Open "Comb.0: 9600 , 8 , n , 1" for Input As #1
Open "Comb.1: 9600 , 8 , n , 1" for Output as #2
Такая конфигурация назначит пин 0 порта B на вход (RxD), а пин 1 на выход (TxD). Оба они настроены на скорость 9600 бод, используют 8 бит даннх, не используют бит четности и используют один стоповый бит. Теперь в программе ссылка #1 будет использоваться для чтения, а #2 - для передачи данных.
software-rs232.bas
$regfile = "2313def.dat"
$crystal = 4000000

Config Pind.6 = Output

Dim Tstr As String * 4
Dim Num As Word

'open channel for output
Open "comb.1:9600,8,n,1" For Output As #1
Open "comb.0:9600,8,n,1" For Input As #2

Do
  Set Portd.6
  Waitms 100
  Reset Portd.6
  Print #1 , "text: "
  Input #2 , Tstr
  Print #1 , Tstr
  Print #1 , "number: "
  Input #2 , Num
  Print #1 , Num
Loop

End
Обратите внимание, что программный UART не посылает эхо. Еще одно отличие, что после передачи каждой строки передаются символы перевода строки/возврата каретки.

Программный UART также использует команды Print, Input, Inputhex, Inkey, Waitkey и Ischarwaiting. Посмотрим, как изменится их использование в этом случае:
Var = Inkey(#2)
Var = Waitkey(#2)
Var = Ischarwaiting(#2)

Если программный порт UART можно открыть, то вполне логично, что его нужно и закрывать:
Close #1
Close #2
Тогда после завершения обмена и закрытия портов, вы можете использовать пины для других целей.

 



DECADALAB ALFA