Юрий Ревич - Занимательная микроэлектроника
- Название:Занимательная микроэлектроника
- Автор:
- Жанр:
- Издательство:БХВ-Петербург
- Год:2007
- Город:Санкт-Петербург
- ISBN:978-5-9775-0080-7
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Юрий Ревич - Занимательная микроэлектроника краткое содержание
Для широкого круга радиолюбителей
Занимательная микроэлектроника - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Перед работой с UART его следует установить в нужный режим, а также задать скорость обмена. Делается это, например, таким образом:
;для семейства Classic при частоте 4 МГц
ldi temp,25 ;скорость передачи 9600 при 4 МГц
out UBRR,temp ;устанавливаем
ldi temp, (1<<<<<���ТХВ8)
out UCR,temp ;разрешение приема/передачи 8 бит
Число BAUD для делителя частоты (в данном случае 25) можно определить из таблиц, которые имеются в каждом описании соответствующего контроллера (там же приводится и ошибка для выбранного значения частоты), или рассчитать по формуле: BAUD = f peз/16(UBRR+1). Для семейства Mega процедура несколько усложняется, потому что регистров в USART больше:
;для семейства Меда при частоте 16 МГц
ldi temp,103 ;9600 при 16 МГц
out UBRRL,temp
ldi temp,(1<< ;разрешение приема/передачи
out UCSRB,temp
ldi temp,(1<< ;формат 8n1
out UCSRC,temp
Чем выше тактовая частота МК /рез, тем точнее может быть установлена скорость. При частоте кварца 4 МГц мы с приемлемой точностью можем получить скорости обмена не более 28 800 бод. Правда, при выборе специального кварца (например, 3,6864 МГц) можно получить с нулевой ошибкой весь набор скоростей вплоть до 115 200, но зато для других целей такие частоты неудобны. Для получения скоростей передачи выше указанных (стандартно COM-порт позволяет установить скорости, как указано ранее до 256 кбод) придется увеличивать частоту. Так, при кварце 8 МГц и общем коэффициенте деления, равном единице, мы получим скорость 250 000, что отличается от стандартных 256 000 на приемлемые 2,4 %.
Теперь перейдем к собственно процессу приему/передачи данных. В общем случае наша задача формулируется так: контроллер все время ожидает команды от компьютера, и при получении ее должен послать в ответ несколько байтов. Такой процесс можно организовать различным образом.
С UART связаны прерывания, причем в силу важности предмета тут их аж целых три: «передача завершена» (ТХ Complete), «регистр передатчика пуст» (ТХ UDR Empty) и «прием завершен» (RX Complete). Для их использования можно поступить следующим образом (примеры приведены для семейства Classic). Сначала вы инициализируете прерывание «прием закончен» (для чего надо установить бит RXCIEв регистре UCR). Возникновение этого прерывания означает, что в регистре данных udr имеется принятый байт. Процедуру обработки этого прерывания иллюстрирует листинг 16.1.
Листинг 16.1
UART_RXC:
in temp,UDR ;принятый байт — в переменной temp
cbi UCR,RXCIE ;запрещаем прерывание «прием закончен»
…
<���анализируем команду, если это не та команда — опять разрешаем прерывание «прием закончен» и выходим из процедуры
sbi UCR,RXCIE
reti
В противном случае готовим данные, самый первый посылаемый байт должен быть в переменной temp>
…
sbi UCR,UDRIE ;разрешение прерывания «регистр данных пуст»
reti
Далее у нас почти немедленно возникает прерывание «регистр данных пуст». Обработчик этого прерывания состоит в том, что мы посылаем байт, содержащийся в переменной temp, и готовим данные для следующей посылки (листинг 16.2).
Листинг 16.2
UART_DRE:
out UDR,temp ;посылаем байт
cbi UCR,UDRIE ;запрещаем прерывание «регистр данных пуст»
…
<���готовим данные, следующий байт — в temp. Если же был отправлен последний нужный байт, то опять разрешаем прерывание «прием закончен» и далее выходим из процедуры, иначе выполняем следующий оператор:>
sbi UCR,UDRIE ;разрешаем прерывание «регистр данных пуст»
reti
Для семейства Mega (USART) вместо UCRв текст примеров надо подставить UCSRB. Обратим внимание на то, что после обработки первого прерывания переменная tempздесь может содержать подготовленный для отправки байт, и не должна в промежутках между прерываниями использоваться еще где-то. В противном случае ее надо сохранять, например, в стеке, или все же отвести для этого дела специальный регистр. Как видите, все довольно сложно.
Однако, как и в случае записи в EEPROM (см. главу 15 ), поскольку эти события (прием и передача) происходят относительно редко, на практике мы не будем использовать прерывания, и процедуры резко упростятся (на примере USART — листинг 16.3).
Листинг 16.3
Out_com: ;посылка байта из temp с ожиданием готовности
sbis UCSRA,UDRE ;ждем готовности буфера передатчика
rjmp out_com
out UDR,temp ;собственно посылка байта
ret ;возврат из процедуры Out_com
In_com: ;прием байта в temp с ожиданием готовности
sbis UCSRA,RXC ;ждем готовности буфера приемника
rjmp in_com
in temp,UDR ;собственно прием байта
ret ;возврат из процедуры In_com
Для семейства Classic надо заменить все UCSRAна USR. Для сформулированной ранее задачи непрерывного ожидания внешних команд обращение к процедуре I n_comпри этом вставляется в пустой цикл в конце программы:
Cykle:
rcall In_com
…
<���анализируем полученный в temp байт, и что-то с ним делаем, например, посылаем ответ через процедуру Out_com>
…
rjmp Cykle ;зацикливаем программу
При таком способе контроллер большую часть времени ожидает приема, непрерывно выполняя проверку бита RXC(в процедуре In_com), этот процесс прерывается только на время выполнения «настоящих» прерываний. Прерывания все равно должны выполняться много быстрее, чем байт, в случае, если он пришел, успевает в UDRсмениться следующим (пауза составляет около 1 мс при скорости 9600, и за это время успеет выполниться порядка нескольких тысяч команд), так что мы ничего не потеряем. А процедура посылки Out_comсама по себе может выполняться долго (как и в случае с записью EEPROM, кроме самого первого обращения: задержка будет, если посылать несколько байт подряд). Но для программиста процедура также в основном будет заключаться в том, что контроллер будет ожидать очистки UDR, и т. к. это не прерывание, то ожидание в любой момент может быть прервано реальным прерыванием, и мы ничего не теряем (даже если длительность прерывания превысит время посылки байта, то это лишь вызовет небольшую паузу в передаче).
Но чтобы ничего действительно не потерять, при таком способе следует быть внимательным: так, нужно следить за использованием tempвнутри возникшего прерывания, а лучше на момент посылки данных вообще прерывания запретить. Правда, если мы будем применять процедуру Out_comвнутри процедуры прерывания, куда другое прерывание «влезть» не может, то tempменяться заведомо не будет, но тогда при посылке нескольких байтов контроллер будет терять значительное время на ожидание, и это может нарушить работу других прерываний. Если это критично, то следует перейти к более сложной процедуре с использованием прерываний UART.
Читать дальшеИнтервал:
Закладка: