Вы находитесь на странице: 1из 17

6/2/2. Работа модуля USART на передачу в асинхронном режиме.

“Въезд” в
режим слитной передачи массива байтов на примере реального устройства
(“причесываю бабушку”).

Да, “бабуся”, ну и видок у тебя … Никакой солидности.


В принципе, ты “бабуся” неплохая, только какая-то некоммуникабельная и строптивая.
“Кусаться-то” зачем?
Защищаешь свою “территориальную целостность” (каждому хочется “бабушку
взлохматить”)?
Это серьезный и вполне понятный довод, но ведь мы-то не какие-то “рвачи”
(“взлохматили” и смылись): если уж “взлохматили”, то и “причешем”.
Даже “макияж” сделаем и “румяна наведем”. И “помолодеешь” ты, “бабуся”, лет эдак
на …адцать.
Согласна?
Ну и ладушки. Поехали …
Функция модуля USART - “транспортный посредник” между двумя устройствами,
связанными между собой интерфейсом RS232.
Пример (в суперупрощенном виде).
В программе ПИКа “делаются какие-то полезные дела”, в результате которых
сформировано содержимое “значимого байта”, например, результата измерения.
Его нужно “переправить” в “епархию” компьютера, с целью, например, вывода
результата измерения на экран монитора.
Значит, в программе ПИКа, после окончания формирования байта результата
измерения, его нужно “переправить” (записать) в некий регистр, “привязанный” к
модулю USART.
Есть такой?
Есть. Это регистр специального назначения с названием TXREG (0-й банк, адрес 19h).
Он выполняет функцию “закромов”, из которых передатчик модуля USART
последовательно “черпает” текущие байты данных.
Соответственно, в процессе работы передатчика модуля USART, нужно периодически
“подбрасывать” в них (в “закрома”) байты данных (чтобы было что “черпать”).
Текущий байт, это байт, подлежащий обработке (переводу из параллельной в
последовательную форму) и “транспортировке” (передаче), по сигнальной “проволочине”,
в “потроха” системного блока компьютера, в одном цикле работы передатчика модуля
USART.
В них (“потрохах”) происходит обратный перевод байта из последовательной в
параллельную форму, после чего его “принимает в свое лоно” программа,
составленная (в Виндах) под “связку ПИК/компьютер”.
После этого, байт “находится в ее власти”, и она, по большому счету, может с ним
“вытворять все что угодно” (зависит от конкретной задумки конструктора).
В данном случае, эта программа, на экране монитора, визуально отобразит числовое
(или символьное) значение принятого байта (а можно и еще что-нибудь “сотворить”).
Теперь предположим, что компьютеру, с целью обеспечения продолжения дальнейшего
“диалога”, нужно сообщить ПИКу об этом “отрадном” событии (“моя твоя очень сильно
понимайт”).
Программа (та что в Виндах) “рождает” некий байт подтверждения.
Он переводится из параллельной в последовательную форму и, в соответствии с
алгоритмом RS232, поступает в другую линейную “проволочину”, которая
противоположным своим концом подключена ко входу приемника модуля USART ПИКа.
Приемник модуля USART ПИКа переводит принятый байт из последовательной в
параллельную форму.
После этого, он “оседает” в регистре специального назначения с названием RCREG
(0-й банк, адрес 1Ah), который “привязан” к приемнику модуля USART.
Далее, в программе ПИКа, байт подтверждения считывается из регистра RCREG, и
содержимое этого байта анализируется с целью ответа на вопрос типа “шлагбаум
открыть или закрыть”.
И т.д. Понапридумать можно много всяких вариантов “развития событий”.

1
Примечание: при “въезде” в “механизм” обмена данными между ПИКом и компьютером
по интерфейсу RS232, не стоит “забивать себе голову” тем, как именно, в компьютере,
происходит “сие таинство”.
Проще всего представить себе то, что в компьютере имеет место быть некий
“компьютерный модуль USART”, аналогичный модулю USART ПИКа, по умолчанию,
работающий в асинхронном режиме и только на стандартных скоростях
приема/передачи.
Естественно, что существует своя, “компьютерная специфика”, но “лезть” в нее, на
данном этапе, не стоит.
Что касается конкретных действий конструктора по обеспечению такого рода “счастья”,
то “не так страшен черт, как его малюют”.
Это означает то, что не нужно пугаться достаточно сложного алгоритма работы модуля
USART.
Почему?
Потому, что, практически весь, он (алгоритм) реализуется аппаратно (“силами и
средствами” модуля USART).
Программно реализуются только его настройки и простые процедуры, связанные с
“наведением порядка” в “очереди”, состоящей из передаваемых/принятых байтов
данных, записью в регистр TXREG передаваемого байта данных и чтением из регистра
RCREG принятого байта данных (“снятие сливок”).
Естественно, что во всем этом “хозяйстве” нужно четко ориентироваться.
Хотя настроек и не мало, но разобраться с ними гораздо проще, чем программно
реализовывать достаточно сложный алгоритм работы модуля USART.
Программно реализовать такой алгоритм можно (например, в PIC16F84A, который не
имеет модуля USART), но подобного рода работа, во всех отношениях, будет “дорого
стоить”.
Именно с целью “удешевления” этой работы и придуман модуль USART (“сервис”).
Красота! По-умному его настроил, “врезал” все это “хозяйство” в текст программы,
организовал простенькое взаимодействие модуля с программой ПИКа, и все …
После этого, в части касающейся работы с модулем USART, можно “собирать ромашки
и наслаждаться пением соловья”.
Как Вам такая перспектива?
По-моему, она выглядит очень заманчиво.
А раз это так, то, как говорится, “вперед и с песней”.
В предыдущем подразделе, основное внимание было акцентировано на асинхронном
режиме работы (не забывайте про слово “псевдоасинхронный”).
Этой “генеральной линии” буду придерживаться и далее.
Уточняю: асинхронный режим работы модуля USART является дуплексным.
Это означает то, что, в части касающейся порядка передачи/приема данных, тракты
приема и передачи модуля USART работают независимо друг от друга (но такт
общий), то есть, передача и прием могут осуществляться и одновременно, и не
одновременно, и комбинированно.
Короче, “полная демократия” (или “анархия”. Даже и не знаю, какое из этих слов
лучше отражает реалии).
Итак, настройка модуля USART, в основном, осуществляется с помощью 2-х регистров
специального назначения с названиями TXSTA и RCSTA (см. 67 и 68 даташита
PIC16F628A).
1. Формально, регистр TXSTA “рулит” настройками передатчика, но часть его битов
“рулит” общими настройками (и передатчика, и приемника).
2 Регистр RCSTA “рулит” настройками приемника.
Исключение - бит №7 (SPEN). Он “рулит” общей настройкой.
При настройке модуля USART, разработчики рекомендуют придерживаться
определенной последовательности действий, но то, как это преподнесено в даташите,
лично мне, не нравится по следующим причинам:
- имеет место быть четкое разделение на настройку передатчика и настройку
приемника (см. стр. 74 и 76 даташита PIC16F628A).
При этом, общие настройки дублируются (повторяются), что несколько не удобно.
- все “свалено в кучу”, а это “порождает режимные ветвления” (многовариантность,
неоднозначность).
2
Совершенно понятно, что таким образом разработчики сразу “убивают 2-х (а может
быть и более) зайцев”, но людям-то каково “распутывать этот клубок”?
В этом случае, вероятность “непонимаек” достаточно высока.
Не знаю где как, но “в моей епархии этот номер не пройдет”.
Разорву на куски (в буквальном смысле).
Сначала нужно “зубами за коготок зацепиться”, а потом, глядишь, и “всю руку
оттяпаем”.
А вот он и “коготок”, легок на помине:

Асинхронный режим. Работа только на передачу


(приемник не работает).

Сразу обращаю Ваше внимание на то, что выключение приемника это такая же
настройка, как и все остальные, и поэтому, в любом случае, понятие “настройка
приемника” “со счетов сбрасывать не нужно”.
Следующее: кроме раздельных настроек передатчика и приемника, имеют место быть
их общие настройки.
В большинстве случаев, то, что относится к общим настройкам, располагается в
начале процедуры настройки модуля USART, но это не есть жесткое правило (имеется
некоторая “степень свободы”).
Формально (по рекомендациям разработчиков), сначала должна быть произведена
общая настройка, а только после нее должны быть произведены раздельные настройки
приемника/передатчика.
Но биты, задействованные в общих настройках, входят в состав регистров TXSTA (№2
и 4) и RCSTA (№7), и поэтому настройку битов регистров TXSTA и RCSTA
эффективнее и разумнее производить не за несколько “функционально обособленных
присестов” (не возбраняется), а как можно более комплексно (желательно).
Ниже, в целях обеспечения эффективного “разложения по полочкам”, я функционально
разделил все типы настроек (см. выделение цветами), но в конечном итоге, все
“функционально обособленные присесты” сведутся к комплексной настройке.

Порядок настройки.
Примечание: зеленым цветом выделены общие настройки.

1. Настройка на работу “на вход” выводов RB1 и RB2.


Именно через эти выводы модуль USART “общается с внешним миром” (к ним
подключаются сигнальные “проволочины”).
Через вывод RB1 данные принимаются приемником USART.
Через вывод RB2 данные передаются передатчиком USART.
Значит, в битах №1 и №2 регистра TrisA нужно выставить единицы.
Настройка вывода RB2 на работу “на вход” не должна Вас смущать. Так определили
разработчики, и это просто нужно принять как данность.
Для PIC16F628A, это выглядит так:
movlw b’ххххх11х’ ; Выводы RB1,RB2 работают на вход,
movwf TrisB ; остальные – по задумке программы
; (к настройке USART не относится)
Напоминание: эти дела делаются в 1-м банке.
Для других типов ПИКов, эти 2 вывода могут иметь другую “прописку” (например, у
PIC16F873A, это выводы RC6 и RC7).

2. Выбор скорости обмена.


В модуле USART имеется только один генератор скорости обмена.
Это означает то, что, в пределах модуля USART, номинал скорости передачи равен
номиналу скорости приема (между ними, “плавающих”, фазовых расхождений нет), и
речь идет не о двух, отдельных настройках скоростей передачи и приема, а об одной,
комплексной настройке, которая должна производиться в любом случае (естественно,
если задействуется модуль USART).
Вопрос: “Что задает номинал скорости передачи/приема”?

3
Ответ: содержимое регистра специального назначения с названием SPBRG.
В области оперативной памяти PIC16F628A, он “лежит” в 1-м банке, адрес 099h.
Вопрос: “Какова привязка скорости передачи/приема к содержимому (числу) регистра
SPBRG”?
Ответ: она определяется формулами.
Вопрос: “Почему формулами, а не формулой”?
Ответ: потому, что имеется 2 скоростных режима - низкоскоростной режим и
высокоскоростной режим.
Их выбором “рулит” бит №2 регистра TXSTA с названием BRGH.
Если BRGH = 0, то включается низкоскоростной режим.
Если BRGH = 1, то включается высокоскоростной режим.
Соответственно, имеются 2 формулы.
С их помощью можно вычислить как величину ошибки (отклонения расчитанной
скорости от заданного, стандартного номинала), так и число, которое нужно записать в
регистр SPBRG.
Для низкоскоростного режима (бит BRGH = 0)
S = Fosc / {64(X + 1)}
S - желаемое значение скорости,
Fosc - частота применяемого кварца,
X - число, которое нужно записать в регистр SPBRG.
Пример для S = 2400 бит/с. и Fosc = 4 Мгц.
S = Fosc / {64(X + 1)}, следовательно, X = (F - 64S) / 64S
X = (4000000 – 64 x 2400) / 64 x 2400 = (4000000 – 153600) / 153600 = 25,041666…
Дробное число в регистр SPBRG не запишешь, следовательно, округляем до целого
значения:
X = 25
Тогда, реальное значение скорости, сформированной генератором скорости обмена
S = 4000000 / {64 x (25 +1)} = 2403,8461… = 2404 бод/с.
Ошибка = 100 x (2404 - 2400) / 2400 = 0,1666… = +0,17% (вполне приемлемо).
Итог: в регистр SPBRG нужно записать число .25.
А теперь откройте стр. 71 даташита PIC16F628A.
На ней имеется таблица с результатами расчетов.
Найдите табличку, в которой “прописан” кварц номиналом в 4 Мгц. и обратите
внимание на результаты расчета (аналогичного произведенному) для скорости 2400
бод/c.
Все “бъет”, за исключением расчетного значения ошибки (указано +1,67%).
???
Ошибка расчета ошибки (извиняюсь за тавтологию).
Вывод: доверяй, но проверяй.
Для высокоскоростного режима (бит BRGH = 1)
S = Fosc / {16(X + 1)}
Пример для S = 2400 бит/с. и Fosc = 4 Мгц.
S = Fosc / {16(X + 1)}, следовательно, X = (F - 16S) / 16S
X = (4000000 – 16 x 2400) / 16 x 2400 = (4000000 – 38400) / 38400 = 103,1666…
Дробное число в регистр SPBRG не запишешь, следовательно, округляем до целого
значения:
X = 103
Тогда, реальное значение скорости, сформированной генератором скорости обмена
S = 4000000 / {16 x (103 +1)} = 2403,8461… = 2404 бод/с.
Результат точно такой же, как и в случае низкоскоростного режима потому, что
64 х 26 = 16 х 104.
Ошибка = 100 x (2404 - 2400) / 2400 = 0,1666… = +0,17% (вполне приемлемо).
Итог: в регистр SPBRG нужно записать число .103.
А теперь откройте стр. 72 даташита PIC16F628A.
На ней имеется таблица с результатами расчетов.
Найдите табличку, в которой “прописан” кварц номиналом в 4 Мгц. и обратите
внимание на результаты расчета (аналогичного произведенному) для скорости 2400
бод/c.
Значение SPBRG “бъет”, а вот все остальное - нет.
4
Это еще один довод в пользу сделанного ранее вывода.
Что касается таблиц, опубликованных на стр. 70 … 72 даташита PIC16F628A, то не
стоит особо доверять “лежащим” в них результатам расчетов.
Лучше перепроверить (пересчитать). Так оно будет спокойнее.
Итак, в случае применения кварца на 4 Мгц. и необходимости обеспечения скорости
передачи/приема 2400 бод/с., есть 2 равноценных варианта:
- бит BRGH = 0, в регистр SPBRG записывается число .25 или
- бит BRGH = 1, в регистр SPBRG записывается число .103.
В данном случае, можно выбрать любой из этих вариантов.
Для других номиналов кварцев и других значений скоростей, расчеты настроек
производятся аналогично.
Примечание: по умолчанию, выставляется низкая скорость (BRGH = 0).
Например, для последнего случая (BRGH = 1), процедура установки номинала скорости
обмена, равного 2400 бод/с., будет выглядеть так:

movlw .103 ; Установка скорости обмена


movwf SPBRG ; 2400 бод/с.
movlw b'ххххх1хх' ; Высокая скорость
movwf TXSTA ; (BRGH=1).
Примечание: эти операции производятся в 1-м банке.

3. Установка асинхронного режима работы.


Этот выбор производится установкой в 0 бита №4 (SYNС) регистра TXSTA.
Тогда, расположенная выше группа команд, будет выглядеть так:

movlw .103 ; Установка скорости обмена


movwf SPBRG ; 2400 бод/с.
movlw b'ххх0х1хх' ; Асинхронный режим (SYNS=0),
movwf TXSTA ; высокая скорость (BRGH=1).

4. Подключение входа приемника и выхода передатчика к выводам RB1 и RB2


соответственно.
Это называется “разрешением работы последовательного порта” и эквивалентно
включению (или выключению) модуля USART.
Проще говоря, модуль USART нужно включить (по умолчанию, он выключен).
Для этого нужно установить в 1 бит №7 (SPEN) регистра RCSTA.

bsf RCSTA,SPEN ; Включение USART (SPEN=1).

Примечание: эта операция производятся в 0-м банке.


Если не “привязываться” к настройкам по умолчанию, то получается, что в регистре
RCSTA будет “лежать” число 1ххххххх
На этом общая часть настройки заканчивается.
Теперь нужно внести определенность в то, что выше обозначено как ххх.. .
Это есть не что иное, как настройки приемника и передатчика.

5. Выключение приемника (настройка приемника).


Этим “рулит” бит №4 (CREN) регистра RCSTA.
CREN = 0 - приемник выключен,
CREN = 1 - приемник включен.
По умолчанию, приемник USART выключен (см. табл. 12-6 на стр. 75 даташита
PIC16F628A) и поэтому можно не предпринимать “лишних телодвижений” по его
выключению.
Проще говоря, в данном случае, можно просто проигнорировать этот пункт.
А можно и “перестраховаться” (на любителя), например, так:
clrf RCSTA ; Выключение приемника.
bsf RCSTA,SPEN ; Включение USART (SPEN=1).
а можно и так:
5
movlw b'1хх0хххх' ; Выключение приемника
movwf RCSTA ; и включение USART (SPEN=1).
___________________________________________________________________

Промежуточный итог (с использованием настроек приемника по умолчанию).

bsf Status,RP0 ; Переход в 1-й банк.


movlw b’ххххх11х’ ; Выводы RB1,RB2 работают на вход,
movwf TrisB ; остальные – по задумке программы
; (к настройке USART не относится)
movlw .103 ; Установка скорости обмена
movwf SPBRG ; 2400 бод/с.
movlw b'ххх0х1хх' ; Асинхронный режим (SYNS=0),
movwf TXSTA ; высокая скорость (BRGH=1).
bcf Status,RP0 ; Переход в 0-й банк.

bsf RCSTA,SPEN ; Включение USART (SPEN=1).

ххх.. остались только в настройках передатчика (регистр TXSTA).

6. Настройка передатчика.

Бит №7 (CSRC - выбор источника такта).


Используется только в синхронном режиме работы модуля USART, а в асинхронном
режиме, его настройка не важна.
В подобных случаях, я “привязываюсь” к нулям, значит выставляю в бите №7 ноль.
Бит №6 (TX9 - разрешение 9-битной передачи).
Так как применяется 8-битная передача, то нужно включить 8-битную передачу
(TX9 = 0). При этом, 9-битная передача выключается.
Значит, выставляю в бите №6 ноль.
Бит №5 (TXEN - разрешение передачи).
Есть 2 варианта: либо сразу ее разрешить (TXEN = 1), либо, изначально, ее запретить
(TXEN = 0), но разрешить позднее (bsf TXSTA,TXEN), то есть, в самом начале цикла
передачи. Так как, с точки зрения простоты объяснения, первый вариант более
предпочтителен, то к нему и “привяжусь”. Значит выставляю в бите №5 единицу.
Бит №4 (SYNС - режим работы USART).
Эта настройка относится к общим настройкам и произведена ранее (SYNC = 0).
Бит №3 не используется и читается как 0.
Но так как, формально, в него нужно что-то записать, значит, выставляю в бите №3
ноль.
Бит №2 (BRGH - выбор скоростного режима).
Эта настройка относится к общим настройкам и произведена ранее (BRGH = 1).
Бит №1 (TRMT - флаг очистки сдвигового регистра передатчика).
Его можно только прочитать.
Значит, формально, выставляю в бите №1 ноль (а можно и 1).
Бит №0 (TX9D - 9-й бит передаваемых данных).
Так как 9-битная передача выключена, то в него можно записать любой уровень.
Значит, выставляю в бите №0 ноль.

Получилось вот что:


bsf Status,RP0 ; Переход в 1-й банк.
movlw b’ххххх11х’ ; Выводы RB1,RB2 работают на вход,
movwf TrisB ; остальные – по задумке программы
; (к настройке USART не относится)
movlw .103 ; Установка скорости обмена
movwf SPBRG ; 2400 бод/с.

6
movlw b'00100100' ; Асинхронный режим (SYNS=0), высокая
movwf TXSTA ; скорость (BRGH=1), 8-битная передача
; (TX9=0), разрешение передачи (TXEN=1).
bcf Status,RP0 ; Переход в 0-й банк.

bsf RCSTA,SPEN ; Включение USART (SPEN=1).

В части касающейся команд с №№4 … 7, можно произвести перестановку:

movlw b'00100100' ; Асинхронный режим (SYNS=0), высокая


movwf TXSTA ; скорость (BRGH=1), 8-битная передача
; (TX9=0), разрешение передачи (TXEN=1).
movlw .103 ; Установка скорости обмена
movwf SPBRG ; 2400 бод/с.

Ни к чему плохому это не приведет.


Зеленым цветом выделены общие настройки.
Синим цветом выделены настройки передатчика.
Используются настройки приемника по умолчанию, и поэтому они никак не выделены
(в программе их нет).
Итак, настройка модуля USART, под асинхронную передачу данных, закончена.

Передача данных.
Прежде чем осуществлять какие-то “телодвижения”, нужно “въехать в механизм”
передачи данных, иначе эти “телодвижения” будут “понятийнорастрепанными” (типичный
“ежик в тумане”).
Не трудно догадаться, что если речь идет о переходе от внутреннего, параллельного
интерфейса к внешнему, последовательному интерфейсу (а это и имеет место быть),
то без сдвигового регистра никак не обойтись.
Есть такой?
Есть. Называется он TSR (см. рис. 12-4 на стр. 74 даташита PIC16F628A).
Он расположен в “дебрях” модуля USART и напрямую управлять им нельзя.
Байт данных автоматически (аппаратно) загружается в него (через входы
предустановки) с 8-ми выходов регистра TXREG, то есть, того регистра, в который
нужно записать байт данных, подлежащий передаче.
Почему, в качестве “посредника”, используется регистр специального назначения
TXREG?
Значит он должен чем-то отличаться от регистра общего назначения?
Общая особенность регистра TXREG состоит в том, что он аппаратно “вмонтирован” в
структуру передатчика модуля USART.
А “детальная” его особенность состоит в том, что, сразу же после окончания записи
байта данных в регистр TXREG, аппаратно (в “автомате”) “запускается механизм” его
(байта) передачи.
Он может быть запущен либо сразу же после окончания записи байта данных в
регистр TXREG (если TSR пуст), либо после “подхода его очереди” (если TSR не
пуст).
Последнее происходит в том случае, когда сдвиговый регистр (TSR) еще не
“выплюнул” находящийся в нем, текущий байт данных (об этом – см. ниже).
Если программа ПИКа, в части касающейся процедуры передачи байтов данных,
организована правильно, то конструктор “отдыхает” (передатчик USART “трудится в
поте лица”).
Теперь возникает хитрый вопрос: “Как организовать эту самую “правильную” передачу
байтов данных”?
Рассуждаем.
Предположим, что первый байт данных “улетел” (из TSR), а в очереди их - “тьма
тьмущая”, и “хвост” ее (очереди) “теряется в дали”.
Когда “подбросить” в регистр TXREG следующий байт?
А затем следующий и т.д.
7
Таким образом, речь идет о некой “очереди” из “несознательных объектов”,
“вожделеющих пробраться к кормушке”.
Следовательно, нужно срочно “наводить порядок в этой очереди”, иначе, “в своем
эгоистическом стремлении добраться до этой самой кормушки”, один байт данных
“наедет” на другой, и будет форменное безобразие (как в очереди за водкой во
времена борьбы с алкоголизмом).
Значит нужен “строгий и неподкупный милиционер” с “дубинкой”: если “кто-то без
очереди лезет” - “бац по почкам”, и порядок в наличии.
Функцию этого “строгого и неподкупного милиционера” (попробуйте-ка “подкупить
железяку”… Вот бы нам таких гаишников …) выполняет флаг TXIF (бит №4 регистра
PIR1. Адрес регистра 0Ch).
Формально, он следит за тем, загружен ли регистр TXREG байтом данных (TXIF = 0)
или нет (TXIF = 1), но, вследствие того, что регистры TXREG и TSR аппаратно друг к
другу “привязаны”, состояние флага TXIF может служить критерием окончания передачи
(или нет) текущего байта данных (этим “рулит” сдвиговый регистр TSR).
В этом случае, логика достаточно простая: пока текущий байт данных не будет
передан (байт считается переданным, если закончилась передача его бита №7), флаг
TXIF запрещает загрузку в сдвиговый регистр (TSR) следующего байта данных.
Только вот делает он это опосредованно (косвенно), через регистр TXREG (напоминаю,
что флаг TXIF реагирует только на содержимое регистра TXREG).
Вот Вам и типичный “хитрый, задний проход” (косвенное воздействие через аппаратную
“привязку”) во всей своей “мозгозаворотной красе”.
Примечание: “а бабушка-то с гонором оказалась. Не внемлет. На облом так и
нарывается. Пусть пеняет на себя. Будем обламывать”.
Как только текущий байт данных будет передан, то есть, “выпихнут” из регистра TSR
(TXIF устанавливается в 1), флаг TXIF “допускает к кормушке” следующий байт
данных.
И т.д., до тех пор, пока вся “очередь” не закончится.
В этом случае, “милиционер отдыхает от трудов праведных” и ожидает следующую
партию несознательных “клиентов”.
Еще раз напоминаю, что флаг TXIF ориентирован на регистр TXREG, который еще
называют буфером передатчика USART (а это так и есть).
Флаг TXIF это флаг прерывания, которое, если оно разрешено, происходит в конце
загрузки каждого байта данных в регистр TXREG.
Особенность этого флага заключается в том, что, вне зависимости от того, разрешено
прерывание от передатчика USART или оно запрещено, флаг TXIF работает.
Ранее мы с подобным сталкивались, например, при работе с флагом прерывания по
окончанию записи в EEPROM память с названием EEIF, но в отличие от него, флаг
TXIF программно не сбрасывается.
Он сбрасывается только аппаратно, что означает: состояние флага TXIF можно только
прочитать.
В данном случае, о прерываниях от передатчика USART речи не идет, и флаг TXIF
используется не в “контексте” прерываний, а в “контексте милиционера”.
Уточняю логику работы флага TXIF:
- после записи в регистр TXREG байта данных, считается, что регистр TXREG полон.
В этом случае, TXIF = 0.
- после “выпихивания”, из регистра TXREG, ранее записанного в него байта данных (в
сдвиговый регистр), считается, что сдвиговый регистр пуст.
В этом случае, TXIF = 1.
Обращаю Ваше внимание на то, что байт данных именно “выпихивается”
(“отфутболивается”) из регистра TXREG в регистр TSR (“тело перемещается из пункта
А в пункт Б”), а не копируется (“размножается”). Подробнее об этом - ниже.
Передача текущего байта занимает какое-то время.
Следовательно, прежде чем приступить к передаче следующего байта данных, нужно
“переждать” время передачи предыдущего (текущего) байта данных.
Критерием окончания передачи байта данных является “опустошение” регистра TXREG.
При этом, TXIF устанавливается в единицу.
“Ломать голову” по поводу величины этого “пережидания” не стоит, так как на основе
флага TXIF можно организовать простенькую (но эффективную), “плавающую” задержку:
8
CYCLE ..................................
..................................
movwf TXREG ; Загрузка байта в буфер передатчика.
btfss PIR1,TXIF ; Байт данных передан или нет ?
goto $-1 ; Если байт еще не передан, то ожидаем.
; Если байт передан, то программа
; исполняется далее.
..................................
goto CYCLE ; Переход на начало цикла передачи
; следующего байта данных.

Обратите внимание на то, что байт данных должен копироваться в регистр TXREG из
регистра W.
Другого просто не дано.
После окончания передачи текущего байта, TXIF = 1, что, в конечном итоге, приводит к
переходу на новый цикл передачи байта данных и соответственно, к передаче
следующего байта данных.
И так далее.
Как видите, в программном отношении, эта базовая процедура очень простая.
Очень часто, количество байтов данных, предназначенных для передачи, “ставится на
счетчик”.
После окончания их передачи, рабочая точка программы выходит из подпрограммы
работы с модулем USART и далее “творит всякие полезные дела”.
На следующем полном цикле программы, она опять входит в эту ПП и т.д., и т.п. (“до
посинения”).
Передача байтов данных может быть осуществлена и без “постановки на счетчик”.
Понапридумать можно много всякого. Это уже кто во что горазд.
Этим достаточно простым объяснением (на программном уровне) можно было бы и
ограничиться, но тогда “за кадром” остается, применяемый в передатчике USART, так
называемый принцип слитной передачи данных.
Именно специфика этого принципа и “накладывает отпечаток” на работу флага TXIF,
делая его “хитрым” флагом.
“Въезд” в принцип слитной передачи данных позволяет глубже понять “механизм”
работы передатчика USART, а это есть залог успешного преодоления возможных
затруднений, связаных с работой модуля USART.
Принцип слитной передачи данных основан на совместной работе нескольких
регистров.
В данном случае, речь идет о двух регистрах: TXREG (буфер передатчика) и TSR
(сдвиговый регистр).

9
Логика работы этой “связки” такая:
До начала передачи массива байтов данных, оба регистра пусты (по нулям).
Соответственно, TXIF = 1.
Если в регистр TXREG происходит запись байта данных, а регистр TSR пуст, то байт
данных, сразу же после его записи в TXREG, переписывается из TXREG в TSR.
При этом, речь идет не о копировании байта данных из TXREG в TSR, а о
перемещении байта данных из TXREG в TSR (об этом я говорил выше).
Иными словами, 1-й байт передаваемого массива байтов, “транзитом проскакивает”
через регистр TXREG.
Это происходит очень быстро и поэтому флаг TXIF устанавливается в 0 на очень
короткое время (см. “всплеск” в начале самой нижней эпюры рис. 1).
Таким образом, к началу сдвигов содержимого регистра TSR, регистр TXREG будет
пуст (свободен), и в него можно записывать следующий, 2-й байт данных, причем, он
может быть записан в регистр TXREG до окончания передачи текущего (в данном
случае, 1-го) байта данных, то есть, в любой момент интервала времени его
“выпихивания” из регистра TSR.
Но в этом случае, “картина” уже другая, так как регистр TSR не пуст, а полон, и
регистр TXREG “не может аппаратно переместить (отдать) свой байт” в регистр TSR.
А раз это так, то 2-й байт данных уже не будет “переправлен транзитом” в регистр
TSR, а “заложится на хранение” в регистр TXREG и будет в нем “дожидаться своей
очереди” (именно поэтому регистр TXREG и называется буфером передатчика USART).
Значит, на время этого хранения, регистр TXREG заполнится, и флаг TXIF установится
в 0.
Вот Вам и критерий “пережидания”, о котором шла речь выше (“уход” в “плавающую”
задержку).
Флаг TXIF будет находиться в нулевом состоянии в течение всего времени
“выпихивания”, из регистра TSR, текущего байта данных.
Концом этого “выпихивания” считается правая “граница” бита №7 текущего байта
данных.
В момент “перехода этой границы” (бит №7 “выпихнут”), флаг TXIF устанавливается
в 1.
Следовательно, в соответствии с логикой “плавающей” задержки, рабочая точка
программы “вырвется” из “плавающей” задержки и “уйдет” на следующий цикл
передачи байта данных.
Какого байта данных?
2-го, то есть, того, который “лежит на хранении” в регистре TXREG (см. выше).
Так как “бег по кольцу” требует некоторого времени, то запись, в регистр TXREG, 3-го
байта данных произойдет с некоторой задержкой относительно правой “границы” бита
№7 (последнего) байта данных, “выпихнутого” из регистра TSR.
Эта задержка может быть различной величины (зависит от конкретной программы), но
она не отражается на длительности стопового бита по той простой причине, что если
стоповый бит начал формироваться (а это и имеет место быть, так как имеется
указанная выше задержка), то, из-за его “привязки” к такту (к фронту тактовой
последовательности импульсов) генератора скорости обмена (BRG), он сформируется
до конца.
Проще говоря, стоповый бит не будет “обрезан”, а сформируется полностью.
Исключением является только тот случай, когда интервал времени между выходом
рабочей точки программы из “плавающей” задержки и загрузкой в регистр TXREG
следующего байта данных, превышает время “выпихивания” текущего байта данных из
регистра TSR.
В этом случае, стоповые биты будут на какое-то время затянуты, и речь идет не о
слитной передаче массива данных, а о “побайтной” передаче массива данных
(моя “самодеятельность”. Может быть это определение и не слишком корректно, но, я
надеюсь, что его смысл Вам понятен).
“Побайтную” передачу массива данных можно рассматривать как способ передачи
массива байтов (по скорости, не самый рациональный) посредством организации (тем
или иным способом) программной задержки между началами передачи предыдущего
кадра и последующего кадра, величиной более интервала времени передачи одного
кадра.
10
При использовании такого способа передачи, состояние флага TXIF проверять не
нужно.
Зачем проверять короткие “всплески” (толка от этого абсолютно никакого)?
На большее, чем серия коротких “всплесков”, можно и не расчитывать, так как байты
данных будут “транзитом проскакивать” (очень быстро) через регистр TXREG.
В этом случае, за счет фиксированной задержки перехода на обработку следующего
байта данных, загрузка в регистр TXREG следующего байта данных гарантированно
происходит только после окончания “выпихивания”, из регистра TSR, предыдущего
байта данных.
Вернусь к слитной передаче (с точки зрения скорости передачи, это наиболее
выигрышный вариант передачи).
Итак, после окончания “выпихивания” 1-го байта данных из сдвигового регистра TSR,
регистр TSR очистился (пуст).
Автоматика передатчика USART сразу же “засекает это дело” и перегружает в регистр
TSR второй байт данных (тот, который “ждет своей очереди” в регистре TXSTA).
Таким образом, регистр TSR заполнился, что есть начало передачи 2-го байта данных.
Он начал передаваться.
В интервале времени передачи 2-го байта данных, в пустой регистр TXSTA,
записывается 3-й байт данных, который “ставится в очередь”.
Момент его записи зависит от величины интервала времени между выходом рабочей
точки программы из “плавающей” задержки и загрузкой байта данных в регистр
TXREG. И так далее (хоть для триллиона байтов).
Итак, имеются 2 способа передачи.

Слитная передача массива данных:


- величина интервала времени между выходом рабочей точки программы из
“плавающей” задержки и загрузкой байта данных в регистр TXREG должна быть
меньше интервала времени “выпихивания” байта данных из сдвигового регистра TSR,
- задействуется флаг TXIF,

“Побайтная” передача массива данных:


- имеет место быть программная задержка между началами передачи предыдущего
кадра и последующего кадра, величиной более интервала времени передачи одного
кадра,
- флаг TXIF не задействуется.

Величина интервала времени передачи текущего байта данных (а также и кадра)


зависит от номинала выбранной скорости передачи/приема (вычисляется легко).
На рис. 1 “разрисована” “механика” слитной передачи данных для случая передачи
массива данных, состоящего из 4-х байтов.
Вспомните про “милиционера с дубинкой” (в данном случае, это флаг TXIF и команды,
которые с ним работают): он перед Вами “во всей своей организаторской красе”.
Теперь пора переходить от слов к делу.
Вашему вниманию предлагается учебное устройство, которое реально работает, и в
его программе Вы найдете подтверждение сказанному выше.
Его разработал Сергей Рослик, и именно на объяснение принципа работы этого
устройства были “нацелены” все предыдущие объяснения.
При этом, против истины я ничуть не погрешил, так как программа Сергея полностью
“вписывается” в рациональную логику работы модуля USART, работающего только на
передачу, по принципу слитной передачи данных.
В данном случае, он сработал как “генератор идеи”, а я просто пытаюсь
“членораздельно” и доходчиво (надеюсь, что это так) объяснить ее “подноготную”.
Слово Сергею (выделено темно – синим цветом).

;********************************************************************************
; RS232.asm ПП вывода данных через MAX232 с использованием модуля USART
;********************************************************************************
; Программу составил Рослик Сергей Львович.

11
;********************************************************************************
; Используется м/контроллер PIC16F873. Частота кварца 4 Мгц.
;================================================================================
LIST p=16f873 ;
__CONFIG 3731H ;

Программа написана для микроконтроллера PIC16F873. Она начинается с определения


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

;================================================================================
; Определение положения регистров специального назначения.
;================================================================================
PC equ 02h ; Счетчик команд.
Status equ 03h ; Регистр Status.
PortC equ 07h ; Регистр Port C.
TrisC equ 87h ; Регистр Tris C-банк1.
PIR1 equ 0Ch ; Регист флагов периферийных прерываний.
RCSTA equ 18h ; Регистр управления и статуса приёмника.
TXREG equ 19h ; Буфер передатчика.
TXSTA equ 98h ; Регистр управления и статуса передатчика.
SPBRG equ 99h ; Регистр генератора скорости обмена.

Определяем положения регистров общего назначения и присваиваем битам регистров


именные значения (для дальнейшего обращения к ним).

;================================================================================
; Определение положения регистров общего назначения.
;================================================================================
Count equ 21h ; Счетчик количества байтов данных.
SecL equ 27h ; Регистры
SecM equ 28h ; 3-байтного
SecH equ 29h ; счетчика.
;================================================================================
; Определение битов регистров.
;================================================================================
RP0 equ 5 ; Бит работы с банками
SPEN equ 7 ; Разрешение работы порта 1-вкл, 0-выкл.
TXIF equ 4 ; Флаг прерывания от передатчика USART
; 1-буфер пуст, 0-полон.
;********************************************************************************
org 0 ; Выполнение программы - с PC=0.

Программа “самотёком” переходит на выполнение подготовительных операций.

;================================================================================
; Начало выполнения программы (подготовительные операции).
;================================================================================
START bsf Status,RP0 ; Банк 1.
movlw b'11000000' ; Подключение к модулю USART
movwf TrisC ; выводов RC6,RC7.

Значение скорости выбирается из таблицы (datasheet) для асинхронного режима


работы. В данном случае, выбрана скорость 9600 бод/с.

movlw .25 ; Установка скорости


movwf SPBRG ; обмена 9600 бод/c.
movlw b'00100100' ; Асинхронный режим (SYNS=0), высокая
movwf TXSTA ; скорость (BRGH=1), 8-битная передача
; (TX9=0), разрешение передачи (TXEN=1).
bcf Status,RP0 ; Банк 0.

bsf RCSTA,SPEN ; Включение модуля USART.

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

;================================================================================
; Вывод информации в компьютер.
;================================================================================

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


данные берутся из заранее сформированной таблицы символов.

RS232 movlw .49 ; Запись числа .49 (количества


movwf Count ; выводимых байт) в регистр Count.
WR_1 movf Count,W ; Копирование содержимого регистра Count в W.
sublw .49 ; .49-Count=... (результат записывается в W).
call TEXT_1 ; Условный переход в ПП TEXT_1.
;---> Возврат по стеку из ПП TEXT_1.

То, что выше, знакомо из “Самоучителя”, только в нашем случае, данные будут
загонятся в буфер передатчика USART. При выходе из ПП условного перехода, в
регистре W «оседает» считанный из таблицы байт. Теперь этот байт необходимо
скопировать в буфер передатчика, но перед этим нужно проверить, предыдущий байт
передан или нет? Для этих целей используется “плавающая” задержка, которая
проверяет состояние флага TXIF регистра PIR1.

btfss PIR1,TXIF ; Байт данных передан или нет?


goto $-1 ; Если байт еще не передан, то ожидаем.
; Если байт передан, то программа
; исполняется далее.

Как только предыдущий байт будет передан, рабочая точка выйдет из “плавающей”
задержки, и байт данных будет скопирован из регистра W в буфер приёмника, после
чего данные побитно “уйдут”, через вывод RC6, и далее, через преобразователь
уровня (MAX232), в порт RS232 (Com) компьютера. Если есть необходимость в
передаче следующего байта данных, то цикл передачи повторяется.

movwf TXREG ; Загрузка байта в регистр передатчика.


decfsz Count,F ; Декремент числа переданых байт.
goto WR_1 ; Если результат не=0, то передача
; следующего байта данных.
; Если =0, то программа
; исполняется далее.
;================================================================================
; Задержка на, приблизительно, на 1 сек.
;================================================================================
movlw .251 ;
movwf SecL ; Запись
movlw .134 ; констант
movwf SecM ; в регистры
movlw .6 ; счетчика.
movwf SecH ;

PPZ decfsz SecL,F ;


goto PPZ ; 3-байтный,
decfsz SecM,F ; вычитающий
goto PPZ ; счетчик.
decfsz SecH,F ;
goto PPZ ;

goto RS232 ; Переход на новый цикл передачи


; 49-ти байтов данных.
;================================================================================
; Таблица выводимых данных.
;================================================================================
TEXT_1 addwf PC,F ; Вычисляемый переход.

13
dt 0C5H,0F1H,0EBH,0E8H, 20H,0C2H,0FBH,20h,20H
dt 0E2H,0E8H,0E4H,0E8H,0F2H,0E5H,20h
dt 0FDH,0F2H,0F3H,20H,0EDH,0E0H,0E4H,0EFH,0E8H,0F1H
dt 0FCH,20H,2CH,20H,20H
dt 0F2H,0EEH,20H,0F3H,20H,0C2H,0E0H
dt 0F1H,20H,0E2H,0F1H,0E5H,20H,0CEH,0CAH,21H,0DH,0DH
;********************************************************************************
end ; Конец программы.

Данные мы передали, а как их вывести на “дисплей” компьютера?


Я для этих целей использовал программу RS232PRO. Для её использования,
необходимо настроить порт. Для этого нажимаем F5 и настраиваем. Нажимаем OК.
Далее, на панели инструментов, нажимаем на зелёный треугольник (как Play на
магнитофоне) и наблюдаем принимаемые данные в окне программы.

Файл текста этой программы (rs232.asm) прилагается.

В данном случае, программа Сергея многоцикловая (имеется ввиду полный цикл


программы).
Имеется ПП задержки (примерно 1 сек.), которая исполняется в конце каждого полного
цикла программы.
Такой способ организации программы позволяет многократно и комфортно наблюдать
процесс вывода надписи в окно программы RS232PRO.
Если эту задержку убрать и заменить команду goto RS232 на goto $ (“закольцовка” в
“вечном кольце”), то программа будет одноцикловой, и надпись, в окно программы
RS232PRO, выведется только один раз.
В этом случае, блок – схема программы предельно упрощается:

В программе Сергея, работа передатчика, в начале передачи массива байтов (49


штук), разрешалась, а в конце передачи этого массива байтов, запрещалась.

14
В целях максимального упрощения программы (наиболее простого и комфортного ее
восприятия), я “взял грех на душу” и убрал из программы эти разрешения/запреты, а в
подготовительных операциях, включил передатчик USART “на постоянку”.
На конечный результат работы данной программы это не влияет.
Обратите внимание: “плавающая” задержка организована не после загрузки байта
данных в регистр (буфер) передатчика, а до этой загрузки.
Это “что в лоб, что по лбу”: на суть “пережидания” не влияет.
Что за сообщение Сергей “зашифровал”, Вы увидите тогда, когда запустите это
устройство в работу.
Принципиальная схема устройства такая:

Программа составлена под PIC16F873, а в нем вход/выход модуля USART подключен к


выводам RC6, RC7 (см. рис. 2).
Примечание: при переходе с PIC16F873 на PIC16F628A, на работу “на вход” нужно
настроить выводы RB1, RB2.
Вывод RC7 (вход приемника USART), к выходу R2OUT преобразователя уровней
MAX232, можно не подключать, так как приемник USART отключен, но на рис. 2 это
соединение обозначено “с расчетом на перспективу”.
MAX232 это распространенная м/схема двухканального преобразователя уровней,
применяемая для двунаправленного согласования пятивольтовых уровней и уровней
COM порта компьютера.
В данном случае, используется один из двух ее каналов.
Если м/схемы MAX232 в наличии нет, то можно применить простенькую схему
преобразователя уровней на двух транзисторах, только нужно учесть, что каскады с
общим эмиттером работают как инверторы.

15
Эту схему преобразователя уровней использовал в своем устройстве Петр Высочанский
(из его информации и взято).
Вы познакомитесь с этим устройством тогда, когда речь пойдет о двунаправленной
работе.
Примечание: к этому подразделу прилагается файл картинки рисунка 1, который
больше по размеру и на нем более четко прорисованы детали, причем, в масштабе.
Чтобы просмотреть “все это хозяйство” в крупном масштабе, откройте файл картинки,
например, в Paint и при необходимости, увеличьте ее.
Техническую информацию по модулю USART, на которую я ссылался в этом
подразделе, Вы можете найти не только в даташите PIC16F628A, но и в “Справочнике
по среднему семейству м/контроллеров PICmicro”.
Она в нем дублируется.

16
"Практикум по конструированию устройств на PIC контроллерах"      http://ikarab.narod.ru       E-mail: karabea@lipetsk.ru

17