Text
                    Тим Уилмсхерст
РАЗРАБОТКА
ВСТРОЕННЫХ
СИСТЕМЕН
с помощью
микроконтроллеров
WWW.MK-PRESS.COM
Принципы
и практические
примеры

Designing embedded systems with PIC microcontrollers PRINCIPLES AND APPLICATIONS Tim Wilmshurst ELSEVIER Elsevier Ltd. Boulevard, Langford Lane, Kidlington, Oxford, 0X5 1GB, UK
Тим Уилмсхерст Разработка встроенных систем с помощью микроконтроллеров PIC ПРИНЦИПЫ И ПРАКТИЧЕСКИЕ ПРИМЕРЫ Перевод с английского: В. Н. Стаценко, В. В. Литвин, Ю. А. Шпак Киев “МК-Пресс” • СПб “КОРОНА-ВЕК” 2008
ББК 32.973-04 У 36 УДК 004.312 Уилмсхерст Т. У36 Разработка встроенных систем с помощью микроконтроллеров PIC. Принципы и практические примеры: Пер. с англ. — К.: "МК-Пресс”, СПб:. “КОРОНА-ВЕК", 2008. — 544с., ил. ISBN 978-5-903383-61-0 (рус.) ISBN 978-966-8806-46-9 (укр.) ISBN 978-0-7506-6755-5 (англ.) Благодаря полезным примерам и иллюстрациям, эта кни!а дае! глубокие познания а сфере проектирования систем с помощью микроконт роллеров PIC, а 1акже — програм- мирования этих устройств на ассемблере и С. Подробно рассмотрены микроконтрол- леры 16F84A, 16F873A и 18F242. Даны примеры реальных проектов, включая модель робота, выполненного в виде транспортного средства с автономным управлением. До- полнительно рассматриваются такие вопросы повышенной сложности, как применение устройств в сетевой среде и построение операционных систем реального времени. ББК 32.973-04 Научный редактор: А. В. Легейда Литературный редактор: А. В. Легейда Гпавный редактор: Ю. А. Шпак Подписано в печать 25.03.2008. Формат 70 х 100 1/16. Бумага офсетная. Печать офсетная. Усл. печ. л. 34. Уч.-изд. л. 40,2. Тираж 2000 экз. Заказ № 406 СПД Савченко Л.А., Украина, г. Киев, тел./ф.: (044) 517-73-77; e-mail: info@mk-press.com. Свидетельство о внесении субъекта издательского дела в Государственный реестр издателей, производителей и распространителей издательской продукции: серия ДК №51582 от 28.11.2003г. Отпечатано з готовых диапозитивов ПП “Мошак В.Я.” (свидетельство ДК № 867 от 22.03.2002 г.) 32300, Хмельницкая обл., г. Каменец-Подольский, ул. Иоаннопредтечинская, 2. Тел./факс (03849) 2-72-01,2-20-79 ISBN 978-5-903383-61-0 (рус.) ISBN 978-966-8806-46-9 (укр.) ISBN 978-0-7506-6755-5 (англ.) © “МК-Пресс”, 2008 © Elsevier Science, 2007
СОДЕРЖАНИЕ Введение..............................................................18 ЧАСТЬ 1. ВВЕДЕНИЕ В ПОНЯТИЕ “ВСТРОЕННЫЕ СИСТЕМЫ”........................21 Глава 1. Миниатюрные компьютеры, невидимый контроль.....................22 1.1. Встроенные системы в сегодняшнем мире..............................22 1.1.1. Что такое встроенная система?..................................22 1.2. Несколько примеров встроенных систем...............................23 1.2.1. Холодильник....................................................23 1.2.2. Механизм автомобильной дверцы..................................24 1.2.3. Электронный “пинг-понг”........................................24 1.2.4. Робокар Derbot.................................................25 1.3. Основы компьютеров.................................................27 1.3.1. Элементы компьютера............................................27 1.3.2. Системы команд — CISC и RISC...................................28 1.3.3. Типы памяти....................................................28 1.3.4. Организация памяти.............................................28 1.4. Микропроцессоры и микроконтроллеры.................................29 1.4.1. Микропроцессоры................................................29 1.4.2. Микроконтроллеры...............................................30 1.4.3. Семейства микроконтроллеров....................................30 1.4.4. Корпуса и внешний вид микроконтроллеров........................32 1.5. Компания Microchip и микроконтроллер PIC...........................33 1.5.1. История........................................................33 1.5.2. Микроконтроллеры PIC сегодня...................................33 1.6. Знакомство с микроконтроллерами PIC на примере семейства 12........35 1.6.1. Архитектура микроконтроллера 12F508.............................36 1.7. Микроконтроллер Freescale...........................................38 Резюме............................................................38 ЧАСТЬ 2. СИСТЕМЫ С МИНИМАЛЬНОЙ ФУНКЦИОНАЛЬНОСТЬЮ И PIC® 16F84A.........................................40 Глава 2. Знакомство с семейством PIC® 16 и микроконтроллером 16F84A.....41 2.1. Семейство PIC 16 — общее представление.............................41 2.1.1. Обзор семейства................................................41 2.1.2. Микроконтроллер 16F84A.........................................43 2.1.3. Предостережение об обновлениях.................................43 2.2. Обзор архитектуры микроконтроллера 16F84A..........................43 2.2.1. Регистр состояния..............................................45 2.3. Обзор технологий памяти............................................46 2.3.1. Статическая память RAM (SRAM)..................................46 2.3.2. Память EPROM...................................................46 2.3.3. Память EEPROM..................................................47 2.3.4. Флэш-память....................................................47
6 Содержание 2.4. Память микроконтроллера 16F84A........................................47 2.4.1. Память программ микроконтроллера 16F84A...........................48 2.4.2. Память данных и регистры специального назначения микроконтроллера 16F84A ....48 2.4.3. Слово конфигурации................................................50 2.4.4. Память EEPROM.....................................................50 2.5. Некоторые вопросы синхронизации.......................................52 2.5.1. Тактовый генератор и командный цикл...............................52 2.5.2. Конвейеризация....................................................53 2.6. Подача питания и сброс................................................53 2.7. Микроконтроллер Atmel АТ89С2051.......................................55 2.8. Встроенная схема сброса микроконтроллера 16F84A.......................56 Резюме..............................................................58 Глава 3. Параллельные порты, электропитание и генераторы синхроимпульсов................................................59 3.1. Основная идея — параллельный ввод-вывод...............................60 3.2. Технические вызовы, связанные с параллельным вводом-выводом...........60 3.2.1. Формирование параллельного интерфейса.............................60 3.2.2. Электрические характеристики порта................................63 3.2.3. Некоторые специальные случаи......................................64 3.3. Подключение к параллельному порту.....................................66 3.3.1. Переключатели.....................................................66 3.3.2. Светодиоды........................................................67 3.4. Параллельные порты PIC 16F84A.........................................68 3.4.1. Порт В микроконтроллера 16F84A....................................69 3.4.2. Порт А микроконтроллера 16F84A....................................70 3.4.3. Выходные характеристики порта.....................................71 3.5. Генератор синхроимпульсов.............................................71 3.5.1. Типы синхрогенераторов............................................73 3.5.2. Практические соображения в отношении генераторов синхросигналов...74 3.5.3. Генератор синхроимпульсов в 16F84A................................74 3.6. Электропитание........................................................75 3.6.1. Потребность в электроэнергии и ее источниках......................75 3.6.2. Эксплуатационные условия 16F84A...................................76 3.7. Аппаратный проект электронной игры в пинг-понг........................78 Резюме..............................................................78 Глава 4. Начнем программировать — введение в Ассемблер.....................79 4.1. Основная идея — что программы делают, и как мы их создаем.............80 4.1.1. Проблема программирования и компромисс, связанный с использованием языка Ассемблера........................................80 4.1.2. Процесс написания программы на Ассемблере.........................81 4.1.3. Процесс разработки программы......................................82 4.2. Набор команд семейства PIC 16 и немного больше об арифметико-логическом устройстве (АЛУ)..................................83 4.2.1. Подробнее об АЛУ семейства PIC 16.................................83 4.2.2. Набор команд семейства PIC 16 — введение..........................84 4.3. Ассемблеры и формат программы на Ассемблере...........................85 4.3.1. Введение в Ассемблеры, а также знакомство с Ассемблером Microchip MPASM™.85 4.3.2. Формат программы на языке Ассемблера..............................85 4.3.3. Директивы Ассемблера..............................................86 4.3.4. Представление чисел...............................................86 4.4. Создание простых программ.............................................87
Разрабспка встроенных систем с помощью микроконтроллеров PIC. Принципы и практические примеры 7 4.4.1. Простая программа перемещения данных..............................87 4.5. Настройка среды разработки............................................90 4.5.1. Введение в MPLAB..................................................90 4.5.2. Элементы MPLAB....................................................90 4.5.3. Структура файла MPLAB.............................................91 4.6. Вводное занятие по MPLAB..............................................91 4.6.1. Создание проекта..................................................92 4.6.2. Ввод исходного текста программы...................................93 4.6.3. Ассемблирование проекта...........................................94 4.7. Введение в имитацию...................................................95 4.7.1. Приступаем к занятию..............................................95 4.7.2. Генерирование входных сигналов порта..............................95 4.7.3. Контроль параметров микроконтроллера..............................96 4.7.4. Сброс и выполнение программы......................................96 4.8. Загрузка программы в микроконтроллер..................................98 4.9. Что делают другие — краткое сравнение наборов команд CISC и RISC.....100 4.10. Двигаемся дальше — формат набора команд семейства PIC 16............101 Резюме.............................................................102 Глава 5. Компоновка программ, написанных на языке Ассемблера..............103 5.1. Основная идея — построение структурированных программ................103 5.1.1. Блок-схемы.......................................................103 5.1.2. Диаграммы состояния..............................................105 5.2. Управление последовательностью выполнения команд — переходы и подпрограммы..................................................106 5.2.1. Условные переходы и работа с битами..............................106 5.2.2. Подпрограммы и стек..............................................108 5.3. Генерирование временных задержек и интервалов........................109 5.4. Работа с данными......................................................И1 5.4.1. Косвенная адресация и регистр выбора файла.......................> 111 5.4.2. Поисковые таблицы................................................112 5.4.3. Пример программы с временной задержкой и поисковой таблицей......113 5.5. Введение в логические команды........................................115 5.6. Введение в арифметические команды и флаг переноса....................116 5.6.1. Использование команд сложения....................................116 5.6.2. Использование команд вычитания...................................116 5.6.3. Пример арифметической программы..................................117 5.6.4. Использование косвенной адресации для сохранения ряда Фибоначчи..119 5.7. Приручение сложности Ассемблера......................................120 5.7.1. Включение файлов.................................................121 5.7.2. Макроопределения.................................................121 5.7.3. Специальные команды MPLAB........................................123 5.8. Дополнительные возможности использования имитатора MPLAB.............123 5.8.1. Контрольные точки................................................124 5.8.2. Таймер с остановом...............................................124 5.8.3. Трассирование....................................................126 5.9. Программа электронного пинг-понга....................................127 5.9.1. Структура программы для электронного пинг-понга..................127 5.9.2. Более подробное рассмотрение программы электронного пинг-понга...129 5.10. Выполнение программы электронного пинг-понга на имитаторе — учебное упражнение.........................................130 5.10.1. Установка входных стимулирующих сигналов........................130 5.10.2. Настройка окна Watch (Наблюдение)...............................131 5.10.3. Пошаговое выполнение программы..................................131
8 Содержание 5.10.4. Анимация.......................................................131 5.10.5. Пуск...........................................................131 5.10.6. Контрольные точки..............................................132 5.10.7. Таймер с остановом.............................................132 5.10.8. Трассирование..................................................132 5.10.9. Отладка программы в целом......................................132 5.11. Что делают другие — графические имитаторы..........................132 Резюме.............................................................133 Глава 6. Работа со временем: прерывания, счетчики и таймеры..............135 6.1. Основная идея — прерывания..........................................136 6.1.1. Структуры прерываний............................................136 6.1.2. Структура прерываний 16F84A.....................................137 6.1.3. Реакция ЦП на прерывание........................................137 6.2. Работа с прерываниями...............................................139 6.2.1. Программирование одного прерывания..............................139 6.2.2. Двигаемся к множественным прерываниям — идентификация источника.141 6.2.3. Не допускайте, чтобы прерывания разрушили вашу программу — правило № 1: сохраняйте контекст........................................141 6.2.4. Не допускайте, чтобы прерывания разрушили вашу программу — правило № 2: определите критические области и используйте маскирование...144 6.3. Основная идея — счетчики и таймеры..................................146 6.3.1. Цифровые счетчики................................................146 6.3.2. Счетчик в роли таймера...........................................146 6.3.3. Модуль таймера 0 в 16F84A.......................................148 6.4. Применение таймера 0 в 16F84A на примере электронного пинг-понга....150 6.4.1. Подсчет объектов или событий.....................................150 6.4.2. Временные задержки, сгенерированные аппаратными средствами......151 6.5. Сторожевой таймер...................................................153 6.6. Режим бездействия...................................................153 6.7. Что делают другие...................................................154 6.8. Двигаемся дальше — время ожидания прерывания........................155 Резюме.............................................................156 ЧАСТЬ 3. БОЛЬШИЕ СИСТЕМЫ И PIC® 16F873A..................................157 Глава 7. Большие системы и PIC® 16F873A..................................158 7.1. Основная идея —PIC 16F87XA..........................................159 7.2. Блок-схема 16F873A и его ЦП.........................................159 7.2.1. Обзор ЦП и ядра.................................................159 7.2.2. Краткий обзор памяти............................................160 7.2.3. Краткий обзор периферийных устройств............................162 7.3. Память 16F873A и карты памяти.......................................163 7.3.1. Память программ 16F873A.........................................163 7.3.2. Память данных 16F873A и специальные функциональные регистры.....165 7.3.3. Слово конфигурации..............................................165 7.4. “Специальные” операции с памятью....................................165 7.4.1. Осуществление доступа к ЭСППЗУ и памяти программ................167 7.4.2. Внутрисхемное последовательное программирование (ICSP™).........168 7.5. Прерывания в 16F873A................................................170 7.5.1. Структура прерываний............................................170 7.5.2. Регистры прерываний.............................................170 7.5.3. Идентификация прерываний сохранение контекста...................172 7.6. Генератор в 16F873A, сброс и электропитание.........................172
Разработка встроенных систем с помощью микроконтроллеров PIC. Принципы и практические примеры 9 7.6.1. Генератор синхроимпульсов........................................172 7.6.2. Сброс и электропитание...........................................172 7.7. Параллельные порты в 16F873A.........................................173 7.7.1. Порт А в 16F873A.................................................173 7.7.2 . Порт В в 16F873A................................................175 7.7.3. ПортС в 16F873A..................................................175 7.8. Инструментальные средства тестирования, диагностики и ввода в эксплуатацию.. 176 7.8.1. Вызов, связанный с тестированием встроенной системы..............177 7.8.2. Осциллографы и логические анализаторы............................179 7.8.3. Внутрисхемные эмуляторы..........................................181 7.8.4. Встроенные отладчики.............................................181 7.9. Внутрисхемный отладчик Microchip (ICD 2).............................182 7.10. Применение 16F873A: АУСМ Derbot.....................................183 7.10.1. Источник электропитания, генератор и сброс......................183 7.10.2. Использование параллельных портов...............................184 7.10.3. Сборка аппаратных средств.......................................186 7.11. Выгрузка, тестирование и выполнение простой программы с использованием ICD 2....................................................186 7.11.1. Первая программа для Derbot.....................................186 7.11.2. Применение ICD 2................................................189 7.11.3. Установка битов конфигурации внутри программы...................190 7.12. Двигаемся дальше - 16F874A/16F877A: порты D и Е.....................192 Резюме.............................................................194 Глава 8. Человеко-машинные и физические интерфейсы........................195 8.1. Основная идея человеко-машинного интерфейса..........................196 8.2. От ключей к малым клавиатурам........................................197 8.2.1. Малая клавиатура.................................................198 8.2.2. Пример проектной разработки: использование малой клавиатуры в ПУ АУСМ Derbot............................................199 8.3. Светодиодные индикаторы..............................................204 8.3.1. Светодиодные матрицы: семисегментный светодиодный индикатор......204 8.3.2. Пример разработки: семисегментный индикатор ПУ АУСМ Derbot.......205 8.4. ЖК-индикаторы........................................................209 8.4.1. Микросхема управления ЖК-индикатором HD44780 и ее производные....210 8.4.2. Пример разработки: использование ЖК-индикатора в ПУ АУСМ Derbot..212 8.5. Основная идея — формирование интерфейса с физическим миром...........214 8.6. Некоторые простые датчики............................................214 8.6.1. Микропереключатель...............................................214 8.6.2. Фотосопротивления................................................215 8.6.3. Оптическое обнаружение объектов..................................215 8.6.4. Использование оптического датчика в качестве датчика поворота....217 8.6.5. Ультразвуковой датчик объектов...................................217 8.7. Больше о дискретных входах...........................................218 8.7.1. Входные характеристики 16F873A...................................218 8.7.2. Обеспечение корректных логических уровней и защиты входных цепей.219 8.7.3. Устранение дребезга контактов переключателя......................222 8.8. Исполнительные механизмы: электромоторы и сервоприводы...............224 8.8.1. Электродвигатели постоянного тока и шаговые электродвигатели.....224 8.8.2. Угловое позиционирование: сервопривод.............................225 8.9. Организация интерфейса с исполнительными механизмами.................226 8.9.1. Простое переключение постоянного тока.............................226 8.9.2. Простое выполнение переключений в АУСМ Derbot....................228 8.9.3. Реверсируемое переключение: Н-образный мост......................229
10 Содержание 8.9.4. Переключение электромоторов в АУСМ Derbot.........................230 8.10. Сборка АУСМ Derbot...................................................231 8.11. Применение датчиков и исполнительных механизмов — программа “слепой” навигации АУСМ Derbot....................................231 Резюме..............................................................234 Глава 9. Дальнейшее исследование вопросов синхронизации....................235 9.1. Основная идея — углубленное исследование вопросов, связанных со счетом и временной привязкой...............................236 9.2. Таймер 0 и таймер 1 в 16F87XA.........................................236 9.2.1. Таймер 0..........................................................236 9.2.2. Таймер 1..........................................................236 9.2.3. Применение таймеров 0 и 1 в качестве счетчиков для замера пройденного расстояния в АУСМ Derbot.........................238 9.2.4. Использование таймеров 0 и 1 для генерирования повторяющихся прерываний.241 9.3. Таймер 2 в 16F87XA, компаратор и регистр PR2..........................243 9.3.1. Таймер 2..........................................................243 9.3.2. Регистр PR2, компаратор и постделитель............................244 9.4. Модули сбора данных/сравпения/ШИМ (ССР-модули)........................245 9.4.1. Краткий обзор вопросов сбора данных/сравнения/ШИМ.................245 9.4.2. Режим сбора данных................................................245 9.4.3. Режим сравнения...................................................246 9.5. Широтно-импульсная модуляция (ШИМ)....................................247 9.5.1. Принцип ШИМ.......................................................247 9.5.2. Генерирование ШИМ-сигналов аппаратными средствами — 16F87XA ШИМ....249 9.5.3. Применение ШИМ для управления электромоторами в АУСМ Derbot.......251 9.6. Программная генерация сигналов ШИМ....................................254 9.6.1. Пример программного генерирования ШИМ.............................254 9.6.2. Дополнительные директивы Ассемблера для распределения памяти и осуществления ветвления программ.............258 9.7. Использование ШИМ для цифро-аналогового преобразования................259 9.7.1. Пример использования ШИМ для цифро-аналогового преобразования.....259 9.8. Измерение частоты.....................................................262 9.8.1. Принцип измерения частоты.........................................262 9.8.2. Измерения частоты (скорости) в АУСМ Derbot........................262 9.9. Управление скоростью в применении к АУСМ Derbot.......................265 9.10. Когда пет таймера....................................................268 9.11. Режим бездействия....................................................270 9.12. Куда двигаться дальше?...............................................271 9.13. Сборка АУСМ Derbot...................................................271 Резюме..............................................................271 Глава 10. Начинаем изучать последовательный информационный обмен............273 10.1. Введение в последовательный информационный обмен: основная идея......274 10.2. Простые последовательные каналы связи — синхронный информационный обмен.............................................275 10.2.1. Основы синхронной связи...........................................275 10.2.2. Реализация синхронного последовательного ввода-вывода в микроконтроллере ..276 10.2.3. Microwire и SPI (Последовательный периферийный интерфейс)........276 10.2.4. Введение множественных узлов.....................................277 10.3. Модуль главного синхронного последовательного порта (MSSP) 16F87XA в режиме SPI...........................................278 10.3.1. Краткий обзор порта..............................................278 10.3.2. Конфигурация порта...............................................279
Разработка встроенных систем с помощью микроконтроллеров PIC. Принципы и практические примеры 11 10.3.3. Установка тактовой частоты........................................281 10.3.4. Управление передачей данных.......................................282 10.4. Простой пример использования SPI......................................282 10.5. Ограничения, характерные для Microwire, SPI и простой синхронной последовательной передачи данных.......................284 10.6. Расширение возможностей синхронного последовательного канала связи, шина 12С......................................................285 10.6.1. Основные характеристики 12С и физические соединения...............285 10.6.2. Нагрузочный резистор..............................................286 10.6.3. Характеристики сигналов 12С.......................................286 10.7. MSSP, сконфигурированный для 12С......................................287 10.7.1. Регистры MSSP для режима 12С и их первичное использование.........287 10.7.2. MSSP в режиме подчиненного устройства 12С.........................290 10.7.3. MSSP в режиме ведущего устройства 12С.............................292 10.8. Применение 12С в АУСМ Derbot..........................................294 10.8.1. Ручной ПУ Derbot как узел последовательной линии связи............294 10.8.2. АУСМ в качестве ведущего устройства ГС............................295 10.8.3. Ручной ПУ как подчиненное устройство ГС...........................299 10.8.4. Практическая оценка программ информационного обмена через 12С для АУСМ Derbot..........................................301 10.9. Оценка синхронного последовательного информационного обмена и введение в асинхронный информационный обмен........................302 10.9.1. Принципы асинхронного информационного обмена......................302 10.9.2. Синхронизация последовательных данных без приходящей тактовой частоты.303 10.10. Адресуемый универсальный синхронно-асинхронный приемопередатчик (USART) в 16F87XA..........................................304 10.10.1. Обзор порта......................................................304 10.10.2. Асинхронный передатчик USART.....................................305 10.10.3. Генератор-контроллер скорости информационного обмена USART.......307 10.10.4. Асинхронный приемник USART.......................................307 10.10.5. Пример асинхронного информационного обмена.......................309 10.10.6. Использование распознавания адреса в режиме приема USART.........311 10.10.7. USART в синхронном режиме........................................311 10.11. Реализация последовательной связи без использования последовательного порта — “битовые серии”...................................311 10.12. Сборка АУСМ Derbot.......................................................312 Резюме...............................................................312 Глава 11. Сбор и манипулирование данными....................................313 11.1. Основная идея — аналоговые и дискретные величины, их сбор и использование.. 313 11.2. Система сбора данных..................................................314 11.2.1. Аналого-цифровой преобразователь..................................315 11.2.2. Кондиционирование сигналов — усиление и фильтрация................317 11.2.3. Аналоговый мультиплексор..........................................317 11.2.4. Выборка и удержание сигнала, а также время отбора сигнала.........318 11.2.5. Синхронизация и управление от микропроцессора.....................319 11.2.6. Сбор данных в микроконтроллерной среде............................320 11.3. Модуль АЦП в PIC® 16F87XA.............................................320 11.3.1. Краткий обзор и блок-схема........................................320 11.3.2. Управление АЦП....................................................321 11.3.3. Аналоговая модель входа...........................................325 11.3.4. Расчет времени отбора сигнала.....................................326 11.3.5. Повторные преобразования..........................................327 11.3.6. Компромисс между скоростью преобразования и разрешением...........327
12 Содержание 11.4. Использование АЦП в программе замера освещенности АУСМ Derbot........328 11.4.1. Конфигурирование АЦП.............................................329 11.4.2. Время отбора сигнала.............................................329 11.4.3. Преобразование данных............................................330 11.5. Некоторые простые методы манипулирования данными.....................330 11.5.1. Арифметика с фиксированной и плавающей точкой....................330 11.5.2. Преобразование из двоичного представления в двоично-кодированное десятичное представление.........................331 11.5.3. Умножение........................................................332 11.5.4. Масштабирование и пример программы замера освещенности для АУСМ Derbot.. 333 11.5.5. Использование для масштабирования опорного напряжения............334 11.6. Программа поиска источника света для АУСМ Derbot.....................335 11.7. Модуль компаратора...................................................337 11.7.1. Обзор работы компаратора.........................................337 11.7.2. Компаратор в 16F87XA и опорное напряжение........................337 11.8. Применение схем Derbot для измерительных целей.......................338 11.8.1. Электронная измерительная рулетка................................338 11.8.2. Измеритель освещенности..........................................340 11.8.3. Вольтметр........................................................340 11.8.4. Другие измерительные системы.....................................340 11.9. Конфигурирование АУСМ Derbot в качестве светопоискового робота.......341 Резюме..............................................................341 ЧАСТЬ 4. БОЛЕЕ СЛОЖНЫЕ СИСТЕМЫ И PIC® 18FXX2...............................342 Глава 12. Более сложные системы и PIC® 18FXX2..............................343 12.1. Основная идея устройств семейства PIC 18 и 18FXX2....................344 12.2. Блок-схема 18F2X2 и регистр состояния................................345 12.3. Набор команд семейства PIC 18........................................348 12.3.1. Команды, которые не изменились...................................353 12.3.2. Команды, которые были доработаны.................................353 12.3.3. Новые варианты команд............................................353 12.3.4. Новые команды....................................................353 12.4. Память данных и специальные функциональные регистры..................354 12.4.1. Карта памяти данных..............................................354 12.4.2. ОЗУ доступа......................................................354 12.4.3. Косвенная адресация и доступ к таблицам, расположенным в памяти данных.355 12.5. Память программ......................................................356 12.5.1. Карта памяти программ............................................357 12.5.2. Счетчик команд...................................................357 12.5.3. Переход от устройств семейства 16 к устройствам семейства 18 и команда вычисляемого безусловного перехода goto.......................357 12.5.4. Регистры конфигурации............................................358 12.6. Стеки................................................................360 12.6.1. Автоматическая работа стека......................................360 12.6.2. Программный доступ к стеку.......................................360 12.6.3. Быстрый регистровый стек.........................................360 12.7. Прерывания...........................................................361 12.7.1. Обзор структуры прерываний.......................................361 12.7.2. Источники прерываний, их разрешение и установка приоритетов......361 12.7.3. Общее разрешение установки приоритетов прерываний................363 12.7.4. Глобальное разрешение............................................363 12.7.5. Другие аспекты логики прерываний.................................364 12.7.6. Регистры прерываний..............................................364
Разработка встроенных систем с помощью микроконтроллеров PIC. Принципы и практические примеры 13 12.7.7. Сохранение контекста при использовании прерываний..................364 12.8. Электропитание и приведение в исходное состояние.......................365 12.8.1. Электропитание.....................................................365 12.8.2. Подача электропитания и сброс......................................367 12.9. Источники тактовой частоты.............................................368 12.9.1. Режимы работы тактового генератора: LP, XT, HS и RC.................370 12.9.2. Режимы работы тактового генератора: ЕС, ЕСЮ и RCIO..................370 12.9.3. Режим HS + PLL работы тактового генератора.........................370 12.9.4. Переключение источника тактовой частоты............................370 12.10. Введение в программирование 18F242....................................371 12.10.1. Использование MPLAB IDE для семейства 18..........................371 12.10.2. Программа расчета ряда Фибоначчи..................................371 Резюме................................................................374 Глава 13. Периферийные устройства в PIC® 18FXX2..............................375 13.1. Основная идея периферийных устройств 18FXX2............................375 13.2. Параллельные порты.....................................................376 13.2.1. ПортА в 18FXX2.....................................................376 13.2.2. Порт В в 18FXX2....................................................377 13.2.3. Порт С в 18FXX2....................................................378 13.2.4. Параллельный подчиненный порт......................................378 13.3. Таймеры................................................................378 13.3.1. Таймер 0...........................................................378 13.3.2. Таймер 1...........................................................380 13.3.3. Таймер 2...........................................................380 13.3.4. Таймер 3...........................................................380 13.3.5. Сторожевой таймер..................................................382 13.4. Модуль сбора данных/сравпения/ШИМ (ССР)................................382 13.4.1. Регистры управления................................................382 13.4.2. Режим сбора данных...л.............................................383 13.4.3. Режим сравнения....................................................383 13.4.4. Широтно-импульсная модуляция (ШИМ).................................385 13.5. Последовательные порты.................................................385 13.5.1. MSSP в режиме SPI..................................................385 13.5.2. MSSP в режиме 12С..................................................385 13.5.3. USART..............................................................385 13.6. Аналого-цифровой преобразователь (АЦП).................................386 13.7. Обнаружение падения напряжения.........................................386 13.8. Применение устройств семейства 18 в АУСМ Derbot-18.....................387 13.9. 18F2420 и расширенный набор команд.....................................388 13.9.1. Нановаттная технология.............................................389 13.9.2. Расширенный набор команд...........................................389 13.9.3. Расширенные периферийные устройства................................390 Резюме................................................................390 Глава 14. Введение в язык С..................................................391 14.1. Основная идея — почему С?..............................................391 14.2. Введение в С...........................................................392 14.2.1. Немного истории....................................................392 14.2.2. Первая программа...................................................392 14.2.3. Трассировка программы — объявления, инструкции, комментарии и пространство .. 393 14.2.4. Зарезервированные слова языка С....................................395 14.2.5. Функции С..........................................................395 14.2.6. Типы и хранение данных.............................................396
14 Содержание 14.2.7. Операции С......................................................397 14.2.8. Контроль за ходом выполнения программы, зарезервированное слово while.397 14.2.9. Препроцессор С и его директивы..................................398 14.2.10. Использование библиотек, Стандартная библиотека................398 14.3. Компиляция программ па С.............................................398 14.4. Компилятор MPLAB С18.................................................399 14.4.1. Основы..........................................................400 14.4.2. Арифметические операции.........................................400 14.5. Учебник по С18.......................................................400 14.5.1. Компоновщик и его сценарии......................................400 14.5.2. Заголовок для компоновки и библиотечные файлы...................401 14.5.3. Компоновка проекта..............................................402 14.5.4. Файлы проекта...................................................403 14.6. Моделирование программы па С.........................................403 14.7. Второй пример программы па языке С — программа Фибоначчи.............404 14.7.1. Предварительные сведения о программе — больше об объявлении переменных ..406 14.7.2. Конструкция do-while............................................406 14.7.3. Метки и зарезервированное слово goto............................406 14.7.4. Моделирование программы Фибоначчи...............................407 14.8. Библиотеки MPLAB С18.................................................407 14.8.1. Функции, предоставляющие технические средства для внешних устройств...407 14.8.2. Функции, предоставляющие программные средства для внешних устройств...407 14.8.3. Библиотека общих функций для программного обеспечения...........408 14.8.4. Математическая библиотека.......................................409 14.9. Дальнейшее чтение ...................................................410 Резюме..............................................................410 Глава 15. Язык С и встроенная среда........................................411 15.1. Главная идея — перенос С во встроенную среду.........................411 15.2. Настройка и управление значениями разрядов...........................411 15.2.1. Управление отдельными разрядами.................................413 15.2.2. Конструкции условного перехода if и if-else.....................413 15.2.3. Установка разрядов конфигурации.................................414 15.2.4. Моделирование и запуск примера программы........................414 15.3. Больше о функциях....................................................415 15.3.1. Прототип функции................................................415 15.3.2. Определение функции.............................................416 15.3.3. Вызовы функции и передача данных................................416 15.3.4. Библиотечные функции задержки и DelaylOKTCYx () ................416 15.4. Больше о переходах и циклах..........................................417 15.4.1. Использование зарезервированного слова break....................417 15.4.2. Использование зарезервированного слова for......................418 15.5. Использование таймера и периферийных устройств ШИМ...................418 15.5.1. Использование периферийных таймеров.............................421 15.5.2. Использование ШИМ...............................................422 15.5.3. Цикл главной программы..........................................423 Резюме..............................................................423 Глава 16. Получение и использование данных с помощью С.....................424 16.1. Главная идея — использование С для манипуляции данными...............424 16.2. Использование АЦП в 18FXX2...........................................424 16.2.1. Структура программы поиска света................................429 16.2.2. Использование АЦП...............................................429
Разработка встроенных систем с помощью микроконтроллеров PIC. Принципы и практические примеры 15 16.2.3. Дальнейшее использование if-else.................................431 16.2.4. Моделирование программы поиска света.............................431 16.3. Указатели, массивы и строки...........................................432 16.3.1. Указатели........................................................432 16.3.2. Массивы..........................................................433 16.3.3. Использование указателей вместе с массивами......................433 16.3.4. Строки...........................................................434 16.3.5. Пример программы: использование указателей, массивов и строк.....434 16.3.6. Несколько слов об использовании условия while....................435 16.3.7. Моделирование примера программы..................................436 16.4. Использование внешних устройств 12С...................................437 16.4.1. Пример программы ГС..............................................438 16.4.2. Использование операторов ++ и --.................................440 16.5. Форматирование данных для вывода па дисплей...........................440 16.5.1. Обзор примера программы..........................................440 16.5.2. Использование библиотечных функций для форматирования данных.....442 16.5.3. Характеристика программы.........................................443 Резюме...............................................................443 Глава 17. Более глубокие знания языка С и его среды окружения..................444 17.1. Основная идея — более глубокие знания С и его среды......................444 17.2. Ассемблерные вставки..................................................445 17.3. Контроль за выделением памяти.........................................446 17.3.1. Директивы распределения памяти...................................446 17.3.2. Установка машинных слов конфигурации.............................447 17.4. Прерывания............................................................448 17.4.1. Программа обслуживания прерываний................................448 17.4.2. Расположение и обозначение программ обслуживания прерываний......448 17.5. Пример прерывания на переполнение — мигание светодиодов па Derbot........449 17.5.1. Использование таймера 0..-.......................................450 17.5.2. Использование прерываний и работа программы обслуживания прерываний.451 17.5.3. Моделирование программы мигания светодиодов......................451 17.6. Классы памяти и их применение.........................................453 17.6.1. Классы памяти....................................................453 17.6.2. Область действия.................................................453 17.6.3. Срок действия....................................................454 17.6.4. Связь............................................................454 17.6.5. Работа с памятью семейства 18....................................455 17.6.6. Примеры классов памяти...........................................455 17.7. Код начальной загрузки: c018i . с.....................................456 17.7.1. Файлы начальной загрузки С18.....................................456 17.7.2. Структура программы c018i . с....................................456 17.7.3. Моделирование c018i . с..........................................457 17.8. Структуры, объединения и битовые поля.................................459 17.9. Заголовочные файлы, специфичные для процессора........................459 17.9.1. SFR определения..................................................459 17.9.2. Утилиты ассемблера в заголовочном файле..........................460 17.10. Идем дальше — компоновщик MPLAB и . шар-файл.........................461 17.10.1. Что делает компоновщик..........................................461 17.10.2. Сценарий компоновщика...........................................461 17.10.3. Файл .тар.......................................................463 Резюме................................................................464
16 Содержание Глава 18. Многозадачность и операционная система реального времени.............465 18.1. Основные идеи — вызовы, связанные с многозадачностью и режимом реального времени................................................465 18.1.1. Многозадачный режим — задачи, приоритеты и сроки выполнения......466 18.1.2. Итак, что же такое “режим реального времени”?....................467 18.2. Обеспечение мультизадачное™ при использовании последовательного программирования.........................................467 18.2.1. Оценка основного цикла...........................................468 18.2.2. Время-ориентировапные и событийно-ориентированные задачи.........468 18.2.3. Использование прерываний с приоритетами — структура “передний план/фон”..469 18.2.4. Введение тактирующих сигналов времени с целью синхронизации программной активности.............................469 18.2.5. Универсальная операционная система...................................470 18.2.6. Пределы возможностей последовательного программирования в случае организации многозадачного режима...............................471 18.3. Операционная система реального времени (ОСРВ)........................471 18.4. Диспетчеризация и диспетчер..........................................472 18.4.1. Циклическая диспетчеризация......................................472 18.4.2. Карусельная диспетчеризация и переключение контекста.............472 18.4.3. Состояния задач..................................................473 18.4.4. Диспетчеризация с предварительной выгрузкой, использующая приоритеты.474 18.4.5. Коллективная диспетчеризация.....................................475 18.4.6. Роль прерываний в диспетчеризации................................476 18.5. Разработка задач.....................................................476 18.5.1. Определение задач................................................476 18.5.2. Программирование задач и установка приоритетов...................477 18.6. Защита данных и ресурсов — семафор...................................477 18.7. Куда мы будем двигаться дальше?......................................478 Резюме..............................................................478 Глава 19. Операционная система реального времени Salvo™....................479 19.1. Основная идея: Salvo — пример ОСРВ...................................479 19.1.1. Основные свойства Salvo..........................................480 19.1.2. Версии Salvo и ссылки на источники...............................480 19.2. Конфигурирование и использование ОСРВ Salvo..........................481 19.2.1. Компоновка приложения Salvo — библиотечная компоновка............481 19.2.2. Библиотеки Salvo.................................................481 19.2.3. Использование Salvo с компилятором С18...........................482 19.3. Написание программ для Salvo.........................................482 19.3.1. Инициализация и диспетчеризация..................................483 19.3.2. Написание задач для Salvo........................................484 19.4. Первый пример программы для Salvo....................................484 19.4.1. Обзор программы и функция main...................................486 19.4.2. Задачи и диспетчеризация.........................................486 19.4.3. Создание проекта Salvo/C18.......................................487 19.4.4. Настройка файла конфигурации.....................................487 19.4.5. Компоновка примера Salvo.........................................488 19.4.6. Имитация выполнения программы Salvo..............................490 19.5. Использование прерываний, задержек и семафоров при работе с Salvo....490 19.5.1. Пример программы, использующей тактирующие сигналы времени, основанные на прерываниях...............................490 19.5.2. Выбор библиотеки и конфигурирование..............................493 19.5.3. Использование прерываний и формирование тактирующих сигналов времени.493
Разработка всгроенных систем с помощью микроконтроллеров PIC. Принципы и практические примеры 17 19.5.4. Использование временных задержек...............................495 19.5.5. Использование двухпозиционного семафора........................495 19.5.6. Имитация выполнения программы..................................497 19.5.7. Выполнение программы...........................................498 19.6. Использование сообщений Salvo и повышение сложности ОСРВ...........498 19.7. Пример программы с сообщениями.....................................500 19.7.1. Выбор библиотеки и конфигурации................................504 19.7.2. Задача USnd_Task...............................................505 19.7.3. Задача Motor_Task..............................................505 19.7.4. Использование сообщений........................................505 19.7.5. Использование прерываний и подпрограмм обслуживания прерываний.506 19.7.6. Имитация или запуск программы..................................508 19.8. Накладные издержки ОСРВ............................................508 Резюме............................................................509 ЧАСТЬ 5. ВЗАИМНЫЕ СВЯЗИ И СЕТИ...........................................510 Глава 20. Взаимные связи и сети..........................................511 20.1. Основная идея: сети и связь........................................511 20.1.1. Мир протоколов.................................................512 20.2. Инфракрасная связь.................................................513 20.2.1. IrDA и микроконтроллеры PIC....................................514 20.3. Радиосвязь...*.....................................................514 20.3.1. Блутус (Bluetooth).............................................514 20.3.2. Стандарт Zigbee................................................515 20.3.3. Zigbee и микроконтроллеры PIC..................................516 20.4. Локальная управляющая сеть (CAN) и локальная сеть взаимосоединений (LIN)...516 20.4.1. Локальная управляющая сеть (CAN)...............................516 20.4.2. CAN и микроконтроллер PIC......................................517 20.4.3. Локальная сеть взаимосоединений (LIN)..........................518 20.4.4. LIN и микроконтроллер PIC......................................520 20.5. Встроенные системы и Internet......................................521 20.5.1. Подключение к Internet при помощи микроконтроллера PIC.........521 20.6. Заключение.........................................................521 Резюме............................................................522 Приложение 1. Набор команд микроконтроллеров PIC® 16.....................523 Приложение 2. Электронный настольный теннис..............................524 Приложение 3. Подробности аппаратной реализации АУСМ Derbot..............529 Приложение 4. Основные сведения об АУСМ Derbot...........................533 Приложение 5. Набор команд (не расширенный) микроконтроллеров PIC® 18....537 Приложение 6. Основы языка С.............................................540
ВВЕДЕНИЕ Эта книга посвящена встроенным системам, реализованным, преимущественно, с по- мощью трех микроконтроллеров PIC. Начав с самого простого уровня подготовки, целью этой книги является превращение читателя в независимого и компетентного специалиста в сфере встроенных систем и доведения его до такого уровня, на котором он, читатель, будет иметь возможность начать профессиональную практику в мире встроенных систем. Книга достигает своих целей путем развития знаний и навыков в сфере современных встроенных систем — как в отношении аппаратной части, так и применительно к прог- раммному обеспечению. С аппаратной точки зрения книга включает в себя глубокое изу- чение как устройства самого микроконтроллера, так и цепей и преобразователей, с кото- рыми он должен взаимодействовать. С точки зрения программного обеспечения, будет рассмотрено программирование на С и ассемблере. Кульминацией учебного курса станет изучение, а затем применение операционных систем реального времени, которые олице- творяют наиболее изящный способ программирования встроенных систем. Книга включает вводную и заключительную главы, между которыми расположены три основных части, каждая из которых описывает применение одного из трех основных типов микроконтроллеров PIC: 16F84A, 16F873A и 18F242. В книге подробно рассмотрено каждое из этих устройств, однако ее нельзя рассматривать как простое руководство по ис- пользованию микроконтроллеров PIC. В ней микроконтроллеры рассматриваются только как средство для изучения основных аспектов проектирования встроенных систем. Знания и навыки, полученные после изучения рассмотренных микроконтроллеров, можно без труда применить и к другим устройствам. Отличительной чертой этой книги является объединение теории с практикой. Почти каждая тема иллюстрируется практическим примером в аппаратной или программной имитации. Таким образом, в этой книге вы не найдете абстрактной теории, которая бы не закреплялась на практике. Основным проектом книги является Автономно Управляемый Самодвижущийся Механизм (АУСМ) Derbot. Это — настраиваемый проект, который можно использовать как самодостаточную платформу разработки. Данный АУСМ мо- жет быть реализован во множестве различных форм. Также его можно адаптировать к другим сферам, например, в генераторе сигналов, в электронном счетчике ленты или в экспонометре. Перед тем как вы начнете изучать Derbot, нами будет рассмотрен про- стой проект: электронный настольный теннис. Читатель может сам реализовать примеры проектов с помощью информации, находящейся на прилагаемом к данной книге ком- пакт-диске. Проекты могут быть также использованы в качестве обычного теоретиче- ского материала. Эта книга ориентирована, прежде всего, на студентов инженерных или технологичес- ких специальностей, однако будет интересна и опытным любителям и, отчасти, даже прак- тикующим профессионалам. Предполагается, что читатель имеет достаточные познания в электронике (примерно на уровне окончания первого курса университета). Он должен по- нимать, как работают транзисторы и диоды, а также простейшие аналоговые и цифровые электронные подсистемы. Также неплохо иметь общее представление об архитектуре компьютера.
Разработка встроенных систем с помощью микроконтроллеров PIC. Принципы и практические примеры 19 Поскольку материал рассматривается в три этапа и по принципу “от простого к слож- ному”, он охватывает несколько учебных курсов. Первые шесть глав книги, посвященные введению в теорию микроконтроллеров и программированию на ассемблере, можно ис- пользовать в качестве учебного пособия на один семестр. В качестве примера в этих гла- вах используется микроконтроллер 16F84A — прекрасный вариант для начального изуче- ния, принимая во внимание его простоту. Главы 7-11 можно рассматривать как проме- жуточный курс, в которых программирование на ассемблере используется для создания более сложных систем. В них подробно освещены периферийные устройства микрокон- троллеров и их использование на примере устройства 16F84A. Главы 12-20 можно ис- пользовать в качество учебного материала для расширенного курса, поскольку в них рассказывается о программировании на С применительно к микроконтроллеру 18F242, а также о применении операционных систем реального времени. Кроме того, лекторы мо- гут выбирать материал из Глав 7-20 выборочно, в зависимости от их предпочтений в языке программирования и типе микроконтроллеров. После изучения Глав 1-6 можно сразу же переходить к Главе 12. Хотя при этом из поля зрения выпадает материал пяти глав, такой вариант также возможен. Тем кто изучает программирование на С совсем не обязательно знать все подробности работы периферийных устройств, как и в случае программирования на ассемблере. Тем же где это необходимо, по тексту книги присут- ствуют ссылки на Главы 7-11. Предполагается, независимо от того в какой последовательности читатель будет изу- чать эту книгу, что^у него под рукой есть, как минимум, интегрированная среда разработки Microchip MPLAB®, которую также можно найти на прилагаемом к книге компакт-диске. Она позволяет эмулировать рассматриваемые примеры программ, а также модифициро- вать их и разрабатывать собственные. Книга начинается с изучения некоторых аппарат- ных вопросов, чтобы читатель получил необходимые знания о системе, для которой будет разрабатывать программы. В некоторой степени первые несколько глав, посвященные ар- хитектуре микроконтроллеров PIC, представляют собой быстрый учебный курс для начи- нающих. Самое же интересное начинается в Главе 4, где начинается программирование и эмуляция. Начиная с этого момента, изучение аппаратного и программного обеспечения происходит практически параллельно. В последней трети книги понадобится компилятор Microchip С18. Его “студенческая” версия включена в состав прилагаемого к книге компакт- диска. Для Главы 19 можно установить операционную систему реального времени Salvo™ версии “Lite”, которая тоже находится на компакт-диске. Желательно чтобы кроме программных эмуляторов у читателя был доступ к средст- вам разработки или тестирования электроники — будь то дома, в колледже, в университете или на работе. Это позволит на практике разработать некоторые из рассмотренных проек- тов или эквивалентных систем, ощутив всю радость от собственноручной реализации на- стоящей встроенной системы. При изучении второй половины книги лекторам рекомен- дуется обеспечить каждого из студентов печатной платой Derbot, а также — базовым на- бором необходимых компонентов. Покажите им начальный пример разработки, а затем дайте рекомендации для дальнейшей настройки. Подробности проекта находятся на при- лагаемом к книге компакт-диске. Для любого профессионального разработчика очень важно уметь работать со специфи- кациями производителей, которые являются главным источником информации при проек- тировании с применением микроконтроллеров. Обычно не рекомендуется работать с про- межуточными схемами, предоставляемыми третьей стороной, даже если они более понят- ные по содержимому. Таким образом, в этой книге было использовано множество схем непосредственно из спецификаций компании Microchip (конечно же, с их разрешения). Большинство из них содержат маркировку, поэтому читателю не составит труда загрузить полную версию с сайта Microchip. Сфера разработки встроенных систем требует глубоких и обширных познаний. Осо- бенно это касается систем, объединяющих в себе аппаратные и программные элементы, полупроводниковые технологии, аналоговую и цифровую электронику, компьютерную архитектуру, датчики, приводы и т.д. Поскольку эта книга сосредоточена на применении
20 Введение микроконтроллеров PIC, рассказать подробно обо всех выше перечисленных в ней компо- нентах — не представляется возможным. По этой причине за дополнительной информа- цией обращайтесь к другим специализированным изданиям. Надеюсь, вам понравится эта книга. Желаю успехов в непростом, и, в то же время, ув- лекательном мире проектирования и разработки встроенных систем. Тим Уилмсхерст Университет Дерби, Великобритания
ЧАСТЬ 1.ВВЕДЕНИЕ В ПОНЯТИЕ “ВСТРОЕННЫЕ СИСТЕМЫ” В данном разделе вы познакомитесь с понятием встроенных систем и микроконтроллеров, а также с рядом микроконтроллеров PIC ® от компании Microchip.
ГЛАВА 1. МИНИАТЮРНЫЕ КОМПЬЮТЕРЫ, НЕВИДИМЫЙ КОНТРОЛЬ Мы живем в эпоху информационной революции, когда для повсеместного исполь- зования доступны компьютеры огромной производительности. И уже невозможно пред- ставить работу любой прогрессивной сферы деятельности без компьютеров. Некоторые компьютеры разработаны для получения просто невероятной производительности, они очень дорогие, поскольку созданы для работы в промышленности или проведения ис- следовательских работ. Другие компьютеры разработаны для работы дома или в офисе, они менее мощные, но и стоят меньше. Но существует еще одна категория компьютеров, о которой не все знают. Отчасти из-за того, что не видят их. Это такой тип компьютера, который встраивается внутрь изделия, чтобы осуществлять над этим изделием контроль. Этот компьютер нельзя увидеть. Таким образом, пользователь даже может не знать, что он там присутствует. Этот тип компьютера называется встроенная система и это как раз то, о чем рассказывает эта книга. Общее название этих компьютеров — микроконтроллеры, и в данной книге мы как раз и рассмотрим подробно одно семейство этих микроконтроллеров. В этой главе вы узнаете о том, • что означает встроенная система; • какие микроконтроллеры встроенных систем являются наиболее важными; • что такое семейство микроконтроллеров Microchip PIC ; • как устроен первый микроконтроллер PIC 12F508; • что представляет собой альтернативная структура микроконтроллера от Freescale. 1.1. Встроенные системы в сегодняшнем мире 1.1.1. Что такое встроенная система? Основная идея встроенной системы на самом деле очень проста. Возьмем, к примеру, какое-либо изделие инженерной сферы, которое требует контроля, и над которым этот контроль осуществляет встроенный в изделие компьютер — вот вам и встроенная система. Таким образом, встроенная система — это система, основная функция которой не вычислительная, а управляющая (или контролирующая), реализованная с помощью маленького компьютера, встроенного в эту систему. В наше время встроенные системы можно встретить везде — дома, в офисе, на заводе, в машине или в больнице. В табл. 1.1 перечислены примеры некоторых изделий, кото- рые спроектированы на основе встроенных систем, при этом все они вам знакомы. Эти изделия значительно отличаются друг от друга, но все они спроектированы согласно од- ному принципу, поскольку одной из их характеристик является встроенная система. Многие пользователи могут даже не знать, что изделие, которое они используют, кон- п тролируется одним или несколькими встроенными компьютерами. Даже если они когда- с либо и видели компьютер, осуществляющий контроль, вряд ли догадывались о том, что он что-то контролирует. Многие узнают компьютер по наличию экрана, клавиатуры, дисков и т.д. Встроенный компьютер этих составляющих не имеет. к
1.2. Несколько примеров встроенных систем 23 Табл. 1.1. Примеры встроенных систем Дома Офис Автомобиль Стиральная машина Ксерокс Дверной механизм Холодильник Устройство контроля ошибок Кондиционер Охранная сигнализация Принтер Тормоза Микроволновая печь Сканнер Двигатель Регулятор центрального отопления Модем Развлекательные программы Игрушки и игры 1.2. Несколько примеров встроенных систем А теперь давайте рассмотрим несколько примеров встроенных систем, причем сначала те из них, которые встречаются нам в реальной жизни, а затем те, которые проиллюстри- рованы далее в этой книге. 1.2.1. Холодильник На рис. 1.1. вы видите простой холодильник. Внутри него нужно постоянно поддержи- вать умеренно стабильную, низкую температуру. Это осуществляется путем сравнения внутренней температуры холодильника с температурой, которая необходима для поддер- жания свежести продуктов. Холодильник, таким образом, сам снижает свою температуру путем включения компрессора. Для измерения температуры необходимы один или два сенсора, схема формирования сигнала и схема считывания данных. Некоторое устройство обработки данных сравнивает сигнал, представляющий собой измеренную температуру, с температурой, которую необходимо поддерживать, и делает соответствующие выводы. Управление компрессором требует того или иного вида электронного интерфейса, кото- рый принимает сигнал низкого уровня, а затем преобразовывает его в электрический управляющий сигнал, необходимый для регулирования мощности компрессора. Встроенный компьютер Рис. 1.1. Первый пример встроенной системы — холодильник Процесс контроля можно осуществлять с помощью обычной электронной схемы или с помощью маленького встроенного компьютера. Такой встроенный компьютер будет спроектирован для реализации простой системы управления, показанной выше. Как только маленький компьютер встроен в изделие, сразу же повышается ценность такого изделия. Ведь имея в наличии сигналы в цифровой форме и способности компьютера, можно доба- вить такие средства, как дисплей, дополнительные элементы управления, улучшенный механизм взаимодействия с пользователем и так далее.
24 Глава 1. Миниатюрные компьютеры, невидимый контроль Принимая во внимание понятие добавочной стоимости, если у нас уже есть встроен- ный компьютер, то можно подсоединить его к другим встроенным компьютерам, создавая при этом сеть. Это открывает перед нами новые горизонты, потому что теперь маленькая система мажет стать подсистемой большой системы и, таким образом, делится своей информацией с этой системой. Это касается и таких устройств домашнего пользования, как холодильник, а также других сложных устройств. На рис. 1.1 изображена схема холодильника, однако эта схема представляет собой об- щее понятие о встроенной системе. Таким образом, такая система содержит встроенный компьютер, фиксирующий изменения температуры и подающий сигнал о включении сис- темы. Этой встроенной системой может также управлять человек (хотя, вообще-то, он и не должен этого делать). С таким же успехом управляющий сигнал может передаваться и по сети. В результате пользователь может даже не имеет представления о том, что внутри холодильника есть встроенный компьютер. 1.2.2. Механизм автомобильной дверцы Совсем другим типом встроенных систем является система машинной дверцы, как показано на рис. 1.2. Здесь снова есть несколько сенсоров, взаимодействие с человеком и набор приводов, которые должны отвечать на требования системы. Один набор датчиков связан с фиксацией дверей, и еще один — с окнами. Присутствует два привода: стекло- подъемника и замка. На первый взгляд может показаться, что машинную дверцу можно спроектировать наподобие автономной встроенной системы холодильника. Поначалу кто-то может даже решить, из-за простоты ее функций, а нужна ли вообще встроенная система машинной дверце? Кнопка управления окном Рис. 1.2. Второй пример встроенной системы — дверка автомобиля И снова стоит повторить, что когда мы создаем встроенную систему, таким образом мы повышаем функциональность того или иного механизма. Теперь состояние двери и приводы находятся под электронным контролем и могут быть интегрированы с остальны- ми частями автомобиля. Теперь можно создать систему запирания дверей с центральным замком управления, или такую систему контроля, которая будет подавать сигнал, как только возникнет такая ситуация, при которой водитель уже отъезжает, но дверца все еще как следует не захлопнута. Я вижу огромное преимущество в том, что существует систе- ма, соединяющая простые действия механизма управления и закрытия двери с другими функциями автомобиля. В следующих главах мы рассмотрим все преимущества суще- ствования сети встроенных систем. 1.2.3. Электронный “пинг-понг” Эта небольшая игра проиллюстрирована на рис. 1.3. Это один из нескольких проектов, использованных специально для пояснения материала этой книги. Это игра для двух игро- ков, у каждого из которых есть пульт ручного управления. Каждый игрок первым может
1.2. Несколько примеров встроенных систем 25 начать игру, нажав соответствующую кнопку пульта управления. Мячик, представлен- ный восемью светоизлучающими диодами, “летит по воздуху” к следующему игроку, ко- торый, в свою очередь, тоже нажимает на кнопку пульта, но только в момент, когда мячик достигает последнего диода, и никак раньше. Игра будет продолжаться до тех пор, пока один из игроков нарушит правила игры. Когда это происходит, то счет игрока, который не нарушал правило, увеличивается и, таким образом, соответствующий светоизлучающий диод не зажигается короткое время. Когда мяч выходит из игры, то тогда зажигается све- тоизлучающий диод “вне игры”. Все действия, описанные выше, контролируются с помощью маленького встроенного компьютера (микроконтроллера) от компании Microchip. Игра выполнена в виде 18-кон- тактной интегральной микросхемы (IC) и не имеет ни одного их тех видимых средств, которые свойственны другим компьютерам. Однако электронные технологии теперь на- столько совершенны, что внутри каждой маленькой микросхемы присутствуют централь- ный процессор, комплекс запоминающих устройств, схем синхронизации и интерфей- сов. Одно из запоминающих устройств хранит программу, управляющую ходом игры. Она может считать с входов позиции переключателей (пультов дистанционного управления игроков) и таким образом просчитать требуемые позиции светоизлучающих диодов. Сле- довательно, программа может управлять еще и светоизлучающими диодами. И вся эта компьютерная система питается всего лишь от двух батареек ААА! Рис. 1.3. Электронный “пинг-понг” 1.2.4. Робокар Derbot Следующий проект, который вы будете изучать в этой книге, — робокар Derbot, изо- браженный на рис. 1.4. Как его свойства сопоставимы со свойствами примеров, которые мы рассмотрели до этого? Посмотрев на фотографию, можно про себя отметить, что на нем полно всяких сенсорных устройств и приводов. Два миниатюрных бамперных детектора распознают момент, когда Derbot наталкивается на преграду. Ультразвуковой детектор, смонтированный наверху сервопривода, гарантирует, что Derbot никогда не испытает слу- чайного столкновения. Два световых сенсора, которые находятся по обе стороны серво- привода, используются как прикладные механизмы отслеживания света, и третий свето- вой сенсор, которого на фотографии не видно, находится в задней части устройства. Еще одно средство навигации, присутствующее в системе, — это компас, предназначенный для определения магнитного поля земли. Система приводится в движение с помощью двух серводвигателей постоянного тока, в каждый из которых вмонтирован датчик (его, опять- таки, на фотографии не видно), определяющий количество оборотов колеса для вычис- ления пройденного расстояния. Повороты реализуют путем разной скорости вращения колес. Для оповещения пользователя системы в состав робокара включен также пьезо- электрический динамик. Derbot приводится в движение с помощью шести щелочных ба- тареек АА, помещенных прямо над колесами. Функциональную схему системы авто- номного управления Derbot можно увидеть на рис. 1.5.
26 Глава 1. Миниатюрные компьютеры, невидимый'контроль Рис. 1.4. Робокар Derbot Щелочные батареи Рис. 1.5. Функциональная схема робокара Derbot
1.3. Основы компьютеров 27 Как и в приведенных до этого примерах, Derbot работает как автономная система, счи- тывая значения с различных сенсоров и определяя результаты для приводов. Он управля- ется микроконтроллером Microchip, невидимым на фотографии из-за батарей. Но этот микроконтроллер значительно более мощный, чем тот, который мы использовали для имитации игры в электронный теннис, так как в данном случае необходима более сложная система входов и выходов микросхемы. Заметим, как мы увидим немного позже, что центральный процессор у всех микрокон- троллеров одинаковый. Они отличаются только возможностями интерфейса. Так вот, как раз такое отличие и делает микроконтроллер, задействованный в Derbot, таким мощным. 1.3. Основы компьютеров Во время работы со встроенными системами нам нужно в деталях ознакомиться со свойствами встроенного компьютера, с которым мы на данный момент работаем. Это со- всем не похоже на работу с настольным компьютером при обработке текста или автома- тизированном проектировании, где внутренние схемы тщательно спрятаны от пользова- теля. Для начала давайте выполним беглый обзор некоторых свойств компьютеров. 1.3.1. Элементы компьютера На рис. 1.6. можно увидеть элементы, присутствие которых необходимо в каждой ком- пьютерной системе. Для начала, он должен выполнять арифметические или логические вычисления. Эту функцию реализует центральный процессор (ЦП), который работает с помощью набора команд, называемого программой, которая хранится в памяти. Каждая из этих команд выполняет одну очень простую функцию. Однако типичный компьютер работает очень быстро, поэтому мы и получаем такой мощный общий эффект. Многие ко- манды предназначены для реализации математических и логических операций. Это проис- ходит в некоторой области центрального процессора, называемой арифметико-логическим устройством (АЛУ). Внешний мир Рис. 1.6. Основные составляющие компьютера Для того чтобы компьютер можно было хоть как-то использовать, он должен быть связан с внешним миром и это осуществляется посредством ввода/вывода данных. При использовании персональных компьютеров это означает, что человек взаимодействует с компьютером посредством клавиатуры, мыши, монитора и принтера. У встроенной систе- мы взаимодействие с физическим миром реализовано с помощью датчиков и приводов. Компьютерная революция, которая происходит на данный момент, является следст- вием не только огромной вычислительной мощи, но также и невероятных возможностей хранения данных и обеспечения доступа к ним. Говоря обобщенно, компьютерная память имеет две сферы применения, как показано на рис. 1.6. Одна часть памяти содержит про- граммы, которые затем выполняет компьютер. Эта память должна быть постоянной. Если так и есть, то программы будут в ней постоянно храниться. При этом не имеет значения, подключен компьютер к источнику питания или нет. Другая часть памяти используется для хранения данных, с которыми программа работает, когда компьютер включен. Этот тип памяти не обязательно должен быть постоянным, ну а если и ее часть постоянная, то ничего плохого в этом нет. И, наконец, между основными блоками системы должны находиться каналы переда- чи данных, как указывают на схеме функциональные стрелки.
28 Глава 1. Миниатюрные компьютеры, невидимый контроль 1.3.2. Системы команд — CISC и RISC Центральный процессор любого компьютера поддерживает некоторую систему команд, которые он распознает и выполняет. На основании данной системы команд тем или иным способом строятся программы. Нам нужно, чтобы компьютер выполнял код программы как можно быстрее, но достичь этого далеко не всегда просто. Одним из методов реше- ния этой проблемы является построение сложного центрального процессора со сложной системой предсказания последовательности выполняемых команд, так, чтобы он, процес- сор, сразу был готов к выполнению любой предсказанной операции. Это ведет к исполь- зованию компьютера с полным набором команд (CISC). Компьютер CISC поддерживает много команд и потому довольно сложен. Вследствие сложности конструкции выполняе- мой последовательности действий требуется выполнять их ветвления с упреждающей подготовкой и выполнением сложных, а значит замедляющих весь процесс операций. Еще одной из характерных свойств CISC-подхода является то, что и команды имеют разный уровень сложности. Простые команды могут быть выражены с помощью короткого ко- мандного кода, умещающегося в один байт памяти, который выполняется очень быстро. Сложные команды могут состоять из нескольких байт кода и занимать много времени на выполнение. Другой подход заключается в использовании очень простого ЦП с ограниченным на- бором команд — так называемого RISC-компьютера. Система команд такого компьютера (а значит, и его структура) очень проста, что ускоряет его работу. Одним из характерных свойств RISC-подхода является то, что одно двоичное слово содержит одну команду. Это слово должно содержать всю необходимую информацию, включая сам командный код, а также любой адрес или данные. Еще одной характерной чертой этого подхода является то, что для выполнения любой команды требуется одинаковое количество времени. 1.3.3. Типы памяти Традиционно, типы памяти разделяются на две категории. • Энергозависимая память. Этот тип памяти работает только тогда, когда компьютер подключен к источнику питания. При отключении питания данные теряются, поэтому такую память используют для временного хранения данных. В основном, в подобных запоминающих устройства применена простая полупроводниковая технология, упро- щающая, с электрической точки зрения, запись данных. По историческим причинам их обычно называют RAM (Запоминающее устройство с произвольной выборкой). Не- много более содержательное название этой памяти — просто “память данных”. • Энергонезависимая память. Эта память продолжает работать даже после отключения питания. В настольном компьютере ей, в основном, соответствует жесткий диск — большое энергонезависимое запоминающее устройство, хранящее данные и программы. Во встроенных системах этого можно достичь с помощью энергонезависимой полупро- водниковой памяти. То, что мы можем пользоваться этим типом памяти, со сложной полупроводниковой технологией, — большое преимущество. Она сложнее именно для записи, в электрическом смысле, принимая во внимание необходимое время и мощно- сти, или же с точки зрения сложности самого процесса записи. Энергонезависимое за- поминающее устройство используется для хранения компьютерных программ и исто- рически обычно называется памятью ROM (Постоянное запоминающее устройство — ПЗУ). Более описательное ее название — “память программ”. Сейчас технологии памяти настолько усложнились, что уже очень сложно провести четкую линию между двумя видами памяти: программ и данных. Во время изучения второй главы мы вернемся к рассмотрению вопросов технологии использования памяти. 1.3.4. Организация памяти В процессе взаимодействия с памятью все опирается на два числа: адрес памяти и дан- ные, хранимые по этому адресу. Им соответствуют два набора соединений, называемых
1.4. Микропроцессоры и микроконтроллеры 29 шиной адреса и шиной данных. Мы должны удостовериться в том, что шина данных и шина адреса (или их подвиды) достигают каждой области памяти. Простой способ достижения этого требования проиллюстрирован на рис. 1.7 (а). Дан- ный тип структуры или архитектуры называется “Фон-Неймайовской1 \ по фамилии ее созда- теля. Компьютер этого типа имеет только одну шину для адреса и данных. При этом одни и те же линии используются как для памяти программ, так и для памяти данных. Схемы ввода-вывода тоже могут быть связаны между собой и, таким образом, будут функциониро- вать как некая память, принимая во внимание взаимодействие с центральным процессором. (Ь) (а) Рис. 1.7. Организация доступа к памяти: (а) — Фон-Неймановская архитектура, (Ь) — Гарвардская архитектура Адрес Данные Память данных Центральный процессор (цп); Адрес f Память программ Данные Другим типом является Гарвардская архитектура, которую можно видеть на рис. 1.7 (Ь). Каждая область памяти имеет собственную шину адреса и собственную шину данных. Этот тип архитектуры был изобретен Гарвардским университетом, поэтому он так и называется. Фон-Неймановская архитектура проста и логична, к тому же имеет определенную гиб- кость. Адресуемую область памяти можно как угодно разделить между памятью программ и данных. Однако здесь существует два недостатка. Первый — это использование подхода “равняй всех под одну гребенку”. Это означает, что одна и та же шина данных используется для всех областей памяти, даже если одной области необходимо работать с длинными сло- вами, а другой — с маленькими. Проблема также заключается в совместном использова- нии всего. Если один человек это использует, то другой не может это использовать. Таким образом, если центральный процессор получает доступ к памяти программ, то на этот пе- риод времени память данных вынуждена простаивать, и наоборот. При использовании Гарвардской архитектуры мы получаем больше гибкости с точки зрения размера шины, но при этом модель немного усложняется. Здесь память программ и память данных имеют собственные шины адреса и данных, размер которых может быть индивидуальным. Но в тоже время организация памяти по Гарвардской архитектуре также имеет свой недостаток — она усиливает различие между памятью программ и памятью данных, даже если в этом нет необходимости. Этот недостаток может проявиться там, где, например, данные хранятся в виде таблицы в памяти программ, хотя на самом деле их нуж- но хранить в области данных. 1.4. Микропроцессоры и микроконтроллеры 1.4.1. Микропроцессоры Первые микропроцессоры возникли в 1970 году. Это были удивительные устройства, с помощью которых впервые удалось поместить ЦП компьютера на отдельный кристалл. У людей впервые появился компьютер небольшого размера по приемлемой цене. Вначале все остальные средства, например, такие как память и интерфейсы ввода-вывода, были реализованы вне микропроцессора, и рабочая система по-прежнему должна была состоять
3» Глава 1. Миниатюрные компьютеры, невидимый контроль из большого числа микросхем. Постепенно микропроцессоры становились все более само- достаточными и уже могли содержать на том же кристалле разные типы памяти. В то же время центральный процессор становился все более мощным и быстродействующим и очень скоро превратился из 8-разрядного в 16- и 32-разрядное вычислительное устройство. Стремительное развитие микропроцессоров привело к появлению такого устройства как персональный компьютер. 1.4.2. Микроконтроллеры По мере того как люди распознали и научились использовать вычислительную мощь компьютеров и микропроцессоров, они поняли, что эти устройства можно использовать и по-другому, например для контроля и управления. Поэтому инженеры начали встраивать микропроцессоры во всевозможные устройства, не имеющие ничего общего с компьюте- ром (например, в холодильник или в дверцу автомобиля, которые мы недавно рассматри- вали). Но здесь уже не требовалась большая вычислительная мощность, много памяти или большое быстродействие. Поэтому появилась особая категория микропроцессоров, пред- назначенная для контроля за определенными действиями, а не для обработки больших чисел. Некоторое время спустя эти микропроцессоры приобрели собственную идентич- ность и стали называться микроконтроллерами. Таким образом, микроконтроллер принял на себя роль встроенного компьютера в относительно небольших встроенных системах. Так как же можно отличить микроконтроллер от микропроцессора? Как и микропро- цессор, микроконтроллер должен уметь вычислять, хотя и не обязательно с применением больших чисел. Но у него также есть и другие потребности. Прежде всего, у него должны быть превосходные возможности ввода-вывода, например для того, чтобы реагировать на открытие и закрытие дверцы автомобиля, или для включения или выключения ком- прессора холодильника. Большинство встроенных систем должны быть дешевыми, иметь небольшой размер и способность работать автономно. Кроме того, они обычно работают далеко не в идеальной среде, как в случае с обычным компьютером. Микроконтроллеру зачастую приходится функционировать в жестких условиях промышленной среды, на- пример, внутри двигателей автомобиля, при высокой температуре и т.д. Обобщенная схема микроконтроллера показана на рис. 1.8. По сути, он состоит из про- стого микропроцессорного ядра со всей необходимой памятью программ и данных. К этому добавляется периферия, обеспечивающая необходимые интерфейсы. Сюда относятся циф- ровой и аналоговый ввод-вывод, элементы синхронизации и счета и др. Также существуют и более сложные функции, о которых вы узнаете немного позже. Как и любая электрон- ная схема, микроконтроллер требует схемы питания и ему необходим синхронизирующий сигнал для управления внутренними логическими схемами (в некоторых микроконтрол- лерах он генерируется встроенными компонентами). 1.4.3. Семейства микроконтроллеров Сегодня в мире существуют тысячи типов микроконтроллеров, выпускаемых раз- личными производителями. Но все они, так или иначе, реализуют одну функциональную схему, изображенную на рис. 1.8. Производитель конструирует семейство микроконтрол- леров на основе одного определенного микропроцессорного ядра. Т.е. разные представи- тели одного семейства микроконтроллеров создаются с использованием однотипного ядра в комплексе с разными периферийными устройствами и объемами памяти. Это символи- чески показано на рис. 1.9. Данный производитель создал три семейства микроконтролле- ров, каждое из которых имеет свое ядро. Одно ядро может быть 8-разрядным с ограничен- ными возможностями, другое — 16-разрядным, а третье быть сложной 32-разрядной маши- ной. К каждому ядру добавляются разные комбинации периферийных устройств и объе- мов памяти, что и формирует линейку семейства микроконтроллеров. Поскольку ядро — фиксированное для всех представителей семейства, система команд для него также фик- сирована, и пользователи таким образом не испытают трудностей в переходе от одного представителя семейства к другому.
1.4. Микропроцессоры и микроконтроллеры 31 На рис. 1.9 представлено только несколько представителей от каждого семейства, но на самом деле их значительно больше. Одно семейство может состоять более чем из 100 микроконтроллеров, каждый из которых отличается своими уникальными возможностями и сферой применения. Семейство 1 Память -Периферия. Рис. 1.9. Портфолио производителя микроконтроллеров Семейство 3
32 Глава 1. Миниатюрные компьютеры, невидимый контроль 1.4.4. Корпуса и внешний вид микроконтроллеров Интегральные схемы производятся в разнообразных формах, и в качестве материала для их корпусов обычно используют пластик или керамику. Взаимосвязь с внешним миром обеспечивается с помощью выводов. Микроконтроллеры должны быть как можно меньше по размеру, и тут возникает вопрос: что определяет размер микроконтроллера? Интересно, что размер микроконтроллера обычно определяется не размером самого кристалла, а коли- чеством соединительных выводов интегральной схемы и их размещением. Таким образом, важно понять, для чего же нужны эти выводы микроконтроллеру. Сле- дует отметить, что микроконтроллер обычно выполняет большой объем операций ввода- вывода. Следовательно, можно предположить, что многие контакты используются для вво- да-вывода. Требуется также линия электропитания и соединение с землей. Логично также предположить, что для систем, с которыми мы будем иметь дело, микроконтроллер будет содержать на кристалле всю необходимую память. Таким образом, ему уже не требуется множество линий, которые были необходимы для работы более ранних микропроцессо- ров при передаче внешних данных и адресов. Однако должно присутствовать достаточное количество взаимосвязей для передачи программной информации в память и, возможно, предоставления дополнительного источника энергии для процесса программирования. Та- ким образом, обычно требуются выводы для подачи синхросигнала, внешнего сброса и, возможно, нескольких запросов на прерывание. На рис. 1.10. показаны несколько микропроцессоров и микроконтроллеров. Как видим, они могут быть выполнены в самых разнообразных корпусах и размерах. Крайним справа изображен массивный микроконтроллер с 64 выводами Motorola 68000. По сравнению с ним остальные устройства кажутся просто карликами. Его корпус — типа DIP (dual-in-line package), в котором выводы расположены параллельно в два ряда вдоль более длинных сторон интегральной схемы. При этом расстояние между выводами составляет 0,1 дюйма. Рис. 1.10. Коллекция старых и новых микропроцессоров и микроконтроллеров. Слева направо: PIC 12F508, PIC 16С72, Motorola 68НС05В16, PIC 16F877, Motorola 68000 Поскольку микроконтроллер Motorola 68000 зависит от внешней памяти, многие из его выводов выделены под функции шины данных и адреса, что и стало причиной его боль- ших размеров. Второй микроконтроллер справа — это относительно новая 40-выводная модель PIC 16F877. Хотя он и напоминает микроконтроллер Motorola 68000, его выводы используются совершенно по-другому. Поскольку память программ и данных в нем встро- ена в кристалл, шины адреса или внешних данных ему совершенно не нужны. В резуль- тате его множество выводов задействовано под различные полезные функции, включая цифровые линии ввода-вывода. Посредине изображен 52-выводной микроконтроллер Mo- torola 68НС705 в квадратном керамическом корпусе, в котором есть окно для стирания встроенной в кристалл памяти EPROM (стираемое программируемое ПЗУ). Здесь проме- жутки между выводами составляют 0,05 дюйма, поэтому размер интегральной схемы здесь более компактный, чем у Motorola 68000, при достаточно большом числе контактов. Сле- ва от него изображен 28-выводной микроконтроллер PIC 16С72 в керамическом корпусе DIP, оснащенный памятью программ типа EPROM. Крайний слева — микроконтроллер
1.5. Компания Microchip и микроконтроллер PIC 33 PIC 12F508 с восемью выводами, а справа от него находится микроконтроллер PIC 16F84A с 18 выводами. 1.5. Компания Microchip и микроконтроллер PIC 1.5.1. История Микроконтроллер PIC был изначально спроектирован компанией General Instruments для простых задач управления. Отсюда и его название: Periferal Interface Controller. В 1970-х годах компания General Instruments выпустила процессоры PIC® 1650 и 1655. Хотя их ди- зайн был несколько непродуманным и ортодоксальным, они могли работать в полностью автономном режиме и содержали некоторые важные новшества. Простой центральный процессор был выполнен по RISC-архитектуре с простым рабочим регистром и всего лишь с 30 командами. Выводы могли выдавать и воспринимать ток большей силы, чем большин- ство микропроцессоров того времени. Уже тогда проявились характерные черты микрокон- троллеров PIC; простота, автономность работы, высокое быстродействие и небольшая цена. Компания General Instruments продала подразделение, занимающееся производством полупроводников, группе предпринимателей, которые, по-видимому, распознали огром- ный потенциал этих маленьких “странных” устройств. В 1990-х годах появлялись все новые модели микроконтроллеров PIC, вследствие чего компания обогнала своих прежде более успешных конкурентов. Во многих ситуациях микроконтроллеры PIC быстрее ра- ботали, требовали более простой чипсет и позволяли быстрее моделировать, по сравнению с аналогами других производителей. В отличие от многих конкурентов, компания Micro- chip сделала свои инструментальные средства разработки простыми и дешевыми (а ино- гда вообще бесплатными). Кроме того, Microchip твердо укрепила свои позиции в сфере восьмиразрядных устройств. Несмотря на все улучшения, даже в самых современных мо- делях еще встречаются свойства старого микроконтроллера, выпущенного компанией Ge- neral Instruments. , 1.5.2. Микроконтроллеры PIC сегодня Глядя сегодня на все разнообразие микроконтроллеров PIC, можно прийти в замеша- тельство. Сейчас существуют буквально сотни различных устройств в различных корпу- сах для самых разнообразных сфер применения. Поэтому мы попытаемся определить об- щие характеристики всех этих микроконтроллеров. На момент написания этой книги все микроконтроллеры PIC — дешевые, работают в автономном режиме, восьмиразрядные, построены по Гарвардской архитектуре, реализуют конвейеризацию и сокращенный набор команд, содержат один накапливающий сумматор (рабочий регистр или регистр W), имеют фиксированные векторы сброса и прерываний. На сегодняшний день компания Microchip предлагает пять основных семейств микро- контроллеров, свойства которых суммированы в табл. 1.2. Можно увидеть четкую эволю- цию от одного семейства к другому, поэтому, ознакомившись с особенностями одного семейства, не составит труда разобраться и с другими. Каждый представитель одного се- мейства имеет одинаковую архитектуру ядра и систему команд. Семейства можно разли- чить по двум первым цифрам маркировки устройства. После них указывают символ, ха- рактеризующий задействованную технологию. Символу “С” соответствует технологии КМОП — это ведущая полупроводниковая технология для реализации маломощных логических систем. Символ “F” обозначает приме- нение Flash-памяти (с использованием технологии КМОП в качестве основной). Символу “А”, после цифр, соответствует технологическая доработка устройства предыдущего выпус- ка. Символ “X” означает, что определенная цифра может принимать несколько значений. Например, микроконтроллер 16С84 был первым в своем роде. Позже его название было изменено на 16F84, поскольку он стал использовать флэш-память. Затем его переделали в 16F84A с реализацией ряда технологических усовершенствований.
34 Глава 1. Миниатюрные компьютеры, невидимый контроль Табл. 1.2. Сравнение семейств микроконтроллеров PIC Семейство микроконтроллера PIC Размер стека (в словах) Разрядность командного слова Количество команд Векгоры прерываний 12CXXX/12FXXX 2 12 или 14 бит 33 - 16C5XX/16F5XX 2 12 бит 33 — 16CXXX/16FXXX 8 14 бит 35 1 17СХХХ 16 16 бит 58, включая аппаратное умножение 4 18CXXX/18FXXX 32 16 бит 75, включая аппаратное умножение 2 (с приоритетами) Компания Microchip дополнительно дает каждому семейству микроконтроллеров опре- деленное название. Так, первое семейство (16С5ХХ) было названо “базовым”. Его продол- жение, маркировка которого начинается с “16F” или “16С” (четвертая цифра должна быть отлична от 5), назвали “средним подсемейством”. Его мощным продолжением стали микроконтроллеры, маркировка которых начинается с “17С” — это представители “стар- шего подсемейства”. Разработки семейств микроконтроллеров на этом не закончились, причем — как очень простых, так и очень сложных архитектур — и названия микрокон- троллеров со временем утратили свой смысл, хотя данную терминологию все еще исполь- зуют. В целях простоты в дальнейшем в этой книге семейства PIC будут идентифициро- ваны просто как “12”, “16”, “18” и т.д. Рассмотрим каждое из семейств в отдельности. Семейство 16С5Х Это семейство микроконтроллеров PIC — прямой потомок старых микроконтроллеров компании General Instrument с характерными свойствами ярда исходной структуры PIC. В них — только двухуровневый стек, отсутствуют векторы прерываний и значительно ограничены возможности по усложнению программ и аппаратуры. В частности, ввиду от- сутствия вектора прерываний, ограничена номенклатура встроенной на кристалл перифе- рии, поскольку большинство периферийных устройств используют векторы прерывания для расширения интерфейса с центральным процессором. Семейство микроконтроллеров 16С5Х с добавлением флэш-памяти было выпущено под кодом 16F5X. Хотя это семейство было хорошо продумано, в нем присутствует ограниченное число представителей — ком- пания Microchip не делала на нем большого ударения. Семейство PIC 16 Этому среднему подсемейству соответствует улучшенная версия 16С5ХХ, в которой уже появились прерывания (хотя только с одним вектором), а также был увеличен размер стека. Набор команд, по сравнению с микроконтроллером 16С5Х, немного расширился. К этому семейству принадлежит множество микроконтроллеров с различной периферией и техническими расширениями. Это более крупные устройства со многими периферийны- ми устройствами и значительным объемом встроенной на кристалл памяти — мощные и гибкие. Семейство 12 Семейство микроконтроллеров 12 рассчитано на применение в небольших устройст- вах и потому выполнено в виде маленьких интегральных схем (с числом выводов 8 или 14). У них простая архитектура. Это семейство можно рассматривать как “урезанную” версию микроконтроллеров 16С5ХХ с тем же набором команд. Несмотря на маленькие размеры, семейство 12 содержит некоторые интересные периферийные устройства, включая АЦП и память данных типа EEPROM (электрически-стираемое программируемое ПЗУ). Несмотря
1.6. Знакомство с микроконтроллерами PIC на примере семейства 12 35 на то, что это довольно небольшое семейство, благодаря миниатюрным корпусам, пользо- ватели* всегда проявляли к нему повышенный интерес, и ожидается, что в скором будущем в нем появятся интересные пополнения. Семейство 17 В этом семействе, по сравнению с микроконтроллерами серии 16, был достигнут ре- альный прогресс в производительности центрального процессора. Хотя стратегия RISC была сохранена, набор команд увеличился почти вдвое, а разрядность командного слова возросла до 16 бит. Таким образом, некоторые программные операции, наподобие таблич- ного чтения или перемещения данных, которые в среднем подсемействе PIC вызывали трудности, здесь реализуются намного проще. В семействе 17 также присутствует аппарат- ный умножитель. Вместо одного, зачастую перегруженного вектора прерываний среднего подсемейства, пользователь получил четыре вектора. Хотя это семейство — гораздо мощ- нее микроконтроллеров семейства 16, все же число его представителей ограничено. Похо- же, компания Microchip сконцентрировала свое внимание на разработке более мощных ми- кроконтроллеров семейства 18. Семейство 18 В этом семействе компания Microchip реализовала ряд значительных усовершенство- ваний процессора. Набор команд опять вырос и теперь состоит из 75 отдельных команд, рассчитанных на возможность использования языка программирования С (в некоторых версиях также поддерживается расширенный набор команд). В семействе 18 реализованы два вектора прерываний, которым можно назначить приоритеты. Это — чрезвычайно мощ- ное семейство микроконтроллеров и в будущем можно ожидать его пополнения. 1.6. Знакомство с микроконтроллерами PIC на примере семейства 12 Будучи самыми простыми, представители семейства 12 очень удобны для общего озна- комления с микроконтроллерами PIC. Особенности этой серии характерны и для других, более развитых микроконтроллеров PIC, где они были дополнены новыми возможностями. Мы рассмотрим микроконтроллеры PIC 12F508/509, схема размещения выводов ко- торых показана на рис. 1.11. Единственная разница между моделями 508 и 509 заключа- ется в том, что у последнего немного больше памяти для программ и данных. Большинство (если не все) обозначения выводов на схеме поначалу не будут читателю ни о чем говорить, однако не беспокойтесь — скоро вы узнаете об их смысле. Обозначения: Vdd GP5/OSC1/CLKIN GP4/OSC2 GP3/MCLR/Vpp Vss GP1/ICSPCLK GP2/TOCK1 Vdd: Питание Vss: Земля Vpp: Подача напряжения программирования MCLR: Общий сброс OSC1.OSC2: Выводы для подключения генератора CLKIN: Вход внешнего синхросигнала GP0-GP5: Линии ввода-вывода общего назначения (двунаправленные, кроме GP3) ICSPDAT: Линия данных внутрисхемного последовательного программирования ICSPCLK: Тактовый сигнал внутрисхемного последовательного программирования Рис. 1.11. Схема размещения выводов микроконтроллера PIC 12F508/509. Этот микроконтроллер удивительно маленького размера, что подтверждает рис. 1.12. Поскольку для начального исследования мы выбрали микроконтроллер 12F508, нельзя не
36 Глава 1. Миниатюрные компьютеры, невидимый контроль отметить, что в данном случае мы имеем дело с одной очень хитрой уловкой. Помните, что было сказано раньше? Микроконтроллер несет большую нагрузку по вводу-выводу. В таком случае, как можно использовать модель 12F508, если в ней — только восемь выво- дов? Мы попробуем ответить на этот вопрос, рассмотрев ниже архитектуру этого микро- контроллера. Рис. 1.12. Размеры микроконтроллера 12F508 1.6.1. Архитектура микроконтроллера 12F508 Функциональная схема микроконтроллера 12F508 показана на рис. 1.13. Возможно, это первая схема от компании Microchip, которую вы увидели в своей жизни. Не беспо- койтесь, если поначалу она покажется сложной — мы рассмотрим ее по частям. Давайте начнем с того, что найдем основные элементы, показанные на рис. 1.8: ядро (содержащее центральный процессор), память программ, память данных (или RAM), тракты данных и какую-либо периферию. Мы будем также сравнивать некоторые из этих средств со схемой размещения выводов, изображенной на рис. 1.11. Центральный процессор, обведенный пунктиром в правом нижнем углу схемы, состоит из арифметико-логического устройства (АЛУ), рабочего регистра (W) и регистра состояния. Последний содержит ряд разрядов с информацией о результатах последней выполненной команды. Мультиплексор (MUX) определяет, данные какого из двух источников должны быть переданы в АЛУ. Объем памяти данных составляет лишь 25 байт для модели 508 и 41 байт — для модели 509. При этом следует отметить, что компания Microchip называет адреса памяти RAM “файловыми регистрами” или просто “регистрами”. Память программ (изображена в левом верхнем углу) содержит до 512 12-разрядных слов для микроконтроллера 12F508 и 1024 слова — для модели 12F509. Как уже было сказано ранее, отличительной чертой архитектуры PIC является исполь- зование Гарвардской архитектуры. Значит, в схеме должны присутствовать две шины адре- са (одна — для памяти программ, а другая — для памяти данных и всей периферии). Проще всего найти шину для памяти данных и периферии. Она находится в правой части схемы. Это восьмиразрядная шина, обслуживающая в первую очередь память данных, устройства ввода-вывода общего назначения (GPIO) и периферию таймера 0. Адресная шина для па- мяти данных обозначена как “Адрес RAM”. Она начинается от мультиплексора адреса, ко- торый выбирает адрес от одного из двух источников. Шина программного адреса начинается от счетчика команд и заканчивается памятью программ. Она — 12-разрядная, а значит, может адресовать 212 = 4096 ячеек памяти. По- скольку объем памяти программ составляет только 512 или 1024 слова, разрядность шины адреса для этой памяти — даже избыточная. От памяти программ отходит 12-разрядная шина команд, передающая командные слова из памяти в регистр команд. Интересно проследить, каким образом разбивается командное слово из памяти про- грамм. Поскольку микроконтроллер PIC — это RISC-компьютер, каждое командное слово должно содержать не только код операции, но и требуемый адрес или данные. На схеме регистр команд получает командное слово и начинает процесс его разбиения на составляю- щие. В зависимости от самой команды, пять разрядов командного слова могут содержать информацию об адресе, и, таким образом, передаются по шине прямого адреса мультип- лексору адреса. Восемь разрядов командного слова могут содержать один байт данных,
1.6. Знакомство с микроконтроллерами PIC на примере семейства 12 37 используемый в качестве константы для выполнения команды. Он передается мультиплек- сору, связанному с АЛУ. Наконец, существует еще и сам код операции, который переда- ется модулю управления и дешифрации команды. FSR- Регистр выбора файлов GRIO - Вход /выход общего назначения MUX - Мультиплексор RC - Резистор-конденсатор W-регистр - Рабочий регистр Рис. 1.13. Функциональная схема микроконтроллера PIC12F508/509 (дополнительные надписи в серых прямоугольниках добавлены автором) Этот микроконтроллер содержит только два встроенных в кристалл периферийных устройства: таймер 0 и порт ввода-вывода общего назначения, которому соответствуют выводы GP0-GP5. Сами выводы интегральной схемы отображены на функциональной схеме в виде квадратиков с крестиками внутри. Каждый из них выполняет две или три функции, поэтому на схеме используется для них по несколько обозначений. На данный момент нам совсем не нужно выяснять, какие же это функции, хотя со временем мы обя- зательно об этом скажем. В левой нижней части схемы расположены компоненты, имеющие отношение к такто- вому генератору, питанию и сбросу. Питания и “земля” соединены, соответственно, с вы- водами Vdd и Vss- Блок “Сброс при подаче питания” обнаруживает подачу питания и удер- живает микроконтроллер в состоянии сброса до момента стабилизации напряжения. Вывод MCLR можно использовать для перевода центрального процессора в состояние сброса, в результате чего программа будет перезапущена. В схеме присутствует внутренний так- товый генератор. Это значит, что для этой функции не нужно выделять внешние выводы. Тем не менее, через выводы GP4 и GP5 к микроконтроллеру можно подключить внешний генератор. Тактовый сигнал готовится к использованию в микроконтроллере с помощью модуля “Формирование синхросигнала”. Сторожевой таймер — это защитное устройство, используемое для сброса процессора в случае его сбоя.
38 Глава 1. Миниатюрные компьютеры, невидимый кошроль Прочитав данный раздел, читатель уже может анализировать схему, показанную на рис. 1.13, как воплощение обобщенной структуры микроконтроллера, изображенного на рис. 1.8. Впрочем, мы пока не вдавались в подробности, оставив это для следующих глав. 1.7. Микроконтроллер Freescale Примерно в то же время, когда компания General Instruments выпустила свой PIC 1650, компания Motorola занималась разработкой своего первого восьмиразрядного микропро- цессора 6800. Оба устройства стали предками для впечатляющей группы наследников. Не оставляя разработку восьмиразрядных устройств, компания Motorola занялась также вы- пуском 16- и 32-разрядных микроконтроллеров. Однако компания признавала важность маленьких восьмиразрядных решений, и примерно в середине 1980-х появился первый из восьмиразрядных микроконтроллеров серии 6805. В последующие 20 лет это семейство развивалось и, в конечном итоге, превратилось в семейство 68НС08. Позже, в 2004 году подразделение компании Motorola, которое занималось производством полупроводников, изменило свое название на Freescale. В то время как Microchip уже владел рынком производства и распространения очень маленьких микроконтроллеров, компания Freescale только начала проявлять активность в этом направлении. В качестве примера кратко рассмотрим типичный восьмиразрядный микроконтроллер Freescale (рис. 1.14), упрощенная функциональная схема которого пока- зана на рис. 1.15. Хотя из рисунка этого явно не видно, данный микроконтроллер построен по Фон-Ней- мановской архитектуре. Одна и та же шина данных используется памятью данных, па- мятью программ и периферией. Поскольку шина данных — восьмиразрядная, разряд- ность командного слова и слова данных составляет 8 бит. Vdd ПортА5/О8С1/Вход 5 клавиатуры по прерыванию ПортА4/О8С2/Вход 4 клавиатуры по прерыванию ПортАЗ/ВеаеиВход 3 клавиатуры по прерыванию г 3 Vss г □ ПортАО/Канал таймера О/Вход 0 клавиатуры по прерыванию с j ПортА1/Канал таймера 1/Вход 1 клавиатуры по прерыванию с □ ПортА2 (только вход)/3апрос прерывания/ Вход 2 клавиатуры по прерыванию /Вход таймера MC68HC908QT1 Рис. 1.14. Микроконтроллер Freescale 68НС908 Как и микроконтроллер 12F508, устройство Freescale содержит встроенную на кристал- ле память программ и данных, однако их объем несколько больший. Впрочем, запомните, что память микроконтроллера F509 оперирует словами разрядностью 12 бит, а не байтами. Микроконтроллер Freescale содержит два периферийных устройства, идентичных тем, которые находятся в микроконтроллерах F508/509: порт ввода-вывода и таймер. Порт микроконтроллера Freescale (шестиразрядный порт А) — почти полный аналог порта об- щего назначения микроконтроллера 12F508. Оба устройства имеют одинаковые характе- ристики надежности: сторожевой таймер (для микроконтроллера Microchip) и устройство контроля за работой компьютера (для микроконтроллера Freescale). Единственным суще- ственным различием между этими двумя устройствами является реализация в структуре Freescale прерываний. Резюме • Встроенная система содержит один или несколько встроенных компьютеров, вы- полняющих, главным образом, функции управления. • Встроенный компьютер — это, как правило, микроконтроллер, т.е. микропроцессор, адаптированный для задач встроенного управления.
1.7. Микроконтроллер Freescale 39 Обозначение СОР: Computer Operating Properly — собственно операционный вычислитель Рис. 1.15. Микроконтроллер Freescale MC68HC908QTI — упрощенная функциональная схема • Микроконтроллеры разработаны согласно общепринятым принципам электроники и компьютерных технологий и в общем случае состоят из микропроцессорного ядра, памяти и периферийных устройств. Важно научиться различать их основные осо- бенности. • Компания Microchip представляет широкий ассортимент микроконтроллеров, разби- тый на различные семейства. Каждое из таких семейств имеет идентичную (или очень похожую) центральную архитектуру и набор команд. Тем не менее, общие черты можно увидеть во всех микроконтроллерах Microchip, и знание одного семей- ства упрощает изучение другого. • Microchip 12F508 — хороший пример для того, чтобы начать общее изучение микро- контроллеров и серии PIC, в частности.
ЧАСТЬ 2. СИСТЕМЫ С МИНИМАЛЬНОМ ФУНКЦИОНАЛЬНОСТЬЮ И PIC® 16F84A В данном разделе, состоящем из пяти глав, на примере небольшого устройства семейства PIC 16 будут раскрыты базовые концепции микроконтроллеров. Особое внимание будет уделено понятию архитектуры ядра и использованию простой периферии. Программирование осуществляется с помощью языка ассемблера, поскольку именно этот язык дает максимально тесный контакт с аппаратным обеспечением микроконтроллера.
ГЛАВА 2. ЗНАКОМСТВО С СЕМЕЙСТВОМ PIC® 16 И МИКРОКОНТРОЛЛЕРОМ 16F84A В Главе 1 мы познакомились с понятием встроенных систем и исследовали различные семейства микроконтроллеров PIC® на примере простейшего устройства 12F508. Теперь мы делаем шаг вперед и переходим к рассмотрению семейства PIC 16, которое относится к среднему подсемейству. В качестве примера для изучения мы воспользуемся микрокон- троллером 16F84A, который является сравнительно маленьким представителем этого се- мейства. Через шесть глав мы перейдем к рассмотрению микроконтроллера 16F873A, ко- торый является более крупным представителем этого же семейства. Здесь следует отме- тить, что микроконтроллер 'F84A фактически является прямым потомком микроконтрол- лера 'F873A. Поэтому, если вы заинтересованы в информации о более “свежих” устройст- вах, не беспокойтесь: все, что вы узнаете о маленьком микроконтроллере, можно с успе- хом применить и к его большому “собрату”. И, разумеется, все, что мы узнаем в следую- щих главах, также можно с успехом отнести ко всему семейству PIC 16. Мы изучим обобщенную архитектуру устройства, подробнее остановившись на его памяти: как на технологиях, так и на распределении адресного пространства. Таким образом, в этой главе вы узнаете: • о семействе микроконтроллеров PIC 16; • об общей архитектуре микроконтроллера 16F84A; • о системе памяти микроконтроллера 16F84A вместе с обзором технологий памяти; • об остальных аппаратных возможностях микроконтроллера 16F84A, включая систему сброса. При желании можно также на основании примера, взятого из семейства микроконтрол- леров иного производителя, получить информацию о реализации альтернативных подходов к структуре микроконтроллеров. 2.1. Семейство PIC.16 — общее представление 2.1.1. Обзор семейства Семейство микроконтроллеров PIC 16 растет очень быстро и в нем появилось много самых разнообразных моделей. Таким образом, когда мы применяем термин “семейство”, то имеем ввиду “расширенное семейство”, которое действительно теперь очень велико. Однако все представители семейства 16 имеют идентичное ядро и набор команд. Различия составляют только периферийные устройства, некоторые другие средства, а также размеры корпусов (табл. 2.1). В табл. 2.1 сведены данные о некоторых представителях семейства PIC 16, выбранных для изучения в этой книге. Даже такой ограниченный состав явно показывает все доступ- ное разнообразие. Внутри расширенного семейства PIC 16 мы можем обнаружить группы очень похожих микроконтроллеров, таких как 16F84A и 16F87AA. Первым в списке идет микроконтроллер 16F84A, особенности которого мы сейчас подробнее и рассмотрим. Он имеет родственника — микроконтроллер 16LF84A, расширенный диапазон питания которо- го позволяет работать при пониженных напряжениях. Каждый из этих микроконтроллеров
42 Глава 2. Знакомство с семейством PIC® 16 и микроконтроллером 16F84A доступен в разных корпусах, может работать в разных диапазонах температур или с разной частотой тактового генератора. Например, микроконтроллер 16F84A существует в верси- ях на 4 и 20 МГц. Табл. 2,1. Некоторые представители семейства PIC 16 Номер устройства Число выводов* Частота генератора Память (К -г- Кбайт, т.е. 1024 байт) Периферия/особенности 16F84A 18 до 20 МГц 1 К памяти программ; 68 байт RAM; 64 байт EEPROM 1 восьмиразрядный таймер; 1 пятиразрядный параллельный порт; 1 восьмиразрядный параллельный порт. 16LF84A Как ука- зано выше Как указано выше Как указано выше Как указано выше, с расширенным диапазоном напряжений питания. 16F84A-04 Как ука- зано выше до 4 МГц Как указано выше Как указано выше. 16F873A 28 до 20 МГц 4 К памяти программ; 192 байта RAM; 128 байт EEPROM 3 параллельных порта; 3 счетчика/таймера; 2 модуля захвата/ сравнения/ШИМ; 2 модуля последовательного обмена данными; 5 10-разрядных каналов АЦП; 2 аналоговых компаратора. 16F874A 40 до 20 МГц 4 К памяти программ; 192 байта RAM; 128 байт EEPROM 5 параллельных портов; 3 счетчика/таймера; 2 модуля захвата/ сравнения/ШИМ; 2 модуля последовательного обмена данными; 8 10-разрядных каналов АЦП; 2 аналоговых компаратора 16F876A 28 до 20 МГц 8 К памяти программ; 368 байт RAM; 256 байт EEPROM 3 параллельных порта; 3 счетчика/таймера; 2 модуля захвата/ сравнения/ШИМ; 2 модуля последовательного обмена данными; 5 10-разрядных каналов АЦП; 2 аналоговых компаратора. 16F877A 40 до 20 МГц 8 К памяти программ; 368 байт RAM; 256 байт EEPROM 5 параллельных портов; 3 счетчика/таймера; 2 модуля захвата/ сравнения/ШИМ; 2 модуля последовательного обмена данными; 8 10-разрядных каналов АЦП; 2 аналоговых компаратора. *Только в корпусах DIP. АЦП — аналого-цифровой преобразователь; ШИМ — широтно-импульсный модулятор.
2.2. Обзор архитектуры микроконтроллера 16F84A 43 Как видим, 16F87AA представляет отдельную группу, которой соответствует два вида корпусов и два объема памяти. Нетрудно заметить, что размер корпуса зависит от числа доступных выводов. Версии с 40 выводами имеют пять параллельных портов (что соответ- ствует 33 линиям параллельного цифрового ввода-вывода) плюс дополнительный анало- говый вход — сравните с 28 выводами у их “родственников”. Во всем остальном разница между ними — незначительная. Каждому типу корпуса обычно соответствует два разных размера памяти. Чем больше память, тем длиннее будут программы и тем больше места для хранения данных, но это, естественно, и стоит больше. Для каждого представителя семейства PIC 16 (как и для всех других своих устройств) компания Microchip на своем Web-сайте предоставляет исчерпывающее техническое опи- сание. Там же можно найти документацию с описанием всех свойств микроконтроллеров данного семейства. Хотя во время изучения этой главы пользоваться упомянутыми ис- точниками не обязательно. Знайте о существовании этой документации, поскольку иногда придется к ней обращаться за более подробной информацией о структуре и применении конкретных микроконтроллеров. 2.7.2. Микроконтроллер 16F84A Микроконтроллер 16F84A вместе со своими прямыми “предками” — один из самых успешных микроконтроллеров Р1С. Сначала он назывался 16С84. Появился он в то время, когда большинство производителей микроконтроллеров пытались сделать свои модели большими, совершенными и сложными. Однако компания Microchip приняла смелое ре- шение и оставила свои модели маленькими, простыми и несложными в использовании. Хотя в то время большинство микроконтроллеров имели встроенную на кристалл память программ — это обычно была память типа EPROM с соответствующим длительным цик- лом стирания. В случае же с микроконтроллером 16С84 было решено снарядить его памя- тью типа EEPROM, что ускорило и упростило его программирование и привело к более частому изменению (модернизации) их программ. Затем появилась версия с технологией Flash, и название микроконтроллера было изменено с 'С84 на 'F84. Принимая во внимание дальнейшие усовершенствования, микроконтроллер стал называться 16F84A. Существует также еще одна версия микроконтроллера этого семейства: 16LF84A, — которая подхо- дит для применения в устройствах с малым энергопотреблением. 2.7.3. Предостережение об обновлениях Наука не стоит на месте, и постоянно появляются новые технологии. Таким образом, структура микроконтроллеров постоянно совершенствуется. Учитывая это, производи- тели обычно корректируют документацию. Появление нового представителя семейства приветствуется, но, при этом, нужно обязательно обращать внимание на изменения, кото- рые были внесены в его структуру, и не игнорировать их. Одни изменения, конечно же, только в пользу. Например, версия “А” микроконтроллера 16F84 может работать быстрее, чем предыдущая (20 МГц, вместо 10). Однако технологические усовершенствования мик- роконтроллеров могут иметь и побочные эффекты. Прямого преимущества они могут не предоставлять, а вот с заменой микроконтроллера в существующем устройстве все же могут возникнуть проблемы. Например, в микроконтроллерах 'F84 и 'F84A отличаются напряжение питания и входные пороги логических сигналов. 2.2. Обзор архитектуры микроконтроллера 16F84A Диаграмма размещения выводов 16F84A показана на рис. 2.1, а его функциональная схема — на рис. 2.2. Если сравнить эти два рисунка с аналогичными схемами для мик- роконтроллеров PIC 12F508, рассмотренными в Главе 1, то мы увидим некоторые инте- ресные сходства и различия. Теперь у нас есть 18 выводов, поэтому нет необходимости использовать одни и те же контакты для различных функций. Например, отдельные вы- воды отведены под тактовый генератор (выводы 15 и 16) и сигнал сброса (вывод 4 —
44 Глава 2. Знакомство с семейством PIC® 16 и микроконтроллером 16F84A MCLR). Тем не менее, в сравнении с большинством других моделей, 'F84A остается не- большим микроконтроллером. Порт А, разряд 2 RA2 с 1 18 □ RA1 Порт А, разряд 1 Порт А, разряд 3 RA3 с J RA0 Порт А, разряд 0 Порт А, разряд 4 RA4/T0CKI Е □ OSC1/CLKIN Сброс MCLR Е J OSC2/CLTOUT Кониюы ittHfipdTopd Земля Vss С 2 Vdd Подача напряжения питания Порт В, разряд 0 RBO/INT Г □ RB7 Порт В, разряд 7 Порт В, разряд 1 RB1 ц J RB6 Порт В, разряд 6 Порт В, разряд 2 RB2 с Э RB5 Порт В, разряд 5 Порт В, разряд 3 RB3 Е 9 10 □ RB4 Порт В, разряд 4 * также счетчик / вход таймера ** также вход по внешнему прерыванию Рис. 2.1. Схема размещения выводов микроконтроллера 16F84A OSC2/CLKOUT MCLR Voo.Vss Порт ввода/еывод! OSCVCLKIN Рис. 2.2. Функциональная схема микроконтроллера 16F84A (информация в дополнительных прямоугольниках серого цвета представлена автором) С точки зрения архитектуры, между микроконтроллерами 12F508 и 16F84A есть явное сходство. По сути, последний — прямое подсемейство 'F84A с почти идентичными про- цессором, памятью, структурой шины и периферией счетчика/таймера (TMR0). Тем не ме- нее, обратите внимание на увеличение разрядности адресной шины, что было сделано для восполнения потребностей всего семейства PIC 16. Будучи младшим представителем этого семейства, 'F84A не во всей полноте использует все эти достижения. Адресная программная шина в нем 13-разрядная, а командное слово — 14-разрядное. Таким образом, для адреса- ции доступно 2Ъ (т.е. 8192) ячеек памяти. Тем не менее, объем памяти программ в 1 К со- ставляет только одну восьмую часть от этого числа. И все же, большая разрядность шины
2.2. Обзор архитектуры микроконтроллера 16F84A 45 находит применение в более развитых устройствах семейства 16, что очевидно, если взгля- нуть на объем программной памяти в микроконтроллерах 16F876A и 16F877A (табл. 2.1). Объем оперативной памяти возрос до 68 ячеек, а размер стека — до восьми ячеек. Вместе с тем появилось несколько важных дополнений. Внедрение памяти EEPROM предоставляет теперь ценную возможность хранить данные даже после отключения пита- ния. Также теперь в наличии два цифровых порта ввода-вывода: порт А, шириной в пять выводов, и порт В, шириной в восемь выводов. Еще одно важное дополнение — обработка прерываний (подробно рассматривается в Главе 6). Это видно по выводу 6, где разряд О порта В используется совместно со входом внешнего запроса на прерывание. Позже мы увидим, что в 16F84A используется также три внутренних источника прерываний, фор- мируемых периферией. Другими словами, перед нами микроконтроллер, который лишь несколько сложнее 12F508, но гораздо более гибок и практичен в небольших приложениях. 2.2.7. Регистр состояния Результат любой операции, выполняемой центральным процессором, сохраняется в рабочем регистре, однако в нем не всегда присутствуют все необходимые данные о только что выполненной операции. Например, что произойдет, если в результате выполнения команды сложения будет превышен 8-разрядный диапазон? Рабочий регистр не умеет распознавать подобные ситуации, и потому сохранит некорректный результат. Учитывая это, в любой центральный процессор компьютера встроен набор логичес- ких разрядов, которые иногда называют флагами условий. Они предназначены для переда- чи дополнительной информации о результате выполнения последней команды, например, является ли он нулевым, отрицательным или положительным. В микроконтроллере 16F84A эти флаги хранятся в регистре состояния (рис. 2.3). По сути, к категории флагов условий можно отнести только три разряда этого регистра: с 0 по 2, т.е. биты С, DC и Z. Как видно из подписей на рисунке, этим аббревиатурам соответствует распознание переноса (Сапу), знака переноса (Digit Carry) и нулевого результата (Zero). Использование этих разрядов рассматривается в Главах 4 и 5. R/W-0 R/W-0 R/W-0 R-1 R-1 R/W-x R/W-x R/W-x IRP RP1 RPO ' ТО PD Z DC С Разряд 7 Разряд О Разряды 7-6 Разряд 5 Разряд 4 Разряд 3 Разряд 2 Разряд 1 Разряд О Зарезервированные: поддерживается как ‘О' RP0: бит выбора банка (используемый как прямая адресация) 1 = Банк 1 (80h—FFh) 0 = Банк 2 (00h—7Fh) ТО: бит блокировки по времени 1 = после включения питания, команды CLRWDT или sleep 0 = сторожевой таймер — произошла блокировка PD: бит пониженного потребления энергии 1 = после включения питания или с командой clrwdt 0 = при выполнении команды sleep Z: бит нулевого результата 1 = если результат арифметической или логической операции является нулевым 0 = если результат арифметической или логической операции не является нулевым DC: бит знака переноса / borrow (команды addwf, addlw, sublw, subwf) (когда borrow, противоположный есть инвертированный) 1 = выходной сигнал знака переноса из 4-го младшего разряда для полученного результата О = нет выходного сигнала знака переноса из 4-го младшего разряда для полученного результата С: бит переноса/borrow (команды addwf, addlw, sublw, subwf) (когда borrow, противоположный есть инвертированный) 1 = выходной сигнал переноса самого старшего разряда для полученного результата О = нет выходного сигнала переноса самого старшего разряда для полученного результата Примечание: Вычитание — это выполнение суммирования дополнительного двоичного (обратного) кода числа второго операнда. Для команд циклического сдвига (RRF, RLF) разряд переноса перегружается со старшего или младшего разряда регистра источника. Рис. 2.3. Регистр состояния микроконтроллера 16F84A
46 Глава 2. Знакомство с семейством PIC® 16 и микроконтроллером 16F84A 2.3. Обзор технологий памяти Для того чтобы проанализировать возможности памяти микроконтроллера 16F84A и научиться работать со встроенными системами в целом, важно иметь определенные позна- ния о характеристиках различных технологий памяти. Ниже представлен краткий обзор различных технологий, используемых в данный момент компанией Microchip. В идеальном варианте считывание из памяти и запись в нее должно происходить за ничтожно малый промежуток времени, она должна занимать ничтожно малое простран- ство и потреблять как можно меньше энергии. На практике же ни одна из технологий памяти не соответствует этим требованиям! Обычно каждая технология имеет преиму- щество по какому-то одному критерию, но по другим критериям уступает остальным тех- нологиям. Не существует самой лучшей технологии памяти, и разные технологии при- меняются согласно разным потребностям. Любая память состоит из массива ячеек, каждая из которых содержит один бит данных. Характеристики отдельной ячейки памяти и определяют характеристики всего массива. Таким образом, каждая из технологий описывается в терминах структуры своей ячейки. 2.3.1. Статическая память RAM (SRAM) Здесь каждая ячейка памяти представляет собой обычный триггер с использованием встречно-параллельного включения двух транзисторных пар. Два дополнительных тран- зистора дают ячейке возможность подключиться к главному массиву. Т.о. каждая из ячеек содержит шесть транзисторов, поэтому можно сделать вывод, что память SRAM не явля- ется компактной. Данные сохраняются до тех пор, пока подается питание. Таким образом, память SRAM — энергозависимая. Однако если ее выполнить по КМОП-технологии, то она будет потреблять очень мало электроэнергии и сможет сохранять данные при пони- женном напряжении (около 2 В). В результате данная технология очень популярна в сис- темах с питанием от батареек. Память SRAM главным образом используется в качестве памяти данных микроконтроллера. 2.3.2. Память EPROM Erasable Programmable Read-Only Memory — стираемая программируемая постоянная память. По этой технологии каждая ячейка памяти состоит из одного МОП-транзистора, однако в данном случае внутри транзистора встроен “плавающий затвор”. Заряжать пла- вающий затвор можно с помощью технологии под названием “инжекция горячих элек- тронов”. В незаряженном состоянии транзистор ведет себя как обычно и во время актива- ции выход ячейки принимает одно логическое состояние. В заряженном состоянии тран- зистор уже не работает “корректно” и не реагирует на активацию. Заряд, помещенный на плавающий затвор, полностью удерживается окружающим изолятором. Таким образом, технология EPROM является энергонезависимой. Тем не менее, память EPROM может быть легко стерта, если ее подвергнуть влиянию сильного ультрафиолетового излучения. Это излучение дает удерживаемым электронам достаточную энергию для выхода из пла- вающего затвора. Специальная версия памяти EPROM называется ОТР (однократно программируемая). В данном случае пластиковый корпус микросхемы не оснащен окошком и, значит, память можно запрограммировать только один раз, без возможности последующего стирания. Поскольку ячейка EPROM содержат только один транзистор, такая память — очень компактная и надежная. Требование к наличию кварцевого окошка и керамического кор- пуса, для возможности стирания, повышает ее себестоимость и снижает гибкость. Тех- нологию EPROM часто использовали для реализации памяти программ, в результате чего весь корпус микроконтроллера приходилось делать керамическим, с кварцевым окошком (см. рис. 1.10). На сегодняшний день технология EPROM повсеместно уступает дорогу флэш-памяти, о которой пойдет речь на следующей странице.
2 4. Память микроконтроллера 16F84A 47 2.3.3. Память EEPROM Память EEPROM (Electrically Erasable Programmable Read-Only Memory — электрон- но-перепрограммируемая постоянная память) также использует технологию плавающего затвора. Но размеры ее ячейки еще меньше, поскольку в ней применен иной метод удер- жания заряда плавающего затвора: туннелирование по Нордхайму-Файлеру. С помощью этой технологии возможно стирание ячейки памяти и запись в нее электрическим спосо- бом. Для этого необходимо, чтобы вокруг самого запоминающего элемента присутство- аало несколько переключающих транзисторов, в результате чего теряется высокая плот- ность памяти EPROM. В основном, в память EEPROM можно записывать (и стирать) побайтно. Это особен- но удобно для сохранения отдельных блоков данных, наподобие телевизионных настроек или номеров мобильных телефонов. Как считывание, так и стирание данных происходит за ограниченный промежуток времени (до нескольких миллисекунд), хотя считывание занимает время, типичное для доступа к полупроводниковой памяти (т.е. в пределах не- скольких микросекунд). Как и в случае с памятью EPROM, плавающий затвор полностью улавливается изолятором, и потому память EEPROM также не является энергозависимой. Структура этой памяти очень точная, и поэтому страдает от своеобразного “износа”. При- нимая это во внимание, производители гарантируют только определенное количество циклов стирания/записи, которое можно воспроизвести с данным типом памяти. 2.3.4. Флэш-память Флэш-память представляет собой дальнейшую эволюцию технологии памяти с плава- ющим затвором. В ней каждая ячейка также содержит один транзистор, но одновременно применяются и технология инжекции горячих электронов, и технология туннелирования по Нордхайму-Файлеру (для записи и стирания электрическим способом). Флэш-память не содержит дополнительных переключающих транзисторов, как в памяти EEPROM, по- этому поддерживает только блочное стирание. Благодаря этому она реализуется с очень высокой плотностью, сравнимой с плотностью памяти EPROM. Как и память EEPROM, она подвержена “износу”, и поэтому процесс записи и стирания — не бесконечен. Если не учитывать неспособность побайтного стирания, Flash — это невероятно мощ- ная технология. Сегодня она является ключевым элементом широкого диапазона устройств, включая цифровые камеры, ноутбуки, а также память программ микроконтроллеров. 2.4. Память микроконтроллера 16F84A На рис. 2.2 можно увидеть, что микроконтроллер 16F84A содержит не менее четырех областей памяти (см. табл. 2.2). Каждая область памяти поддерживает при этом опреде- ленную функцию или средства доступа. Табл. 2.2. Особенности памяти микроконтроллера 16F84A Функция памяти Технология Объем Энергозависимость Особые характеристики* Память программ Flash 1 К x 14 бит Энергонезависимая Типично — 10 000 циклов стирания/записи Память данных (регистры файлов) SRAM 68 байт Энергозависимая Сохраняет данные при напряжении питания вплоть до 1,5 В Память данных (EEPROM) EEPROM 64 байта Энергонезависимая Типично — 10 000 000 циклов стирания/записи Стек SRAM 8x13 бит Энергозависимая • Информация получена из полного технического описания микроконтроллера 16F84A.
48 Глава 2. Знакомство с семейством PIC® 16 и микроконтроллером 16F84A 2.4.1. Память программ микроконтроллера 16F84A Распределение памяти программ микроконтроллера 16F84A показано на рис. 2.4. По сути, схема эта содержит три элемента: счетчик команд, стек и, собственно, память про- грамм. Все три элемента не могут работать друг без друга. Память программ загружается в виде программного кода, выполняемого микроконтроллером. Программа представляет собой список команд, а адрес следующей команды, которую должен выполнить микрокон- троллер, хранится в счетчике команд. Таким образом, как показано на схеме, он выполняет функцию указателя памяти программ. Значение счетчика команд можно также поместить в стек. Это происходит в случае перехода к подпрограмме или возникновения прерывания. Все команды, обозначенные на схеме как CALL (вызвать), RETURN (вернуться), RETFIE и RETLW, относятся к подпрограммам и прерываниям (познакомимся мы с ними в последу- ющих главах — не беспокойтесь, если сейчас они ничего для вас не означают). Как видим, диапазон адресов памяти программ составляет 0000,.03FFH. Имея 13-разряд- ный счетчик команд, микроконтроллер теоретически может адресовать область 0000..1FFFH. Дополнительное адресное пространство окрашено в серый цвет, так как здесь оно не ис- пользуется. Первая ячейка памяти программ называется вектором сброса. При запуске программы на выполнение (например, при подаче питания), счетчик команд устанавливается в 0000, поэтому первая ячейка памяти, на которую он указывает, — это вектор сброса. Таким образом, программист должен поместить первую команду именно в этой ячейке. Вектор прерывания от периферии, для подпрограмм обслуживания этих прерываний, действует аналогичным образом, но об этом мы поговорим позже, в Главе 6. Рис. 2.4. Память программ и стек микроконтроллера 16F84A (подписи в серых прямоугольниках добавлены автором) 2.4.2. Память данных и регистры специального назначения микроконтроллера 16F84A Распределение памяти RAM этого микроконтроллера изображено на рис. 2.5. Область памяти распределена по банкам и разбита на две важные области. Нижняя из них — память данных общего назначения, занимающая ячейки от ОСн до 4Fh. Над ней размещены реги- стры специального назначения. Давайте рассмотрим два вышеупомянутых понятия под- робнее, поскольку они, скорее всего, читателю не знакомы.
2.4. Память микроконтроллера 16F84A 49 Адресация с применением банков Проблема, которая присуща любой области памяти, заключается в том, что чем боль- ше памяти, тем шире должна быть ее шина адреса. Одним из методов уменьшения адрес- ной шины является разбиение памяти на несколько меньших блоков одинакового размера, называемых банками. Это позволяет использовать более узкую шину адреса, с помощью ко- торой можно одинаковым образом получить доступ ко всем банкам. При этом в определен- ный момент времени в качестве целевого может быть идентифицирован только один банк. В микроконтроллерах PIC структура с банками применяется для памяти RAM. Так, микроконтроллер 16F84A содержит только два таких банка. Адрес каждого из них — семи- разрядный адрес RAM (см. рис. 2.2). Активный банк выбирается с помощью разряда 5 из регистра состояния (см. рис. 2.3). Перед получением любого доступа к памяти программист должен удостовериться, что в регистре состояния разряд банка установлен правильно. Рис. 2.5. Память данных и схема размещения регистров специального назначения микроконтроллера 16F84A (дополнительная надпись в сером прямоугольнике добавлена автором) Регистры специального назначения Регистры специального назначения (РСН) являются “шлюзом” для взаимодействия цен- трального процессора и периферийных устройств. Поэтому их необходимо очень хорошо
50 Глава 2. Знакомство с семейством PIC® 16 и микроконтроллером 16F84A изучить. Для центрального процессора РСН выглядят как обычные ячейки памяти, к ко- торым можно обращаться на запись и чтение. Но что делают эти регистры “особенными” — это двойное назначение их разрядов. Каждый разряд закреплен за одним из перифе- рийных устройств микроконтроллера и используется или для установки рабочего режима, или для обмена данными между внешним устройством и ядром микроконтроллера. Изучая периферию микроконтроллера 16F84A сразу же необходимо изучать и регистры специаль- ного назначения, изображенные на рис. 2.5. Следует отметить, что на рис. 2.2 были пока- заны только четыре таких регистра. Можете сами определить их назначение? Адресация памяти RAM На рис. 2.2 показано, что существует два возможных источника адреса RAM, один из которых выбирается с помощью мультиплексора адресов. Если адрес является частью ко- манды и поступает на мультиплексор из регистра команд, то он называется прямым. Кроме того, адрес можно получить из регистра FSR (File Select Register — регистр выбора файла) — один из РСН-регистров (рис. 2.5). Если пользователь загружает адрес в регистр FSR, который может быть использован в качестве адреса памяти данных, то такая методика называется косвенной адресацией (рассматривается в Главе 5, в подразделе 5.4.1). Фактические адреса памяти изображены на рис. 2.5 в столбце “Адрес в файле”. Эти адреса (по крайней мере, те из них, которые расположены в правом столбце) — восьми- разрядные, однако из рис. 2.2 мы уже знаем, что разрядность шины адреса RAM составля- ет только семь бит, а при прямой адресации доступны только пять разрядов адреса. Важно понимать, что эти адреса состоят из семиразрядного адреса RAM и разряда выбора банка из регистра состояния (Status), подставляемого вместо старшего, восьмого разряда. Во время программирования важно разделять эти источники, удостоверившись, что старший разряд задействован для выбора банка. Как только мы начнем программирование, эта особен- ность станет более понятна. 2.4.3. Слово конфигурации Особым элементом памяти программ микроконтроллера 16F84A является слово кон- фигурации (рис. 2.6). С его помощью пользователь может, во время загрузки программы, определить некоторые свойства конфигурации микроконтроллера. Впоследствии они оста- ются фиксированными до следующего программирования микроконтроллера. Этот под- ход отличается от других возможностей, наподобие записи в регистры специального на- значения. Хотя слово конфигурации является частью памяти программ, к нему нельзя по- лучить доступ из программы или любым другим способом во время работы программы. Ресурсы, которыми оно управляет, будут рассмотрены в этой и последующих главах. 2.4.4. Память EEPROM Память EEPROM — энергонезависимая и особенно удобна для хранения переменных данных, которые, скорее всего, потребуется хранить длительный период времени. Пример таких данных — параметры настройки телевизора, номера телефонов, хранимые в мобиль- никах, или калибровочные настройки измерительного прибора. В микроконтроллере 16F84A (как и в любом другом микроконтроллере PIC) память EEPROM не размещается в области основных данных. Вместо этого (см. правый верхний угол рис. 2.2) она адресуется с помощью регистра EEADR, а данные передаются через регистр ЕЕ DATA. Оба эти регистра относятся к регистрам специального назначения (см. рис. 2.5). Как уже было отмечено ранее, в ходе обзора технологий памяти, считывание из памяти EEPROM — простой процесс, в то время как запись — нет. По меркам электрических процессов, б данном случае процесс записи занимает много времени (миллисекунды), и поэтому следует по возможности избегать случайной записи в память EEPROM. Таким образом, необходим набор средств управления — для инициализации процесса записи и определения момента его окончания. Эти функции выполняют разряды регистра EECON1 (см. рис. 2.7).
2.4. Память микроконтроллера 16F84A 51 R/P-u R/P-u R/P-u R/P-u R/P-u R/P-u R/P-u R/P-u R/P-u R/P-u R/P-u R/P-u R/P-u R/P-u СР СР СР СР СР СР СР СР СР СР PWRTE WDTE F0SC1 F0SC0 Разряд О Разряд 13 Разряды 13-4 СР (Code Protection) — бит защиты кода: 1 = защита кода отключена 0 = вся память программ защищена Разряд 3 PWRTE (Power-up Timer Enable) — бит разрешения включения таймера вкл. питания: 1 = включение питания запрещено 0 = включение пигания разрешено Разряд 2 WDTE (Watchdog Timer Enable) — бит включения сторожевого таймера: 1 = сторожевой таймер включен 0 = сторожевой таймер отключен Разряды 1-0 FOSC1:FOSCO — бит выбора генератора: 11 = RC-генератор 10 = HS-генератор 01 = ХТ-генератор 00 = LP-генератор Рис. 2.6. Слово конфигурации микроконтроллера 16F84A U-0 U-0 U-0 R/W-0 R/W-x R/W-0 R/S-0 R/S-0 - - - EEIF WRERR WREN WR RD Разряд 7 Разряд 0 Разряды 7-5 Разряд 4 Зарезервированы: считываются как ‘О' EEIF (EEPROM Write Operation Interrupt Flag) — флаг прерывания по операции записи в память EEPROM: 1 = операция запрей завершена (флаг должен быть сброшен программно), 0 - операция записи не завершена или не начиналась Разряд 3 WRERR (EEPROM Error Flag) — флаг ошибки памяти EEPROM: 1 = операция записи досрочно прекращена (по причине сброса по входу MCLR или сброса от сторожевого таймера) 0 = операция записи завершена Разряд 2 WREN (EEPROM Write Enable) — бит разрешения записи в память EEPROM: 1 = разрешает циклы записи 0 = запрещает запись в память EEPROM Разряд 1 WR (Write Control) — бит контроля за записью: 1 = начинает цикл записи. Разряд обнуляется аппаратно, как только процесс записи будет завершен. Бит WR может быть установлен в “1” только программно, 0 = цикл записи в память EEPROM завершен Разряд 0 RD (Read Control) — бит контроля за считыванием: 1 = с началом процесса считывания из памяти EEPROM разряд RD обнуляется аппаратно; этот разряд может быть установлен в “1” только программно; 0 = не начинать считывание из памяти EEPROM. Рис. 2.7. Регистр специального назначения EECON1 (адрес 88н) Для того чтобы считать данные из ячейки памяти EEPROM, необходимый адрес тре- буется поместить в регистр ЕЕ ADR и установить в “1” бит RD регистра EECON1. Данные из соответствующей ячейки памяти будут сразу же скопированы в регистр ЕЕ DATA, где их можно сразу же и прочитать. Для записи в ячейку памяти EEPROM соответствующие данные и адрес нужно поместить в регистры EEDATA и EEADR, соответственно. Процесс записи разрешается с помощью бита WREN, который нужно установить в “1”, а затем —
52 Глава 2. Знакомство с семейством PIC® 16 и микроконтроллером 16F84A передать последовательно байты 55н и ААн в регистр EECON2. Встроенные требования для этих кодов помогают обезопаситься от случайной записи (например, при включении питания или при его исчезновении). Затем устанавливается в “1” бит WR, чем фактиче- ски и начинается процесс записи. О завершении этого процесса сигнализирует установка в “1” бита EEIF в регистре EECON1. 2.5. Некоторые вопросы синхронизации 2.5.1. Тактовый генератор и командный цикл Любой микроконтроллер или микропроцессор — это сложная электронная схема, со- стоящая из последовательных и комбинационных логических схем. Она с фантастической скоростью переходит из одного сложного состояния в другое, и каждое такое состояние определяется последовательностью выполняемых команд. Хотя детали этого процесса от нас скрыты, все же необходимо обеспечить для него стабильный тактовый сигнал — не- прерывную последовательность прямоугольных логических импульсов фиксированной час- тоты. Общее быстродействие микроконтроллера всецело зависит от частоты его тактового генератора. К тому же от тактового сигнала зависит не только центральный процессор, но и другие важные функции, опирающиеся на синхронизацию, начиная от счетчика/таймера и заканчивая последовательным обменом данными. Более того, потребление микроконтрол- лером энергии очень сильно зависит от частоты генератора, ведь высокоскоростные опе- рации требуют больше энергии, чем низкоскоростные. Как показано в табл. 2.1, каждый микроконтроллер имеет заданный диапазон возмож- ной тактовой частоты, и уже дело разработчика — определить, какая частота необходима, и избрать приемлемый способ для формирования источника синхроимпульсов. Учитывая, как много зависит от частоты и стабильности генератора, это решение иногда бывает при- нять очень непросто. Но об этом мы поговорим позже, в Главе 3. Внутри любого микропроцессора основной тактовый сигнал сразу же делится на фик- сированное значение, превращаясь в сигнал более низкой частоты. Каждый цикл такого замедленного сигнала называется машинным или командным. Компания Microchip исполь- зует последнее определение. Таким образом, командный цикл становится основной едини- цей времени в работе процессора (например, с его помощью можно определить, сколько времени уйдет на выполнение команды). Сигнал первичного генератора сохраняется, что- бы создавать фазы или временные периоды внутри командного цикла. В семействе микро- контроллеров PIC 16 длительность командного цикла определяется путем деления час- тоты основного тактового сигнала на 4. Табл. 2.3. Длительность командного цикла для разных тактовых частот микроконтроллеров семейства PIC 16 Тактовая частота Командный цикл Частота Период 20 МГц 5 МГц 200 нс 4 МГц 1 МГц 1 мкс 1 МГц 250 кГц 4 мкс 32,768 кГц 8,192 кГц 122,07 мкс В табл. 2.3 представлены наиболее популярные тактовые частоты и результирующие длительности командного цикла. Для самой высокой тактовой частоты 20 МГц частота командного цикла составляет 5 МГц с периодом 200 нс. В более дешевой версии этого микроконтроллера (16F84-04) максимальная тактовая частота составляет 4 МГц, а длитель- ность командного цикла составляет 1 мкс. Как мы увидим позже, это — очень удобное значение для многих простых задач, опирающихся на синхронизацию, в которых исполь- зуются программные циклы временной задержки и счетчики/таймеры. Популярная так- товая частота для систем с очень низким энергопотреблением, включая наручные часы,
2.6. Подача питания и сброс 53 составляет 32,768 кГц, что соответствует периоду командного цикла 122,07 мкс. Это дает очень малую мощность, но при крайне медленных вычислениях! 2.5.2. Конвейеризация Сочетание набора команд RISC и распределения памяти по Гарвардской архитектуре, используемого в микроконтроллерах PIC, дает дополнительное преимущество: команды могут обрабатываться в конвейерном режиме. Каждая команда в памяти программ ком- пьютера сначала должна быть выбрана, а затем выполнена. Во многих центральных про- цессорах эти два действия выполняются одно за другим: сначала центральный процессор извлекает команду, а затем — выполняет ее. Однако если память программ имеет собствен- ные шины адреса и данных, отделенные друг от друга (как в Гарвардской архитектуре), то- гда почему бы не организовать работу центрального процессора таким образом, чтобы во время выполнения одной команды он уже извлекал следующую. Это и называется конвей- ерной обработкой. Конвейеризация наиболее эффективна, когда циклы выборки и выпол- нения всегда одинаковы, как, например, в структуре RISC. Такое простое усовершенст- вование архитектуры повышает быстродействие системы сразу в два раза! Конвейеризация реализована во всех микроконтроллерах PIC, и это — одна из причин их сравнительно большого быстродействия. Пока выполняется одна команда, уже извле- кается очередная. Конвейеризация не действует только для команд, изменяющих значение счетчика команд (например, команд ветвления или безусловного перехода). Ведь извле- ченная команда может оказаться совсем не той, которая необходима. В таком случае про- цесс конвейеризации должен начаться заново, при соответствующей потере одного коман- дного цикла. Процесс конвейерной обработки в микроконтроллерах семейства 16 показан на рис. 2.8. Как видим, во время выполнения команды 1, сразу же выбирается команда 2. То же са- мое происходит и при выполнении команды 2 и т.д. Слева от схемы показан пример по- следовательности команд. Впрочем, для того, чтобы понять суть схемы, нам не нужно понимать значение этих команд, кроме команды CALL, сигнализирующей о ветвлении программы. Команда, расположенная за ней (под номером 4) выбирается центральным процессором, в то время, как команда 3 уже выполняется. В результате ветвления про- граммы команда 4 больше не нужна, и цикл таким образом будет утерян на извлечение новой команды. Tcyo TCY1 TCY2 TcY3 TCY4 TcY5 1. MOVLW 55h Извлечение 1 Выполнение 1 2. MOVWF PORTB Извлечение 2 Выполнение 2 3. CALL SUB_1 Извлечение 3 Выполнение 3 4. BSF PORTA, BIT3 (Forsed NOP) Извлечение 4 Пропуск 5. Instruction @ address SUB_1 Извлечение SUBJ Выполнение SUBJ Извлечение SUB_1 +1 Все команды занимают один цикл, кроме команд любых программных ветвлений, занимающих два цикла (когда команда “выпадает” из конвейера, требуется еще один цикл, чтобы извлечь новую команду). Рис. 2.8. Конвейерная обработка команд 2.6. Подача питания и сброс Когда микроконтроллер включается, его программа должна начать выполняться с самого начала (например, для микроконтроллера 16F84A — с вектора сброса, который можно увидеть на рис. 2.4). Это произойдет только в том случае, если в него встроена со- вокупность схем для регистрации подачи питания и обнуления счетчика команд. Кроме
54 Глава 2. Знакомство с семейством PIC® 16 и микроконтроллером 16F84A того, очень полезно таким образом инициализировать регистры специального назначения, чтобы периферийные устройства изначально находились в безопасном, т.е. отключенном состоянии. Состояние, при котором программа готова к запуску, называется сбросом (Reset). Как только центральный процессор покидает состояние сброса, он начинает вы- полнение программы. ______ В микроконтроллере 16F84A есть вход сигнала сброса, MCLR (вывод 4 на рис. 2.1). До тех пор, пока на этом входе удерживается низкий уровень, микроконтроллер находится в состоянии сброса. Как только на нем появляется высокий уровень сигнала, сразу же на- чинается выполнение программы. Если на этом выводе появляется низкий уровень во время работы программы, то выполнение программы сразу же прерывается, и микроконтрол- лер переходит в режим сброса. Мы еще пока не рассмотрели вопрос о том, когда же все-таки следует разрешать за- пуск программы на выполнение. Момент подачи питания опасен для любой встроенной системы. Как источнику питания, так и тактовому генератору требуется определенное время для того, чтобы стабилизироваться, а в сложной системе подача энергии в разные части схемы может быть стабилизирована за разное время. Думаю, ни у кого не вызывает сомнения, что в данной ситуации необходимо соблюдать большую осторожность. Как же задержать начало выполнения программы до стабилизации питания? Простой способ решения этой проблемы показан на рис. 2.9. Его можно применить для любого микроконтроллера с активным низким уровнем сигнала на входе Reset (Сброс). Если к входу сброса подключить резистивно-емкостную схему, то при подаче питания напряжение на конденсаторе возрастает согласно постоянной времени RC-цепи, которую можно сделать сколь угодно большой. Поскольку уровень сигнала нарастает сравнительно медленно, определенный промежуток времени на входе Reset (Сброс) будет логический 0. Таким образом микроконтроллер может удерживаться в режиме сброса, пока не стабили- зируется его питание, и не будет готов к работе тактовый генератор. Простая внешняя схема сброса показана на рис. 2.9 (а). (а) (Ь) Рис. 2.9. Внешние схемы сброса — общий вид микроконтроллера со входом Reset: (а) — сброс по подаче питания, самый простой вариант; (Ь) — сброс по подаче питания с разряжающим диодом и защитным резистором; (с) — кнопка сброса, нажимаемая пользователем. С этой схемой возникает проблема, если сначала отключить питание, а затем сразу же опять подать его (тяжелая ситуация для любого электронного прибора). В случае схемы, изображенной на рис. 2.9 (а), конденсатор не имеет достаточно времени для разрядки, и при повторной подаче питания состояние сброса может оказаться некорректным. Что еще опаснее, напряжение на конденсаторе может превысить напряжение, подаваемое на мик- роконтроллер, в результате через конденсатор на вход Reset будет подан ток чрезмерной силы. Добавив простой разряжающий диод (рис. 2.9 (Ь)), мы гарантируем, что конденсатор будет разряжаться примерно с той же скоростью, что и скорость изменения напряжения питания Vdd. Также следует, для ограничения тока через вход Reset, включить в схему ре- зистор Rs — на тот случай, если напряжение на конденсаторе значительно превышает уровень напряжения питания микроконтроллера, или возникает какой-либо другой сбой. 4
2.7. Микроконтроллер Atmel АТ89С2051 55 Если разработчик хочет задействовать кнопку сброса, то тогда нужно применить схе- му, изображенную на рис. 2.9 (с). Она особенно удобна при применении макетных схем, для которых предполагается большое количество тестов. Кроме того, кнопка — это очень удобный способ перезагрузки “зависшей” программы. В данном случае R — это подтя- гивающий резистор, номинал которого следует выбирать в диапазоне 10-100 кОм. В про- мышленных изделиях кнопку сброса обычно не используют, поскольку ее функции должны быть скрыты от пользователя внутри самого устройства. Одной из целей компании Microchip является минимизация количества внешних компонентов микроконтроллеров, что напрямую относится и к компонентам, изображен- ным на рис. 2.9. По этой причине микроконтроллер 16F84A содержит ряд сложных, встро- енных на кристалл схем сброса, благодаря чему компоненты, изображенные на рис. 2.9 (а) и рис. 2.9 (Ь), обычно излишни. Кроме того, на кристалле встроен таймер включения питания (PWRT), который пользователь может запустить с помощью разряда 3 слова конфигура- ции (см. рис. 2.6). Микроконтроллер 16F84A определяет подачу питания, а таймер включе- ния удерживает микроконтроллер фиксированное время в состоянии сброса. По истече- нии этого времени микроконтроллер выходит из состояния сброса и начинается выпол- нение программы. На практике, схема, показанная на рис. 2.9 (Ь), применяется только в том случае, если напряжение питания возрастает очень медленно. О таймере включения питания и подробности о встроенной системе сброса см. в разделе 2.8. А что же делать с входом MCLR микроконтроллера 16F84A, если он нам не нужен? Самое главное — это помнить, что он не должен оставаться просто отключенным. Про- стейшее, что можно с ним сделать, — это подключить к шине питания и забыть о его су- ществовании. 2.7. Микроконтроллер Atmel АТ89С2051 Компания Atmel занимается выпуском небольших (но не миниатюрных) микрокон- троллеров, сравнимых по размеру с меньшими микроконтроллерами семейства PIC 16, хотя они и несколько больше модели 16F84A. Они основаны на ядре 8051, первоначально разработанном компанией Intel, и с тех пор принятом на вооружение множеством других производителей, включая Atmel и Philips. Микроконтроллер АТ89С2051 показан на рис. 2.10. Сброс/Vpp С (RXD — вход последовательных данных) РЗ.О С (TXD — выход последовательных данных) Р3.1 С XTAL2 С XTAL1 С (Внешнее прерывание 0) Р3.2 С (Внешнее прерывание 1) РЗ.З С (Вход таймера 0) Р3.4 С (Вход таймера 1) Р3.5 С Земля С ядро 8051 (CISC) рабочий диапазон напряжений 2,7-6 В 15 программируемых линий ввода-вывода шесть источников прерывания • 2 • и • д • -п э Vcc 3 Порт1.7 3 Р1.6 3 Р1.5 2 Р1.4 2 Р1.3 2 Р1.2 3 Р1.1 (Вход аналогового компаратора 1) 2 Р1.0 (Вход аналогового компаратора 0) 2 Р3.7 Кбайт перепрограммируемой флэш-памяти 28 х 8 бит внутренней памяти RAM ва 16-раз рядных таймера/счетчика эограммируемый последовательный канал UART выходы с поддержкой прямого управления светодиодами • встроенный аналоговый компаратор Рис. 2.10. Схема размещения выводов микроконтроллера АТ89С2051 компании Atmel и общая информация об устройстве Этот микроконтроллер имеет 20 выводов и лишь немного превышает по размер мик- роконтроллер 16F84A. Это отражено и в его внутренних возможностях. Несмотря на раз- личия, очень важно подмечать также и сходства. Оба микроконтроллера имеют встроенную память программ (Flash) и данных (SRAM). Входы кристалла, сброса и подачи питания в
56 Глава 2. Знакомство с семейством PIC® 16 и микроконтроллером 16F84A обоих микроконтроллерах очень похожи. В микроконтроллере PIC присутствует 13 циф- ровых линий ввода-вывода, а в микроконтроллере Atmel — 15, и в обоих случаях они под- держивают прямое управление светодиодами. У микроконтроллера PIC — одно внешнее прерывание, а в устройстве Atmel — два. У микроконтроллера Atmel — два 16-разрядных таймера, а у PIC — один восьмиразрядный. Кроме того, микроконтроллер Atmel оснащен средствами последовательного обмена данными, которых у микроконтроллеров PIC про- сто нет. Впрочем, в семействе PIC 16 можно без труда найти “старшего брата” ‘F84A, также оснащенного такими средствами. Еще одна интересная особенность микроконтроллера АТ89С2051 — наличие встроенного компаратора, который позволяет микроконтроллеру поддерживать простые аналоговые функции. Но у устройства Atmel есть и недостаток: в нем отсутствует память EEPROM, которая есть у микроконтроллера PIC. Впрочем, все эти сравнения касаются только периферийных устройств, которые произ- водители могут добавить к микроконтроллеру, а могут и убрать. Какие же отличия микро- контроллеров мы заметим, если начнем их использовать? Ответ находится в ядре и наборе команд. Микроконтроллер Atmel — устройство CISC с системой команд 8051 (наборы команд мы сравним позже, в Главе 4). Сейчас же мы просто продемонстрируем преиму- щества ядра микроконтроллера PIC. Являясь RISC-процессором, он требует только четыре тактовых цикла на одну команду, в то время как у микроконтроллера 2051 их 12. Кроме того, многие команды требуют больше одного машинного цикла. К тому же, микрокон- троллер PIC использует конвейеризацию, отсутствующую в микроконтроллере Atmel. 2.8. Встроенная схема сброса микроконтроллера 16F84A Рассмотрим поближе встроенную схему сброса микроконтроллера 16F84A, которая в несколько упрощенной форме показана на рис. 2.11. Для того чтобы в ней разобраться, потребуется немного времени, однако это того стоит. Рис. 2.11. Схема сброса микроконтроллера 16F84A Фактический сигнал сброса центрального процессора, Chip_Reset, формируется с помощью триггера, изображенного в правой части схемы. Он имеет два входа: S (уста- новка) и R (сброс). Центральный процессор переходит в режим сброса, когда на линии
2.8. Встроенная схема сброса микроконтроллера 16F84A 57 Chip_Reset появляется низкий уровень сигнала, обусловленный высоким уровнем сиг- нала на входе S триггера. Он будет оставаться в этом режиме до тех пор, пока триггер не выдаст сигнал низкого уровня, обусловленный сигналом высокого уровня на входе R. В таком случае, что же становится причиной сброса? Вход S триггера переходит в состояние высокого уровня сигналом с выхода трехвходового вентиля “ИЛИ”, если на одной из перечисленных ниже линий возникает сигнал высокого уровня: • Внешний сброс с линии MCLR • Сброс по истечении времени ожидания сторожевого таймера (см. Главу 6). • Сброс по подаче питания — выход схемы обнаружения напряжения питания. Как только появляется один из перечисленных сигналов, триггер устанавливается, линия Chip_Reset переходит в состояние низкого уровня, и микроконтроллер PIC удер- живается в режиме сброса. Линия Chip_Reset возвращается в состояние логической 1 (и микроконтроллер PIC включается) в результате активизации входа R триггера. Для этого должны быть соблю- дены три требования, обусловленные входами соответствующего вентиля “И”. Источник питания и генератор должны быть стабилизированы, а также должны быть сняты все за- просы на сброс. Первые два требования реализуют с помощью двух интересных таймеров: таймера включения питания (PWRT) и таймера запуска генератора (OST). Таймер включе- ния питания активизируется путем установки соответствующего разряда в слове конфигу- рации (см. рис. 2.6), а таймер запуска генератора — с помощью линии Разрешение OST. На ней автоматически устанавливается “1” пользовательской настройкой генератора в слове конфигурации, разрешающей эту линию для всех режимов генератора, кроме RC. Таймер включения тактируется собственным встроенным RC-генератором. После активи- зации он, до появления на его выходе логической 1, отсчитывает 1024 цикла, что соответст- вует 72 мс. Этого времени вполне достаточно для стабилизации среднего источника пита- ния, однако недостаточно для медленно растущего питающего напряжения. Как только таймер включения завершил свой отсчет, активизируется таймер запуска генератора, ко- торый, в свою очередь, также отсчитывает 1024 цикла главного тактового сигнала. Этим подтверждается, что тактовый генератор работает стабильно, поскольку в противном случае подсчет циклов не велся бы. Выходные сигналы обоих счетчиков логически пере- множаются с инвертированным входным сигналом S триггера, формируя сигнал на входе R триггера. Если на всех линиях установлен высокий уровень сигнала (т.е. оба счетчика завершили счет, и нет запроса на сброс), то триггер сбрасывается. В результате централь- ный процессор выходит из состояния сброса и начинает работу. Рис. 2.12. Последовательность сигналов при сбросе по подаче питания, когда на вывод MCLR подано пи- тающее напряжение VDd- Описанная выше последовательность сигналов при сбросе показана на рис. 2.12. В нем представлена типичная ситуация, когда вывод MCLR соединен с линией Vdd. Подачу пита- ния можно увидеть по подъему кривой VDD, параллельно с которой поднимается и кривая
58 Глава 2. Знакомство с семейством PIC® 16 и микроконтроллером 16F84A MCXR. Это изменение обнаруживается, о чем свидетельствует состояние линии ‘Internal POR’. В результате активизируется таймер включения, который работает в течение времени Tpwrt- По истечении периода Tpwrt активизируется таймер запуска генератора, который обеспечивает задержку на время Tost- Следует отметить, что задержка Тозтзависит от того, насколько успешно работает главный тактовый генератор, а также — от тактовой частоты. Для генератора на 4 МГц это время составляет 1024 х 250 нс, т.е. 256 мкс. По истечении периода TOst на линии R появляется сигнал высокого уровня, выводя микроконтроллер из состояния сброса. Резюме • Семейство PIC 16 — очень эффективное семейство и содержит разнообразные мо- дели микроконтроллеров. • Архитектура микроконтроллера 16F84A олицетворяет архитектуру всех микрокон- троллеров семейства PIC 16: Гарвардская архитектура, конвейеризация и система команд RISC. • У микроконтроллера 16F84A ограничено количество периферийных устройств, выбран- ных для применения в небольших и недорогих системах. Таким образом, это — младший представитель семейства, содержащий средства, присутствующие во все остальных, старших представителях семейства. • Микроконтроллер 16F84A использует три различные технологи памяти. • Особая область памяти — регистры специального назначения, выполняющие роль связующего звена между центральным процессором и периферией. • Механизмы сброса гарантируют, что центральный процессор начнет работать толь- ко при соблюдении всех необходимых условий. Также они могут быть использова- ны для перезапуска процессора в случае возникновения программного сбоя.
ГЛАВА 3. ПАРАЛЛЕЛЬНЫЕ ПОРТЫ, ЭЛЕКТРОПИТАНИЕ И ГЕНЕРАТОРЫ СИНХРОИМПУЛЬСОВ В предыдущих главах мы довольно поверхностно рассматривали теорию архитектуры микроконтроллеров и реализацию этой архитектуры в микроконтроллерах PIC®. В этой главе мы будем двигаться от изученной теории к практике разработки мелкомасштабных аппаратных проектов. Как мы уже знаем, ядро микроконтроллера имеет внутренние шины данных и адреса. Они несколько похожи на автострады или скоростные магистрали, неся в обоих направле- ниях к ряду различных адресатов потоки информации большого объема. При этом микро- контроллер должен располагать некоторым механизмом обеспечения соединения с внеш- ним миром с тем, чтобы получать внешние цифровые значения, а также выдавать нужные цифровые значения во внешний мир. Другими словами, требуется эквивалент развязок автострады, где данные могут покидать шину (или приниматься ею) в нужное время и в нужном месте. В мире микроконтроллеров эти развязки имеют много форм — соответст- венно, имеется и много различных способов, которыми данные могут вводиться в микро- контроллер или выводиться из него. Наиболее универсальный из них — это параллель- ный порт ввода-вывода. Этот порт является одним из наиболее важных периферийных устройств микроконтроллеров, и именно его мы будем рассматривать в этой главе. Если взять, к примеру, работающий автомобильный двигатель, то для его работы тре- буется два основных компонента: топливо и последовательность искр, поступающая от соответствующих разъемов. Микроконтроллер имеет похожие потребности. Топливо — это низкоуровневое электропитание, а вместо последовательности искр микроконтрол- леру требуется регулярная последовательность импульсов от генератора синхроимпуль- сов. Исследованию этих вопросов посвящена вторая часть данной главы. Объединив вместе уже полученные базовые знания с умением работать с цифровым вводом-выводом, а также с приобретенными навыками по проектированию источников питания и генераторов синхроимпульсов, мы сможем, наконец, приступить к проектиро- ванию реальных систем. В этой главе вы узнаете: • о том, почему нам нужен параллельный ввод-вывод; • о том, как можно спроектировать простые логические схемы, которые обеспечат гиб- кий интерфейс между шиной данных микроконтроллера и внешним миром — это па- раллельные порты; • о том, как внешние устройства могут подключаться к параллельному порту; • о параллельном вводе-выводе, обеспечиваемом PIC 16F84A; • о важных аппаратных свойствах источника электропитания и генератора синхроим- пульсов; • о подходе фирмы Microchip к конструкции источника электропитания и генератора синхроимпульсов, реализованном в 16F84A; • об аппаратной реализации электронной игры в пинг-понг.
60 Глава 3. Параллельные порты, электропитание и генераторы синхроимпульсов 3.1. Основная идея —- параллельный ввод-вывод Почти любая встроенная система должна осуществлять обмен цифровыми данными между центральным процессором и внешним миром. Этот информационный обмен может относиться к ряду категорий, а именно: • прямой пользовательский интерфейс, включая использование переключателей, вспо- могательных клавиатур, светодиодов и индикаторов; • входная измерительная информация от внешних датчиков, возможно, получаемая че- рез аналого-цифровой преобразователь; • выходная управляющая информация, поступающая, например, на двигатели или дру- гие приводные элементы; • массовая передача данных в или из других систем или подсистем, осуществляемая в последовательной или параллельной форме; например передача последовательных дан- ных во внешнее запоминающее устройство. При таком изобилии принимаемых и выдаваемых данных, вероятно, что нам необхо- димо располагать целым рядом цифровых входов и/или выходов. С общепринятой точки зрения их можно разделить на последовательные и параллельные порты. При последовательной передаче данных информация перемещается бит за битом — по одному биту одновременно. Для передачи непосредственно данных используется толь- ко одна линия, хотя обычно используются и другие (вспомогательные) линии, предназна- ченные для передачи сигналов синхронизации и управления. При параллельной передаче данных используется определенный набор линий (напри- мер, восемь). Через каждую отдельную из набора линию передается 1 бит, и каждая такая линия работает параллельно с другими из набора, точно такими же линиями. В результате данные могут передаваться группами битов, например байтами. Параллельный ввод- вывод — это настоящая “рабочая лошадка” для всего базисного информационного обмена микроконтроллера, включая интерфейсы с переключателями, светодиодами, индикатора- ми и так далее. Группа параллельных однотипных линий ввода-вывода, подведенная к штырькам микроконтроллера, называется параллельным портом. 3.2. Технические вызовы, связанные с параллельным вводом-выводом Первый непосредственный вызов связан с тем, как обеспечить требуемый интерфейс между шиной данных и адресной шиной микроконтроллера — с одной стороны, и внеш- ним миром — с другой стороны. Как уже говорилось ранее, мы начнем с шины данных — многоцелевой информационной “автострады”. Как можно снять требуемые нам данные с шины и передать их во внешний мир через параллельный порт? И наоборот — как можно взять внешние входные данные и внедрить их на шину данных (в нужное время и в пра- вильное место) с тем, чтобы они попали туда, куда нужно внутри микроконтроллера? И наконец, предположив, что у нас есть порт, который может все это делать, как можно сде- лать его действительно гибким, с тем, чтобы он мог использоваться для ввода или вывода, или и того, и другого вместе, передавая комбинации данных, возможно, для совершенно разных задач. 3.2.1. Формирование параллельного интерфейса Создание набора выходных штырьков для формирования порта вывода является отно- сительно простым делом (рис. 3.1). Давайте присвоим порту адрес в карте памяти. Всякий раз, когда этот адрес будет выбираться командой программы, будет активироваться ли- ния, называемая Port Select (Выбор порта). Другая линия — Read/Write, (Чтение/Запись)
3.2. Технические вызовы, связанные с параллельным вводом-выводом 61 будет указывать на то, выполняет ли центральный процессор операцию чтения (состояние линии соответствует логической 1) или операцию записи (состояние линии соответству- ет логическому 0). Эта линия стробируется сигналом Port Select (Выбор порта). Каждая линия шины данных соединена с триггером, и все они одновременно синхронизуются ли- нией Port Select (Выбор порта). После этого значение шины данных заносится в триггеры — всякий раз, когда в режиме записи адресуется ячейка памяти, присвоенная порту. Вы- ходы линейки триггеров делаются доступными для соединения с внешним миром. Равным образом просто создается и набор входных штырьков (рис. 3.2). Все что нам необходимо — это буфер с тремя устойчивыми состояниями, подключенный через логи- ческие элементы между внешними штырьками и линиями шины данных. Когда буфер ак- тивируется, опять-таки логической комбинацией линии Port Select (Выбор порта) и сиг- нала управления Read/Write (Чтение/Запись), то логическое значение внешнего штырька на короткое время становится идентичным значению на соответствующей линии шины дан- ных. При этом оно может считываться центральным процессором. Обратите внимание на то, что в этом проекте внешние данные не захватываются портом, — они определен- ное время должны удерживаться в стабильном состоянии внешним источником. Рис. 3.2. Два разряда возможного цифрового порта ввода
62 Глава 3. Параллельные порты, электропитание и генераюры синхроимпульсов Эти идеи весьма привлекательны, но действительность состоит в том, что будет крайне нерационально ограничивать внешний штырек микросхемы выполнением только одной функции — или ввода, или вывода. Было бы намного изящнее, если бы мы каким-либо образом объединили две схемы, используемые для ввода и вывода, и дали бы возмож- ность пользователю самому решать, какое направление перемещения данных он предпо- читает в данный момент. Схема, показанная на рис. 3.3, делает именно это. На ней присут- ствует цепь “драйвера штырька” для одного разряда параллельного порта. На схеме легко можно отыскать цепи, показанные на рис. 3.1 и 3.2. Что является новым, так это еще один триггер (‘Направление’), состояние которого определяет, как должен данный штырек мик- роконтроллера работать — на ввод или на вывод данных. Состояние триггера направле- ния задается программой. Этот триггер контролирует “выходной буфер”, который акти- вируется, когда данный разряд порта находится в состоянии вывода. Специальный функциональный регистр 'Направление' Рис. 3.3. Схема управления штырьком двунаправленного порта Эта схема формирует основу очень полезного двунаправленного драйвера штырьков ввода-вывода и очень просто можно прийти к выводу, что какой-либо ее вариант имеется в большинстве популярных микроконтроллеров. Наборы штырьков ввода-вывода группи- руются, формируя параллельный порт ввода-вывода. Каждый триггер данных формирует один разряд специального функционального регистра ‘Данные’, а каждый триггер направ- ления формирует один разряд специального функционального регистра ‘Направление’, как это показано на рис. 3.3. Каждый специальный функциональный регистр отображается на ячейку памяти и имеет свой собственный уникальный адрес. Этот адрес определяет его линию выборки, которая переходит в состояние, соответствующее логической 1, когда эта позиция адресуется. Сигнал Port Select (Выбор порта) выбирает Data SFR (Специальный
3.2. Технические вызовы, связанные с параллельным вводом-выводом 63 функциональный регистр ‘Данные’), а сигнал Direction Select (Выбор направления) выби- рает Direction SFR (Специальный функциональный регистр ‘Направление’). Выполняя запись в специальный функциональный регистр ‘Направление’, пользова- тель может определять, какие разряды должны быть входными, а какие — выходными. Выполняя запись в специальный функциональный регистр ‘Данные’, пользователь может устанавливать значения всех триггеров данных, вне зависимости от того, объявлен ли со- ответствующий штырек фактически выходом или нет. Эти значения затем передаются че- рез буфер на те штырьки ввода-вывода, которые фактически объявлены выходными. Вы- полняя чтение из специального функционального регистра ‘Данные’, программа может получить логическое значение соответствующего штырька ввода-вывода. Если этот штырек объявлен выходным, то его значение будет просто значением, удерживаемым триггером данных и выставленное на штырек ввода-вывода через буфер вывода. Если же штырек объявлен входным, то на него должен быть подан внешний сигнал, и кон- троллер считает его значение. Итак, разработав этот базисный проект, мы можем расширять его, вводя в него новые функции. Мы увидим это, когда будем рассматривать некоторые примеры с микроконтрол- лерами PIC. Однако одна простая доработка уже присутствует на рис. 3.3. Это линия ’Альтернативная функция ввода’, позволяющая внутренним периферийным устройствам использовать линии штырьков ввода-вывода. 3.2.2. Электрические характеристики порта Логические элементы разработаны таким образом, чтобы легко совмещаться друг с другом. Так если мы соединяем логические элементы только одной серии, то обычно нам не приходится волноваться по поводу электрической совместимости. Если же мы соеди- няем логические устройства (в данном случае через штырьки порта микроконтроллера) к не-логическим элементам (например, светодиодам или переключателям), то нам требуется понимание электрических характеристик логических схем. В частности, мы должны будем знать их входные и выходные характеристики. Рис. 3.4. Моделирование выхода логического элемента: (а) — обобщенная модель; (Ь) — модель выхода логического элемента на основе КМОП-структур Выход логического элемента может визуализироваться, или “моделироваться”, как это показано на рис. 3.4 (а). Если выход элемента имеет высокое логическое значение (т.е. логи- ческую единицу), то внутренний переключатель модели находится в верхнем положении. Нижнее положение переключателя соответствует низкому логическому сигналу или ло- гическому нулю. В любом случае выход моделируется как источник напряжения, вклю- ченный последовательно с резистором (в теории схем это называется “эквивалентной схе- мой с источником напряжения”). Vlh — это логически высокое выходное напряжение при
64 Глава 3. Параллельные порты, электропитание и генераторы синхроимпульсов выходном сопротивлении Rs(high). Vll — это логически низкое выходное напряжение с выходным сопротивлением RS(|0W). В случае CMOS (комплементарная МОП-структура) ситуация будет очень простой, поскольку VLh равно напряжению питания, a Vll — равно О В. Эта ситуация иллюстриру- ется на рис. 3.4 (Ь). Таким образом, если питающее напряжение будет равно 5 В, то логи- ческими 0 и 1 будут, соответственно, 0 и 5 В, если никакой ток не будет поступать от вы- хода логического элемента. На практике Rs(high) и Rs(iow) не являются константами. Они до определенной степени зависят от тока, идущего от выхода логического элемента. По этой причине изготовители часто публикуют графическую информацию, относящуюся к выходным характеристикам логических элементов. Вскоре мы увидим это на примере 16F84A. 3.2.3. Некоторые специальные случаи Ниже мы рассмотрим две специальные характеристики ввода-вывода, которые будут важны при исследовании параллельных портов 16F84A. Ввод сигналов при помощи триггера Шмитта Триггер Шмитта (рис. 3.5) отражает определенный тип приема входных сигналов ло- гического элемента, который был спроектирован для того, чтобы “очистить” деградиро- ванный логический сигнал. Он имеет два входных порога, при этом порог “положитель- ного перепада” выше, чем порог “отрицательного перепада”. Сигнал, начинающийся от его низкого значения, должен сначала пройти порог отрицательного перепада (при этом ничего не происходит), а затем перейти порог положительного перепада — при этом выходной сигнал изменит свое состояние. Состояние выходного сигнала не изменится до тех пор, пока входной сигнал (теперь уже спадающий) вновь не пересечет уровень порога отрицательного перепада. Таким образом, небольшие флюктуации сигнала, которые вновь пересекают только что пересеченный сигналом порог, не приведут к каким-либо непред- виденным изменениям выходного сигнала. (Ь) Порог положительного \ перепада Порог отрицательного перепада Рис. 3.5. Характеристики триггера Шмитта: (а) — буфер с входом на триггере Шмитта; (б) — характеристики входа/выхода Выход “открытого стока” Выход открытого стока — это гибкий стиль формирования выходного сигнала, кото- рый может адаптироваться либо как стандартный логический выход, либо как непосред- ственный источник тока нагрузки в случае небольших нагрузок. Кроме того он может ис- пользоваться для реализации специальной логической функции, известной как “Зашитое ИЛИ”. Упомянутый выход иллюстрируется на рис. 3.6 (а). Здесь мы видим, что логический элемент управляет затвором полевого МОП-транзистора, неподключенный вывод стока которого формирует выход. Когда выход логического элемента соответствует логиче- ской 1, полевой транзистор будет в проводящем состоянии и на выводе открытого стока будет логический 0. Если же выход логического элемента будет соответствовать логиче- скому 0, то полевой транзистор будет в непроводящем состоянии и выход открытого стока
3.2. Технические вызовы, связанные с параллельным вводом-выводом 65 будет в неопределенном состоянии (при отсутствии каких-либо иных подключений). Если между стоком и напряжением питания будет включен нагрузочный резистор, то рассмот- ренный выход полевого транзистора будет работать как более-менее обычный логический выход. Однако без активной нагрузки нормального логического выхода, время нараста- ния сигнала на нем будет несколько великовато, а количество тока, снимаемого с него, будет ограничено сопротивлением резистора. Рис. 3.6. Выход открытого стока и некоторые его применения: (а) — выход открытого стока; (Ь) — работа выхода открытого стока на нагрузку; (с) — соединение по схеме "Зашитого ИЛИ" Выход открытого стока может также использоваться для работы на простую нагрузку, как это показано на рис. 3.6 (Ь). В этом случае является существенным, чтобы нагрузка не подключалась к тому же напряжению, что и логические схемы, хотя это напряжение и дол- жно иметь ту же полярность. Следовательно, например, микроконтроллер, запитываемый от 5 В (Vsi на схеме), мог бы управлять нагрузкой, запитываемой от 12 В (Vs2 на схеме), ес- ли все эксплуатационные требования соблюдены. Другое важное применение выхода открытого стока — это соединение по схеме “За- шитого ИЛИ”, показанное на рис. 3.6 (с). Здесь несколько выходов открытого стока соеди- нены вместе и подключены к напряжению питания через один нагрузочный резистор, Rpu. Если все выходы выключены, то общая линия (Vo) будет находиться в состоянии, соответствующем логической единице. Если же хотя бы на любом одном выходе будет ло- гический 0, то общая линия будет находиться в состоянии, соответствующем логическому нулю. Это возможный способ реализации логических функций ИЛИ и HE-ИЛИ. Он важен, как мы это увидим позже, для некоторых типов последовательных каналов связи.
66 Глава 3. Параллельные порты, электропитание и генераторы синхроимпульсов 3.3. Подключение к параллельному порту 3.3.1. Переключатели Переключатели широко используются во встроенных системах. Наш основной инте- рес в отношении переключателей связан не столько с переключениями напряжения либо тока, сколько с тем, как преобразовать позицию переключателя в уровни логических значе- ний, которые могут считываться разрядами портов микроконтроллера. Переключатели используются при формировании прямого интерфейса пользователя в форме кнопок, тумблеров, ползунковых переключателей, поворотных переключателей или кнопочных поворотных переключателей. Они также используются в форме микропереключателей с целью обнаружения некоторых видов механического движения. Самый простой способ определения уровня логического значения по положению перек- лючателя показан на рис. 3.7 (а). На этом рисунке представлен однополюсный двухпози- ционнный переключатель (ОПДП), один вывод которого соединен с землей, а другой — с напряжением питания. Скользящий контакт переключателя просто выбирает один из этих выводов в качестве входа логической схемы. Для некоторых семейств логических схем не рекомендуется непосредственное подключение логических входов к напряжению питания — в этих случаях может быть использован добавочный резистор (показан пунктиром). Рис. 3.7. Подключение переключателей к логическим входам: (а) — соединение ОПДП; (Ь) — соединение ОПОП с нагрузочным резистором; (с) — соединение ОПОП с отводным резистором Имеется небольшой недостаток использования соединений по схеме согласно рис. 3.7 (а), поскольку оно требует применения переключателя типа ОПДП. Более простой вариант, связанный с использованием однополюсного однопозиционного переключателя (ОПОП), например кнопки, показан на рис. 3.7 (Ь). В этом случае нагрузочный резистор подключа- ется к одному выводу переключателя, а другой его вывод включается на землю. Если пе- реключатель замкнут, то входной сигнал логического элемента Vi будет равен О В, а ток Vs/R будет идти на землю. Если переключатель разомкнут, то V) будет равно Vs- Чтобы уменьшить потери тока при замкнутом переключателе, значение R должно быть большим. Если же, однако, оно будет слишком большим, то может оказаться, что напряжение соот- ветствующее логической 1 и, как предполагается, является заданным, не будет правиль- но поддерживаться. Чтобы оценить верхний предел нагрузочного резистора, необходимо провести расчет с учетом входного тока утечки и логического порога (как это показано в Главе 2). Для микроконтроллеров PIC обычно будут приемлемыми значения нагрузки в диапазоне 10-100 кОм. Схема по рис. 3.7 (Ь) очень полезна и широко используется. Так многие простые переключатели (например, ползунковые переключатели, монтируемые на печатных платах, и кнопки) доступны только в исполнениях ОПОП. Схема переключателя по рис. 3.7 (Ь) может быть переконфигурирована так, как это по- казано на рис. 3.7 (с). Однако характеристики некоторых семейств логики (например, ТТЛ), устанавливают ограничения на использование такой схемы, поскольку ток, снимаемый с входа логического элемента, значительно воздействует на функцию отводного резистора. Эта схема может применяться с микроконтроллерами PIC.
3.3. Подключение к параллельному порту 67 3.3.2. Светодиоды В некоторых полупроводниковых материалах наблюдается излучение света, когда ток проходит через р-n переход, смещенный в прямом направлении. Светодиоды используют это явление. Светодиоды, выполненные из арсенида галлия (GaAs) испускают свет в ин- фракрасной области спектра. При этом если к арсениду галлия в возрастающих пропорци- ях добавлять фосфор, то световое излучение будет смещаться к видимому диапазону, ста- новясь красным и, в конечном счете, — зеленым. На практике широко распространены све- тодиоды с красным, зеленым и желтым свечением. Они могут иметь исполнение отдель- ных устройств, матриц, диаграммных панелей и текстовых дисплеев. Поскольку светодиоды — это диоды, то они демонстрируют нормальные вольтампер- ные характеристики, как для диодов с прямым смещением перехода. Это означает, что с приемлемым приближением можно считать, что напряжение на светодиоде будет посто- янным, если он находится в проводящем состоянии. Обратите внимание, однако, что это прямое напряжение значительно выше для диодов на GaAs, чем на кремнии. Пример ха- рактеристик для красных и зеленых светодиодов фирмы Kingbright показан на рис. 3.8. На показанных графиках видно, что напряжение на красном светодиоде изменяется от 1,90 до 2,00 В при росте тока от 5 до 20 мА. Для зеленого светодиода напряжение изме- няется от 1,95 до 2,20 В для того же самого диапазона изменения тока. Эти значения на- пряжения типичны для всех светодиодов подобного типа, при этом красные светодиоды имеют немного более низкое прямое напряжение, чем зеленые или желтые. (а) (Ь) Прямое напряжение (В) ПРЯМОЙ ТОК И ПРЯМОЕ НАПРЯЖЕНИЕ прямой ток и ПРЯМОЕ НАПРЯЖЕНИЕ Код типа:L-441D Длина волны = 627 шп 15mcd typ.@ 10 мА Код Tnna:L-44GD Длина волны =565 шп 12mcd typ.@ 10 мА Рис. 3.8. Пример характеристик светодиодов фирмы Kingbright: (а) — высокоэффективный красный; (Ь) — зеленый. Воспроизведено с разрешения Kingbright Elec. Со. Ltd Как видно из рис. 3.8, различные цвета не обеспечивают одинаковую интенсивность свечения для равных токов возбуждения. Красные светодиоды в этом смысле наиболее эффективны, что и объясняет их большую популярность. Для того чтобы комфортно на- блюдалось свечение отдельного светодиода, обычно требуется пропускать через светоди- од ток, примерно равный 10 мА. Более яркие светодиоды могут потреблять до 20 мА, но специальные маломощные устройства (типа высокоэффективных красных светодиодов) требуют всего 1 или 2 мА для того, чтобы их свечение было заметным.
68 Глава 3. Параллельные порты, электропитание и гёнераторы синхроимпульсов Светодиод может управляться выходом логического элемента, например портом мик- роконтроллера, при условии, что его токовые требования могут быть удовлетворены. В зависимости от возможностей выхода порта, светодиоды могут подключаться так, чтобы выход логического элемента был источником тока (рис. 3.9 (а)) или же его приемником (рис. 3.9 (Ь)). Рис. 3.9. Управление светодиодами от логических элементов: (а) — выход логического элемента является источником тока, проходящего через светодиод; (Ь) — выход логического элемента отводит ток, идущий от светодиода. Семейства логических элементов на основе КМОП-структур имеют симметричные вы- ходы. Поэтому схемы как с исходящим, так и с входящим током работают одинаково хо- рошо, так что на практике может применяться любая из схем, показанных на рис. 3.9. На- против, логика ТТЛ может обеспечить только очень небольшой исходящий ток и, в то же время, может отводить с выхода достаточно значительный ток. Следовательно, в этом случае конфигурация соединения по рис. 3.9 (Ь) будет более предпочтительной. Обычно последовательно со светодиодом должен включаться токоограничивающий резистор. Его сопротивление рассчитывается так, как это показано ниже, учитывая напря- жение в цепи. Точные значения обычно не требуются. Для схемы с источником тока: Рон = RId + Ко R = (Кон- KD)//D (3.1) Для схемы с отводом тока: Ks = Kql + Rin + Ко 7? = (Ks-Kd-Kol)//d (3.2) Исключением для использования последовательно-включенного резистора (который в таком случае должен применяться с осторожностью) являются случаи, когда логические элементы запитываются относительно низким напряжением и внутреннее выходное сопро- тивление само по себе формирует соответствующее значение токоограничивающего рези- стора. 3.4. Параллельные порты PIC 16F84A Как было показано в Главе 2, микроконтроллер 16F84A имеет два порта, — А и В. Порт А — 5-ти разрядный, в то время как порт В — 8-ми разрядный. Обратите внимание, что согласно рис. 2.1, некоторые разряды портов выполняют больше, чем одну функцию.
3.4. Параллельные порты PIC 16F84A 69 Как мы увидим далее, 16F84A может работать со схемой управления штырьками общего назначения, приведенной на рис. 3.3, и обеспечивает рациональное использование соот- ветствующих дополнительных функций. Специальные функциональные регистры (SFR), которые связаны с портами, показаны на рис. 2.5. В любом случае сами по себе данные порта заносятся в регистры PORTЛ или PORT# (т.е., согласно рис. 3.3, эти регистры работают как специальный функциональный регистр ‘Данные’), в то время как направление движения данных определяется значения- ми разрядов регистров TRIS/4 или TRISB (т.е. эти регистры работают как специальный функциональный регистр ‘Направление’ согласно рис. 3.3). Сейчас мы исследуем эти порты несколько подробнее. Возможно, что наиболее про- стым из названных портов является порт В, с которого мы и начнем наше рассмотрение. 3.4.1. Порт В микроконтроллера 16F84A Это 8-разрядный двунаправленный порт общего назначения, имеющий схему управ- ления штырьками, подобную изображенной на рис. 3.3. На рис. 3.10 (а) иллюстрируются самые простые цепи, соответствующие разрядам от 0 до 3. В каждой цепи присутствует триггер данных, в то время как триггер TRIS на рис. 3.10 заменяет триггер ‘Направление’ со схемы, приведенной на рис. 3.3. Можно заметить, что если выход триггера TRIS уста- новлен в 0, то активируется буфер, которым он управляет, и соответствующий разряд порта переходит в режим вывода. (а) (Ь) RBPllW VOO Триггер 'Данные' Шина данных [Р Слабая нагрузка RBPLlW Vdd Сигн. записи в порт Триггер TRIS О Q I/O штырек2 Сигн. записи Сигн. чтения из порта Триггер 'Данные' Шина данных $ Слабая нагрузка Сигн. записи в порт Триггер TRIS О О Входной Ду буфер ТТЛ У Сигн. записи I/O штырек2 Входной Ду буфер ТТЛ у Линия RB0/INT Сигнал чтения из триггера TRIS Буфер на триггере Шмитта Сигнал чтения из порта Входные данные заносятся в триггер всякий раз, когда порт выполняет операцию чтения в триггер TR|S Сигн. Чтения из TRIS Сигн. чтения из порта Линия RBIF От штырьков Триггер О Прим. 1: TRISB = 1 активирует слабую нагрузку (если RBPU = 0 в регистре OPT1ON_REG); 2: Штырьки ввода-вывода имеют диодную защиту по Vdd и Vss- Удерживает зна- чение, которое было занесено в триггер ранее EN Сравнивает предыдущие и текущие входные значения порта / Сигнал чтения из порта Прим. IbTRISB = 1 активирует слабую нагрузку р (если RBPU = 0 в регистре OPTION_REG); 2: Штырьки ввода-вывода имеют диодную защиту по Vdd и Vss- в триггер TRIS ► СК~~^ D Рис. 3.10. Структурная схема управления штырьками порта В: (а) — штырьки от RB3 до RB0; (Ь) — штырьки от RB7 до RB4 (дополнительные надписи в заштрихованных прямоугольниках добавлены автором) Имеются четыре доработки простой схемы управления штырьками, которую мы рас- сматривали ранее. • Входящие данные на схеме буферизуются самым нижним триггером, а не считываются их мгновенные значения. • Состояние триггера TRIS может считываться через буфер, управляемый линией RD TRIS (Сигнал чтения из триггера TRIS). Отсюда следует, что регистры TRIS работают
70 Глава 3. Параллельные порты, элекфопитание и генераторы синхроимпульсов как обычные ячейки памяти, по отношению к которым можно выполнять операции счи- тывания-записи. Таким образом, программа, в случае необходимости, может считы- вать значение, занесенное ранее в эту ячейку. • Линия RB0/INT (Разряд О/Внутрисистемный) является также входом для внешнего прерывания и имеет интерфейс на триггере Шмитта. • Резистивные элементы “слабой нагрузки” могут быть включены для всех разрядов пор- та, используемых как входы. Они могут применяться для того, чтобы заменить рези- стор в схемах, подобных приведенной на рис. 3.7 (Ь). Нагрузка выполнена на р-каналь- ном полевом МОП-транзисторе, который можно увидеть в верхней части схемы. Эти нагрузки активируются для всего набора разрядов порта, работающих как входы, по- средством очистки разряда RBPU в регистре OPTION (Опции). (Он показан как ото- браженный на пространство памяти — на рис. 2.5, и полностью — на рис. 6.9.) Разряды от 4 до 7 порта В показаны на рис. 3.10 (Ь). Они реализуют полезную функцию “прерывания по изменению”. Как и в случае с разрядами, имеющими меньшие номера, значение данных заносится в триггеры, когда входные данные считываются портом. В этих разрядах, однако, предыдущее входное значение, считанное, когда порт последний раз выполнял чтение данных, сохраняется в другом триггере. Это сохраненное значение сравнивается с новым входным значением. Любое различие обнаруживается логическим элементом “Исключающее ИЛИ”, выход которого может генерировать прерывание. Эта функция будет подробно рассматриваться в Главе 6. Рис. 3.11. Структурная схема управления штырьками порта А: (а) — штырьки от RA0 до RA3; (Ь) — штырек RA4/T0CKI (дополнительные надписи в заштрихованных прямоугольниках добавлены автором) 3.4.2. Порт Д микроконтроллера 16F84A Как и порт В, этот порт также может использоваться как двунаправленный дискретный порт общего назначения. Базовая схема управления штырьками порта (рис. 3.11 (а)) очень похожа на схему управления штырьками порта В. В этот раз на схеме полностью показан
3.5. Генератор синхроимпульсов 71 выходной буфер, имеющий три устойчивых состояния. Разряд 4 (рис. 3.11 (Ь)) дублирует- ся как вход синхроимпульсов таймера 1. Он также имеет вход с характеристиками триг- гера Шмитта, а также выход открытого стока, который рассматривался в подразделе 3.2.3. Данные, предоставляемые изготовителем устройства, показывают, что абсолютное макси- мально-допустимое напряжение, которое можно прикладывать к выходу открытого стока, равно 8,5 В. Следовательно, способность управления по выходу открытого стока внешней нагрузкой, запитанной внешним напряжением, в данном случае превосходит нагрузоч- ную способность самого микроконтроллера и должна использоваться с осторожностью. 3.4.3. Выходные характеристики порта Выходные характеристики порта 16F84A приведены на рис. 3.12 для напряжения пи- тания 3,0 В. На рис. 3 12 (а) мы видим, что (при 25 °C) выходное напряжение логической 1 равно 3 В, когда выходной ток равен 0, однако падает примерно до 1,7 В, когда ток, выхо- дящий из логического элемента, равен 10 мА. Точно так же (при 25 °C) из рис. 3 12 (Ь) мы видим, что выходное напряжение логического 0 равно 0 В, когда выходной ток равен 0 мА, однако повышается приблизительно до 0,8 В, когда выходной ток логического эле- мента (направленный в логический элемент) становится приблизительно равным 22,5 мА. По подобным графикам можно определить величины Vol и Voh, используемые в уравне- ниях (3.1) и (3.2), если только известно значение ID. В полном варианте технических дан- ных приводятся также характеристики для напряжения питания, равного 5 В. Другой способ применения этих кривых состоит в том, чтобы вывести из них прибли- зительное значение выходного сопротивления. Это может быть выполнено посредством определения характеристики кривой в конкретной точке. Простая графическая конструк- ция, позволяющая это сделать, была добавлена к каждому графику. Деля вертикальную ко- ординату точки (т.е. напряжение) на ее горизонтальную координату (т.е. ток), мы получим по каждому из графиков, что выходное сопротивление будет приблизительно равно 170 Ом — для единичного логического значения выходного сигнала и 36 Ом — для нулевого логи- ческого значения выходного сигнала. Если назовем эти два значения, соответственно, Roh и ROl, то уравнения (3. 1) и (3.2) могут быть записаны в другом виде: Для схемы с источником тока: Fs = (R + RohVd + FD R = (Es-Rd)//d-Roh (3.3) Для схемы с отводом тока: Fs= (R + 7?он)Ъ + FD R = (Es-Ed)/7d-Roh (3.4) 3.5. Генератор синхроимпульсов Выбор источника синхроимпульсов микроконтроллера определяет некоторые из его фундаментальных рабочих характеристик. В то время как принцип “чем быстрее, тем лучше” справедлив в терминах скорости работы и выполнения программ, однако “быст- рее” определенно хуже в терминах потребляемой мощности, а также, возможно, в терми- нах генерирования электромагнитных помех. Все синхронизированные элементы внутри микроконтроллера почти неизбежно зависят от характеристик синхрогенератора. Если требуется устойчивая и точная синхронизация, то генератор синхроимпульсов должен быть стабильным и точным. Учитывая все это, становится ясным, что источник синхро- импульсов нужно выбирать с осторожностью и пониманием. Этот раздел начинается с рассмотрения доступных технологий синхронизации, после чего мы перейдем к рассмот- рению опций, предлагаемых в микроконтроллере 16F84A.
72 Глава 3. Параллельные порты, электропитание и генераторы синхроимпульсов (а) (Ь) Рис. 3.12. Выходные характеристики порта для 16F84A: (а) — V0H от 10н (VDD = 3 В, от -40 до +125 °C); (Ь) — Vol от IOl (VDd = 3 В, от -40 до +125 °C) (штриховые линии добавлены автором.)
3.5. Генератор синхроимпульсов 73 3.5.1. Типы синхрогенераторов Говоря в общем, можно сказать, что имеются два типа схем синхрогенераторов, кото- рые нашли широкое применение в микроконтроллерах, — они иллюстрируются рис. 3.13. В синхрогенераторе резисторно-конденсаторного (RC) типа (рис. 3.13 (а)), конденсатор за- ряжается через резистор от шины питания. Напряжение, снимаемое с конденсатора, управ- ляет входом триггера Шмитта. Когда будет превышен порог триггера Шмитта, его выход переходит в состояние, соответствующее логической единице, и включает полевой МОП- транзистор, с которым он соединен. Конденсатор быстро разряжается, выход триггера Шмитта переходит в состояние, соответствующее логическому нулю, полевой МОП- транзистор выключается и процесс заряда начинается вновь. Эти процессы продолжа- ются непрерывно, пока подается напряжение питания. Сигнал синхроимпульсов гене- рируется как выход триггера Шмитта и имеет прямоугольную форму. Эта простая цепь интегрирована во многие большие интегральные схемы (БИС), требующие наличия по- следовательности синхроимпульсов. От пользователей здесь обычно требуется, чтобы они подключили внешние резистор и конденсатор, выбор которых определяет результи- рующую частоту. Важно, однако, отметить, что RC-генераторы могут быть реализованы также полностью во встроенном в микросхему варианте. RC-генераторы очень дешевы и обеспечивают надежное генерирование последовательности синхроимпульсов. Однако, поскольку сопротивление резистора, емкость конденсатора, величина напряжения пита- ния и пороговое значение триггера Шмитта изменяются при изменении температуры, то частота RC-генератора не достаточно стабильна. Следовательно, генераторы этого типа не могут использоваться в случаях, когда необходима точная синхронизация. Принцип работы кварцевого генератора (рис. 3.13 (Ь)) основан на использовании пьезоэлектрических свойств кристалла кварца. Любая механическая деформация этого материала приводит к возникновению электрического напряжения на противоположных сторонах кристалла; и наоборот — если к материалу приложить электрическое напря- жение, то это приводит к механическим деформациям кристалла. Кристаллы аккуратно вырезаются с приданием им формы очень тонких пластин (обычно дисков). К их проти- воположным сторонам крепятся тонкие электроды. Вся сборка монтируется так, чтобы допускались вибрации. Будучи включенным в цепь обратной связи вокруг логического инвертора, как показано на рисунке, кристалл, благодаря пьезоэлектрическому эффекту, начинает механически вибрировать. Эти вибрации преобразуются в электрические ко- лебания, усиливаемые действием логического элемента. Конденсаторы малой емкости, подключенные между землей и каждой стороной кристалла, оптимизируют электриче- ские параметры, необходимые для генерации колебаний. Рис. 3.13. Схемы синхрогенераторов микроконтроллеров: (а) — резистивно-емкостная (RC) схема; (Ь) — схема, использующая кварцевый кристалл или керамический резонатор (Ь)
74 Глава 3. Параллельные порты, электропитание и генераторы синхроимпульсов Вибрация кристалла происходит на фиксированной и весьма стабильной частоте — это большое преимущество кварцевого генератора. Вместе с тем сами по себе кристаллы демонстрируют тенденцию к тому, чтобы быть достаточно дорогими (хотя их стоимость постоянно снижается) и механически непрочными. Альтернативой кварцевому кристаллу является керамический резонатор. Он имеет пьезоэлектрические свойства, подобные кварцевому кристаллу и подключается таким же образом. Вместе с тем, он имеет меньшую стоимость и отличается несколько меньшей стабильностью частоты. Кварцевые кристал- лы являются единственным выбором, когда необходимо реализовать прецизионные функ- ции синхронизации, основанные на использовании синхрогенератора. 3.5.2. Практические соображения в отношении генераторов синхросигналов Все изготовители микроконтроллеров прошли длинный путь для того, чтобы обес- печить легкость генерации синхросигналов для выпускаемых ими микроконтроллеров. Обычно это достигается использованием встроенных в микросхемы контуров, соответ- ствующих рис. 3.13, возможно в гибридной форме. В силу этого можно понять тех, кто предполагает, что синхронизация микроконтроллеров — это простой вопрос, однако фак- тически это не так — ненадежные или нефункционирующие генераторы — это причина реальных нервных расстройств у разработчиков-новичков. Частота генератора, как прави- ло, демонстрирует большую или меньшую зависимость от напряжения питания, темпе- ратуры, влажности, характера разводки печатной платы, а также, возможно, ряда других факторов. Кварцевые генераторы, в частности, особо чувствительны к неудачной компо- новке печатной платы. Очень важно исключить паразитные сопротивления, емкости и индуктивности (за счет использования максимально коротких печатных проводников), поместив для этого кварцевый генератор как можно ближе к корпусу микроконтроллера. 3.5.3. Генератор синхроимпульсов в 16F84A 16F84A может быть сконфигурирован на работу в четырех различных режимах син- хронизации, позволяя использовать RC, кристаллические или керамические генераторы синхросигналов. Детально эти режимы рассматриваются далее. Может также быть ис- пользован внешний источник синхроимпульсов. Пользователь сам выбирает режим, кото- рый должен использоваться, устанавливая нужные разряды в слове конфигурации (рис. 2.6). • Режим XT — это режим применения кварцевого генератора в стандартной конфигу- рации. Он предназначен для использования кварцевых кристаллов или керамичес- ких резонаторов в диапазоне от 1 до 4 МГц. • Режим HS — это режим высокой скорости, представляющий собой более напряжен- ный вариант режима XT. Этот режим основан на признании того факта, что более вы- сокочастотные генераторы и керамические резонаторы в общем случае требуют ис- пользования больших токов возбуждения. Этот режим предназначен для кварцевых генераторов в диапазоне частот, выше 4 МГц и/или керамических резонаторов. В этом режиме наблюдается самое высокое потребление мощности из всех режимов синхро- низации. • Режим LP — это режим низкой мощности. Этот режим предназначен для использо- вания низкочастотных кварцевых генераторов. При этом обеспечивается самое низ- кое, из возможных, потребление мощности. Во многих случаях будет использоваться частота 32,768 кГц (то есть 215 Гц), которая является наиболее популярной частотой для маломощных, чувствительных ко времени приложений, например для наручных часов. Этот режим, однако, может использоваться для любой частоты, лежащей ниже примерно 200 кГц.
3.6. Электропитание 75 • Режим RC — это режим резистивно-конденсаторной схемы. Для его использования внешние резистор и конденсатор должны быть соединены со штырьком 16, копируя схему рис. 3.13 (а). Это самый затратно-эффективный способ формирования генера- тора, но он не должен использоваться, когда нужна высокая точность синхронизации. Номинальная частота колебаний в этой схеме может быть предсказана теоретически и только с ограниченной точностью. И при этом впоследствии будет наблюдаться неко- торый дрейф частоты при изменении температуры, величины напряжения питания, а также временной дрейф. Пример использования RC-генератора мы рассмотрим при изучении практического случая реализации электронной игры в пинг-понг в конце данной главы. Как можно видеть из рис. 2.1, в 16F84A для генератора имеется два штырька: OSC1 (штырек 16) и OSC2 (штырек 15). Внутри между ними включены логический инвертор и соответствующие электронные схемы. Рис. 3.14 демонстрирует возможные конфигура- ции генераторов, которые подключаться с использованием этих штырьков. При формиро- вании генераторной цепи, соответствующей рис. 3.14 (а), может использоваться как квар- цевый, так и керамический генераторы. Любой из трех диапазонов быстродействия, упо- мянутые выше, может устанавливаться через команду конфигурации. Как показано на рис. 3.14 (Ь), может также использоваться RC-генератор. Приблизительная частота коле- бания может быть выбрана посредством использования графиков, приведенных в разделе “Электрические характеристики” справочных технических данных на изделия, как это показано на примере рис. 3.15. И, наконец, внешний источник синхроимпульсов может быть просто соединен со штырьком OSC1 (рис. 3.14 (с)). Более подробное руководство по проектированию синхрогенераторов для контроллеров фирмы Microchip может быть найдено в. (Ь) (а) Рис. 3.14. Способы синхронизации 16F84A: (а) — кварцевый или керамический генераторы: режимы HS, XT или LP; (Ь) — резистивно-конденсаторный контур (RC); (с) — внешняя подача сигнала синхронизации 3.6. Электропитание 3.6.1. Потребность в электроэнергии и ее источниках Как и любые иные электронные цепи, микроконтроллер и встроенная система в целом должны быть обеспечены электрической энергией. Традиционно большое количество ло- гических схем запитывается от 5 В. Так сложилось исторически — именно это напряже- ние было специфицировано для питания семейства логических элементов ТТЛ. С рас- ширением номенклатуры электронного оборудования с питанием от батареек, а также
76 Г лава 3. Параллельные порты, электропитание и генераторы синхроимпульсов прогрессом в области электронных технологий, значение напряжения электропитания понизилось, и сейчас уже обычными являются значения напряжения питания, равные 3,0 и 3,3 В, Рис. 3.15. Усредненные зависимости частот RC-генератора от VDD для переменного R, С = 100 пФ и температуре, равной 25 °C Эксплуатационные условия для электронных компонент указываются в специфика- циях изготовителя. В терминах электропитания имеются два важных вопроса: требуемое напряжение питания и ток, который устройство будет брать от источника питания. Этот ток будет зависеть от рабочей частоты. Кроме того обычно указываются абсолютные мак- симально-допустимые значения, которые указывают те уровни напряжения и рассеяния энергии, при превышении которых данное устройство использоваться не может. 3.6.2. Эксплуатационные условия 16F84A Основные эксплуатационные условия для 16F84A приведены на рис. 3.16. Из него можно видеть, что необходимо использовать напряжение питания, лежащее в диапазоне между 4,0 и 5,5 В, если только не используется режим синхронизации HS. Если же исполь- зуется HS-режим синхронизации, то напряжение питания не должно быть ниже 4,5 В. Если система находится в режиме сна или бездействия (когда приостановлено выпол- нение всех программ, а генератор синхроимпульсов выключен), то напряжение питания может быть снижено вплоть до 1,5 В. При этом данные в оперативной памяти все еще бу- дут сохраняться. Если необходимо, чтобы система работала при более низких значениях напряжения питания, то необходимо использовать микропроцессор 16LF84A. При дальнейшем изучении таблицы можно видеть, насколько ток питания зависит от частоты генератора. Типичное значение тока питания, равное 1,8 мА, может ожидаться при частоте в 4 МГц и напряжении питания, равном 5,5 В. Если частота генератора уве- личивается до 20 МГц, то это приведет к возрастанию тока питания до 10 мА. Следует отметить, что оба эти значения фактически “очень хорошие”, если сравнивать их с соот- ветствующими параметрами других микроконтроллеров, более “голодных” по отноше- нию к мощности. Однако, если необходимо работать при действительно низких токах потребления, то оцените, что предлагает микропроцессор 16LF84A для низких частот — ошеломительные 15 мкА!
3.6. Электропитание 77 Следует признать, что для систем с батарейным питанием требуемый ток потребления 16F84A делает питание от трехсекционной батареи щелочных аккумуляторов полезной опцией. Так обеспечивается напряжение питания, приблизительно равное 4,5 В. Предпо- ложим, что мы используем в качестве источника питания три аккумулятора размера АА, каждый из которых имеет номинальную емкость 800 мА-часов. Тогда работа устройства при токе потребления в 1,8 мА обеспечит срок службы батареи аккумуляторов, равной 444 часам, или, что то же самое, 18,5 дней. При токе потребления в 10 мА соответствую- щий срок службы будет равен 80 часам или 3,3 дня. А при токе потребления в 15 мкА срок службы названной батареи будет равным 53333 часа, или 2222 дня, что дольше шести лет! В этой случае саморазряд батареи становится существенным фактором. Конечно же, надо понимать, что вышеприведенные подсчеты принимали во внимание только ток потребле- ния микроконтроллера и не учитывали энергопотребление иных электронных компонент. Существенная возможность экономии электроэнергии заключается в использовании режима бездействия системы (или режима “сна”). Этот режим описывается в разделе 6.6. Главы 6. № пара- метра Сим- вол Характеристика Мин. Типич. Макс. Ед. изм. Условия D001 D001 D001A Vdd Напряжение питания 16LF84A 2,0 - 5,5 В Конфигурации синхронизации XT, RC и LP 16F84A 4,0 5,5 В Конфигурации синхронизации XT, RC и LP 4,5 - 5,5 В Конфигурация синхронизации HS D002 Vdr Напряжение сохранения данных в ОЗУ (Примечание 1) 1,5 - - В Устройство в режиме бездействия (“сна”) D003 Vpor Стартовое напряжение VDd, гарантирующее прохождение внутреннего сигнала “Сброс по включению питания” - VSS в См. раздел “Сброс по включению питания” для ознакомления с деталями D004 Svdd Скорость нарастания сигнала Vdd. гарантирующая прохожде- ние внутреннего сигнала “Сброс по включению питания” 0,05 В/мс D010 D010 D010A D013 D014 Idd Ток питания (Примечание 2) 16LF84A - 1 4 мА Конфигурации синхронизации XT и RC (Примечание 3), Fosc = 2,0 МГц, Vqd = 5,5 В 16F84A - 1,8 4,5 мА Конфигурации синхронизации RC и XT (Примечание 3) Fosc = 4,0 МГц, Vdd = 5,5 В 3 10 мА Конфигурации синхронизации RC и XT (Примечание 3) Fosc 4,0 МГц, Vdd " 5,5 В (во время программирования ФЛЕЩ-памяти) - 10 20 мА Конфигурация синхронизации HS (PIC16F84A-20) Fosc = 20 МГц, Vdd = 5,5 В 18LF84A - 15 45 мкА Конфигурация синхронизации LP Fosc = 32 кГц, Vdd = 2,0 В. Режим WDT блокирован. Примечание 1: это предельное значение, до которого может снижаться VDd без потери данных в ОЗУ. Примечание 2: дается дальнейшая информация по факторам, которые влияют на ток потребления. Примечание 3: даются рекомендации о том, как вычислять ток, потребляемый внешними RC-контурами, если они используются. Рис. 3.16. Базовые рабочие условия 16F84A
78 Глава 3. Параллельные порты, электропитание и генераторы синхроимпульсов 3.7. Аппаратный проект электронной игры в пинг-понг Об аппаратном проекте электронной игры в пинг-понг мы уже говорили в Главе 1. Соответствующая принципиальная схема приведена на рис. 2.1 в приложении 2. Теперь мы уже можем понять все детали этой схемы. Напряжение питания подается от двух акку- муляторов размера ААА, которые подсоединены к выводам микроконтроллера VSs и VDD через двухпозиционный переключатель. Так как используется напряжение электропита- ния, равное всего 3 В, то используется версия микроконтроллера LF. Развязывающий конденсатор емкостью 100 нФ, включенный параллельно источнику электропитания, сгла- живает выбросы напряжения, которые могут быть вызваны действием внутренних элек- тронных цепей микроконтроллера. Линия MCLR просто выведена на шину питания, по- скольку нет нужды в довольно простой игре использовать функцию сброса. Можно видеть, что в рассматриваемой схеме используется RC-генератор. Такое ре- шение вполне приемлемо, так как это недорогое приложение, не имеющее критичных ко времени элементов. Рис. 3.15 показывает, что для используемых номиналов компонент при напряжении питания, равном 3,0 В, частота генератора будет равна 800 кГц. Теперь давайте обратим внимание на использование параллельных портов. Из схемы можно заметить, что две игровые кнопки подсоединены к разрядам 3 и 4 порта А, при этом воспроизводится контур согласно рис. 3.7 (Ь) с нагрузочными резисторами, рав- ными 10 кОм. Светодиоды счета и состояния “вне игры” занимают остальные разряды порта А, а все светодиоды “полета шарика” подсоединены к порту В. Все использованные светодиоды относятся к высокоэффективному типу, они подключаются согласно рис. 3.9 (а). Приняв во внимание приблизительное значение выходного сопротивления в 170 Ом, по- лученное в подразделе 3.4.3 этой главы, можно сделать вывод о том, что общее сопротив- ление при последовательном включении каждого светодиода будет равно (560 + 170) Ом. Учитывая, что прямое напряжение на светодиоде приблизительно равно 1,8 В, согласно уравнения (3.3) получим, что его ток будет равен: I = (3 - 1,8) / (560 + 170) = приблизительно (1,64) мА Это значение тока адекватно только для данного типа приложения и светодиодов, когда ожидается наблюдение свечения только с близкого расстояния. В общем же случае его следует рассматривать как низкое. Резюме • Параллельный порт всегда готов к обмену цифровыми данными между внешним ми- ром и центральным процессором контроллера. • Важно понять электрические характеристики параллельного порта и то, как они взаи- модействуют с внешними элементами. • В то время как имеется значительное разнообразие в логическом проектировании портов, все они демонстрируют тенденцию использовать похожие схемы. Внутренние электронные схемы портов требуют понимания, поскольку это ведет к более эффек- тивному использованию портов. • 16F84A имеет разнообразные и гибкие параллельные порты. • Для работы микроконтроллера необходимы сигналы синхронизации. Характеристики генератора синхроимпульсов определяют быстродействие системы и стабильность син- хронизации, а также в большой степени влияют на потребляемую мощность. Активные элементы генератора обычно встроены в микроконтроллер, однако разработчик дол- жен сам определить для себя тип генератора, его частоту и конфигурацию. • Для работы микроконтроллера необходимо электропитание. Требования к электропи- танию нужно понимать и они должны удовлетворяться посредством использования источника питания соответствующего типа.
ГЛАВА 4. НАЧНЕМ ПРОГРАММИРОВАТЬ — ВВЕДЕНИЕ В АССЕМБЛЕР Проект встроенной системы состоит из двух основных частей: аппаратной и программ- ной. В начале эпохи микропроцессоров создание встроенных систем было весьма трудо- емким процессом, требовавшим использования большого количества интегральных схем. Память этих систем была очень ограничена, поэтому для них можно было писать только ма- ленькие программы. Хотя и очень медленно, но те не менее доступные интегральные схемы становились все более и более сложными, и разработчики могли затрачивать все меньше труда при проектировании рабочей аппаратной системы. Тем временем и память возрас- тала в объеме, поэтому стало возможным писать все более длинные программы. Теперь на- стало время, когда памяти много и она дешева. В то же время аппаратные средства сложны и легкодоступны. Сейчас сложные аппаратные системы могут создаваться сравнительно легко, и во многих проектах центр тяжести созидательной активности переместился в об- ласть разработки программных средств. В этой главе мы начинаем длинный, но захваты- вающий путь, ведущий к разработке хороших программ. Мы начнем этот путь, используя язык программирования Ассемблера, но далее в этой книге мы продолжим его, используя язык программирования высокого уровня —- язык С. Мы имеем одну проблему, если мы должны начать создание программ: на чем эти прог- раммы должны отрабатываться? Конечно же, в конечном счете, программы встроенных систем пишутся в расчете на то, что они будут выполняться на аппаратных средствах це- левой системы. Вы можете работать с аппаратными средствами учебной системы PIC , вы можете также реализовать на ней электронный пинг-понг. Во многих случаях, однако, вы не захотите зависеть от аппаратных средств, чтобы реализовать программную идею. Что может действительно оживить изучение программирования — так это использование имитатора — программы, реализованной на настольном компьютере, которая будет вы- полнять программу, которую мы разрабатываем. Поэтому приоритетным направлением этой главы будет введение в интегрированную среду разработки MPLAB® от фирмы Mic- rochip, а также встроенного в нее имитатора. Как только вы освоите эти программные сред- ства, то сможете очень быстро проверять работу своих программных идей, кроме того, вы начнете быстро продвигаться вперед в благородном, но сложном искусстве программиро- вания микроконтроллеров! В этой главе вы узнаете: • о некоторых принципах, связанных с составлением программ для компьютеров; • о существенных моментах программирования на языке Ассемблера, а также о том, как написать простую программу на Ассемблере; • о среде разработки программ, а также об интегрированной среде разработки Microchip MPLAB; • о наборе команд семейства PIC 16 (краткий обзор); • об использовании некоторых команд набора семейства PIC 16; • об имитационном программном обеспечении и программном имитаторе MPSIM™, входящем в состав MPLAB. При желании вы сможете также узнать о том:
80 Глава 4. Начнем программировать — введение в Ассемблер • как набор команд RISC (компьютер с сокращенным набором команд) семейства PIC 16 соотносится с набором команд аналогичного микроконтроллера CISC (компьютер с полным набором команд); • как конструируется командное слово семейства PIC 16. 4.1. Основная идея — что программы делают, и как мы их создаем В первую очередь перечислим основные, по мнению автора, идеи программирования: 1. Компьютер имеет набор команд; он может распознать каждую команду из этого на- бора и выполнить ее. 2. Программа, которую выполняет компьютер, представляет собой список команд, при- надлежащих его набору команд; он считывает эти команды в двоичной форме из па- мяти программ. Программа в этой (двоичной) форме называется машинным кодом. 3. При выполнении программы компьютер работает строго последовательно, перебирая все команды программы с самого начала, делая в точности то, что каждая команда должна делать — ничего больше, ничего меньше, за исключением моментов, когда выполнение программы временно прерывается по сигналу прерывания. И еще — это вроде бы просто, но в тоже время сложно: 4. Программист должен отыскать средства разбиения и преобразования его/ее идей в простейшие шаги, которые компьютер может выполнить — и каждый шаг должен быть именно командой из его набора команд. 4. 1.1. Проблема программирования и компромисс, связанный с использованием языка Ассемблера Проблема программирования иллюстрируется на рис. 4.1. Дело в том, что мы, люди, вы- ражаем наши идеи в сложных и часто неправильно оформленных лингвистических формах. Компьютер же “читает и понимает” только двоичные коды и реагирует абсолютно точно на точные команды. Компьютер безжалостно логичен и делает в точности то, что ему ука- зывают. Должен ли я сравнивать тебя с солнечным днем...? 110 1001 о 01010010 11010101 01001011 01100011 Рис. 4.1. Проблема программирования Учитывая такой лингвистический конфликт, как же программист может все же писать программы для компьютера? Имеются три следующих пути преодоления препятствия:
4.1. Основная идея — что программы делают, и как мы их создаем 81 1. Человек изучает машинный код. Это именно то, что делали программисты в самые ран- ние дни эпохи компьютеров. Они затрачивали чрезмерно много усилий, записывая каж- дую команду в двоичном коде — точно так же, как впоследствии компьютер их счи- тывал. Это было невыносимо медленно, утомительно и порождало ошибки. Однако при этом программист непосредственно распоряжался всеми возможностями компьютера. 2. Использовать язык программирования высокого уровня. (HLL). Это несколько похоже на то, что мы попросили бы компьютер изучить наш язык. При использовании языка программирования высокого уровня команды записываются в форме, которая позво- ляет распознать слова естественного языка — например, русского или английского. Другая компьютерная программа, компилятор либо интерпретатор, затем преобразует программу в машинные коды, которые компьютер сможет понять. При использовании языка программирования высокого уровня программисту на много легче писать очень сложные программы. Однако он/она в этом случае полностью отрезаны от фактиче- ских ресурсов компьютера, а результирующая программа может оказаться совершен- но неэффективной с точки зрения скорости ее выполнения и использования памяти. 3. 'Использовать язык Ассемблера. Это компромиссное решение. При его использовании каждой команде из набора команд компьютера присваивается мнемоническое имя. Это обычно трех- либо четырехбуквенное слово, которое может использоваться для прямого обращения к команде из данного набора команд. Программист затем пишет программу, используя мнемонические обозначения команд. При этом программист фактически должен мыслить на уровне компьютера, поскольку он/она работают непо- средственно с командами. В этом случае у программиста есть, по крайней мере, мне- монические обозначения — он не работает непосредственно с машинными кодами. Специальная компьютерная программа, называемая Кросс-Ассемблером, в наши дни запускаемая обычно на ПК, преобразует программу, написанную с использованием мнемонических обозначений, в машинные коды, которые в последствии компьютер и будет выполнять. Поскольку преобразование от языка Ассемблера в машинные коды выполняет компьютер, то в этот процесс можно встроить ряд других преимуществ. Так, например, кросс-ассемблер может взять на себя большую часть работы по распределе- нию ресурсов программы по пространству памяти машины, он также может понимать метки, присвоенные числам и ячейкам памяти, что значительно облегчает задачу про- граммиста. В ранние дни компьютерной эры программирование на Ассемблере использовалось для организации работы почти всех компьютеров. В наши же дни его интенсивно исполь- зуют и разработчики встроенных систем, особенно тогда, когда они используют для этого маленькие 8-ми разрядные устройства. Для разработчиков встроенных систем Ассемблер предоставляет большое преимущество, связанное с тем, что он позволяет им работать не- посредственно с ресурсами устройства и порождает эффективные машинные программы, которые быстро выполняются. Поскольку Ассемблер непосредственно связан со структу- рой вычислительной системы, работа на нем помогает пользователю лучше понимать струк- туру и организацию работы системы. Однако программирование на Ассемблере имеет и недостатки — процесс написания программы достаточно медленен, большая вероятность возникновения ошибок, а в результате не всегда получается хорошо структурированная программа. Мы попытаемся решить эти головоломки в последующих главах. Сейчас же с целью написания простых программ и большего понимания микроконтроллеров мы при- ступим к изучению Ассемблера. 4. 1.2. Процесс написания программы на Ассемблере Фактический процесс написания программы на Ассемблере иллюстрируется на рис. 4.2. Программист пишет программу на языке Ассемблера того микропроцессора или микро- контроллера, который он предполагает использовать в целевой системе. Это может быть
82 Глава 4. Начнем программировать — введение в Ассемблер сделано при использовании всего лишь только текстового редактора. Скоро мы узнаем, что две строки программы на Ассемблере, приведенные на рис. 4.2, — это команды из на- бора команд семейства PIC 16. Компьютер, на котором он или она пишет программный код, выполняет программу, называемую кросс-ассемблер. Термин “кросс-ассемблер” под- разумевает, что один компьютер ассемблирует код для компьютера другого типа, а не для себя. Обычно, и это несколько может сбивать с толку, кросс-ассемблер называют просто Ассемблером. Кросс-ассемблер ассемблирует программу, т.е. переводит ее из мнемо- ники Ассемблера в машинные коды, готовые для выполнения микроконтроллером. На рис. 4.2. видно, что кросс-ассемблер преобразует две строки текста на Ассемблере в 14-ти разрядные машинные слова семейства PIC 16. Для большинства микроконтроллеров суще- ствуют специальные средства программирования, которые могут выгрузить программу в машинных кодах из главного ПК и записать ее в память программ микроконтроллера. Рис. 4.2. Программирование на Ассемблере 4. 1.3. Процесс разработки программы Процесс написания программ на Ассемблере необходимо рассматривать в более ши- роком контексте разработки проекта в целом. Возможные стадии процесса разработки программы для простого проекта встроенной системы иллюстрируются рис. 4.3. Программист пишет то, что называется исходным текс- том программы, на языке Ассемблера. Этот текст затем ассемблируется кросс-ассембле- ром, работающем на хост-компьютере. Если программист имеет доступ к имитатору, то он может выполнить на нем тестирование программы. Вероятно, что это приведет к тому, что в программе будут найдены ошибки и потребуется внести коррекции в исходный текст программы. Будучи удовлетворенным программой, разработчик затем записывает ее в па- мять программ микроконтроллера, используя либо автономный программатор, связанный с хост-компьютером, либо средства программирования, включенные непосредственно во встроенную систему. После этого разработчик тестирует программу, работающую на реальных аппаратных средствах. Опять-таки, это может привести к тому, что потребуется еще раз внести изменения в исходный текст программы.
4.2. Набор команд семейства PIC 16 и немного больше об арифметико-логическом устройстве (АЛУ) 83 Рис. 4.3. Разработка простого проекта Очевидно, что при разработке даже простого проекта возможность выбора среди раз- личных инструментальных программных средств является плюсом. Эти средства обычно связываются вместе в том, что называется Интегрированной Средой Разработки (ИСР). 4.2. Набор команд семейства PIC16 и немного больше об арифметико-логическом устройстве (АЛУ) 4.2.1. Подробнее об АЛУ семейства PIC16 Перед рассмотрением набора команд семейства PIC 16, имеет смысл немного подроб- нее рассмотреть АЛУ этой серии (рис. 4.4). Поняв, как оно работает, мы также сможем лучше понять рассматриваемый набор команд. 8-ми разрядный литерал (из слова команды) Регистровый файл d = ‘0’ или литеральные команды | Регистр W | бит d d = ‘Г или 1-ми разрядное регистровое значение g (по прямому либо косвенному адресу команды) команды с обращением в память данных Специаль- ные функци- ональные регистры (SFR) и ОЗУ общего назначения Рис. 4.4. Блок-схема АЛУ семейства PIC 16
84 Глава 4. Начнем программировать — введение в Ассемблер Итак, если посмотреть на рис. 4.4, то можно видеть, что АЛУ может работать с данны- ми, получаемыми из двух источников. Одним из них является регистр W (“рабочий”). Вто- рым является либо значение литерала, либо значение из памяти данных (эти ячейки памяти фирма Microchip называет “регистровыми файлами”). Значение литерала — это байт данных, связанный с конкретной командой, которую программист включает в программу. Таким образом, мы можем ожидать встретить как команды, которые обращаются к памя- ти данных, так и команды, которые перед своим использованием требуют специфициро- вания литеральных данных. Далее мы рассмотрим соответствующие примеры. Данные, с которыми команда работает или которые она использует, называются операндами. Опе- ранды могут быть как данными, так и адресами. Мы уввдим, что одни типы команд всегда требуют специфицирования операндов, а другие •— нет. А где сохраняется результат после того как команда будет выполнена? Для многих команд Microchip предлагает выбор: результат может сохраняться либо в регистре W, либо заноситься в память. То, какой вариант будет использован, фиксируется определен- ными командами; в таких случаях это определяется состоянием специального d-бита, спе- цифицируемого внутри команды. 4.2.2. Набор команд семейства PIC16 — введение Теперь давайте обратим наше внимание на набор команд семейства PIC 16, который приведен в Приложении 1. Посмотрите на него долгим пристальным взглядом — наша цель ознакомиться с ним весьма близко! Вы можете ввдеть, что таблица разделена на шесть столбцов, а каждой из 35 команд отведена одна строка. В первом столбце приведено фак- тическое мнемоническое обозначение команды вместе с кодом, определяющим тип опе- рандов, с которым работает эта команда. Имеется четыре типа (и кода) таких операндов: • f — для файла (т.е. адрес ячейки в оперативной памяти) — 7-разрядное число; • Ь — для бита уже специфицированного файла — 3-разрядное число; • d — для адресата, как описывалось выше — один разряд; • к — для литерала: или 8-разрядное число, если это данные, или 11-разрядное число, если это адрес. Второй столбец подводит итог того, что данная команда делает. В некоторых случаях это дает достаточную информацию. Намного более полное описание того, как работает каждая команда, может быть найдено в технической документации по микроконтроллеру. Третий столбец показывает, сколько циклов отводится на выполнение команды. В слу- чае процессора RISC можно было бы ожидать, что это всегда будет только один цикл. Это, в общем-то, так и есть. Только за исключением тех команд, которые вызывают в прог- рамме передачу управления. Их использование мы обсудим в Главе 5. В четвертом столб- це для каждой команды приведен фактический 14-разрядный код операции. Это те коды, которые генерирует кросс-ассемблер, когда преобразовывает команды исходной прог- раммы на языке Ассемблера в машинные коды. Здесь важно обратить внимание, как коды операндов, перечисленные выше, внедряются в код операции. Пятый столбец показывает, на какие разряды регистра состояния (см. рис. 2.3) воздействует данная команда. Давайте для примера прямо сейчас рассмотрим пять команд, чтобы ввдеть, как в них представляется информация. Кстати, обратим внимание и на то, что программирование на Ассемблере, как правило, уже не чувствительно к регистру, и все примеры, приведенные в этой книге, также не чувствительны к регистру. Следовательно, не волнуйтесь, если вы увидите, что мнемоника команд и операндов в разных источниках приводится как заглав- ными, так и строчными буквами — это не имеет уже никакого значения. В этой книге дано предпочтение, по стилистическим соображениям, программы на Ассемблере записывать строчными буквами. Найдите теперь каждую из перечисленных далее команд в таблице набора команд (Приложение /):
4.3. Ассемблеры и формат программы на Ассемблере 85 • clrw — эта команда очищает значение регистра W, обнуляя его. У команды отсутст- вуют операнды, которые нужно специфицировать. Из столбца 5 видно, что команда воздействует на бит Z регистра состояния. Поскольку результат выполнения команды всегда нулевой, то упомянутый бит всегда выставляется в 1. Команда не воздействует ни на какие другие разряды регистра состояния. • с 1 г f f — эта команда очищает значение, находящееся в ячейке памяти, символичес- ки обозначенной как f. Программист должен специфицировать значение для f. Опять- таки, поскольку результат выполнения данной команды нулевой, то она оказывает воздействие только на бит Z регистра состояния. • addwf f, d — эта команда добавляет содержимое регистра W к содержимому ячей- ки памяти, обозначенной как f. Программист должен специфицировать значение для f. Имеется выбор того, куда будет помещен результат, как обсуждалось выше. Это определяется значением бита операнда d. Вследствие того, что результат может при- нимать различные значения, данная команда оказывает воздействие на все три разря- да кода состояния, а именно: бит Z, бит переноса С и бит дискретного переноса DC. • be f f, b — эта команда очищает один биг ячейки памяти. Как бит, так и ячейка памяти, должны быть определены программистом. Номер бита b может принимать значение от О до 7, т.е. может идентифицировать любой из 8 разрядов ячейки. Команда не изменяет никакие флаги регистра состояния, хотя, в принципе, и можно предположить, что резуль- татом выполнения этой команды будет установка нулевого значения ячейки памяти. • addlw к — эта команда складывает значение литерала к, которое должно быть спе- цифицировано программистом, со значением, находящимся в регистре W. Результат со- храняется в регистре W; возможность выбора места хранения результата отсутствует. Подобно команде addwf, данная команда также может воздействовать на все разряды кода состояния. 4.3. Ассемблеры и формат программы на Ассемблере 4.3Л. Введение в Ассемблеры, а также знакомство с Ассемблером Microchip MPASM™ Для любого микропроцессора или микроконтроллера имеется большое количество (кросс-) Ассемблеров. Некоторые из них распространяются бесплатно изготовителями процессоров, чтобы поощрить людей покупать их изделия. Другие же, обычно более слож- ные, созданы фирмами, специализирующимися на разработке программного обеспечения, и продаются на коммерческой основе. Многие из таких средств поставляются как часть ИСР, как об этом говорилось в подразделе 4.1.3. В данной книге будет использоваться MPASM, — Ассемблер, предлагаемый Microchip. Он обычно используется как часть ИСР MPLAB. Как MPASM, так и MPLAB с определенной степенью детализации будут рассмот- рены позже в этой и следующей главе. В то время как много аспектов программирования на языке Ассемблера являются об- щими для всех кросс-ассемблеров, некоторые из них будут специфичными для конкрет- ного Ассемблера, который будет использоваться. 4.3.2. Формат программы на языке Ассемблера Теперь, после того как мы бросили первый взгляд на набор команд, нам нужно понять, как из этих команд можно создать программу. Программы Ассемблера имеют простой формат, который важно понимать и которого нужно придерживаться. Этот формат пока- зан на примере программы 4.1.
86 Глава 4. Начнем программировать — введение в Ассемблер movlw В’00011000’ ; структура конфигурирования порта А movwf trisa movlw 53 Пример программы 4.1. Формат программы на языке Ассемблера Имеются четыре возможных компонента строки программы на Ассемблере: • Метка. Метка — необязательный элемент строки программы. Когда метка специфи- цируется первый раз, она должна начинаться с крайней левой символьной позиции строки. Ассемблер интерпретирует все, что начинается в этой позиции, как метку. Бу- дучи один раз таким способом определенной, метка может использоваться как опе- ранд. Метки всегда должны начинаться с буквы или символа подчеркивания, но не числа. Допускается, чтобы в строке кроме метки ничего не было — в таком случае эта метка присваивается следующей строке, которая содержит команду. • Мнемоническое обозначение команды. Оно берется из набора команд. Мнемоническое обозначение команды может размещаться где угодно в строке, за исключением на- чальной крайней левой позиции. От метки, если она присутствует, мнемоническое обозначение команды должно отделяться, по крайней мере, одним пробелом. • Операнд. Операнды должны быть точно согласованы с форматом, определенным в на- боре команд. Для лучшей ясности программы, метки используются чаще конкретных чисел. Если в команде имеется больше одного операнда, то они отделяются запятой. • Комментарий. Это необязательный элемент строки программы. Он используется, чтобы повысить информативность программы и ее читабельность. Комментарий дол- жен всегда начинаться с символа “точка с запятой” (;). Кросс-ассемблер игнорирует все, что следует за символом “точка с запятой” в любой строке. Комментарии могут следовать за командами в строке; в качестве альтернативы, вся строка может ис- пользоваться только для комментария. Строка программы на языке Ассемблера может содержать правильно отформатиро- ванную команду, как рассматривалось выше. Она также может содержать только коммен- тарий. Или же строка может быть оставлена совершенно чистой (часто это помогает улуч- шить внешний вид и удобочитаемость всей программы). 4.3.3. Директивы Ассемблера В то время как программа на языке Ассемблера пишется для целевого микроконтрол- лера, она сначала должна быть обработана Ассемблером. Чтобьт помочь этому процессу, а также сделать его более мощным и гибким, необходим способ передачи информации и команд к Ассемблеру, который распознавал бы их так, как ему указывается. Такие коман- ды называются директивами Ассемблера. Они используются для разнообразных целей — например, для определения целевого процессора или специфицирования (определения) того, где программа должна размещаться в памяти. Несколько примеров для Ассемблера MPASM показаны в табл. 4.1. Они написаны на Ассемблере и очень похожи на мнемони- ческие обозначения из набора команд, однако их назначение совершенно иное. 4.3.4. Представление чисел Еще одно приближение к пониманию внутренних операций микроконтроллера — это принять, что иногда кому-то проще думать в двоичных кодах, кому-то — в десятичных, а кому-то — в шестнадцатеричных (или даже восьмеричных). Следовательно, для программы
4.4. Создание простых программ 87 на Ассемблере было бы очень полезно иметь возможность распознавать и соответствую- щим образом реагировать на различные базы счисления. Ассемблер MPASM делает это посредством разрешения установок, используемых по умолчанию. Так, например, если кто-то хочет работать только (или в основном) с шестнадцатеричными числами, то все числа будут интерпретироваться именно так. Любые числа, которые программист захочет представить в иной форме, должны иметь префикс, как показано в табл. 4.2. В примере программы 4.1, во второй строке ставилась цель определить число в двоичной форме, по- этому использовался соответствующий формат из табл. 4.2. В четвертой строке использо- валось шестнадцатеричное число 53 в качестве операнда. Поскольку шестнадцатеричная система используется “по умолчанию”, то нет нужды специфицировать ее явным образом. Табл. 4.1. Некоторые обычные директивы Ассемблера MPASM Директивы Ассемблера Действие list Включает опцию формирования листинга ^include Вставляет дополнительный файл исходного текста программы org Устанавливает начальную позицию программы equ Определяет константу Ассемблера; это позволяет присвоить значение метке end Конец программного блока Табл. 4.2. Представление чисел в Ассемблере MPASM Основание системы счисления Пример представления Десятичное D'255' Шестнадцатеричное H'8d' или 0x8d Восьмеричное 0'574 ' Двоичное В'01011100' Символы ASCII 'G' или А ' G ' Обратите внимание на то, что шестнадцатеричное число не должно начинаться с бук- вы — в противном случае оно может быть интерпретировано как метка. Вследствие этого любым шестнадцатеричным числам, начинающимся с a, b, с, d, е или f, должен предше- ствовать ноль. Так, например, число Ь2н должно вводиться как 0Ь2. 4.4. Создание простых программ 4.4.1. Простая программа перемещения данных Теперь давайте посмотрим на простую программу, написанную для Ассемблера MPASM с использованием ИСР (Интегрированной Среды Разработки) MPLAB. Она приведена в примере программы 4.2. Данная программа написана для аппаратных средств, реализую- щих электронную игру в пинг-понг (см. Приложение 2). Скоро мы будем использовать ее для имитации. Программа начинается с заголовка, составленного из пяти строк комментариев, каж- дая из которых начинается символом “точка с запятой”. В нем приводится название про- граммы, кратко описывается то, что программа делает, а также указывается дата написа- ния программы и имя ее автора. Затем приводится информация об установках конфигура- ции (см. рис. 2.6), которая является фундаментальной для выполнения программы. Скоро
88 Глава 4. Начнем программировать — введение в Ассемблер мы увидим, что имеется более одного способа ввести эту информацию в микроконтроллер. Затем следует первая активная строка программы — все строки до нее были комментари- ями. Она определяет микроконтроллер, который будет применяться, используя директиву list. Пример программы 4.2. Простая программа перемещения данных /ПЕРЕМЕЩЕНИЕ ДАННЫХ ДЛЯ ЭЛЕКТРОННОГО ПИНГ-ПОНГА Данная программа переносит значения кнопочного переключателя из порта А на светодиоды, подключенные к порту В TJW 21.02.05 Тестировано 22.02.05 /Слово о конфигурации: WDT выкл., таймер подачи напряжения питания вкл., / защита кода выкл., RC-генератор г list р =16F84A г ;специфицируем СФР status equ 03 porta equ 05 trisa equ 05 portb equ 06 trisb equ 06 org 00 /Инициализация start bsf status,5 /Выбор банка памяти 1 movlw B' 00011000 ' movwf trisa /порт А в соответствии /с вышеприведенной структурой movlw 00 movwf trisb /вывод всех разрядов порта В bcf status,5 /выбор банка 0 r /"Главная" программа начинается здесь/ clrf porta /очищаем все разряды порта А loop movf porta,0 /перенос порта А в регистр W movwf portb /перенос регистра W в порт В goto end loop Далее следует секция, которая использует директиву equ для того, чтобы определить ячейки памяти специальных функциональных регистров, которые будут использоваться. Для некоторых людей является сюрпризом, что это необходимо делать. Ведь разве мы только что не сообщили Ассемблеру, какой процессор мы будем использовать, поэтому он уже вроде бы должен все “знать”? Однако это не так, и поэтому мы должны предоста- вить соответствующую информацию. Эта программа использует регистр состояния, пор- ты А и В, а также их регистры управления — trisa и trisb. Для них определены метки, при этом адреса памяти взяты непосредственно из карты памяти, приведенной на рис. 2.5. Помните (см. подраздел 2.4.2), что бит выбора банка памяти находится в регистре состоя- ния. Поскольку он удален из списка адресов специальных функциональных регистров, показанных на рис. 2.5, то метки porta и trisa, а также portb и trisb имеют те же самые значения. Есть смысл использовать в программе только одну метку для каждой из названных пар, вместо двух. Хотя мы предпочли не делать это в данном программном при- мере для лучшей ясности, когда используются различные ячейки памяти.
44- Создание простых программ 89 Перед фактическим запуском программы очень важно использовать директиву org, чтобы определить адрес начала программы. У нас нет никакого выбора в отношении этого хдреса — это должен быть адрес вектора сброса, как показано на рис. 2.4. Собственно программа, которая следует после директивы org, использует семь команд. Зсе они манипулируют битами и байтами данных, за исключением одной команды пере- вода. Это следующие команды: • cl г f f — эта команда обнуляет значение в ячейке памяти f; • movwf f — эта команда перемещает содержимое регистра W в ячейку памяти f; • movf f, d — эта команда перемещает содержимое ячейки памяти f в регистр W, если бит d установлен в 0; если же он установлен в 1, то тогда содержимое f просто воз- вращается в f; • movlw k — эта команда перемещает литеральное значение к. Это 8-разрядное число, сопровождающее команду в регистр W; • be f f, b — эта команда очищает бит b (то есть устанавливает значение 0) в ячейке памяти f; • bsf f ,b — эта команда устанавливает значение логической 1 для бита Ь ячейки памяти f; • goto k — эта команда передает управление выполнением программы команде по адресу памяти к. Далее следует секция инициализации программы. Она устанавливает направление пе- редачи данных для всех разрядов каждого из двух портов — это требует доступа к реги- страм управления портов TRISA и TRISB. Поскольку они размещены в банке оператив- ной памяти 1, то, прежде всего, необходимо установить разряд 5 регистра состояния в 1 (как объяснялось в Главе 2). Это выполняется в первой строке собственно программы, поме- ченной меткой start, используя команду bsf. Может использоваться метка status, потому как она ранее была определена в программе числом 3. Если бы это не было сде- лано, то необходимо было бы записать: start bsf 3,5 s /выбираем банк памяти 1 что будет несколько менее понятно. Необходимые направления перемещения данных для штырьков порта определяются по принципиальной схеме (см. рис. А2.1). Из нее можно видеть, что с разрядами 3 и 4 порта А соединяются две кнопки. Следовательно, эти разряды должны быть, соответственно, установлены как входы. Три других разряда порта А соединены со светодиодами, поэтому они должны быть установлены как выходы. Как описывалось в разделе 3.4, для того, чтобы штырек порта был выходом, этот штырек должен иметь логический 0 в соответст- вующем разряде регистра TRIS. Если же он должен быть входом, то в соответствующем разряде должна быть логическая 1. Следовательно, мы должны послать в TRISA слово 00011000. Обратите внимание на то, что TRISA — это 8-разрядная ячейка памяти, хотя порт А имеет только 5 разрядов. Следовательно, необходимо определить для передачи пол- ное 8-разрядное слово, установив даже те 3 разряда, которые не используются. Нет ко- манды, которая позволила бы нам передавать байт данных непосредственно из програм- мы в ячейку памяти, поэтому нужно будет использовать две командные строчки. Сначала требуемое слово 00011000 мы помещаем в регистр W, используя команду movlw. При выполнении этой команды используется двоичное основание системы счисления вместо шестнадцатеричного, используемого по умолчанию (см. табл. 4.2). Содержимое регистра W затем перемещается, при использовании команды movwf, в trisa. Аналогичный про- цесс используется для установки направлений перемещения данных для штырьков порта В. Быстрый взгляд на принципиальную схему показывает, что все штырьки порта В со- единены со светодиодами, поэтому все они должны быть объявлены выходами. Следова- тельно, слово, которое нужно послать в trisb будет равно 00н- Секция инициализации заканчивается выбором банка памяти 0 в регистре состояния, так как через него будет осу- ществляться доступ к портам, которым поставлены в соответствие ячейки памяти в банке 0.
90 Глава 4. Начнем программировать — введение в Ассемблер Ну, наконец, мы дошли до собственно самой программы — до всех ее пяти строк! Прог- рамма непрерывно считывает значения из порта А и передает их в порт В. Таким образом, если будет нажата любая кнопка, то это должно быть отражено светодиодами, соединен- ными с разрядами 3 и 4 порта В. Когда производится чтение из порта А, то считываются все 5 разрядов, даже хотя три из них объявлены выходами. Для них считываются значе- ния внутренних триггеров данных (см. рис. 3.11). Все разряды порта А при этом перво- начально устанавливаются программой в 0 посредством использования команды clrf. Часть программы, выполняющая фактическую передачу данных, использует коман- ду movf для того, чтобы переместить значение порта А в регистр W, затем следует ко- манда movwf, перемещающая значение регистра W в порт В. Команда goto формирует непрерывный цикл, используя ранее определенную метку loop. • Здесь стоит отметить, что значения меткам назначаются двумя различными способа- ми. Некоторым из них, например меткам porta или portb, конкретные значения при- сваиваются программистом, использующим директиву equ. Другие же, подобно метке loop, вводятся собственно в программу, и Ассемблер сам присваивает им значения. Программа заканчивается директивой end. 4.5. Настройка среды разработки 4.5.1. Введение в MPLAB MPLAB — это интегрированная среда разработки (ИСР), которая может быть выгру- жена бесплатно с веб-сайта фирмы Microchip. Имеется также копия этого пакета на ком- пакт-диске, прилагаемом к этой книге. MPLAB содержит все программные инструмен- тальные средства, необходимые для того, чтобы написать программу на Ассемблере, ас- семблировать ее, выполнить на имитаторе ее тестирование и, наконец, загрузить программу в программатор. Последний должен быть собран, куплен или же встроен в целевую сис- тему. Впоследствии могут быть приобретены, а затем интегрированы в MPLAB, дополни- тельные программные инструментальные средства, поставляемые как фирмой Microchip, так и другими поставщиками. Они могут составлять альтернативу тем программным сред- ствам, которые предлагаются MPLAB — например, Ассемблеры или имитаторы, а также инструментальные средства, которые обеспечивают гораздо больше возможностей для разработки, подобно компиляторам языка С или драйверам эмулятора. MPLAB — это пакет, который непрерывно эволюционирует. К нему прилагаются от- дельные руководства, он имеет встроенную интерактивную справочную систему. Данная книга не стремится заменить собой полное руководство по MPLAB. Она, однако, будет стремиться послужить понятным введением в использование MPLAB с тем, чтобы вы с пониманием могли начать применять этот пакет. Далее в этой главе, а также и в после- дующих главах, используются снимки экранов MPLAB версий 7.00 и 7.22. 4.5.2. Элементы MPLAB MPLAB состоит из ряда отдельных компонентов, которые работают вместе, чтобы создать завершенную среду разработки. Это следующие компоненты:. • Текстовый редактор. Он обеспечивает возможность ввода исходного текста. Его ра- бота до некоторой степени похожа на работу простого текстового редактора, напри- мер такого, как Notepad. Но вместе с тем он может распознавать основные элементы языка программирования, который используется. Так, при работе на Ассемблере он одним цветом раскрашивает команды, другим — метки, а третьим — комментарии. Благодаря этому программист может непосредственно видеть, имеется ли ошибка в представлении или использовании текста в строке программы на Ассемблере.
4.6. Вводное занятие по MPLAB 91 • Менеджер проекта. Предпочтительный способ разработки программ в MPLAB — это создание проекта. Проект MPLAB группирует все файлы, относящиеся к одному про- екту, вместе. Менеджер проекта обеспечивает, что все эти файлы будут правильно вза- имодействовать друг с другом и, в случае необходимости, надлежащим способом об- новляться. • Ассемблер и Компоновщик. Функции Ассемблера уже обсуждались. Пока мы пред- полагали, что имеется единственный исходный файл. Однако в сложных проектах программный код может быть скомпонован из группы различных файлов. Роль ком- поновщика заключается в том, чтобы объединить их воедино, присваивая каждому фрагменту правильные адреса памяти, и при этом гарантировать, что переходы и об- ращения из одного файла к другому будут оформлены правильно. • Программный имитатор и отладчик. Программный имитатор позволяет тестировать программу, которая находится в стадии разработки. Это тестирование выполняется посредством ее запуска на ЦП, который имитируется хост-компьютером. Входные сигналы также могут имитироваться, выходные значения и состояния ячеек памяти могут наблюдаться. Отладчик включает средства, обеспечивающие полный контроль за выполнением программы, например пошаговое выполнение программы, запуск ее с пониженной скоростью выполнения либо останов по конкретному адресу памяти. Табл. 4.3. Некоторые файловые расширения, используемые в ИСР MPLAB Расширение файла Функция . asm Исходный файл на языке Ассемблера . err Файл ошибок . hex Файл машинной программы в шестнадцатеричном формате . inc Включаемый файл на языке Ассемблера . lib Библиотечный файл . 1st Файл абсолютного листинга . о Объектный файл . mep Файл проектной информации . mew Файл информации о рабочем пространстве 4.5.3. Структура файла MPLAB Даже в случае простых проектов MPLAB очень быстро создает значительное число файлов. Каждый тип файла обозначается соответствующим расширением, список кото- рых приведен в табл. 4.3. Всякий раз при объявлении проекта создаются файлы типа . тер и . mew. При использовании Ассемблера, первоначальный исходный текст сохра- няется в файле с расширением . asm. Исходный текст программы может включать в себя файл с расширением .inc, как это будет описано в Главе 5. Если исходный текст будет успешно ассемблирован, то на выходе будут сгенерированы файлы с расширением .1st и .hex. Если же имеются ошибки, то они будут занесены в файл .err. 4.6. Вводное занятие по MPLAB Это занятие проведет вас через стадии создания проекта, написания исходного текста простой программы и его ассемблирования, с целью создания выходных файлов. Чтобы отработать это занятие, вы должны загрузить и установить текущую версию MPLAB, если она еще не установлена в системе на вашем месте работы или учебы. Запустите программу MPLAB IDE, при этом должно появиться окно, показанное на рис. 4.5. Если дополнительно откроется пустое окно Ouput (Выход), то закройте его.
92 Глава 4. Начнем программировать — введение в Ассемблер Главный экран будет пустым, если не считать окна Workspace (Рабочая область), рас- положенного в левой верхней части главного экрана. Это окно не может быть закрыто. Рис. 4.5. Экран MPLAB IDE 4.6.1. Создание проекта Щелкните на кнопке Project (Проект) панели инструментов для получения доступа к разворачивающемуся меню, как показано на рис. 4.6. Protect Jj/izaid.. Set Active Protect . ► guild AU ' Ctrl+FIO Make ' F10 Bjyild Options ► Find in Protect Flea, gave Protect Save Protect As.. Add Filet to Pt j|e:t flemove File From Protect » Select language Joolsuite... Set Language Tool Location* Version Control. Рис. 4.6. Разворачивающееся меню Project (Проект)
4.6. Вводное занятие по MPLAB 93 Имеется два способа создания проекта — оба они могут быть использованы из.этого меню. Первый из них связан с использованием команды меню Project Wizard (Мастер проекта), а другой — с использованием команды меню New... (Новый). Итак, щелкните по команде Project Wizard (Мастер проекта) и, работая с диалоговыми окнами, задайте сле- дующие значения: Device: PIC16F84A Active Toolsuite: Microchip MPASM Toolsuite which will display: MPASM Assembler MPLINK Object Linker MPLIB Librarian as Toolsuite contents Project Name Project Directory Add existing files... <your own choice> <your own choice> Make no additions (Устройство: Активный инструментальный набор: в состав которого входят: Ассемблер MPASM Объектный компоновщик MPLINK Библиотекарь MPLIB в качестве компонент инструментального набора PIC16F84A Microchip MPASM Toolsuite Наименование проекта Каталог проекта Существующие файлы... <ка ваш выбор> <на ваш выбор> Отсутствуют) Когда вы щелкните на кнопке Finish (Завершить), обновится состояние окна Work- space (Рабочее пространство) и в нем появятся пути к выбранным файлам, как показано на рис. 4.7 (а). В данном случае наш проект называется f red. (а) I Source Files Header Files I" Object Files Library Files j Linker Scrjpts Other File* (b) 3 fred.mcp" Е-Э- Source Files 1 •• fred.a:m Header Files !•••• Object Files Library F,les /•Linker Scripts ! '•••• Other Files Рис. 4.7. Окно Workspace (Рабонзе пространство): (а) — для вновь созданного проекта; (Ь) — для проекта,, к которому добавлен на.Ассемблере исходный текст программы 4.6.2. Ввод исходного текста программы Теперь откройте новый файл, выполнив команду меню File (Файл) > New (Новый), и начинайте вводить программу, соответствующую примеру профаммы 4.2.
94 Глава 4. Начнем программировать — введение в Ассемблер Введя несколько строк, сохраните их, выполнив команду File (Файл) > Save As... (Сохранить как...). В качестве типа файла выберите Assembly Source File (Файл исходного текста программы на Ассемблере), и сохраните его с именем <Наименование вашего проекта>. asm. Продолжайте вводить исходный текст программы — обратите внима- ние на то, что теперь MPLAB идентифицирует этот файл, как файл исходного текста про- граммы на Ассемблере. Она применила цветную кодировку к меткам, мнемоническим обозначениям команд, численным данным, директивам Ассемблера и комментариям. После того как вы завершите работу, опять перейдите к меню Project (Проект), щелкните по команде подменю Add Files to Project... (Добавить файлы к проекту) и выберите файл, который вы только что сохранили. Ваше окно Workspace (Рабочее пространство) теперь должно появиться в виде, соответствующем рис. 4.7 (Ь), с введенным вами именем файла. Сейчас вы сможете оценить по достоинству ценность этого окна, которое огражает пол- ную картину состояния файлов, связанных с проектом. 4.6.3. Ассемблирование проекта Теперь мы приближаемся к одному из моментов тестирования, неизбежному в любой проектной разработке. Вы ввели новый исходный текст и должны знать, будет ли он пра- вильно ассемблироваться. Ассемблер подвергает ваш программный код ряду проверок. Он возвращает состояние ошибки, если обнаруживает неправильное использование фор- мата Ассемблера, мнемонических обозначений команд, меток и других составляющих программы. Помните, однако, что Ассемблер только с грамматической точки зрения мо- жет эффективно проверить правильность вашей программы; но, при этом, он не может гарантировать, что ваша программа будет жизнеспособной. Кроме всего прочего, Ассем- блер ничего не знает о целевых аппаратных средствах, помимо того факта, что был опре- делен микроконтроллер. Правильное ассемблирование не гарантирует правильной работы программы! Убедитесь в том, что используемое по умолчанию основание системы счисления вы- брано правильно. Для этого выполните Project (Проект) > Build Options (Опции компо- новки) > Project (Проект) > MPASM Assembler (Ассемблер MPASM) и убедитесь в том, что в диалоговом окне выбрано значение Hexadecimal (Шестнадцатеричная). В этом же диалоговом окне вы можете разрешить или запретить чувствительность к регистру для всех исходных текстов программ, Это не является необходимым, если вы просто ско- пировали пример программы 4.2. Однако возможно, что в будущем вам эта опция по- надобится. Вызовите Ассемблер MPASM, выполнив команду Project (Проект) > Build АП (Ком- поновать все). Это также гарантирует, что все файлы будут обновлены в случае необходи- мости. Откроется окно Output (Выход), сообщающее о ходе компоновки. В окне Output (Выход) вы либо получите сообщение “Build succeeded” (Компоновка успешна), либо со- общение “Build failed” (Компоновка не удалась). На экране также появится информацион- ное окошко с зеленой (в случае успеха) или красной (в случае ошибок) полосой. Вне зависимости от того, прошла ли ваша первая компоновка успешно, или потерпела неудачу, откройте файл <ваше имя проекта>. 1st. Он должен быть в каталоге, кото- рый вы определили для проекта. Щелкните на позициях File (Файл) > Open (Открыть) и убедитесь в том, что в диалоговом окошке для позиции Files of Туре (Файлы типов) вы- брано значение All Files (Все файлы). Файл с расширением .1st очень информативен — он дает вам первоначальный исходный текст, наряду с ассемблированными машинными кодами, а также приводит любые ошибки и предупредительные сообщения, которые, воз- можно, были сгенерированы. Часть файла листинга для примера программы 4.2 показана в примере программы 4.3. Обратите внимание на то, как представляется машинный про- граммный код и на то, что после основной распечатки программы приводится необходи- мая информация по программе. Если вы получите сообщения об ошибках, то будет указан номер ошибки и будет при- водиться текст сообщения об ошибке в файле ошибок. В большинстве случаев это будут
4.7. Введение в имитацию 95 просто ошибки ввода информации, которые могут быть легко откорректированы в исход- ном тексте программы с последующей повторной компоновкой. Если ошибка вызывает затруднения, то необходимо получить полную информацию об ошибке. Для этого исполь- зуйте или меню Help (Справка), или обратитесь к и найдите описание ошибки по ее номе- ру. По завершении сессии разработки закройте текущий проект, выполнив команду меню Project (Проект) > Close (Закрыть). Пример программы 4.3. Часть файла листинга Data Move 00029 ;Здесь начинается "главная" программа 0006 3000 00030 movlw 00 ;очистка всех разрядов портов А и В 0007 0085 00031 movwf porta 0008 0086 00032 movwf portb 0009 0805 00033 loop movf porta, 0 перемещение порта А в регистр W 000А 0086 00034 movwf portb ;перемещение регистра W в порт В 000В 2809 00035 goto loop 00036 end MPASM 03. 90 Released DATA MOVE.ASM 3-10-2005 15:55:03 PAGE 2 SYMBOL TABLE LABEL VALUE 16F84A loop porta portb start status trisa trisb и т.д. 00000001 00000009 00000005 00000006 00000000 00000003 00000005 00000006 Как только вы правильно скомпонуете исходный файл, вы сможете или выгрузить полученную программу в память микроконтроллера, или выполнить ее на имитаторе. Сейчас мы рассмотрим второй вариант. 4.7. Введение в имитацию Следующий подраздел является введением в имитатор MPSIM™’ входящий в состав MPLAB. Это введение будет иметь форму учебного занятия, посвященного имитации вы- полнения программы, которую вы только что скомпоновали. 4.7.1. Приступаем к занятию Находясь в MPLAB, вызовите имитатор, выполнив команду Debugger (Отладчик) > Select Tool (Выбрать инструментальное средство) > MPLAB SIM (Имитатор MPLAB). Под позицией главного меню Debugger (Отладчик) появится меню имитатора, показанное на рис. 4.8. 4.7.2. Генерирование входных сигналов порта Эта программа предназначена для работы с аппаратными средствами электронной иг- ры в пинг-понг, поэтому для имитации ее выполнения нам необходимо имитировать вход- ные сигналы от двух кнопок, идущие на штырьки 3 и 4 порта А. Имеется два способа
96 Глава 4. Начнем программировать — введение в Ассемблер имитации входных сигналов. Выбор одного из них зависит от того, должен ли входной сигнал подаваться синхронно с выполнением команды, или нет. Мы выберем простей- ший вариант — асинхронный сигнал, управляемый пользователем. Qear‘Memory . ► ,.ЙЛ ’ Animate ’ Halt • F5 Step Into F7 Step fiver • F8 Step Out Asset ► Breakpoints... F2 . Stopwatch ' Stimulus Controller ► SCL generator ► Profile ► Refresh PM Settings... Рис. 4.8. Меню имитатора Выберите Debugger (Отладчик) > Stimulus Controller (Контроллер стимулирующих сигналов) > New Scenario (Новый сценарий). Внимательно рассмотрите диалоговое окно, которое появится — оно позволяет задавать различные типы входных сигналов штырьков портов, которые в требуемый момент инициируются щелчком на кнопке Fire (Иницииро- вать). Под позицией Pin (Штырек) выберите RA3, а затем RA4 со значением Toggle (Двух- позиционное переключение) под позицией Action (Действие) для каждого. Когда вы за- кроете проект, ваши установки будут сохранены в файле с расширением . st с. 4.7.3. Контроль параметров микроконтроллера Вы можете наблюдать ряд параметров микроконтроллера в ходе моделирования, вклю- чая состояние памяти программ, специальных функциональных регистров, памяти данных и так далее. Соответствующее окно может быть открыто для каждого из названных пара- метров с использованием меню View (Вид). Однако если вы напрямую сделаете это, то скоро убедитесь, что экран быстро заполнится и станет перегруженным информацией. Окно Watch (Наблюдение) позволяет сделать выбор только тех переменных, которые вы хотите контролировать, опуская другие. Позиции для окна Watch (Наблюдение) выбира- ются, используя разворачивающиеся меню в верхней части окна. Откройте окно Watch (Наблюдение) и выберите PCL, TRISA, PORTA, TRISB и PORTB. В дальнейшем окно Watch (Наблюдение) будет выглядеть так, как это показано чуть ниже на рис. 4.10. 4.7.4. Сброс и выполнение программы Вы можете привести моделируемый центральный процессор в исходное состояние двумя путями. Или же путем нажатия функциональной клавиши F6, или же путем выбо- ра команды меню Debugger (Отладчик) > Reset (Сброс). При использовании последнего, предлагаются четыре варианта сброса, отражающие возможности сброса микроконтрол- лера PIC (см. раздел 2.8). В качестве альтернативы (и более просто), вы можете щелкнуть на кнопке Reset (Сброс) инструментальной панели Debugger (Отладчик) (рис. 4.9). Если
4.7. Введение в имитацию 97 эта панель не отображается, то вызовите ее, выполнив команду меню View (Вид) > Tool- bars (Панели инструментов) > Debug (Отладка). Рис. 4.9. Панель инструментов отладчика программного имитатора MPSIM Имеются три способа выполнить программу. Каждый из них может быть выбран в раз- ворачивающемся меню Debugger (Отладчик) или щелчком на кнопке инструментальной панели. Рассмотрим их. • Single Step (Пошагово). Этот способ позволяет пошагово выполнять программу — по одной команде одновременно. В этой версии MPLAB для данного режима используется термин Step Into (Шаг вперед). • Animate (Анимировать). Этот режим похож на автоматизированный пошаговый режим. Программа выполняется медленно, но непрерывно. Состояние экрана обновляется по- сле каждой команды. Скорость выполнения программы может устанавливаться посред- ством выбора: Debugger (Отладчик) > Settings (Настройки) > Debugger Animation (Анимация отладки). • Run (Запуск). Это режим выполнения программы без обновления состояния экрана по мере выполнения программы. В этом режиме допускается ввод стимулирующих сиг- налов. Также возможно выбрать режим Step Over (Перейти через) или Step Out (Выйти) для подпрограммы. Каждому из них также поставлена в соответствие кнопка на инструмен- тальной панели. Эти режимы особенно полезны для подпрограмм с временной задерж- кой, которые на имитаторе могут имитироваться неприемлемо длительное время. Если вы до этого момента выполняли приводимые рекомендации, то экран вашего компьютера должен иметь вид, подобный показанному на рис. 4.10, хотя, вероятно, что окна могут быть упорядочены по-другому. На приведенном изображении мы видим в левой верхней части экрана окно Watch (Наблюдение), в правой верхней части — окно Stimulus Controller (Контроллер стимулирующих сигналов), а внизу слева — окно исход- ного файла программы. Имитируемый центральный процессор был сброшен, поэтому стрелка, отображающая счетчик команд программы, указывает на первую команду. Зна- чение счетчика команд может быть проверено, если посмотреть значение PCL (Счетчик команд программы) в окне Watch (Наблюдение). Теперь, щелкая на кнопке Step Into (Шаг вперед), пошагово пройдите всю программу. Когда программа будет проходить этап инициализации, вы увидите, что значения SFR (Специальный функциональный регистр) будут изменяться в окне Watch (Наблюдение), а значение PCL (Счетчик команд программы) будет увеличиваться. Выполнение програм- мы будет идти в цикле, сформированном последними тремя командами. Теперь попро- буйте запустить сигналы RA3 или RA4. Состояние экранных окон не изменится вплоть до выполнения следующей команды. Наблюдайте изменения значений для портов А и В по мере того, как вы будете пошагово выполнять программу. Попробуйте теперь щелкнуть на кнопке Animate (Анимировать). Обратите внимание, что теперь программа будет вы- полняться непрерывно, однако не будет реагировать на ввод стимулирующих сигналов.
98 Глава 4. Начнем программировать — введение в Ассемблер Рис. 4.10. Вид экрана MPSIM в случае простой имитации 4.8. Загрузка программы в микроконтроллер Большинство современных микроконтроллеров оборудовано встроенной памятью, выполненной на основе флэш-технологии. Процесс ее программирования требует, чтобы данные поступали в микросхему точно синхронизованным способом. При программиро- вании должны использоваться более высокие значения напряжения, чем обычное напря- жение питания рабочего режима. Определенные штырьки микроконтроллера при этом имеют вторичные функции, используемые только в режиме программирования и предна- значенные для того, чтобы передать программные данные в микросхему и принять напря- жения, используемые при программировании. В прошлые времена процесс программирования всегда требовал, чтобы интегральная схема, несущая память (то ли как автономное устройство, то ли как память в микрокон- троллере), была помещена в программатор. Программатор был связан с настольным ком- пьютером для реализации процесса программирования. По мере развития технологии изготовления памяти, процесс стал более простым, и стало гораздо проще разрабатывать необходимые электронные цепи программирования, внедренные в целевую систему. Это означает, что многие микроконтроллеры теперь могут программироваться, будучи уста- новленными по месту назначения, то есть внутри целевой системы. Мы рассмотрим со- ответствующие методы в последующих главах. В данной же главе мы еще будем работать с традиционными программаторами, которые требуют, чтобы микроконтроллер был удален из целевой схемы и помещен в программатор. Популярным и одновременно дешевым программатором, предлагаемым фирмой Mic- rochip, является устройство PICSTART® Plus, показанное на рис. 4.11. Имеется много аль- тернатив этому программатору, включая множество вариантов, предназначенных для
4.8. Загрузка программы в микроконтроллер 99 домашнего использования и распространяемых через Web. Программатор PICSTART соединяется с хост-компьютером кабелем последовательного интерфейса. В состав MPLAB входит программное обеспечение, предназначенное для организации этой связи. В про- грамматор PICSTART может устанавливаться широкий диапазон микросхем с различным типом корпусов (с двойным рядом выводов). Количество штырьков может быть от 18 до 40. При использовании адаптера он может программировать и другие типы микросхем. Рис. 4.11. Программатор PICSTART Plus Описанные далее шаги проведут вас через фактическую загрузку программного кода в микроконтроллер с использованием программатора PICSTART Plus. Если вы располагаете программатором и аппаратными средствами электронной игры в пинг-понг, то вы можете немедленно загрузить программу, которую вы только что создали на предыдущем занятии. Вам понадобится подать напряжение питания на программатор PICSTART и соединить его с последовательным портом компьютера. Находясь в главном окне MPLAB IDE, выбе- рите Programmer (Программатор) > Select Programmer (Выбор программатора) > PIC- START Plus. Затем активируйте программатор, выбрав Programmer (Программатор) > Enable Programmer (Активировать программатор). Положительный ответ должен быть выдан через окно Output (Выход). Если имеется проблема, то, возможно, необходимо про- верить настройки: Programmer (Программатор) > Settings (Настройки) > Communication (Связь). Убедитесь в том, что в окне отображается инструментальная панель программа- тора (рис. 4.12). Если это не так, то отобразите ее, выполнив команду меню View (Вид) > Toolbars (Панели инструментов) > Picstart. Рис. 4.12. Инструментальная панель программатора MPLAB
100 Глава 4. Начнем программировать — введение в Ассемблер На PICSTART переведите рукоятку разъема с нулевой силой вставки (ZIF) в открытое положение. Поместите 16F84A в этот разъем, убедившись по ориентации маркировки, что микросхема находится в правильном положении. Затем закройте рукоятку разъема с нуле- вой силой вставки. При проекте, открытом в MPLAB, вы можете теперь использовать все команды инструментальной панели программатора, показанные на рис. 4.12. 4.9. Что делают другие — краткое сравнение наборов команд CISC и RISC Поскольку они являются процессорами типа CISC (компьютер с полным набором ко- манд), то можно ожидать, что микроконтроллеры Atmel 8051 будут иметь намного более обширный набор команд, по сравнению с микроконтроллерами семейства PIC 16, отно- сящимися к типу RISC (Компьютер с сокращенным набором команд). Кроме того, можно было бы ожидать, что некоторые из его команд будут более мощными, а также то, что цена, которая платится — это более длительное время выполнения команд. Все эти ожидания оказываются справедливыми. Ядро 8051 работает с 111 командами. Большинство команд выполняется в одном машинном цикле, каждый из которых длится 12 периодов синхроге- нератора (по сравнению с четырьмя циклами синхрогенератора для команд PIC). Некото- рые команды занимают два цикла. Две “усложненные” команды — MUL (умножение) и DIV (деление) — требуют для своего выполнения по четыре цикла. Эксплуатационная гибкость, предлагаемая набором команд CISC, кажется привлека- тельной, если на нее смотреть из RISC-мира. Простые действия, которые требуют несколь- ких RISC-команд, сведены в одну команду. Две команды, иллюстрирующие это, показаны в примере программы 4.4. В первой команде байт постоянных данных (называемый лите- ральными данными в PIC-мире, и, насколько мы знаем, непосредственными данными в 8051-мире) перемещается в ячейку памяти, называемую mem_loc. Это требует две коман- ды PIC или одну команду 8051. Программист получает преимущество, связанное с тем, что при использовании 8051 ему нужно записывать меньшее количество строк програм- мы, однако одновременно можно видеть, что отсутствует очевидное преимущество по вре- мени выполнения программы, поскольку каждая из двух упомянутых команд в 8051, в. конечном счете, требует для своего выполнения те же 2 машинных цикла. Действительно, поскольку машинный цикл 8051 значительно больший, то преимущество по времени вы- полнения программы, в конечном счете, остается за микроконтроллером PIC. Интересно, что полученное преимущество PIC становится менее очевидном в следую- щем примере. Семейство PIC 16 имеет только условные команды пропуска и не имеет ко- манд перехода. Таким образом, условные ветви программы должны быть сформированы из команд пропуска, за которыми следует команда goto. Таким образом, для выполне- ния команды условного перехода в микроконтроллерах PIC необходимы три цикла, по сравнению с двумя для микроконтроллера 8051, и, в то же время, для записи команды 8051 необходима одна строка программы. Теперь временное преимущество остается за процессором 8051, если командные циклы будут одинаковыми по длине. Пример программы 4.4. Сравнение возможностей команд RISC и CISC: (а) — перемещение непосредственных/литеральных данных в ячейку памяти; (Ь)переход по установленному биту переноса Семейство PIC 16 Atmel 8051 movlw 22 ;1 цикл movwf mem_loc ;1 цикл (а) mov mem_loc,#22 ;2 цикла btfsc status,0 ;1 цикл (пропуска нет) goto new place ;2 цикла (Ь) jc new_place ;2 цикла
4.10. Двигаемся дальше — форма г набора команд семейства PIC 16 101 Недостаток необходимости дополнительных строк программы, требуемых для RISC- процессоров — не такой уж значительный. При этом мы увидим в следующих двух гла- вах, что даже этот небольшой недостаток может быть почти устранен — на Ассемблере за счет использования макрокоманд, а также за счет использования языка высокого уровня, такого как С, когда программист больше непосредственно не интересуется числом строк результирующего программного кода на Ассемблере. 4.10. Двигаемся дальше — формат набора команд семейства PIC16 Интересно уделить некоторое время для того, чтобы немного глубже понять способ, которым код команды собирается из различных компонент, о чем уже писалось в связи с 12F508/9 в Главе 1. Семейство PIC 16 имеет четыре возможных формата командного слова, как показано на рис. 4.13. Командное слово, которое передается по программной шине (см. рис. 2.2), состоит из 14 разрядов. На рис. 4.13 они пронумерованы, как разряды 0-13. Код операции, фактическая командная часть командного слова, всегда занимает старшие разряды слова. Это именно та часть командного слова, которая поступает в блок декоди- рования команд и управления, показанный на рис. 2.2. При этом эта часть слова не всегда имеет одинаковую длину. Побайтно-ориентированные файловые регистровые операции 13_______________8 7 6____________________О Код операции d f (Файл №) d = 0 по адресу W d = 1 по адресу f f = 7-ми битный адрес файлового регистра Побитно-ориентированные файловые регистровые операции '13 10 9 7 6______________О Код операции b (Бит №) f (Файл №) b = 3-х битный номер бита f = 7-ми битный адрес файлового регистра Литеральные и управляющие операции Общий формат 13 8 7 О Код операции к(литерал) к = 8-ми битное непосредственное значение Только для команд CALL и GOTO 13 11 10 0 Код операции к(литерал) к = 11-ти битное непосредственное значение Рис. 4.13. Форматы команд средних микроконтроллеров PIC Если команда относится к типу, который содержит адрес файла, то она имеет первый показанный формат. Старшие 6 разрядов содержат код операции, в то время как младшие 7 разрядов используются для хранения адреса. Эти разряды подаются на шину “Прямой
102 Глава 4. Начнем программировать — введение в Ассемблер адрес”, показанную на рис. 2.2. Фактически, потому что F84A имеет маленькую память, то используются только самые младшие 5 разрядов, как это можно видеть из приведенной на рис. 2.2 размерности шины “Прямой адрес”. Разряд 7 содержит бит d. Различные форма- ты командного слова используются для других категорий команд. Их можно изучить по рис. 4.13. Резюме Если вы усвоили материал этой главы, то сделали огромный шаг вперед — теперь вы на пути к тому, чтобы стать программистом встроенных систем! Основными являются следующие моменты: • Ассемблер — язык программирования, который является частью комплекта инстру- ментальных средств, используемого при программировании встроенных систем. Он имеет свои собственные правила и методы работы с программами. • Очень важно при разработке программ изучить и освоить Интегрированную Среду Разработки (IDE). MPLAB IDE — это превосходный инструмент для работы с микро- контроллерами PIC. Причем как для начинающих, так и для профессионалов. К тому же его цена весьма невелика. • В то время как некоторые люди стремятся загрузить программы в аппаратные сред- ства немедленно, чрезвычайно полезно узнать возможности имитаторов. Имитатор, встроенный в MPLAB, позволяет пользователям проверять возможности программы с большой скоростью, кроме того — это бесценный инструмент обучения.
ГЛАВА 5. КОМПОНОВКА ПРОГРАММ, НАПИСАННЫХ НА ЯЗЫКЕ АССЕМБЛЕРА В Главе 4 были изложены основные правила программирования на языке Ассемблера, наряду с изучением некоторых команд из семейства PIC 16. Это немного похоже на то, как будто мы изучили некоторые начальные сведения по теории создания кирпичной кладки. Однако необходимо дальше расширять наши знания — мы должны начать думать о струк- турах, в которые мы собираемся встраивать наши “кирпичики” знаний. Следовательно, сейчас мы должны развить наши знания с тем, чтобы уметь создавать полноценные про- граммы, которые имеют понятную структуру, являются функциональными и надежными. В этой главе узнаете: • о том, как визуализировать программу и представлять ее схематически; • о том, как нужно использовать подпрограммы; • о том, как можно реализовать временные задержки; • о том, как использовать поисковые таблицы; • о логических и арифметических командах; • о том, как упростить и оптимизировать программирование на Ассемблере; • о более усложненных функциях программных имитаторов. 5.1. Основная идея — построение структурированных программ Когда мы только начинаем разрабатывать программу, которая должна делать что-ни- будь большее, нежели решение некой примитивной задачи, то важно перед началом на- писания текста программы подумать о планировании ее структуры. И это особенно истин- но в случае использования Ассемблера — в Главе 4 предупреждалось, что одна из проблем работы на Ассемблере связана с тем, что непродуманное программирование может при- вести к созданию неструктурированных программ, построенных по принципу “спагетти”. Следовательно, вначале мы должны рассмотреть схематические средства представления программы. Давайте сделаем это на двух примерах распространенных бытовых устройств (холодильник и стиральная машина) и посмотрим, как это может быть реализовано для этих конкретных примеров. 5ЛЛ. Блок-схемы Хорошо разработанной методикой схематического изображения программ является использование блок-схем. Хотя в блок-схемах можно использовать множество структур- ных символов, мы ограничимся двумя: прямоугольником — для отображения процесса или действия, и ромбом — для принятия решения. Рис. 5.1 демонстрирует простой пример блок-схемы программы работы контроллера холодильника. Пользователь в этом случае располагает единственным органом управления — переменным потенциометром, который позволяет ему/ей устанавливать нужную тем- пературу. Внутри холодильника имеется датчик температуры. Управление температурой
104 Глава 5. Компоновка программ, написанных на языке Ассемблера выполняется посредством включения или выключения компрессора — при работе ком- прессора температура будет понижаться. Программа выполняет считывание значений как фактической, так и требуемой температуры, а затем определяет, какое из этих значений выше. Если выше значение фактической температуры, то компрессор включается. Если различие между двумя значениями слишком большое, то подается предупредительный сигнал. На блок-схеме эти действия отображены с использованием только двух упомяну- тых выше структурных символов. Обратите внимание, что каждый ромбовидный символ принятия решения содержит внутри вопрос, а из него выходят линии, соответствующие ответам “Да” или “Нет”. Эти два выхода и соответствуют двум возможным ответам. Можно видеть, что в данном примере программа будет “циклить” неопределенно долго. Это обыч- ная структура программы для встроенной системы, которую иногда называют суперциклом. Рис. 5.1. Блок-схема простой программы управления холодильником Блок-схемы можно вычерчивать как очень детально, так и очень схематично. Однако, накопив некоторый опыт и потратив некоторое время, можно научиться вычерчивать блок- схемы, которые почти непосредственно можно преобразовать в программу на Ассемблере. В некоторых случаях может подойти общая блок-схема, отдельные части которой пред- ставляются в виде отдельных блок-схем. Некоторые рассматривают составление блок-схем как старомодную методику, под стать самому Ассемблеру, так как этот подход не стимулирует структурированность прог- раммы. Однако они просты в изучении и использовании, а также помогают ясно пред- ставлять простые программные идеи. В силу этого мы будем их использовать для дости- жения наших целей.
5.1. Основная идея — построение структурированных программ 105 5.1.2. Диаграммы состояния Блок-схемы трактуют действительность, как последовательность действий или собы- тий, которые быстро проходят. Многие системы, однако, ведут себя по-другому. Они де- монстрируют тенденцию к тому, чтобы переходить из одного состояния в другое, возмож- но находясь в отдельных состояниях длительный период времени, и выходя из них только по истечении определенного периода времени или же при возникновении определенных событий. Поведение таких систем лучше всего представляется диаграммами состояний, которые формируют альтернативу блок-схемам. Как и в случае с блок-схемами, имеются некоторые сложности при использовании диаграмм состояний в их полной форме. Для достижения наших целей, однако, все что мы должны сделать — это вычертить каждое состояние как кружок, снабженный надписью, и связать эти кружки стрелками. Так мы покажем, при каких условиях система переходит из одного состояния в другое. Каждая стрелка снабжается надписью, в которой указываются условия, приводящие к этому пе- реходу. Начало! Рис. 5.2. Программа управления стиральной машиной, представленная в форме диаграммы состояний Рис. 5.2 демонстрирует работу бытовой стиральной машины, представленную в форме простой диаграммы состояний. После включения машина переходит в состояние готов- ности. Если дверца машины закрыта и пользователь инициализирует цикл стирки, то ма- шина сначала заполняется водой. Датчик уровня обнаруживает момент, когда уровень воды в машине номинальный. Однако машина одновременно контролирует и время, в течение которого идет ее заполнение водой. Если заполнение не выполняется в течение определен- ного отрезка времени, то предполагается наличие неисправности. Причиной этого может
106 Глава 5. Компоновка программ, написанных на языке Ассемблера быть недостаточное давление в водопроводе или же отказ механизма клапана. Исполь- зование тайм-аута —- это недорогая альтернатива замеру расхода воды или собственно давления. После состояния заполнения водой наступает состояние нагрева воды. Опять- таки, наступает тайм-аут, если вода не будет нагрета за отведенное для этого время. Про- цесс продолжается, как показано на диаграмме. При этом каждое состояние имеет как “успешное” условие выхода, так и “Неуспешное”, ведущее к состоянию отказа. С точки зрения программирования, диаграмма состояния — это более абстрактное средство, чем блок-схема — она не преобразуются столь же легко в текст программы на Ассемблере. Фактически часто необходимо преобразовывать каждое состояние в собст- венную блок-схему. А для сохранения ясности структуры и обеспечения хорошего стиля программирования, каждое состояние должно иметь конкретно определенную точку вхо- да и конкретно определенные точки выхода. Использование блок-схем и диаграмм состо- яний, для представления структуры программы, иллюстрируется далее в этой главе для случая написания программы для управления электронной игрой в пинг-понг. 5.2. Управление последовательностью выполнения команд — переходы и подпрограммы Как видно из рис. 5.1 и 5.2, программы редко выполняются в виде одной непрерывной монолитной последовательности команд. Методы, используемые для того чтобы при вы- полнении программы обеспечить возможность перехода к различным ее частям, в целом, называются управлением потоком команд. Именно они будут рассматриваться в этом разделе. Мы уже встречались с командой goto из набора команд PIC, которая выполня- ет безусловный переход из одного места программы в другое. Теперь мы исследуем во- прос об использовании условных переходов и подпрограмм. 5.2Л. Условные переходы и работа с битами Одним из наиболее важных свойств любой программы для микропроцессора или мик- роконтроллера является ее способность “принимать решения”, то есть действовать раз- личным образом, в зависимости от состояния некоторых логических переменных. Многие микропроцессоры имеют в своих наборах целый ряд команд, которые позволяют им прове- рять состояние конкретного бита и/или продолжать выполнение программы, если условия не выполнены, и/или переходить к другой части программы, если условия выполнены. Этот условный переход иллюстрируется рис. 5.3. Наиболее часто соответствующие переменные представляют собой значения битов кода условий либо регистра состояния. Микроконтроллеры семейства PIC 16 ведут себя несколько необычно, когда дело дохо- дит до условных переходов, поскольку в наборе их команд вообще нет команд условного перехода. Взамен этого они имеют четыре команды условного “пропуска”. Эти команды проверяют справедливость некоторых условий и, если условия справедливы, пропускают ровно одну команду. В противном случае — нормальное выполнение программы продол- жается. Из команд пропуска чаще всего используются следующие две универсальные ко- манды: btfsc f,b btfss f,b Первая из этих команд проверяет состояние бита b в ячейке памяти f и пропускает ровно одну команду, если этот бит установлен (т.е. находится в состоянии логической 1). Вторая команда работает подобным же образом, но пропускает одну команду, если прове- ряемый бит сброшен (т.е. находится в состоянии логического 0). Давайте изучим, как рабо- тают эти команды, на примере программы.
5.2. Управление последовательностью выполнения команд — переходы и подпрограммы 107 Рис. 5.3. Условный переход Нашим первым примером будет простая программа перемещения данных из примера программы 4.2. Сейчас она работает хорошо, однако предположим, однако, мы не хотим перемещать в порт А все содержимое порта В. Возможно, мы хотели бы передать всего один бит или дополнительно еще переместить его из одной позиции порта В в другую позицию порта А. Затем мы могли бы использовать “битово-ориентированные” команды из набора команд семейства 16, которых всего имеется четыре: о двух из них мы только что прочитали выше, а двумя другими являются команды bsf и bcf. Пример программы 5.1. Проверка состояния и манипулирование отдельными битами ;Здесь loop начинается "главная" программа очищаем все разряды портов А и В movlw movwf movwf bcf btf ss bsf 00 porta portb portb, porta, portb, 3 ; 3 3 ; :предварительная очистка 3-го разряда порта В :если кнопка нажата, то установка bcf btf ss bsf goto end portb, porta, portb, loop 4 ; 4 4 ; :предварительная очистка 4-го разряда :если кнопка нажата, то установка порта В Фрагмент программы, приведенный в примере программы 5.1, работает почти иден- тично фрагменту программы из примера программы 4.2, но в нем используются команды манипулирования битами, о которых мы только что говорили. При этом если выполняется манипулирование отдельным битом, то это не оказывает воздействия на какие-либо иные разряды порта, в который производится запись. Если нажат соответствующий микропе- реключатель, то включается светодиод. Вместе с тем даже эта простая задача требует неко- торого размышления. Поскольку при нажатии кнопки вход порта переходит в состояние,
108 Глава 5. Компоновка программ, написанных на языке Ассемблера соответствующее логическому 0, то программе необходимо установить выходной бит в состояние, соответствующее логической 1 (чтобы включить светодиод), при состоянии входа, соответствующее логическому 0, и наоборот. Это подразумевает реализацию про- цесса выбора — на языке высокого уровня мы могли бы воспользоваться структурой if ... else Простая команда пропуска не способна сделать это самостоятельно. Один из способов это реализовать состоит в том, чтобы предварительно установить выходной бит в какое то одно значение, а затем изменить его, если окажется, что бит установлен неверно. УПРАЖНЕНИЕ ПО ПРОГРАММИРОВАНИЮ 5.1 Откройте новый проекте рекомендованным именем Bit_Set или выберите какое- либо иное имя. Скопируйте пример программы 4.2 в исходный файл, однако заме- ните секцию кода “main” (главная) примером программы 5.1. Скомпонуйте проект и выполните его прогон на имитаторе. При помощи контроллера стимулирующих сиг- налов создайте входные сигналы для штырьков 3 и 4 порта А и выберите Toggle (Двухпозиционный переключатель) в качестве значения поля Action (Действие). От- кройте окно Watch (Наблюдение), выбрав в качестве контролируемых переменных PCL, PORTA, PORTB и регистр W. Пошагово пройдите через всю программу, пода- вая в нужные моменты входные сигналы и наблюдая эффект. Измените программу так, чтобы: (1) Устанавливались разряды 3 и 4 порта В, если будут нажаты соответствующие кнопки; (2) При нажатии кнопок устанавливались другие разряды порта В. 5.2.2. Подпрограммы и стек По мере того, как разрабатываемые вами программы будут становиться все большими и большими, вы быстро обнаружите, что имеются программные секции, которые являют- ся настолько полезными (если выразиться точнее — со стандартными функциями), что правильно было бы их использовать и в других местах. Ведь это очень утомительно, да и расточительно, с точки зрения использования памяти, — всякий раз писать программную секцию, когда она понадобиться. Это подводит нас к понятию подпрограммы. Подпрограмма — это программная секция, структурированная таким образом, что ее можно было вызвать из любого места программы. Как только выполнение подпрограммы будет завершено, программа продолжает выполняться с того места, где ее выполнение было прервано вызовом подпрограммы. Эта идея иллюстрируется рис. 5.4. В некоторой точке основной программы имеется команда Call SR1. Управление выполнением программы в этом месте переключается на подпрограмму SR1, идентифицированную ее меткой. Каж- дая подпрограмма должна завершаться командой “возврат из подпрограммы” (Return). Выполнение программы затем продолжается с команды, следующей сразу после команды Call. Немного позже в программе вызывается еще одна подпрограмма, а еще несколько позже вновь вызывается первая подпрограмма. Действие команды Call является двойным. Так, во-первых, она сохраняет в стеке со- держимое счетчика команд — с тем, чтобы ЦП знал, к какой команде он должен возвра- титься сразу после завершения подпрограммы. Во-вторых, она загружает стартовый адрес подпрограммы в счетчик команд. Таким образом, выполнение программы продолжается в подпрограмме. Команда Return дополняет действие команды Call — она загружает счетчик команд данными, содержащимися на вершине стека. Эти данные представляют собой адрес команды, следующий сразу после команды Call. В результате выполнение программы продолжается с этого адреса. Команда вызова подпрограммы и команда Re- turn должны всегда работать в паре.
5 3. Генерирование временных задержек и интервалов 109 Рис. 5.4. Вызовы подпрограмм Команды вызова подпрограммы и возврата из подпрограммы для набора команд се- мейства PIC 16 указаны в Приложении 1 — они называются просто call и return. Име- ется также специальная команда возврата — retlw. Соответствующие примеры подпро- грамм будут рассматриваться в следующем подразделе. Подпрограмма, вызываемая из другой подпрограммы, называется вложенной подпро- граммой. При выполнении таких вызовов следует помнить, что каждый раз после вызова подпрограммы занимается одна ячейка стека, вновь освобождаемая после возврата из под- программы. Если мы вызываем подпрограмму из другой подпрограммы, то будут заняты уже две ячейки стека, три — если имеется еще один вложенный вызов и т.д. Поскольку в микроконтроллерах семейства 16 стек имеет всего восемь уровней или ячеек, то необхо- димо уделять внимание тому, чтобы не произошло “переполнение стека”. 5.3. Генерирование временных задержек и интервалов “Вечная” тема встроенных систем — это то, как учитывать время — т.е. как обеспе- чивать своевременную реакцию на внешние события, а также как замерять время и гене- рировать временные задержки. Даже при наших ограниченных на данный момент знаниях в области программирования мы все же можем приступить к рассмотрению вопроса при- вязкй ко времени посредством создания программных циклов, которые будут обеспечивать временные задержки заранее определенной и точной длительности. Изначальная концепция является простой: выбирается ячейка памяти, которая будет действовать как счетчик. Затем в этот счетчик загружается некоторое значение, после чего от содержимого счетчика в цикле будет отниматься 1 — до тех пор, пока содержимое счетчика не станет нулевым. Время, которое на это уйдет, зависит от загруженного в счет- чик значения, а также от времени, которое занимает однократное выполнение цикла. Для реализации точных временных задержек частота синхрогенератора должна быть точной и стабильной, кроме того мы должны знать эту частоту. Здесь заключено одно из преимуществ использования кварцевого генератора, поскольку он обеспечивает велико- лепную точность и стабильность частоты. Приблизительные временные задержки могут, конечно, выполняться и при использовании иных источников синхроимпульсов, как мы делали это в случае электронной игры в пинг-понг. В случае PIC, мы должны всегда
110 Глава 5. Компоновка программ, написанных на языке Ассемблера помнить, что каждый командный цикл занимает четыре тактовых цикла, как это было описано в подразделе 2.5.1 Главы 2. Простой пример цикла временной задержки, взятый из программы электронной игры в пинг-понг, приведен в примере программы 5.2. Он имеет форму подпрограммы, назы- ваемой delay5. Подпрограмма начинается с занесения числа в ячейку памяти del on tri. В данном случае это число равно 200р, хотя оно может быть изменено для получения вре- менной задержки иной длительности (вплоть до максимума, который для 8-разрядной ячейки памяти равен 255d). Фактический цикл задержки — это секция программного кода, начинающегося с метки dell. Две команды пор, которые вообще ничего не делают, но занимают время, используются для того, чтобы увеличить время, требуемое для одной итерации цикла. Затем выполняется команда de of sz. Это приводит к вычитанию единицы от содержимого ячейки памяти delcntrl, которая ранее была загружена. Если после вычитания единицы результат будет нулевым, то последующая команда пропускается и отрабатывается команда return. Для 199 циклов результат после вычитания единицы еще не будет нулевым, поэтому пропуск команды не будет иметь места, а будет отраба- тываться переход на метку dell. Пример программы 5.2. Подпрограмма формирования временной задержки /Время задержки приблизительно равно 5 мс. /Время командного цикла равно 5 мкс. delay5 movlw D'200' /запрограммировано 200 циклов, каждый из /которых займет 5x5=25 мкс movwf delcntrl dell nop /1 командный цикл nop /1 командный цикл decfsz delcntrl,! /1 командный цикл, /если нет пропуска, то переход на метку dell goto dell /2 командных цикла return Продолжительность временной задержки, формируемой этой подпрограммой, можно легко определить, приняв во внимание время, занимаемое каждой командой цикла (бе- рется из таблицы набора команд, Приложение 7). Эти времена указаны в комментариях. В то время как delcntrl последовательно уменьшается на 1 от ее начального значения, цикл сформирован из двух команд пор, а также команд decf sz и goto. Когда команда decf sz выполняется без скачка (без пропуска следующей команды), то она занимает толь- ко один цикл, в то время как команда goto всегда занимает два. Следовательно, общее количество на один проход программного цикла — пять командных циклов. В элек- тронном пинг-понге частота синхроимпульсов приблизительно равна 800 кГц, и, следо- вательно, частота командных циклов равна 200 кГц, т.е. один период командного цикла равен 5 мкс. Следовательно, каждый проход программного цикла с его пятью командны- ми циклами будет занимать 25 мкс. Запрограммировано две сотни проходов программного цикла; следовательно, общая продолжительность временной задержки будет равна 5 мс. Для более точного формирования временной задержки необходимо также принять во внимание продолжительность времени заключительного цикла, а также время входа и вы- хода из подпрограммы. На заключительной итерации цикла, например, команда decf sz отрабатывает пропуск следующей команды и, следовательно, занимает два командных цикла. В то же время команда goto пропускается. Простой цикл временной задержки, использованный в примере программы 5.2, по- лезен при формировании сравнительно коротких временных задержек, — ну, скажем, до десятков миллисекунд. Однако имеется много ситуаций, когда необходимо сформировать намного более длительную временную задержку. Простой способ значительно увеличить временную задержку состоит в том, чтобы создать вторую подпрограмму, подобную пер- вой, но которая будет вызывать первую также изнутри цикла. Соответствующий пример приведен в программе 5.3. Использованный в нем программный цикл выполняет 100d
5.4. Работа с данными 111 обращений к подпрограмме de lay 5, которую мы только что рассматривали. Результи- рующая временная задержка будет, следовательно, примерно равной 500 мс. Еще один способ написания программы, обеспечивающей более длительную временную задержку, связан с использованием “цикла внутри цикла” — он иллюстрируется несколько далее, в примере программы 5.4. Пример программы 5.3. Вложение подпрограмм, обеспечивающее более длительную временную задержку____________________________________________________________ .-Временная задержка в 500 мс (приблизительно) .-Выполняется 100 обращений к подпрограмме delay5 selay500 movlw movwf D' 100' delcntr2 sel2 call delay5 decfsz delcntr2,1 goto del2 return Подпрограммы временной задержки — это очень полезное решение и оно очень широ- ко используются. Однако применять их нужно с осторожностью, поскольку все то время, пока выполняется подпрограмма временной задержки, ЦП не делает ничего другого. Ис- пользовать подпрограмму временной задержки — это сопоставимо с тем же, что, скажем, попросить Эйнштейна сесть и считать бобы — это неразумное использование мощных ре- сурсов. В Главе 6 мы рассмотрим другие способы формирования временных задержек. 5.4. Работа с данными Мы уже видели, как легко можно перемещать единичные байты в или из памяти дан- ных, вне зависимости от того, является ли данная ячейка памяти специальным функци- ональным регистром или же ячейкой памяти, предназначенной для хранения конкретной переменной. В последнем, рассмотренном нами, примере программы мы делали это следу- ющими командами: movlw D'100' movwf delcntr2 При использовании этих команд мы специфицировали требуемый фактический адрес ячейки памяти. В данном примере de lent г 2 — это метка, явным образом определяю- щая адрес. Если же, например, мы захотим работать с блоками данных, то использование подобного метода адресации для перемещения блока данных будет крайне нас ограничи- вать. При работе, например, со списком чисел, будет очень неудобным определять фикси- рованный адрес для каждой ячейки памяти. Вместо этого было бы полезно располагать указателем, который бы определял, где мы находимся в списке, и который мог бы менять- ся так, чтобы указывать на следующую ячейку памяти. Было бы очень полезным иметь возможность организовывать такой указатель для памяти данных. В этом случае програм- ма могла бы формировать блоки данных, а затем манипулировать ними. Полезно также уметь организовывать указатель и для памяти программы — в этом случае программа смогла бы получать доступ к заранее определенным блокам данных, однако не могла бы их модифицировать. В следующем подразделе рассматриваются два метода, используе- мых для работы с блоками данных — в памяти данных и памяти программы. 5.4.1. Косвенная адресация и регистр выбора файла На рис. 2.2 и 2.5 был показан регистр, называемый регистром выбора файла (РВФ или FSR). Как видно из рис. 2.2, вместо внедрения адреса в командное слово, число, хранимое в РВФ, может быть использовано для адресации памяти данных. В этом случае оно будет
112 Глава 5. Компоновка программ, написанных на языке Ассемблера называться косвенным адресом. РВФ запрашивается всякий раз, когда адресуется ячейка памяти INDF. INDF фактически не существует как регистр; ее использование просто за- ставляет ЦП использовать режим косвенной адресации. Преимущество этого режима за- ключается в том, что РВФ может быть объектом манипулирования точно так же, как обыч- ная ячейка памяти и при этом указывать на нужное место в памяти данных. Когда вы- полняется обращение к INDF, то используемая команда будет работать с ячейкой памяти, на которую указывает РВФ. Пример использования косвенной адресации будет показан в примере программы 5.7, в котором мы разрабатываем программу, которая формирует список данных. Этот пример обсуждается в подразделе 5.6.4. 5.4.2. Поисковые таблицы Команда movlw позволяет нам внедрить в программу байт постоянных данных, кото- рые могут затем использоваться так, как мы этого захотим. Мы уже встречались с исполь- зованием этой команды в предыдущем примере программы. Эта команда хорошо подходит для манипулирования отдельными байтами. Однако давайте предположим, что мы хотим поместить в программу целый список чисел, которые нам понадобятся во время выполне- ния программы — возможно для генерирования сигнала или формирования выходной структуры на экране дисплея. Предположим также, что мы хотим иметь возможность за- поминать, в каком месте списка мы находимся, применяя какой-либо вид маркера. Ко- манда movlw не в состоянии выполнить эту работу, поэтому мы должны применить иной способ группирования данных, известный как поисковые таблицы. Поисковая таблица — это блок данных, содержащийся в памяти программы — такой, к которому программа имеет доступ, и который может использоваться внутри программы. В структуре фон Неймана (см. рис. 1.7 (а)), с ее одной шиной адреса и шиной данных, достаточно легко формировать и использовать поисковые таблицы, поскольку все ячейки памяти имеют одинаковый размер и доступ к ним может быть получен с одинаковой лег- костью. В гарвардской структуре (см. рис. 1.7 (Ь)) это тяжелее, поскольку данные должны быть перемещены из одной отдельной карты памяти в другую. Ситуация дополнительно усложняется в результате разницы в размерах ячеек памяти, которая обычно существует между памятью данных и памятью программы. Следовательно, в случае использования гарвардской структуры, которая лежит в основе PIC, при создании поисковых таблиц дол- жны использоваться специальные методы. Это подводит нас к нескольким новым идеям. Подход к созданию поисковых таблиц, применяемый в семействе PIC 16, иллюстри- руется рис. 5.5. Таблица оформляется как подпрограмма. Каждый байт данных в таблице сопровождается специальной командой retlw. Данная команда — это еще один “воз- врат из подпрограммы”, однако он имеет существенное отличие — ему требуется 8-раз- рядный литеральный операнд. Если эта команда используется для возврата из подпро- граммы, то она помещает свой операнд в регистр W. Таблица в этом случае будет, по су- ществу, представлять собой список команд retlw, имеющих каждая свой байт данных. Что нам теперь нужно — так это методика, которая позволит выбрать одну команду retlw из списка этих команд — мы используем прием, называемый вычисляемым go to. Посмотрите внимательно на самую первую команду подпрограммы, addwf pci. Эта ко- манда добавляет содержимое регистра W к pci, т.е. к младшему байту счетчика команд. Вообще-то это небезопасная операция, поэтому применять ее нужно с осторожностью. Результатом выполнения этой команды будет то, что, поскольку к счетчику команд было добавлено какое-то число, управление выполнением программой будет передано со сдви- гом вперед на добавленное число. В нашем примере ЦП выполнит команду retlw, а за- тем управление возвратится основной программе. Обратите внимание, что какой бы длин- ной подпрограмма не оказалась, в ней каждый раз будет выполняться всего две команды — addwf pci и выбранная retlw. Очевидно, что программист должен обеспечить, что бы при вызове подпрограммы регистр W уже был загружен нужным значением смещения.
5.4. Работа с данными 113 Главная программа Я W-регистр. Во мне содержится код, записан- ный главной программой, который указывает на номер числа в поисковой Поисковая таблица в форме подпрограммы table addwf pci retlw 23 retlw 3f retlw 47 retlw 7f retlw 0a2 retlw If retlw 03 retlw 67 retlw 0c5 retlw 32 Рис. 5.5. Выборка данных из поисковой таблицы Давайте посмотрим на примере рис. 5.5, как это работает. Используя команду movf, главная программа передает в регистр W содержимое ячейки памяти с меткой sample,„„no. Затем она вызывает подпрограмму table. В данном примере предполагается, что метка sample_no уже содержала число 5, которое и будет находиться в регистре W на момент входа в подпрограмму. Как только подпрограмма начинает выполняться, командой addw f число 5 добавляется к pci. В результате этого, поскольку счетчик команд увеличился на 5, управление выполнением программы передается на команду, находящуюся на 5 позиций ниже от текущей, т.е. на retlw 1 f. Это приводит к отработке возврата из подпрограммы с числом If, находящимся теперь в регистре W. Главная подпрограмма сразу же исполь- зует это число, передавая его, в данном случае, в порт В. Таким образом, регистр W как бы играет роль гонца, посылаемого к подпрограмме. Он приходит в подпрограмму, неся код (который работает указателем), сообщающий, какое число требуется, а затем возвращается назад, неся это число. При использовании этого подхода возможно возникновение одной проблемы: мани- пулируя только младшим байтом счетчика команд, мы можем работать только с первыми 256 словами памяти программы, т.е. в пределах одной страницы. Если же поисковая таб- лица будет очень длинной или же она пересечет границу страницы, то возникнет проб- лема, связанная с вычислением точки перехода для go to. В этом случае будет сущест- венно важным использовать более полную версию вычисляемого перехода go to. 5.4.3. Пример программы с временной задержкой и поисковой таблицей Пример программы 5.4 — это простой пример, объединяющий цикл временной за- держки и использование поисковой таблицы в приложении к аппаратным средствам элек- тронной игры в пинг-понг. Программа берет 8-разрядное значение из поисковой таблицы и передает его на светодиоды электронного пинг-понга с отработкой временной задержки между передачами данных. Общим эффектом будет то, что светодиоды будут мигать в случайном порядке. Начальная секция этой программы очень похожа на пример программы 4.2, хотя теперь нам необходимо специфицировать адрес для pci из рис. 2.5. Кроме того
114 Глава 5. Компоновка программ, написанных на языке Ассемблера специфицируется ячейка ОЗУ, названная pointer, адрес которой выбирается так, чтобы он лежал в пределах доступного диапазона — от ОС to 4F (см. также рис. 2.5). Ядро программы начинается с метки loop. Как показано на рис. 5.5, значение ячейки памяти pointer перемещается в регистр W, а затем вызывается подпрограмма с именем table. После возврата из подпрограммы, значение, находящееся в регистре W, переда- ется в порт В. Оно высвечивает определенную структуру из светодиодов. Затем вызыва- ется подпрограмма временной задержки с именем delay. Обратите внимание на структуру этой подпрограммы, которая подобна по концепции примеру программы 5.3, однако для увеличения времени задержки использует одну подпрограмму и вложенные циклы. Прог- рамма продолжает работать в цикле, проверяя, не достигла ли ячейка памяти pointer своего максимального значения. Если это так, то-перед продолжением выполнения про- граммы названная ячейка обнуляется. Пример программы 5.4. Использование поисковой таблицы /МИГАЮЩИЕ СВЕТОДИОДЫ /Данная программа непрерывно выдает последовательности светодиодных /структур, используя имитацию или аппаратные средства электронного /пинг-понга TJW 05.03.05. Проверено на имитаторе 11.03.05. /Частота синхрогенератора равна 800 кГц /Слово конфигурации: WDT откл., таймер включения вкл., /кодовая защита откл., RC-генератор list p=16F84A /Специфицируем СФР: pci equ 02 status equ 03 porta equ 05 trisa equ 05 portb equ 06 trisb equ 06 t pointer equ 10 delcntrl equ 11 delcntr2 equ 12 org 00 /Инициализация start bsf status,5 /выбор банка памяти 1 movlw В'00011000' movwf trisa /устанавливаем порт А в соответствии /с вышеприведенной структурой movlw 00 movwf trisb /вывод всех разрядов порта В bcf status,5 /выбор банка 0 /"Главная" программа начинается здесь movlw 00 /очищаем все разряды порта А movwf porta movwf pointer /также очищаем указатель loop movf pointer,0 /перемещаем указатель в регистр W call table movwf portb /перемещаем регистр W, обновленный /по таблице, в порт В call delay
5.5. Введение в логические команды 115 Пример программы 5.4. Окончание incf pointer,1 btfsc pointer,3 /проверяем, не стало ли значение /указателя равным 8 clrf pointer /если да, то очищаем указатель, /чтобы начать снова goto loop Подпрограммы .•Вводим задержку, примерно равную 500 мс для синхрочастоты 800 кГц delay movlw D'100' movwf delcntr2 outer movlw D'200' movwf delcntrl inner nop nop decfsz delcntrl, 1 goto inner decfsz delcntr2,l goto outer return .•Подпрограмма поисковой таблицы cable addwf pci retlw 23 retlw 3f retlw 47 retlw 7f retlw 0a2 retlw If retlw 03 retlw 67 end УПРАЖНЕНИЕ ПО ПРОГРАММИРОВАНИЮ 5.2 Некоторые считают, что концепция поисковых таблиц, заложенная в PIC слишком труд- на для понимания. Поэтому вдвойне хорошей идеей будет выполнить имитацию нашего программного примера. Создайте проект с именем Flashing LEDs (Мигающие свето- диоды), скопируйте исходный текст программного примера 5.4 с компакт-диска, прила- гаемого к этой книге, и включите его в проект. После этого выполните имитацию. От- кройте окно Watch (Наблюдение) с контролируемыми переменными pcl, portb, wreg и pointer. Пошагово продвигайтесь по программе и внимательно следите за тем, как меняются значения регистра W при входе и выходе из подпрограммы. Используйте опцию Step Over (Перейти) для предотвращения длительного выполнения циклов в подпрограмме временной задержки. Убедитесь в том, что вы понимаете все стадии работы программы, а также работу новых команд, которые были использованы. 5.5. Введение в логические команды Итак, мы уже знаем некоторое количество команд семейства 16, однако до сих пор мы не рассматривали ни одной логической команды. Такие команды, как andwf, andlw,
116 Глава 5. Компоновка программ, написанных на языке Ассемблера iorwf и xorwf выполняют логические операции для содержимого регистра W и/или ли- терального значения, или значения, хранимого в ячейке памяти. Они делают это побитно. Например, если мы используем команду andlw к, то разряд 0 литерального значения ло- гически УМНОЖАЕТСЯ на разряд 0 регистра W, разряд 1 логически УМНОЖАЕТСЯ на разряд 1 регистра W и т.д. Эти команды полезны при выполнении реальных логических операций. Обычно команды and используются для подавления нежелательных разря- дов в слове, а команды or — для установки отдельных разрядов слова. В качестве примера давайте рассмотрим альтернативный способ повторного сброса указателя в примере программы 5.4. Помните, что всякий раз, когда в процессе последо- вательного прибавления 1 указатель достигает значения 8 (0000 1000), его необходимо сбрасывать в 0. Однако, вместо того чтобы это делать, почему бы нам просто не подавить старшие 5 разрядов слова, которые не используются в данном применении? Упомянутая альтернатива, использующая логическую команду andlw, показана в примере программы 5.5. Вместо того чтобы всякий раз проверять значение pointer по- сле прибавления к нему 1, теперь эта переменная логически умножается с числом 07 или 0000 0111в- В результате, когда после прибавления 1 значение переменной pointer станет равным 0000 1000в, разряд 3 (который установился в 1) логически умножается на 0 и, тем самым, значение переменной pointer возвращается в 0. Пример программы 5.5. Введение в логические команды Loop movf pointer,0 /перемещаем указатель в регистр W call table movwf portb /перемещаем регистр W, /обновленный по таблице SR, в порт В call delay incf pointer,0 /прибавляем 1 к указателю, /помещаем результат в регистр W andlw 07 movwf pointer goto loop 5.6. Введение в арифметические команды и флаг переноса Набор команд семейства 16 имеет шесть арифметических команд: addwf, addlw, subwf, sublw, incf и decf. Их использование является центральным пунктом в любой арифметической обработке информации, которую микроконтроллер должен будет выпол- нять, как мы это скоро увидим, в следующем примере программы. 5.6Л. Использование команд сложения Использование двух имеющихся команд сложения выполняется достаточно прямоли- нейно. При использовании команды addwf содержимое регистра W добавляется к содер- жимому специфицированной ячейки памяти. При использовании команды addlw лите- ральное значение добавляется к содержимому регистра W. Ситуация немного усложняется, когда мы осознаем, что 2 восьмиразрядных числа, сложенные вместе, могут дать 9-ти раз- рядное значение. Этот девятый разряд появляется в регистре состояния флагом переноса. 5.6.2. Использование команд вычитания Команды вычитания работают приблизительно по той же схеме, что и операции сложения. Только разряд переноса работает теперь, как бит заимствования, при этом его полярность реверсирована (смотрите регистр состояния, рис. 2.3). Следовательно, если
5.6. Введение в арифметические команды и флаг переноса 117 выполняется вычитание и результат положителен, то бит переноса устанавливается в еди- ницу. Если же результат отрицателен, то бит переноса сбрасывается в ноль. 5.6.3. Пример арифметической программы Пример программы 5.6 демонстрирует использование некоторых простых арифме- тических методов. Он генерирует ряд Фибоначчи как результат выполнения процесса сложения. Счетчик указывает, как много членов ряда было уже вычислено. Когда это число превысит 8-разрядный диапазон, ряд реверсируется посредством реализации про- цесса вычитания. Распознавание переполнения диапазона выполняется посредством кон- троля состояния бита переноса после каждого сложения. Программа начинает свою работу с предварительной загрузки в память первых трех чисел ряда. Затем она начинает перемещаться по ряду, начиная от метки forward. Два самых последних числа складываются, после чего проверяется состояние бита переноса. Если он установлен, то это означает, что 8-разрядный диапазон превышен, и программа должна быть реверсирована. Если бит переноса не был установлен, то программа добав- ляет единицу к счетчику и перемещает числа в памяти, стирая самое старое. Затем про- грамма возвращается к метке forward. Если, однако, бит переноса был ранее установ- лен, программа переходит на метку reverse. Теперь она начинает двигаться по ряду в обратном направлении, выполняя операцию вычитания. Она проверяет значение счет- чика для определения того, когда следует возвратиться к метке forward. Пример программы 5.6. Генерирование ряда Фибоначчи /Каждый член ряда Фибоначчи представляет собой сумму двух предшествующих /членов, например: 0,1,1,2,3,5,8,13,21..... /Данная программа вычисляет числа Фибоначчи в пределах 8-разрядного /диапазона, сначала в прямом направлении, а затем — в обратном. /Программа предназначена только для имитации, поэтому в ней /нет никакого ввода-вывода. /Программа демонстрирует операции сложения, вычитания и сравнения. /TJW 17.03.05. Тестировано на имитаторе 18.03.05 list p=16F84A /порты ввода-вывода не используются status equ 0 3 c equ 0 z equ 2 /эти ячейки памяти содержат три самых больших значения ряда Фибоначчи fibO equ 10 /наименьшее число (самое старое — при перемещении /вперед и самое новое — при перемещении в обратном /направлении) fibl fib2 fibtemp counter equ 11 /среднее число equ 12 /максимальное число equ 13 /временная ячейка для самого нового числа equ 14 /индицирует достигнутое значение, начальное значение - 3 org 00 /предварительная загрузка начальных значений movlw 0 movwf fibO movlw 1 movwf fibl movwf fib2 movlw 3
118 Глава 5. Компоновка программ, написанных на языке Ассемблера Пример программы 5.6. Окончание_____________________________________________ movwf counter;мы предварительно загрузили первые /три числа, поэтому начинаем отсчет с 3 forward movf fibl,О addwf fib2,0 btfsc status,с /тестирование на переполнение ;8-разрядного диапазона goto reverse /переполнение, меняем направление на обратное movwf fibtemp /последнее число сейчас помещено в fibtemp incf counter, 1 /перемещаем хранимые числа, стираем самое старое movf fibl,0 /сначала перемещаем среднее число, /перезаписывая самое старое movwf fibO movf fib2,0 movwf fibl movf fibtemp,0 movwf fib2 goto forward /при реверсировании направления, вычитаем fibO из fibl /для формирования нового fibO reverse movf fibO,О subwf fibl,0 movwf fibtemp /последнее число сейчас помещено в fibtemp decf counter,1 /перемещаем хранимые числа, стираем самое старое movf fibl,0 /сначала перемещаем среднее число, /перезаписывая самое старое Movwf fib2 Movf fibO,0 Movwf fibl Movf fibtemp,0 Movwf fibO /проверяем, не достиг ли счетчик значения 3, если да, /то реверсируем направление на прямое movf counter,О sublw 3 btfsc status,z goto forward goto reverse r end УПРАЖНЕНИЕ ПО ПРОГРАММИРОВАНИЮ 5.3 Создайте в MPLAB® проект с именем Fibonacci. Скопируйте с компакт-диска, прила- гаемого к этой книге, исходный файл примера программы 5.6 в созданный проект и выполните имитацию. В окне Watch (Наблюдение) отобразите следующие контролиру- емые переменные: counter, fibO, fibl, fib2, fibtemp, wreg и status. Пошагово перемещайтесь по программе и наблюдайте генерируемые члены ряда Фибоначчи в fibO, fibl и fib2. Какое количество членов ряда попадает в 8-разрядный диапазон? Обратите внимание на то, что бит переноса будет установлен, когда диапазон будет превышен — при этом программа реверсирует направление генерирования членов ряда. Обратите внимание на то, что теперь бит переноса (работающий сейчас как бит “НЕ-заимствования”) устанавливается после выполнения каждой операции вычитания.
5.6. Введение в арифметические команды и флаг переноса 119 Попытайтесь остановить программу на метке reverse и установите два значения для fibO и fibl, которые дадут отрицательный результат. Пошагово перемещайтесь по участку программы, включающему вычитание, контролируйте результат в регистре -W — обратите внимание, когда бит переноса будет сброшен. Наблюдайте, как будет достигнут этап сравнения counter с литеральным числом 3 и программа возвратится на метку forward. 5.6.4. Использование косвенной адресации для сохранения ряда Фибоначчи Пример программы 5.7 расширяет программу генерирования членов ряда Фибоначчи с тем, чтобы она включала сохранение с использованием косвенной адресации, при этом в примере показана главная секция программы. Добавленные строки текста программы выделены жирным шрифтом. Блок данных сохраняется в памяти данных, начиная с адре- са 20н- Первые три члена ряда вводятся, используя обычную адресацию (в этом случае также могла быть использована и косвенная адресация, однако это потребовало бы ис- пользования некоторого количества дополнительных строк программы). Регистр выбора файла (РВФ) затем загружается числом 23н, которое является адресом ячейки памяти блока данных, которая должна загружаться следующей. Если начать отрабатывать глав- ный цикл, то можно будет увидеть, что всякий раз, когда генерируется новое число, оно будет записываться в блок данных командой movwf indf. Значение РВФ затем увеличи- вается на единицу — так происходит до тех пор, пока значение РВФ не достигнет заранее определенного максимума. Пример программы 5.7. Сохранение ряда Фибоначчи с использованием косвенной адресации f • • • (строки заголовка программы опущены) f • • • /эти ячейки памяти содержат самые последние члены ряда Фибоначчи fibO equ 10 /наименьшее число (самое /вперед, и самое новое — старое — при движении при движении назад) fibl fib2 fibtemp equ equ equ 11 12 13 /среднее число /самое большее число /временная ячейка памяти для хранения counter equ 14 /самого нового числа /указывает, какое значение мы достигли, org 00 ; предварительная /начальное значение равно 2 загрузка начальных значений movlw 0 movwf fibO movwf 20 movlw 1 /сохранение в начале списка movwf fibl movwf 21 /сохраняем в списке movwf fib2 movwf 22 /сохраняем в списке movlw 3 movwf counter /первые три числа загружены, начинаем с 3-го movlw 23 /инициализируем регистр выбора файла, загрузив Movwf fsr /в него следующий адрес сохраняемого списка чисел
120 Глава 5. Компоновка программ, написанных на языке Ассемблера Пример программы 5.7. Окончание forward movf addwf btf sc fibl,0 fib2,0 status,с /проверка на переполнение /8-разрядного диапазона goto reverse /переход в случае переполнения, /реверсирование ряда Movwf movwf movf fibtemp /последнее число заносится в fibtemp indf /сохраняем с использованием косвенной адресации fsr,0 /проверяем, не указывает ли РВФ /на вершину диапазона sublw btf ss incf 30 status,z fsr,l /инкрементируем РВФ, если доступный /диапазон не исчерпан incf counter, 1 /перемещаем хранимые числа, аннулируем самое старое movf fibl,0 /сначала смешаем среднее число, /перезаписывая старое самое movwf movf movwf movf movwf goto fibO fib2,0 fibl fibtemp,0 fib2 forward УПРАЖНЕНИЕ ПО ПРОГРАММИРОВАНИЮ 5.4 Создайте в MPLAB® проект с именем Fibo+storage (Ряд Фибоначчи + сохранение), или выберите любое другое имя. Скопируйте с компакт-диска, прилагаемого к этой кни- ге, исходный файл примера программы 5.7 в созданный проект и выполните имитацию. Отобразите окно File Registers (Файловые регистры), выбрав для этого View (Вид) > File Registers (Файловые регистры). Используя опцию Step Into (Шаг вперед), поша- гово продвигайтесь по программе и наблюдайте, как ряд Фибоначчи формируется в блоке данных, размещенном в памяти, начиная с адреса 20н. По завершении вы долж- ны иметь окно, похожее на то, которое приведено на рис. 5.6. Обратите внимание на два банка специальных функциональных регистров (СФР), а также на то, как состояния переменных pcl, status и fsr отображаются на эти банки. Что программа делает, когда fsr (Регистр выбора файла) достигнет своего максимального значения? Попы- тайтесь изменить определение вершины блока, изменяя литеральное значение в ко- манде sublw 30. После того как вы это сделаете, обратите внимание на изменения в поведении программы. 5.7. Приручение сложности Ассемблера Сейчас вы начинаете осознавать, насколько сложными могут быть даже простые про- граммы на Ассемблере. Поэтому необходимо использовать все возможные средства для того, чтобы программа была настолько короткой и понятной, насколько это только возмож- но. Сейчас мы рассмотрим несколько опций, способствующих этому.
5.7. Приручение сложности Ассемблера 121 5.7.1. Включение файлов Директива Ассемблера #include позволяет включать в программу любые файлы, эко- номя этим труд и пространство, связанные с копированием в большие программы секций, которые уже существуют. Включенный таким образом файл называется включенным файлом. Изначально наиболее полезным способом использования этой опции является замена всех микроконтроллерно-ориентированных определений памяти, которые должны присутствовать в начале программы. Как и другие ассемблеры, MPLAB содержит вклю- чаемые файлы для каждого микроконтроллера, содержащие операторы equ для всех спе- циальных функциональных регистров (СФР) и их битов. Эти файлы можно найти в одной из папок MPLAB. Использование включенных файлов полезно для малых микроконтрол- леров, — таких как 16F84A, если файл достигает в длину нескольких страниц. Их исполь- зование является почти жизненно важным для больших процессоров, которые имеют об- ширные массивы СФР и, следовательно, очень длинные включаемые файлы. Как только включенный файл использован, то, конечно, необходимо проверить, что микропроцес- сорно-ориентированные метки, на которые есть ссылки в программе, идентичны мет- кам, использованным во включенном файле. Преимущества использования включенных файлов даже для очень малых приложений иллюстрируется в примере программы 5.8. Рис. 5.6. Ряд Фибоначчи, сохраненный в блоке данных, который начинается с адреса 20н Пример программы 5.8. Использование включаемых файлов ;специфицируем СФР timer equ 01 status equ 03 porta equ 05 #include pl6f84A.inc trisa equ 05 ИЛИ portb equ 06 include pl6f84A.inc trisb equ 06 intcon equ 0B все вышеприведенные команды, и даже намного большее их количество, могут быть заменены одной показанной директивой #include 5.7.2. Макроопределения Из тех программ, которые мы уже рассмотрели, можно видеть, что разработка про- грамм для процессоров RISC (процессоры с сокращенным набором команд) — это трудо-
122 Глава 5. Компоновка программ, написанных на языке Ассемблера емкий процесс, причиной чего является ограниченная функциональность каждой отдель- ной команды. Наборы команд процессоров CISC (процессоры с полным набором команд) с их более мощными командами, обеспечивают некоторые преимущества, как мы это видели в подразделе 4.9, но не столь уж большие. Имеется ли какой-либо способ “обойти” минималистскую природу набора команд RISC, оставаясь в то же время в среде Ассемб- лера? Один из способов решения этой проблемы заключается в использовании макроопре- делений. Макроопределение — это поименованная группа команд, определенная програм- мистом. Если макроопределение один раз определено, то оно может использоваться в про- грамме в любое время. В каком-то роде макроопределение предбставляет возможности подпрограммы, однако они используются различным образом. Когда исходный текст про- граммы ассемблируется, макроопределение разворачивается в исходные команды, из которых оно состоит. Следовательно, использование макроопределений — это скорее фор- ма сокращенной записи в программировании, а не способ структурирования программы. Пример программы 5.9 показывает три макроопределения, вставленные в начало про- граммы электронного пинг-понга (Приложение 2). Само макроопределение находится между директивами macro и endm. Для макроопределения определяются аргументы, представляющие собой значения данных, которые макроопределение сможет использовать. Макроопределение movlf перемещает постоянное значение данных в ячейку памяти. Оно использует два аргумента: const и address. Макроопределения bfbset (на него вы- полняется переход, если установлен специфицированный бит) и bfbclr (на него вы- полняется переход, если специфицированный бит сброшен) определяются аналогичным образом. Все три макроопределения затем используются в первых нескольких строках программы. При этом всякий раз экономится одна строка программного кода — таким образом, восемь присутствовавших ранее строк программного кода в цикле wait пре- вратились в четыре. Пример программы 5.9. Применение макроопределений к программе электронного пинг-понга____________________________________________________________________ /готовность к работе /макроопределение для перемещения литерального значения в файл movlf macro const,address movlw const movwf address endm /макроопределение для перехода, если установлен специфицированный бит bfbset macro file,bit,target btfsc file,bit goto target endm / макроопределение для перехода, если специфицированный бит сброшен bfbclr macro file,bit,target btfss file,bit goto target endm wait movlf 04,porta /состояние покоя, "вне игры" movlf 00,portb /все светодиоды выключены /обе кнопки должны быть сброшены перед тем, как игра сможет начаться bfbclr porta,4,wait /переход на метку wait, /если нажата правая кнопка bfbset porta,3,wait /переход на метку wait, /если нажата левая кнопка
5.8. Дополнительные возможности использования имитатора MPLAB 123 УПРАЖНЕНИЕ ПО ПРОГРАММИРОВАНИЮ 5.5 Введите программный код примера программы 5.8 в копию программы электронного пинг-понга, удаляя строки программного кода, которые он замещает. Выполните ас- семблирование программного кода и откройте файл листинга. Обратите внимание на то, что первичное макроопределение не занимает пространство памяти, а также на то, как макроопределение разворачивается в свою первичную форму всякий раз, когда к нему производится обращение, таким образом воспроизводя исходную про- грамму пинг-понга. Продолжайте работать с программой, применяя последние два макроопределения везде, где только сможете. Сколько раз вы смогли это сделать и сколько строк программного кода вы сэкономили? Имеются ли другие макроопреде- ления, которые вы считаете полезным определить? 5.7.3. Специальные команды MPLAB Продолжая работать над дальнейшим облегчением проблемы ограничительной приро- ды набора команд RISC, фирма Microchip определила набор “специальных команд”. Эти команды распознаются Ассемблером и разворачиваются в набор эквивалентных команд. Примеры этих команд приведены в табл. 5.1, в то время как полный список этих команд вы сможете найти в соответствующей документации. Большинство из этих команд выполня- ют операции, использующие либо манипулирующие битом Z или С регистра состояния. Некоторые из них, как, например, Ьс или Ъпс, не обеспечивают экономии строк программ- ного кода, однако повышают ясность программы. Другие же, как, например, addcf, фор- мируют новые полезные функции, отсутствующие в исходном наборе команд — они очень похожи на команды наборов CISC. Табл. 5.1. Пример “специальных” команд MPASM™ Мнемоника Описание Эквивалент Затрагиваемые флаги состояния addcf f,d Добавление цифры переноса к файлу BTFSC 3,1 INCF f,d Z Ьс k Переход по переносу BTFSC 3,0 GOTO k - bnc k Переход по отсутствию переноса BTFSS 3,0 GOTO k - clrc Сброс переноса BCF 3,0 - movfw f Перемещение файла в W MOVF f,0 z subcf f,d Вычитание цифры переноса из файла BTFSC 3,0 DECF f,d z tstf f Проверка файла MOVF f,1 z 5.8. Дополнительные возможности использования имитатора MPLAB Мы уже смогли оценить чрезвычайную ценность программного имитатора как средства прогона программ и контроля выходных сигналов. Мы делали это, используя простые ор- ганы управления выполнением программы: пошаговое выполнение, анимацию или пуск. Однако по мере увеличения объема программ начинает ощущаться потребность в более сложных способах выполнения программ и одновременного контроля за их поведением.
124 Глава 5. Компоновка программ, написанных на языке Ассемблера 5.8.1. Контрольные точки Как только программа становится достаточно длинной, пошагово выполнять ее в про- цессе имитации становится весьма утомительно. Нам необходимы какие-то средства для обеспечения беспрепятственного прохождения тех участков программного кода, которые нас не интересуют, и обязательного останова в тех местах, где нам важно поближе рассмот- реть то, что там происходит. Контрольные точки обеспечивают эту возможность. В своей простейшей форме контрольные точки позволяют выполнять программу вплоть до специ- фицированной команды. Затем выполнение программы^прерывается и можно спокойно просмотреть содержимое памяти и регистров. В MPSIM м можно задавать и удалять лю- бую контрольную точку простым двойным щелчком на соответствующей команде в окне программы. Количество контрольных точек неограниченно, поэтому их следует исполь- зовать во всех случаях, когда это может быть полезным. BBS subwf decf И C:\My Documents\MPLAB Project»Mibo1.aam ’в’ iuf f le goto goto sublw ht fsc fibO.O fib 1.0 raovf fibO, 0 mmrf fibl movf fibreiap^O movtrf fibO xiu mb e r 5 novf fiblzO raowf fihZ. ; first- bove xaiddlc nuabcr Рис. 5.7. Две контрольные точки, вставленные в программу генерации ряда Фибоначчи number now placed ir. fihr, r-xap 3 УПРАЖНЕНИЕ ПО ПРОГРАММИРОВАНИЮ 5.6 Программа, генерирующая ряд Фибоначчи, — это, по видимому, самая длинная про- грамма из всех примеров, которые мы до сих пор рассматривали. Если мы хотим рас- смотреть что-либо происходящее внутри этой программы, то выполнять это в режиме пошагового выполнения программы будет достаточно утомительно. Однако в нашем распоряжении есть такое средство, как контрольные точки. Откройте проект с програм- мой генерации ряда Фибоначчи, который вы создали ранее (или создайте его), и запус- тите имитатор MPLAB, выбрав Debugger (Отладчик) > Select Tool (Выбрать инстру- ментальное средство) > MPLAB SIM. Переместите экран по исходному файлу с рас- ширением .asm и два раза щелкните на строке с меткой reverse. При этом должен появиться символ контрольной точки, как это показано на рис. 5.7. Убедитесь также и в том, что двойным щелчком вы можете убрать ненужную контрольную точку. Вы- полните сброс имитатора и запустите программу. Наблюдайте, как программа оста- новится в контрольной точке. В этом месте вы можете исследовать все открытые окна и, по желанию, продолжить выполнение программы, например, в пошаговом ре- жиме. Попытайтесь установить еще одну контрольную точку на второй строке, пока- занной на рис. 5.7, и выполните программу до останова в этой точке. 5.8.2. Таймер с остановом Слабой стороной программного имитатора является то, что он не работает в реальном времени, хотя в случае встроенных систем нам весьма необходимо понимать временные
5-8. Дополнительные возможности использования имитатора MPLAB 125 характеристики наших программ. Функция Stopwatch (Таймер с остановом) имитатора позволяет выполнять имитацию точных замеров времени. Эта функция требует, чтобы имитатор “знал” частоту тактового генератора. В силу того, что он может зарегистриро- вать число выполненных командных циклов, он также сможет затем выполнить подсчет израсходованного времени. В MPSIM частота тактового генератора задается в окне Simulator Settings (Настройки имитатора) посредством выбора Debugger (Отладчик) > Settings (Настройки) > Osc/Trace (Тактовая частота/Трассирование) (рис. 5.8 (а)). Окно Stopwatch (Таймер с остановом) (рис. 5.8 (Ь)) отображается в результате выбора Debugger (Отладчик) > Stopwatch (Таймер с остановом). Рис. 5.8. Использование опции Stopwatch (Таймер с остановом): (а) — окно Simulator Settings (Настройки имитатора); (Ь) — окно Stopwatch (Таймер с остановом) ПРИМЕР ПРОГРАММИРОВАНИЯ 5.7 Все еще при открытом проекте программы генерирования ряда Фибоначчи, установите частоту процессора, равную 4 МГц. Это в результате даст длительность командного цикла, равную 1 мкс. Оставьте контрольные точки там, где они были установлены в примере программирования 5.6. Выберите Debugger (Отладчик)> Stopwatch (Таймер с остановом) и щелкните на кнопке Zero (Обнулить) в окне Stopwatch (Таймер с ос- тановом). Сбросьте имитатор и запустите программу до контрольной точки. В окне Stopwatch (Таймер с остановом) вы должны увидеть показания, равные 166 мкс. Не могли бы вы обосновать это значение?
126 Глава 5. Компоновка программ, написанных на языке Ассемблера 5.8.3. Трассирование Различные функции, реализуемые MPSIM, дают нам хорошую картину состояния процессора и ячеек памяти на любой момент времени, однако они не говорят нам об исто- рии выполнения программы. Даже если выполнение программы было остановлено в кон- трольной точке, может существовать целый ряд путей выполнения программы, ведущих к этой точке. Функция Trace (Трассирование), реализованная в MPLAB, предназначена для регистрации “недавнего прошлого” в ходе выполнения программы. В памяти функции Trace (Трассирование) имитатор сохраняет непрерывную запись всех команд, которые были выполнены. Эти записи могут быть изучены после того, как выполнение программы будет остановлено. В MPLAB реализована функция трассирования с объемом памяти, по- зволяющим осуществить запись о выполнении 32 767 строк программы. Функция трасси- рования активируется в окне Simulator Settings (Настройки имитатора) (см. рис. 5.8 (а)). Для ее активирования необходимо осуществить выбор Debugger (Отладчик) > Settings (Настройки) > Osc/Trace (Тактовая частота/Трассирование). Обратите внимание, что после активирования функции трассирования скорость работы имитатора становится несколько медленнее. Окно Trace (Трассирование) открывается после выбора View (Вид) > Simulator Trace (Трассирование имитатора) (рис. 5.9). Назначение почти всех столбцов в этом окне понятно само по себе, за исключением четырех: SA = исходный адрес — адрес символа исходных данных; SD = исходные данные — значение исходных данных; DA = целевой адрес — адрес или символ целевых данных; DD = целевые данные — значение целевых данных. ПРИМЕР ПРОГРАММИРОВАНИЯ 5.8 Возвратимся еще раз к настройкам примера программирования 5.6. Убедитесь в том, что опция Trace (Трассирование) активирована, как описывалось выше, сбросьте имитатор и запустите программу до контрольной точки в метке reverse. Теперь от- кройте окно Trace (Трассирование), которое должно иметь вид, показанный на рис. 5.9. Обратите внимание, что в этом окне присутствует список всех команд, которые бы- ли выполнены недавно, заканчивая (в строке 142) командой goto, которая передала управление на командную строку, соответствующую контрольной точке. Посмотрев на столбцы SD и DD, мы видим генерируемый ряд Фибоначчи. Значение регистра со- стояния в строке 141 равно 19н или 0001 10018. Мы видим, что разряд 0, являющийся битом переноса, установлен и осуществлен вызов команды goto. И Trace BBS Line Addr op •XabeL"'" Instruction SA SD DA DD Cycles I 134 000F 0812 MOVF 0x12, W 0012 90 0012 90 : 30000009B 135 0010 0091 MOVWF 0x11 — ООН 90 Э0000009С 136 ООН 0813 MOVF 0x13, W 0013 E9 0013 E9 90000009D 137 0012 0092 MOVWF 0x12 — 0012 E9 30000009E 138 0013 2807 GOTO 0x7 — — 30000009F 139 0007 0811 forward MOVF Oxll, W ООН 90 OOH 90 Э000000А1 140 0008 0712 ADDWF 0x12, W 0012 E9 0012 79 3OOOOOOA2 141 0009 1803 BTFSC 0x3, 0 0003 19 — ЗООООООАЗ 142 000A 2814 GOTO 0x14 — — Э000000А4 W Рис. 5.9. Окно Trace (Трассирование) для секции программы генерации ряда Фибоначчи
5.9. Программа электронного пинг-понга 127 5.9. Программа электронного пинг-понга Сейчас представляется полезным просмотреть полную программу электронного пинг- понга, которая показана в Приложении 2. Всегда непросто смотреть на программный код на Ассемблере, написанный кем-то другим (на самом деле часто трудно смотреть даже на свой собственный программный код, написанный на Ассемблере!), поэтому не тревожь- тесь, если поначалу у вас возникнут затруднения. 5.9.1 Структура программы для электронного пинг-понга Прежде всего, давайте попытаемся получить общее представление о структуре про- граммы в целом. Для данной программы диаграмма состояний обеспечивает четкое общее представление, которого трудно было бы достигнуть при использовании блок-схемы. Эта диаграмма показана на рис. 5.10. Нарушение правил 1. Попытка ударить по шарику, когда он не на вашей стороне. 2. Отсутствие попытки ударить по шарику, когда он на вашей стороне. Счет Вы выиграли, если ваш противник нарушил правила. Удачный ответный удар Удар по шарику, когда он на вашей стороне. Примечание: шарик находится на вашей стороне, когда зажегся ближайший к вам светодиод. Рис. 5.10. Диаграмма состояний для программы электронного пинг-понга Программа начинает свою работу из состояния Инициализации. Когда инициализация завершится, программа сразу же переходит в состояние Ожидания, в котором и находится до момента начала игры. Если левый игрок нажимает кнопку, то программа входит в состо- яние Слева-направо. В этом состоянии “шарик” начинает двигаться со своей самой левой позиции вправо. Выход из этого состояния имеет место либо в случае нарушения правил (приводятся соответствующие определения), либо в случае успешного ответного удара, когда шарик достиг самой правой позиции. При отсутствии нарушения правил, игра про- должается с переменным вхождением в состояния Слева-направо и Справа-налево. Когда
128 Глава 5. Компоновка программ, написанных на языке Ассемблера какой-либо из игроков допускает ошибку, то это классифицируется как нарушение правил и игра входит в состояние Выигрыш. Она выходит из него после индикации счета и возвра- щается в состояние Ожидание. Итак, поняв диаграмму состояний электронного пинг-понга, теперь попытайтесь най- ти каждое состояние в листинге на Ассемблере. Три из пяти состояний —- Инициализа1!ия, Ожидание и Выигрыш можно легко идентифицировать. Конечно же, в Главе 4 мы уже встречались с первым состоянием. Два других состояния, в которые программа входит во время игры, — это состояния Слева-направо и Справа-налево. Понять их несколько труд- нее. Каждое из них является зеркальным отображением другого, поэтому, если понять одно, то понимание другого приходит автоматически. В то время как общая схема данной программы лучше всего отображается диаграммой состояний, фактически состояния Справа-налево/Слева-направо представляют собой цик- лические структуры и легче всего отображаются в форме блок-схем (рис. 5.11). Рис. 5.11. Блок-схема состояний Справа-налево/Слева-направо
5.9. Программа электронного пинг-понга 129 Здесь мы, возможно, впервые столкнулись со сложностью выписки деталей, которые требует подобная программа; это даже в системе, которая на первый взгляд кажется очень простой. Для каждого состояния имеется, конечно, ряд требований, которые должны быть удовлетворены. “Движение шарика” выполняется посредством подсветки серии светоди- одов, каждый из которых должен светиться заданный период времени. Состояние кнопок постоянно контролируется: в определенный момент нажатие кнопки является законным действием, а в остальное время это будет нарушением правил. Если бы привязка ко вре- мени выполнялась просто посредством введения цикла временной задержки, то функция контроля входных сигналов не могла бы выполняться. Поэтому время свечения каждого светодиода задается как некоторое число итераций цикла — внутри каждой итерации проверяется состояние входов, после чего выполняется краткая временная задержка. 5.9.2. Более подробное рассмотрение программы электронного пинг-понга Чтобы облегчить последующее понимание программы электронного пинг-понга, сей- час будут подробно рассмотрены некоторые ее секции. Секция заголовка и распределения памяти В секции заголовка программы приводятся комментарии, описывающие детали ис- пользования аппаратных средств. За ней следует секция распределения памяти. В ней вво- дятся имена ячеек области памяти общего назначения в ОЗУ. Используемые имена, на- пример delcntrl и т.д., выбираются программистом и объявляются в форме меток, ко- торые начинаются с самой левой позиции командной строки. Используется директива equ, а адреса памяти выбираются по карте памяти, приведенной на рис. 2.5, которая показывает, что допустимый диапазон доступных адресов памяти простирается от адреса ОСн до ад- реса 4FH. Состояние ожидания Теперь исследуем это состояние, изучив начальную часть собственно программы элек- тронного пинг-понга, которая следует за секцией инициализации. В первых четырех строках программы выполняется включение светодиода “вне игры” и выключение всех других светодиодов. Затем выполняется контроль состояния обеих кнопок. Помните, что после нажатия кнопки входной бит ключа переходит в состояние логического 0. Если никакая кнопка не нажата, то отрабатывается переход вперед на метку waitl. Однако если нажата одна или две кнопки, то программа перейдет на метку wait и будет циклить до тех пор, пока кнопка не будет отпущена. Это делается для пре- дотвращения “ложного старта” игры, который мог бы в противном случае иметь место, если бы игрок включил игру при нажатой кнопке. Поскольку это именно та точка, в кото- рую переходит программа после перезапуска игры в результате выигрыша очка, то упомя- нутая особенность также гарантирует, что предыдущий раунд игры полностью завершен перед новым запуском игры. Обратите внимание, что выполнение цикла включает также установку состояний светодиодов. Это не есть столь уж абсолютно необходимо, однако это не вредно и к тому же минимизирует количество используемых меток. Затем выполняется другой цикл — waitl. Обе кнопки были сброшены, поэтому игра может быть начата. Вновь контролируется состояние обеих кнопок. В этот раз, однако, если была нажата кнопка, программа вместо возврата назад в цикле переходит вперед — или на метку l_to_r, или на метку r_to_l.
130 Глава 5. Компоновка программ, написанных на языке Ассемблера Основное состояние игры Давайте начнем изучать это состояние с рассмотрения секции r_to_l. Эта секция начинается с выключения светодиода “вне игры” и определения начальной позиции ша- рика и, следовательно, состояния светодиодов. Далее со строки с меткой rtl_0 начинается больший цикл. В его начале счетчик цикла loop_cntr загружается числом led_durn. Это число было определено в начальной секции программы — оно указывает количество повторений внутреннего цикла. Этот внутренний цикл начинается в строке с меткой rtl_l. Большая часть этого цикла посвящена контролю за нарушением правил, интерпретация которых зависит от положения шарика. Общая структура внутреннего цикла показана на блок-схеме, в то время как фактическая интерпретация правил может быть исследована в результате изучения исходного текста программы на Ассемблере. Засчитывание очка имеет место при определении какого-либо нарушения правил. В конце цикла имеется обращение к подпрограмме временной задержки, которая обеспечивает задержку в 5 мс. Счетчик циклов декрементируется. Если он стал нулевым, то задается новая позиция ша- рика посредством сканирования ячейки памяти led_.posn. Выигрыш имеет место, если это приводит к тому, что позиция шарика выходит за пределы 8-разрядного диапазона; это случится, если не было успешного обратного удара, когда шарик находился в своей конечной позиции. Состояние выигрыша разделено на две части, оно очень простое. Так, в нем произво- дится включение соответствующего светодиода выигрыша, затем запрашивается полусе- кундная задержка и светодиод выключается. Затем программа выходит из этого состоя- ния и возвращается в состояние ожидания. 5.10. Выполнение программы электронного пинг-понга на имитаторе — учебное упражнение Программа электронного пинг-понга не является из ряда вон сложной, однако в ней много циклов и временных задержек и, следовательно, она иллюстрирует соответствую- щие проблемы, связанные с тестированием программы на имитаторе. Искусство тести- рования на имитаторе заключается в использовании каждой его функции именно там, где это нужно. В общем случае к программному сегменту, который должен быть иссле- дован в деталях, необходимо применять режим пошагового выполнения или анимацию. Те секции программного кода, которые вы хотите пройти быстро, следует просто прого- нять в общем режиме с остановом на заранее установленной контрольной точке. Далее опи- сывается учебное практическое занятие, которое проведет вас через имитацию выполне- ния данной программы. Убедитесь в том, что вы создали и скомпоновали проект, содержащий копию програм- мы электронного пинг-понга. 5.10.1. Установка входных стимулирующих сигналов Программа электронного пинг-понга имеет два цифровых входа — кнопки двух игро- ков, сигналы от которых необходимо имитировать. Выберите Debugger (Отладчик) > Sti- mulus Controller (Контроллер стимулирующих сигналов). Это приведет к открытию диа- логового окна Stimulus Controller (Контроллер стимулирующих сигналов). В поле Pin (Штырек) выберите RA3, а в поле Action (Действие) выберите Set High (Установка логи- ческой 1). Повторите эти действия для штырька RA4. Затем создайте еще раз две линии для RA3 и RA4, на сей раз со значением Pulse Low (Импульс низкий) в поле Action (Дей- ствие). Установите длительность сигнала, равную 50 мс, что типично для быстродейству- ющих кнопочных переключателей. Можете ли вы определить из программы, какая мак- симальная, теоретически допустимая длительность нажатия игроком кнопки?
5.10. Выполнение программы электронного пинг-понга на имитаторе — учебное упражнение 131 5.10.2. Настройка окна Watch (Наблюдение) Щелкните View (Вид) > Watch (Наблюдение) для выполнения настройки окна Watch (Наблюдение). Целесообразным выбором для программы электронного пинг-понга будет выбор следующих контролируемых переменных: PCL (для отслеживания того, где вы находитесь в программе), PORTA и PORTB, с использованием кнопки Add SFR (Добавить СФР), а также duration, led_posn и delcntrl, с использованием кнопки Add Sym- bol (Добавить символ). Щелкнув правой кнопкой мышки на титульной полосе окна Watch (Наблюдение) в верхней части этого окна вы увидите, что можете отобразить больше столбцов, например для данных, отображаемых в двоичной форме. Настройки окна Watch (Наблюдение), которые вы выполнили, будут сохранены в конце сессии. 5.10.3. Пошаговое выполнение программы Нажмите клавишу F6 для сброса счетчика команд, а затем попытайтесь выполнить в пошаговом режиме программу электронного пинг-понга. Вы сможете видеть, как по мере выполнения команд изменяется содержимое регистров, при этом изменения будут выде- ляться красным цветом. Если одна либо обе пользовательские кнопки установлены в логи- ческий 0 (т.е. на “нажатие”), то процесс имитации будет циклить в первом цикле ожидания. (Вы сможете наблюдать соответствующие состояния, контролируя порт А в окне Watch (Наблюдение).) Установите эти линии в состояние логической единицы, щелкнув по кноп- кам Fire (Запуск) в диалоговом окне Stimulus Controller (Контроллер стимулирующих сигналов). Вы должны наблюдать отображение изменений в окне Watch (Наблюдение). Теперь вы должны иметь возможность пошагово выполнять программу до цикла waitl. Пройдя по циклу один или два раза, запустите импульс RA3. Вы должны теперь выйти из цикла и перейти на метку l_to_r. Обратите внимание, что значение для порта В изменится на 01 после установки позиции шарика. Вы можете продолжать пошаговое выполнение программы от данного момента и либо пропустить подпрограмму delay5, либо войти в нее. Если вы вошли в нее, то вы всегда сможете выйти из нее, используя оп- цию Step Out (Выход). Не вызывает сомнений, что будет достаточно утомительно пройти всю подпрограмму в пошаговом режиме. Даже если мы пропустим эту подпрограмму, по- вторение циклов станет бесконечным, что явно продемонстрирует недостатки пошагового режима. 5.10.4. Анимация Еще раз нажмите клавишу F6 и попытайтесь запустить программу в режиме Animate (Анимация). Настройте скорость так, чтобы она вас устраивала, используя настройки De- bugger (Отладчик) > Settings (Настройки) > Debugger Animation (Анимация отладки). Теперь вы не сможете использовать функцию Step Over (Перейти через) и вновь обнару- жите, что надолго застряли в подпрограмме временной задержки. Вы сможете наблюдать, как в окне File Registers (Файловые регистры) декрементируется значение de lent г. 5.10.5. Пуск Если вы выберете Run (Пуск), то не сможете многого увидеть — окна памяти по мере работы программы не будут больше обновляться. Стимулирующие входные сигналы при этом все еще будут восприниматься. Следовательно, в этом режиме будет лучше всего ис- пользовать контрольные точки.
132 Глава 5. Компоновка программ, написанных на языке Ассемблера 5.10.6. Контрольные точки Установите контрольную точку сначала на метку l_to_r. Теперь сбросьте имити- руемый ЦП, установите в диалоговом окне Stimulus Controller (Контроллер стимулиру- ющих сигналов) RA3 и RA4 в состояние логической единицы и запустите программу. Запустите импульс на RA3. После этого программа должна остановиться в заданной вами контрольной точке. Без перезапуска программы попытайтесь установить контрольную точку на метке ltr_l и вновь щелкните на кнопке Run (Пуск). Число контрольных точек в имитаторе MPLAB не ограничено, поэтому их можно использовать без ограничений. 5.10.7. Таймер с остановом Используя Debugger (Отладчик) > Settings (Настройки) > Osc/Trace (Тактовая час- тота/Трассирование), установите частоту процессора, равную 800 кГц, что является но- минальным значением частоты для электронного пинг-понга. Установите контрольную точку в первой строке подпрограммы delay5 и запустите программу до останова в этой контрольной точке. Теперь выберите Debugger (Отладчик) > Stopwatch (Таймер с оста- новом). Обнулите таймер с остановом и установите контрольную точку на команду Re- turn данной подпрограммы. Запустите программу до останова в этой контрольной точке. Совпадают ли показания в окне Stopwatch (Таймер с остановом) с расчетным значением задержки, отрабатываемой подпрограммой? Это очень полезная функция — замер вре- менных интервалов во время выполнения программы. 5.10.8. Трассирование Попытайтесь активировать опцию Trace (Трассирование), запустите программу до кон- трольной точки, а затем исследуйте память трассирования, выбрав View (Вид) > Simula- tor Trace (Трассирование имитатора). 5.10.9. Отладка программы в целом Попытайтесь расставить контрольные точки в позициях, показанных в табл. 5.2 на следующей странице. Обратите внимание на то, что все контрольные точки должны вво- диться в строки, содержащие команды. Сбросьте счетчик команд, нажав клавишу F6, и запустите программу. В пошаговом режиме перемещайтесь от одной контрольной точки к другой и наблюдайте в окне Watch (Наблюдение) значения переменных, указанных в таблице. Пройдите несколько раз циклы и, поняв поведение программы, попытайтесь, нахо- дясь в имитаторе: • выполнить “незаконное” нажатие кнопки для перехода в состояние выигрыша; • отрабатывать циклы до тех пор, пока шарик не достигнет крайней точки, а затем воз- вратите его “законным” нажатием кнопки. 5.11. Что делают другие — графические имитаторы Последние две главы имели целью обеспечить хорошее введение в MPLAB и ее ими- татор MPSIM. Хотя эти программные продукты являются по-своему мощными, однако не стоит забывать, что они бесплатны. А что если кто-то желает потратить деньги на приоб- ретение более стоящего имитатора?
5.11. Что делают другие — графические имитаторы 133 Табл. 5.2. Рекомендованные позиции контрольных точек при отладке программы электронного пинг-понга Контроль- ная точка Действия по достижении контрольной точки wait Проверьте значение порта А — находятся ли разряды 3 и 4 в состоянии логической 1 ? Щелкните на кнопке Run (Пуск) для отработки цикла и наблюдайте, как программа включит светодиод “вне игры”. Установите разряды 3 и 4 в состояние логической 1 при помощи генератора стимулирующих сигналов. Щелкните на кнопке Run (Пуск). waitl Порт А должен быть 0001 1100. Инициализируйте низкое состояние импульса RA4 при помощи генератора стимулирующих сигналов (т.е. это значит, что игрок начал игру); он будет в низком состоянии в течение 50 мс времени прогона. Щелкните на кнопке Run (Пуск). r_to_l l_to_r В этом месте программа будет при подаче сигнала RA4/RA3, обратите внимание, что соответствующий разряд порта А будет находиться в состоянии логического 0. Щелкните на кнопке Run (Пуск). rtl_l ltr_l В пошаговом режиме пройдите несколько командных строк от этого места и обратите внимание, установилась ли led_posn в новое значение. Эта переменная отражает позицию шарика. Щелкните на кнопке Run (Пуск). Наблюдайте, как значение loop_cntr уменьшается на единицу в каждой итерации цикла. Наблюдайте также изменение состояния led_posn. rtlend 1trend Закончен один внутренний цикл, сейчас предстоит вызов подпрограммы задержки. Щелкните на кнопке Run (Пуск). Удалите контрольные точки для более быстрого выполнения программы. score_left В данное место программа попадает при “незаконном” нажатии кнопки, инициализирующем выигрыш противника. Щелкните на кнопке Run (Пуск). score_right В данное место программа попадает при “незаконном” нажатии кнопки, инициализирующем выигрыш противника. Щелкните на кнопке Run (Пуск). delay5 В пошаговом режиме несколько раз пройдите этот цикл. Наблюдайте, как значение delcntrl будет сначала установлено, а затем декрементировано. Щелкните на кнопке Run (Пуск). Удалите контрольные точки для более быстрого выполнения программы. delay500 В данном состоянии программы будет светиться светодиод выигрыша. Он будет подсвечиваться в течение 0,5 секунд. Щелкните на кнопке Run (Пуск). В настоящее время доступен целый ряд имитаторов, которые далеко ушли от простого текстово-ориентированного интерфейса MPSIM. Примером может быть имитатор, опи- санный в, его интерфейс показан на рис. 5.12. В данном случае имитируется микрокон- троллер 16F84. На приведенном рисунке видно, что отчетливо отображаются: состояние регистра W, следующей команды режима конвейерной обработки, текущей команды, сте- ка, регистра состояния, портов, а также листинг программы. Программа может быть запу- щена либо выполнена в пошаговом режиме, при этом ее внутреннее состояние будет четко обновляться и отображаться. Резюме • В процессе разработки важно спроектировать правильные структуры программ. В этом могут помочь блок-схемы и диаграммы состояний. • Целый ряд методов могут помочь в создании четких хорошо структурированных про- грамм. В их состав входит использование подпрограмм, поисковых таблиц, макрооп- ределений и включаемых файлов.
134 Глава 5. Компоновка программ, написанных на языке Ассемблера Рис. 5.12. Экран имитатора “Виртуальный Р1Смикро" фирмы Matrix Multimedia • Полный набор команд 16F84A может быть использован для создания больших и слож- ных программ. • Более сложные программы требуют большего опыта разработчика в использовании методов имитации.
ГЛАВА 6. РАБОТА СО ВРЕМЕНЕМ: ПРЕРЫВАНИЯ, СЧЕТЧИКИ И ТАЙМЕРЫ Наша повседневная жизнь, кроме, возможно, немногих счастливчиков, управляется временем. У нас есть будильники, чтобы разбудить нас утром, секундомеры, чтобы изме- рить продолжительность интервалов времени, таймеры, запускающие одиночные события (например, запись на видеокамеру), а также таймеры, поддерживающие периодические со- бытия (например, ежедневное включение в одно и то же время системы обогрева помеще- ний). У тех, кто учится, рабочий день управляется учебным расписанием — сложным рядом запланированных событий. Для встроенных систем время также очень важно. На простейшем уровне система дол- жна своевременно реагировать на внешние события. Может также потребоваться измерить время между внешними событиями и сгенерировать последовательность действий, привя- занных к определенному времени. Эти требования удовлетворяются, прежде всего, двумя различными, но связанными между собой особенностями микроконтроллера: прерывани- ями и счетчиком/таймером. В то время как каждый из названных элементов является сам по себе автономным, оба они настолько полезны, что стали вездесущими, проложив себе дорогу ко многим другим функциям микроконтроллера. Прерывания генерируются почти каждым периферийным устройством микроконтроллера. Счетчики/таймеры обеспечива- ют синхронизацию целого ряда процессов — от управления мотором, с широтно-импульс- ной модуляцией сигналов, до задания значения скорости информационного обмена в пос- ледовательных каналах связи. В этой главе излагаются принципиальные основы функцио- нирования каждого из названных элементов — они должны быть изучены в деталях. В силу того, что они используются как на элементарном уровне, так и в продвинутых и сложных вариантах, мы будем возвращаться к этим понятиям в ряде случаев на протяжении всей книги. В конечном счете, можно сказать, что прерывания и счетчики/таймеры вместе фор- мируют часть мощной технологии, лежащей в основе программирования в масштабе ре- ального времени. В этой главе вы узнаете: • о том, почему нам нужны прерывания и счетчики/таймеры; • об основной структуре аппаратных средств генерирования прерываний; • о структуре прерываний микроконтроллера 16F84A; • о том, как программировать с использованием прерываний; • об основной структуре аппаратных средств счетчиков/таймеров микроконтроллера; • о структуре таймера 0 микроконтроллера 16F84A; • о простых применениях счетчика/таймера; • о режиме бездействия. При желании вы также сможете: • узнать об альтернативных подходах к стратегиям работы с прерываниями с использо- ванием примеров, относящихся к другим семействам микроконтроллеров; • глубже изучить вопросы, связанные с прерываниями в 16F84A, в частности с воз- можным временем ожидания прерываний.
136 Глава 6. Работа со временем: прерывания, счетчики и таймеры 6.1. Основная идея - прерывания Как мы знаем, ЦП компьютера — это глубоко организованный объект; он выполняет одну за другой команды программы и делает то, что ему командуют точно и предсказуе- мо. Прерывания же нарушают этот порядок. Поступая тогда, когда они, возможно, меньше всего ожидались, каждое прерывание недвусмысленно информирует ЦП о том, что прои- зошло некоторое важное внешнее событие, требующее, чтобы процессор остановил свою текущую работу и (с максимально возможной скоростью) отреагировал на то, что произо- шло. Первое время прерывания применялись чаще для того, чтобы внешние аварийные со- бытия привлекали внимание ЦП — т.е. события типа сбоя питания, перегрева системы или отказа подсистемы. Но концепция прерываний оказалась настолько мощной, что с течени- ем времени все большее и большее число подсистем получило право генерировать преры- вания. Это, в свою очередь, привело к повышению сложности структуры прерываний, а также к необходимости признания того, что не все прерывания одинаковы по важности. Чтобы успешно работать с прерываниями, мы должны понять как аппаратную структу- ру прерываний, так и программные методы, необходимые для того, чтобы успешно прог- раммировать с использованием прерываний. Далее следует введение в упомянутые темы. 6.1.1. Структуры прерываний Разные микроконтроллеры имеют довольно различные структуры прерываний. Неиз- бежно они имеют более чем один источник прерываний, при этом одни прерывания генери- руются внутренне, а другие — внешне. Обобщенная структура, иллюстрирующая основ- ные аппаратные принципы прерываний, показана на рис. 6.1. Слева мы видим один из нес- кольких источников прерываний — Прерывание X. Если происходит прерывание, то оно устанавливает S-R триггер. Таким образом регистрируется возникшее прерывание, даже если оно носит мгновенный характер. Выход триггера, т.е. сохраненная версия прерыва- ния, называется флагом прерывания. Выход триггера стробируется сигналом разрешения прерывания — Разрешение прерывания X. Если сигнал стробирования имеет состояние, соответствующее логической 1, то сигнал прерывания идет на логический элемент ИЛИ. Если же сигнал стробирования имеет состояние, соответствующее логическому 0, то сиг- нал прерывания дальше никуда не поступает. Если сигнал прерывания разрешен, то он по- дается на схемы логического ИЛИ вместе с другими разрешенными сигналами прерыва- ний микроконтроллера. Выход логического ИЛИ будет соответствовать логической 1, ко- гда любое прерывание на входе логического ИЛИ будет находиться в состоянии, соответ- ствующем логической 1. Выход первичного каскада логического ИЛИ стробируется сиг- налом Глобальное разрешение прерываний. Только в случае, если значение этого сигнала соответствует логической 1, любой сигнал прерывания может достигнуть ЦП. Когда ЦП от- реагировал на прерывание, то необходимо сбросить флаг прерывания. В некоторых про- цессорах это выполняется автоматически, в других же эта операция должна выполняться программно. Аналогично для других маскируемых прерываний Другие маскируемые прерывания Разрешение прерывания X Прерывание X о----------- S Q Флаг* прерывания Сигнал “Глобальное разрешение прерываний' (Сброс от ЦП или программы) — R Входы преры- ваний ЦП Немаскируемые___________________________ ________________________________ прерывания * биты специального функционального регистра Рис. 6.1. Простая структура прерываний общего назначения
6.1. Основная идея - прерывания 137 Действие запрета прерывания иногда называется маскированием прерывания. Это может показаться странным, что должна быть возможность отключить функцию, которая является настолько важной и которая, как предполагается, должна быть всегда включена, чтобы можно было сообщить об аварии. Действительно, некоторые микроконтроллеры име- ют прерывания, которые не могут маскироваться. Они всегда внешние (то есть идут не от внутренних периферийных устройств) и используются для того, чтобы подключаться к внешним сигналам прерываний самой большой важности. Немаскируемое прерывание по- казано на рис. 6.1. Поскольку ЦП всегда реагирует, если происходит такое прерывание, то имеется меньше смысла сохранять его в виде флага, в силу этого такое сохранение иногда вообще не выполняется. 6.7.2. Структура прерываний 16F84A Микроконтроллер 16F84A имеет четыре источника прерывания, каждый из которых можно индивидуально разрешить или запретить: • Внешнее прерывание. Это единственный внешний вход прерывания. Он разделяет шты- рек разряда 0 порта В (рис. 2.1). Этот вход тактируется перепадом сигнала. • Переполнение таймера. Это прерывание, вызываемое модулем таймера 0, который является темой второй половины этой главы. Оно происходит, когда переполняется 8-разрядный счетчик таймера. • Прерывание по изменению состояния порта В. Это прерывание возникает, когда об- наружено изменение состояния любого из старших 4 разрядов порта В. Этот механизм был описан в подразделе 3.4.1. • Завершение записи в ЭСППЗУ. Это прерывание возникает, когда команда записи в па- мять EEPROM (или ЭСППЗУ) завершена. На рис. 6.2 показана структура прерываний, а специальный функциональный регистр (СФР) INTCON, контролирующий эту структуру, — на рис. 6.3. Полезно эти две схемы изучать параллельно, поскольку каждый бит регистра INTCON отражен на логической схеме структуры прерываний. Четыре источника прерываний помечены в левой части рис. 6.2. При сравнении этой схемы с рис. 6.1 интересно обратить внимание на отсутствие триггеров флагов прерываний. На самом деле они существуют, но не отражаются на схемах, предоставляемых фирмой Microchip. Каждый источник прерывания имеет линию разреше- ния (помеченную ...Е) и линию флага (помеченную ...F). Таким образом, линии TOIF, INTF и так далее — это, скорее, линии флагов прерываний, чем входы прерываний непо- средственно. Всем им соответствуют биты в регистре INTCON, за исключением флага и разрешения завершения записи ЭСППЗУ. Обратите внимание, что внешнее прерывание тактируется перепадом сигнала. Перепад, на который выполняется реакция, управляется установкой бита INTEDG регистра OPTION (Опции) (рассматривается позже, поскольку он главным образом касается таймера 0, показанного на рис. 6.9). Как показано на рис. 6.1, каждый флаг логически умножается с сигналом разрешения (TOIE, INTE, RBIE и EEIE). Разряды сигнала разрешения размещены в регистре INTCON, они могут устанавливаться программистом. Выходы четырех логических элементов “И” логически складываются вместе перед передачей сигнала на логический элемент глобаль- ного разрешения прерываний. Флаги прерывания должны очищаться посредством управ- ления состоянием разрядов INTCON. 16F84A не имеет никаких входов для немаскируемых прерываний. 6.7.3. Реакция ЦП на прерывание Давайте предположим, что произошло прерывание, а также то, что как локальный приз- нак разрешения прерывания, так и глобальный признак разрешения прерываний установ- лены. Прерывание, следовательно, обнаружено ЦП и он выполняет специальную секцию
138 Глава 6. Работа со временем: прерывания, счетчики и таймеры программы, называемую программой обработки прерывания (ISR). Важно понять подроб- ности того, что происходит — эти подробности иллюстрируются блок-схемой на рис. 6.4. ЦП завершает команду, которую он выполняет в настоящее время и сохраняет значение счетчика команд в вершине стека. Таким образом, оно будет “знать”, куда ему возвра- титься, когда ISR завершит свою работу. Чтобы избежать других прерываний, которые в принципе могли бы прервать обработку текущего прерывания возможно прерывающих это прерывание, ЦП также очищает глобальный признак разрешения прерываний. Рис. 6.2. Структура прерываний 16F84A (дополнительные надписи в зачерненных прямоугольниках добавлены автором) R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-x GIE EEIE T0IE INTE RBIE T0IF INTF RBIF разряд 7 разряд О разряд 7 GIE: бит глобального разрешения прерываний 1 = разрешает все немаскированные прерывания О = запрещает все прерывания разряд 6 EEIE: бит разрешения прерывания по завершению записи ЭСППЗУ 1 = разрешает прерывание по завершению записи ЭСППЗУ О = запрещает прерывание по завершению записи ЭСППЗУ разряд 5 Т01Е: бит разрешения прерывания по переполнению TMR0 1 = разрешает прерывание по переполнению TMR0 О = запрещает прерывание по переполнению TMR0 разряд 4 INTE: бит разрешения внешнего прерывания RB0/INT 1 = разрешает внешнее прерывание RB0/INT О = запрещает внешнее прерывание RB0/INT разряд 3 RBIE: бит разрешения прерывания по изменению состояния порта 1 = разрешает прерывание по изменению состояния порта RB О = запрещает прерывание по изменению состояния порта RB разряд 2 T0IF: бит флага прерывания по переполнению TMR0 1 = регистр TMR0 переполнился (должен быть очищен программно) О = регистр TMR0 не переполнялся разряд 1 INTF: бит флага внешнего прерывания RB0/INT 1 = произошло внешнее прерывание RB0/INT (должно быть сброшено программно) О = внешнее прерывание RB0/INT не происходило разряд О RBIF: бит прерывания по изменению состояния порта RB 1 = по крайней мере один из штырьков RB7:RB4 изменил свое состояние (бит должен быть сброшен программно) О = ни один из штырьков RB7:RB4 не изменил свое состояние Рис. 6.3. Регистр INTCON 16F84A
6.2. Работа с прерываниями 139 В семействе PIC® 16, ISR должна запускаться по вектору прерывания, расположенно- му по адресу 0004 памяти программ (рис. 2.4). Следовательно, когда происходит прерыва- ние, это значение загружается в счетчик команд и затем выполнение программы продол- жается от вектора сброса. Для любого процессора ISR должна заканчиваться специальной командой “возврат из прерывания”. В семействе PIC® 16 это будет команда ret fie. Когда ЦП обнаруживает эту команду, он устанавливает GIE в 1, загружает счетчик команд значе- нием из верхней части стека, а затем продолжает выполнение программы. Таким образом, он возвращается к команде, которая следует сразу же за командой, при выполнении ко- торой было обнаружено прерывание. Выполняется основная программа Начало выполнения программы обработки прерывания Продолжение выполнения основной программы Рис. 6.4. Последовательность событий реакции 16F84A на прерывание 6.2. Работа с прерываниями 6.2.1 Программирование одного прерывания Писать простые программы, в которых используется только одно прерывание, сравни- тельно просто. Для успеха следует учитывать следующие моменты: • Следует запускать ISR по вектору прерывания, расположенному по адресу 0004; • Нужно разрешить прерывание, которое должно использоваться, установив бит разре- шения в регистре INTCON; • Нужно установить бит глобального разрешения прерываний, GIE; • Следует очистить флаг прерывания внутри ISR; • ISR следует завершать командой retf ie; • Следует убедиться в том, что источник прерывания, например порт В или таймер 0, действительно настроены на генерирование прерываний! Пример программы 6.1 приводит очень простой пример прерывания, предназначенный для имитации. Все требования, приведенные выше, выполнены. Программа начинается, как
140 Глава 6. Работа со временем: прерывания, счетчики и таймеры обычно, по вектору сброса 0000. Однако, вектор прерывания теперь также используется. Первым действием программы является выполнение перехода через вектор сброса на метку start, по которой начинается инициализация. В рамках инициализации мы видим, что устанавливаются биты GIE и INTE. Эти метки могут использоваться, поскольку они вво- дятся во включаемом файле 16F84A. Основная программа просто выводит битовые струк- туры 0Ан и 15н в порт В по очереди. Когда происходит прерывание, адрес вектора прерывания загружается в счетчик ко- манд, с которого и продолжается выполнение программы. Первое действие ISR заключа- ется в переходе по адресу Int__Routine. Этому адресу соответствует ячейка памяти про- грамм 0080н, а цель этого действия заключается в обеспечении четкости имитации. ISR просто очищает порт А перед снятием флага прерывания и возвращает управление основ- ной программе. Пример программы 6.1. Простое применение прерывания /Демонстрация прерывания 1 ;Данная программа демонстрирует простое использование одного прерывания /Программа предназначена для имитации. ;Int Demol 14.04.05 .*************х********************************************************* #include pl6f84A.inc /Выдается весь порт А. Порт В: бит 0 = прием прерывания org 00 goto start org 04 /Здесь начинается подпрограмма /обслуживания прерывания goto Int_Routine org 0010 /Инициализация start bsf status,rpO /выбор банка 1 movlw 01 movwf trisb /выдача разрядов 1-7 порта В /прием разряда 0 movlw 00 movwf trisa /выдача всех разрядов порта А bcf status,rpO /выбор банка 0 bsf intcon,inte /разрешение внешнего прерывания bsf intcon,gie /разрешение глобального прерывания /удалите символ точки с запятой из нижеследующей команды /для изменения перепада прерывания / bsf option_reg,intedg wait movlw 0a /установка начальных выходных значений порта movwf porta movlw 15 movwf porta goto wait org 0080 Int_Routine /здесь продолжается подпрограмма обслуживания прерывания movlw 00 movwf porta bcf intcon,intf retfie end
6.2. Работа с прерываниями 141 УПРАЖНЕНИЕ НА ИМИТАЦИЮ 6.1 Скопируйте программу int_Demoi с компакт-диска, прилагаемого к этой книге, в при- ложение MPLAB® и создайте проект, включающий эту программу. Скомпонуйте проект и активируйте имитатор. Откройте окно Watch (Наблюдение), отобразив в нем перемен- ные porta, portb, intcon и pcl. Откройте окно Hardware Stack (Аппаратный стек) (разворачивающееся меню View (Вид)), чтобы наблюдать содержимое стека. Запустите контроллер стимулирующих сигналов и установите штырек RB0 на Toggle (Триггер). По- шагово продвигайтесь через программу и наблюдайте, пытаясь понять, изменения сос- тояния каждой контролируемой переменной после выполнения каждой команды. Те- перь запустите стимулирующий сигнал на штырек RB0, установив тем самым RB0 в со- стояние логической 1, и продолжайте пошаговое выполнение программы. Это не приве- дет к изменению в выполнении программы, поскольку реакция на перепад сигнала пре- рывания выставлена на срабатывание по отрицат. льному перепаду (бит intedg был оставлен в исходном состоянии, соответствующем логическому 0). Еще раз подайте стимулирующий сигнал на штырек RB0 — теперь последовательность отработки пре- рывания должна запуститься по мере того, как вы пошагово будете продвигаться по программе далее. Наблюдайте изменение состояния аппаратного стека, когда управ- ление будет передано ISR, и тогда, когда после завершения ISR программа продолжит свое выполнение после команды, на которой произошло прерывание. Попытайтесь из- менить бит intedg, как указано в программе, изменив перепад, на который будет реа- гировать прерывание. Если вы успешно реализовали вышеупомянутую программу, попробуйте внести в нее перечисленные далее ошибки. Они типичны для новичков. Наблюдайте эффект: • не выполняется очистка флага прерывания — удалите команду bcf intcon, intf • некорректное завершение ISR — замените retfie на return. 6.2.2. Двигаемся к множественным прерываниям — идентификация источника Использование одного прерывания в программе в общем случае выполняется достаточ- но просто, однако предупреждаем вас — как только мы начинаем использовать более одного прерывания, они, прерывания, могут взаимодействовать друг с другом способами, которые являются далеко не простыми. Сложность при этом, по-видимому, растет приблизительно пропорционально квадрату от числа используемых прерываний! Как мы уже знаем, 16F84A имеет четыре источника прерываний и только один вектор прерывания. Следовательно, если разрешается более чем одно прерывание, то вначале ISR совсем не очевидно, какое именно прерывание произошло. В этом случае программист так должен написать ISR, чтобы вначале она проверяла флаги всех возможных прерываний и определяла по ним, какое прерывание ее вызвало. Пример фрагмента программного кода, который делает это в предположении, что все четыре источника прерываний разрешены, показан в примере программы 6.2. 6.2.3. Не допускайте, чтобы прерывания разрушили вашу программу — правило № 1: сохраняйте контекст Так как прерывание может происходить в любое время, оно имеет чрезвычайно разру- шительный потенциал. Пример программы 6.3 написан для того, чтобы проиллюстриро- вать это. Он использует подпрограмму 16-разрядного сложения. Чисто для примера, 16-раз- рядное число 9999н добавляется само к себе — ожидается, что это даст 17-разрядный результат 13332н- В подпрограмме складываются младшие 2 байта — qlo и plo. Любой
142 Глава 6. Работа со временем: прерывания, счетчики и таймеры сгенерированный перенос добавляется в один из старших байтов, а затем складываются старшие два байта. Написана также ISR, которая воздействует как на флаг переноса, так и на регистр W, как это делают большинство ISR. Пример программы 6.2. Идентификация источника прерывания interrupt btfsc intcon,0 ;проверка RBIF goto portb_int btfsc intcon,1 ;проверка внешнего флага прерывания goto ext_int btfsc intcon,2 ;проверка флага переполнения таймера goto timer_int btfsc eeconl,4 ;проверка флага завершения portb_int goto eeprom_int ;записи ЭСППЗУ помещаем сюда программу обслуживания прерывания по изменению состояния порта В bcf intcon,О retfie ext int ;и очищаем флаг прерывания помещаем сюда программу обслуживания внешнего прерывания bcf intcon,1 retfie ;и очищаем флаг прерывания timer int помещаем сюда программу обслуживания прерывания по переполнению таймера bcf intcon,2 ;и очищаем флаг прерывания retfie eeprom_int помещаем сюда программу обслуживания прерывания по завершению записи ЭСППЗУ bcf eeconl,4 retfie ;и очищаем флаг прерывания Пример программы 6.3. Воздействие прерываний Int__context Эта программа демонстрирует необходимость сохранения контекста Предназначена для имитации TJW 15.04.05 Тестировано 17.04.05 ;Порт А не используется. Бит 0 порта В используется для индикации ;внешнего прерывания. ♦include pl6f84A.inc rhi equ 10 rlo equ 11 phi equ 12 plo equ 13
6.2. Работа с прерываниями 143 Пример программы 6.3. Окончание qhi qlo equ equ org goto org goto 14 15 00 start 04 Int_Routine /в это место, если происходит прерывание start org 0010 bsf intcon,inte ;разрешение внешнего прерывания bsf intcon,gie /разрешение глобального прерывания loop movlw 99 movwf phi /предварительная загрузка чисел, /которые будут складываться movwf plo movwf qhi movwf qlo call Double add movlw 00 /очистка результата movwf rhi movwf rlo goto loop / Эта подпрограмма складывает 2 16' -разрядных числа, хранящихся в phi-plo /и qhi-qlo, а также сохраняет результат в rhi-rlo. В конце операции /16-разрядное переполнение индицируется флагом переноса. Double_add movf addwf movwf btfsc incf movf addwf movwf return plo, 0 qlo, 0 rlo status,0 phi, 1 phi, 0 qhi, 0 rhi /перемещение plo в регистр W /сложение младших байтов /сложение с битом переноса /сложение старших байтов Int Routine bcf status,0 /очистка флага переноса movlw Off /изменение значения регистра W bcf retfie end intcon,intf Предположим, что прерывание происходит сразу же после выполнения первой команды подпрограммы — movf, когда регистр W содержит значение plo. ISR изменяет содержи- мое регистра W, так что когда управление выполнением возвращается к программе, то ре- гистр W будет иметь неправильное значение. Предположим теперь, что прерывание про- исходит немедленно после выполнения первой команды addwf. Значение бита переноса существенно для успеха операции сложения, но опять-таки оно тоже теряется в ISR. Временные данные, используемые при специфической активности ЦП, называются контекстом. В семействе PIC 16 в их состав входит, по крайней мере, значение регистра W и регистра состояния. Очевидно, что крайне важно сохранить контекст, когда происхо- дит прерывание. Некоторые микроконтроллеры делают это автоматически, но микрокон- троллеры семейства PIC 16 этого не делают. Следовательно, программист должен обеспе- чить программное сохранение любого необходимого контекста.
144 Глава 6. Работа со временем: прерывания, счетчики и таймеры УПРАЖНЕНИЕ НА ИМИТАЦИЮ 6.2 Скопируйте программу int_Context с компакт-диска, прилагаемого к этой книге, в MPLAB и создайте с ней проект. Скомпонуйте проект и активируйте имитатор. Откройте окно Watch (Наблюдение), отобразив qhi, qlo, phi, plo, rhi, rlo, status и wreg в качестве контролируемых переменных. Запустите контроллер стимулирующих сигна- лов и установите RB0 на Toggle (Переключение). Пошагово выполняйте программу, убедитесь в том, что дополнение работает корректно и ожидаемый результат достиг- нут. Теперь попробуйте вставлять прерывания в разных точках программы. Обратите внимание, как и в каких точках программы вхождение ISR разрушает достоверность результата сложения. Пример программы 6.4 демонстрирует метод, рекомендуемый Microchip для сохране- ния регистра W в заранее определенной ячейке памяти W_TEMP, а регистра состояния — в ячейке памяти с именем STATUS_TEMP. Используются команды swapf и movwf, потому что они не воздействуют на какие-либо биты регистра состояния. Пример программы 6.4. Сохранение контекста PUSH ISR movwf w_temp ;Копируем регистр W в W_TEMP /Состояние своппинга должно быть сохранено /Сохраняем состояние в регистр STATUS_TEMP /Подпрограмма обработки прерываний swapf movwf status,0 status_temp Сюда вводится собственно подпрограмма обработки прерываний POP swapf movwf swapf swapf statuS—temp,0 status w_temp,1 w_temp,0 /Своппинг полубайтов в регистр STATUS_TEMP /и помещение результата в W /перемещение W в регистр состояния /установка банка в исходное состояние /Своппинг полубайтов в W_TEMP и сохранение /результатов в W_TEMP /Своппинг полубайтов в W_TEMP и сохранение /результатов в W здесь выполняется очистка флагов прерываний retfie УПРАЖНЕНИЕ НА ИМИТАЦИЮ 6.3 Сократите фрагмент сохранения контекста из примера программы 6.4 и вставьте его в программу lnt_Context (пример программы 6.3). Вы должны будете определить ячейки памяти для w_temp и status_temp. Проверьте, что теперь программа функ- ционирует правильно с той точки, где вы инициализируете прерывание. 6.2.4. Не допускайте, чтобы прерывания разрушили вашу программу — правило № 2: определите критические области и используйте маскирование Соответствующим сохранением контекста, как обсуждалось выше, мы можем решип только некоторые из проблем, связанных с возникновением прерываний, встречающих* в программных секциях типа подпрограмма. К сожалению, этим мы не можем реши все проблемы, по крайней мере, не только сохранением контекста.
6.2. Работа с прерываниями 145 Что, если прерывание произошло в подпрограмме временной задержки, например та- кой, какая приведена в примере программы 5.2? Длительность временной задержки увели- чилась бы на продолжительность выполнения 1SR, что в принципе могло бы иметь катастро- фические последствия, и никакое сохранение контекста не смогло бы улучшить ситуацию. Рассмотрим более тонкую проблему. ISR, показанная в примере программы 6.5, берет слово, содержащееся в rhi-rlo, рассчитанное в подпрограмме из примера программы 6.3, и выводит его на 12-разрядный цифро-аналоговый преобразователь (ЦАП), соединенный с портами А и В. Мы принимаем, что полная программа ограничивает слово в rhi-rlo 12 битами. Предположим, что ISR, показанная в примере программы 6.5, будет вызвана во время выполнения подпрограммы из примера 6.3. Сохранение контекста выполнено, так есть ли проблема? К сожалению, проблема есть. ISR использует результат, который вычисляется в прог- раммной секции, выполнение которой она прервала. Предположим, что когда произошло прерывание, rlo была только что модифицирована, а г hi — еще нет. ISR выдает новое значение rlo и старое значение г hi. Вместе они могли бы дать число, которое не имеет никакого смысла, что потенциально могло бы иметь катастрофические последствия. Пример программы 6.5. Прерывание, использующее данные, вычисляемые в программе Int_Routine movwf W_temp /копирование W в регистр TEMP swapf status,0 /своппинг статуса в W movwf status temp /сохранение статуса в регистре STATUS TEMP bcf status,5 /работа с банком 0 movf rhi, 0 /вывод старших 4 битов на ЦАП movwf movf porta rlo, 0 /вывод младших 4 битов на ЦАП movwf swapf portb statuS—temp,0 /своппинг полубайтов в регистре STATUS _ТЕМР movwf status /и помещение результата в W /перемещение W в регистр состояния swapf W temp,1 /установка банка в исходное состояние /своппинг полубайтов в W_TEMP swapf W_temp,0 /и помещение результатов в W_TEMP /своппинг полубайтов в W_TEMP bcf retfie intcon,intf /и помещение результатов в W Таким образом, мы должны принять тот факт, что в некоторых областях программы мы не можем допустить вторжения прерывания ни при каких обстоятельствах, независимо — с или без сохранения контекста. Мы будем называть такие области программы критиче- скими областями. Значит, в этих областях программы мы должны Отключать или маски- ровать прерывания, манипулируя битами разрешения прерываний регистра INTCON. Кри- тические области в общем случае включают все чувствительные ко времени программные процессы, а также любые вычисления, если ISR использует их результаты. В состав чув- ствительных ко времени процессов входят циклы временных задержек, а также многоко- мандные настройки выходов. Правильно применяя методы сохранения контекста и учета критических областей, мы сможем эффективно использовать прерывания без воздействия на программы разруши- тельной стороны их природы.
146 Глава 6. Работа со временем: прерывания, счетчики и таймеры 6.3. Основная идея — счетчики и таймеры 6.3.1. Цифровые счетчики Очень просто сформировать цифровой счетчик, используя тригтеры. Можно сформи- ровать счетчики, которые считают в сторону увеличения или в сторону уменьшения, счет- чики, которые сами сбрасываются в ноль или предварительно загружают какое-то значение, а также счетчики, выходы которых, с учетом переполнения, каскадируются с другими счет- чиками. Простой пример показан на рис. 6.5. Восемь J-K триггеров, переключаемых отри- цательным фронтом сигнала, взаимосвязаны так; что Q-выход одного управляет тактовым входом следующего. На входах J и К постоянно присутствует сигнал логической 1, поэтому триггер переключается по каждому входному отрицательному фронту тактового импульса. Счетчик содержит 8-разрядное двоичное число, сформированное Q-выходами триггеров, при этом Q7 — это самый старший разряд, Qo — самый младший. К счетчику добавляется единица по каждому поступающему отрицательному фронту тактового импульса. Временная диаграмма выходов счетчика показана в нижней части рисунка. Можно видеть, что после одного входного цикла Qo переходит в состояние логической 1. После завершения 16 входных циклов (то есть в течение цикла 17) 8-разрядное слово формирует 00010000в, то есть 16D, а после 31 цикла — 00011111в, то есть 31D. Когда будут завершены 255 входных цикла, счетчик будет содержать слово 11111111в или FFH. После поступления следующего входного сигнала все триггеры сбрасываются в 0 и выход счетчика возвраща- ется к состоянию 00000000b. При этом отрицательный фронт Q7 может использоваться для того, чтобы индицировать переполнение счетчика. Счетчик, показанный на рис. 6.5, может быть сброшен в ноль, если будет активирована линия сброса. Если схему немного усложнить, то можно обеспечить возможность предва- рительной загрузки счетчика любым желаемым числом. Если мы это сделаем, то получим гибкую цифровую подсистему, которая является основой счетчиков, используемых в мик- роконтроллерах. Эта подсистема может быть представлена посредством упрощенной схе- мы, показанной на рис. 6.6. Единственно важными взаимосоединениями в ней являются тактовый вход, выход сигнала переполнения и 8-ми разрядный тракт чтения/записи, кото- рый может стробироваться при разделении одной двунаправленной информационной ма- гистрали. 6.3.2. Счетчик в роли таймера Конечно же, способность считать чрезвычайно полезна для микроконтроллера, — на- пример, он может считать узлы, проходящие мимо него на конвейерной ленте, жетоны в автомате метро или людей, проходящих через дверь. Однако, еще даже более полезным свойством микроконтроллера была бы его способность измерять время, и счетчик позво- ляет ему это делать. Предположим, что входной сигнал на рис. 6.5 — это стабильная тактовая частота с пе- риодом следования в 1 мс. Это значит, что к счетчику каждую миллисекунду прибавляет- ся 1. После 16 тактовых циклов пройдет точно 16 мс, после 31 тактового цикла — точно 31 мс и так далее. Начав подачу тактовой частоты в определенный момент, мы, таким об- разом, сможем измерять время, прошедшее с этого момента: Разрешение измерений опре- деляется периодом тактовых импульсов. В данном примере разрешение равно 1 мс и мы не сможем проводить измерения с большей точностью, например с точностью до долей миллисекунды. Опять-таки, в случае периода следования входного сигнала, равного 1 мс, 8-разрядный счетчик сможет измерить период времени вплоть до 255 мс, после чего на- ступит переполнение счетчика. Использование счетчиков в роли таймеров столь важно, что сам счетчик иногда называют счетчиком/таймером (С/Т) или просто таймером, чтобы обозначить эту важность.
6.3. Основная идея — счетчики и таймеры 147 Рис. 6.5. Цифровой счетчик, сформированный из восьми триггеров Чтение Загрузка Рис. 6.6. Цифровой счетчик в виде блок-схемы Очевидное применение счетчика/таймера связано с измерением времени между двумя событиями. Оба эти события могут быть сгенерированы вне системы. Или альтернативно — первое может быть сгенерировано микроконтроллером, а второе происходит некоторое время спустя как реакция на первое. Может также оказаться необходимым измерить время между двумя импульсами или же продолжительность одного импульса. Общее требование к измерению времени иллюстрируется на рис. 6.7. Собственно измерение кажется простым: запустить счетчик/таймер, когда происходит первое событие и остановить его, когда про- исходит второе событие. Практически же вышеописанная процедура связана с рядом вы- зовов. Так, для обеспечения точности замеров, начало и конец работы счетчика/таймера должны быть строго синхронизованы с событиями. Самый лучший способ реализации это- го требования — использование прерывания. Если у нас не будет прерывания, то нам при- дется непрерывно сканировать вход, чтобы обнаружить, когда произойдет событие — в
148 Глава 6. Работа со временем: прерывания, счетчики и таймеры этом случае едва ли стоит использовать счетчик/таймер, поскольку мы могли бы выполнить программную привязку ко времени. А если имеются два внешних события на двух разных линиях, то мы также имеем проблему, поскольку в семействе PIC 16 мы имеем только одно внешнее прерывание. Событие 1 Т Событие 2 Время —к | Запустить счетчик здесь j | Остановить счетчик здесь j (С) Рис. 6.7. Вызов, связанный с измерением времени Мы рассмотрим хороший пример измерения времени в Главе 10. Мы также ознако- мимся с доработками счетчика/таймера, которые позволят решить проблему точной син- хронизации начала и конца работы счетчика/таймера с событиями, временной интервал между которыми измеряется. б.3.3. Модуль таймера 0 в 16F84A Таймер 0 в 16F84A типичен для простых счетчиков/таймеров, используемых в малых микроконтроллерах. В его состав входит 8-разрядный счетчик (подобный показанному на рис. 6.5), подключаемый как специальный функциональный регистр в карте памяти и па- кетированный с обеспечением некоторых полезных дополнительных функций. Его блок- схема с 8-разрядным счетчиком, обозначенным как TMR0, показана на рис. 6.8. Если воз- вратиться к рис. 2.5, то можно видеть, что этот счетчик отражен на нем как регистр TMR0 по адресу памяти 01 в банке памяти 0. Как и все качественные периферийные устройства микроконтроллеров, таймер 0 конфигурируется с управлением по ряду битов регистра OPTION, который показан на рис. 6.9. Если посмотреть на левую часть рис. 6.8, то можно увидеть, что имеются два возмож- ных источника подачи тактовой частоты на счетчик TMR0. Одним из них является штырек RA4 (т.е. штырек 3 16F84A — смотри рис. 2.1). Другим — внутренняя частота командного цикла, обозначенная как Fosc/4. Выбор источника входной тактовой частоты выполняется мультиплексором, управляемым битом T0CS регистра опций. Цепь подачи внешней такто- вой частоты обеспечивает возможность выбора инверсии сигнала схемой “Исключающее ИЛИ”. Эта инверсия управляется битом T0SE. Выход первого мультиплексора разветвля- ется перед достижением второго мультиплексора. Имеется возможность выбора либо пря- мого пути, либо пути, идущего через программируемый предварительный делитель. Этот выбор управляется битом PSA регистра опций. Сложность здесь состоит в том, что пред- варительный делитель фактически разделяется со сторожевым таймером (WDT), который мы рассмотрим немного ниже в этой главе. Сейчас же будет достаточным сказать, что ес- ли PSA установлен в 1, то предварительный делитель назначен WDT, и мультиплексор
6.3. Основная идея — счетчики и таймеры 149 выбирает путь подачи входного сигнала, который обходит предварительный делитель. Сам предварительный делитель управляется битами PS2, PS1 и PS0 регистра опций. Из рис. 6.9 видно, что эти биты задают выбор коэффициента деления тактовой частоты для входного сигнала. Выход второго мультиплексора синхронизируется с внутренней тактовой часто- той, перед тем как он становится входным сигналом собственно счетчика. Когда счетчик переполняется, он устанавливает флаг переполнения таймера — один из четырех источ- ников прерывания микроконтроллера PIC, из показанных на рис. 6.2. Выбор входного перепада Штырек RA4/T0CKI FOSC/4 TOSE Программируемый предварительный делитель Мультиплексор выбора источника счетных импульсов Мупьтиппеиюр выбора предварительного делителя XT5 SOOT Синхронизация по внутреннему генератору тактовых импульсов Шина данных 8-разрядный счетчик TMRO PSOut (Задержка на 2 периода) О 8 Установка флага переполнения TOIF на переполнение PS2.PS1.PS0 PSA TOCS Примечание: 1. TOCS, TOSE, PSA, PS2:PS0 (OPTION_REG<5:0>). 2. Предварительный делитель разделяется со сторожевым таймером (смотрите детальную блок-схему на рис. 5.2). Ссылки, указанные здесь, относятся к рис. 5.2. оригинальной документации на 16F84A Рис. 6.8. Модуль Таймера 0 в 16F84A (дополнительные надписи в затемненных прямоугольниках добавлены автором) R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 RBPU INTEDG TOCS TOSE PSA PS2 PS1 PSO разряд 7 разряд 6 разряд 5 разряд 4 разряд 3 RBPU: PORTB бит активирования нагрузки 1 = PORTB нагрузка заблокирована 0 = PORTB нагрузки активируются индивидуальными триггерами порта INTEDG: бит выбора фронта прерывания 1 = Прерывание по подъему фронта сигнала на штырьке RB0/INT 0 = Прерывание по спаду фронта сигнала на штырьке RB0/INT T0CS: бит выбора источника синхроимпульсов для TMR0 1 = Переключение на штырьке RA4/T0CK1 0 = Внутренняя синхропоследовательность командного цикла (CLKOUT) T0SE: бит выбора фронта источника синхроимпульсов для TMR0 1 = Инкрементирование по переключению от 1 в 0 на штырьке RA4/T0CK1 0 = Инкрементирование по переключению от 0 в 1 на штырьке RA4/T0CK1 PSA: бит назначения предварительного делителя 1 = Предварительный делитель назначен WDT 0 = Предварительный делитель назначен модулю таймера 0 PS2-PS0: выбор коэффициента деления разряды 2-0 Значение разрядов Коэффициент WDT Коэффициент TMRO ООО 1: 2 1: 1 001 1:4 1:2 010 1:8 1:4 011 1: 16 1: 8 100 1: 32 1: 16 101 1: 64 1: 32 110 1: 128 1: 64 111 1: 256 1: 128 Рис. 6.9. Регистр OPTION 16F84A
150 Глава 6. Работа со временем: прерывания, счетчики и таймеры 6.4. Применение таймера 0 в 16F84A на примере электронного пинг-понга Простые счетчики/таймеры, подобные таймеру 0, могут использоваться для многих приложений. Мы рассмотрим два примера. Оба они основаны на программе электронного пинг-понга и могут легко имитироваться. 6.4.1. Подсчет объектов или событий Самое простое применение таймера 0 заключается в его использовании в качестве счетчика, считающего импульсы, поступающие в микроконтроллер через внешний вход. Если посмотреть на схему электронного пинг-понга (Приложение 2, рис. А2.1), то можно увидеть, что правая кнопка соединена со штырьком 3 16F84A. Программа из примера 6.6 — это очень простой пример такого подсчета. Она соответствующим образом активирует счетчик и использует правую кнопку, как источник входных импульсов для счетчика, со- стояние которого непрерывно отображается на светодиодах, подсоединенных к порту В. Для конфигурирования таймера 0 нам потребуется выбрать внешний вход, то есть ус- тановить TOCS = 1. Направление изменения фронта входного сигнала, которое будет вы- зывать переключение, не очень важно. Однако, поскольку имеется риск дребезга кнопки, то мы выберем направление изменения фронта, связанное с отпусканием кнопки, т.е. воз- растающий фронт, поскольку в этом случае риск дребезга будет меньшим. Следовательно, устанавливаем T0SE = 0. Нам не понадобится предварительный делитель, поскольку мы хотим подсчитать точное число нажатий кнопки. Следовательно, PSA = 1. Таким образом, биты PS2, PS1 и PS0 не имеют значения (поскольку это приложение не использует WDT). Все биты регистра опций, которые не были упомянуты в этом абзаце, не имеют значения для электронного пинг-понга, поэтому установим их в 0. Итак, окончательное значение регистра опций будет равно 00101000b. Данная программа может быть запущена на аппаратных средствах электронного пинг- понга, при этом каждое нажатие правой кнопки будет приводить к тому, что двоичная структура, отображаемая игровыми светодиодами, будет инкрементироваться с шагом 1. Пример программы 6.6. Инициализация таймера 0 для измерения длительности периода быстрого обмена ударами в электронном пинг-понге ;cntr_demo Демонстрация счетчика /данная программа демонстрирует использование таймера 0 в качестве /счетчика при использовании аппаратных средств электронного пинг-понга /TJW 15.4.05 Тестировано 15.4.05 /Тактовая частота приблизительно равна 800 кГц (RC-генератор) /Port А 4 Вход счетчика от правой кнопки (вход) / 2 Светодиод "вне игры" (выход) /Port В 7-0 Светодиоды "игры" (все выходы) /Прерывания не используются /Слово конфигурирования: RC-генератор, WDT выкл., /PU таймер вкл. , кодовая защита выкл. list p=16F84A ♦include pl6f84A.inc org 00 / Инициализация bsf status,rpO /выбор банка памяти 1
6.4. Применение таймера 0 в 16F84A на примере электронного пинг-понга 151 Пример программы 6.6. Окончание movlw movwf movlw movwf movlw movwf bcf B'00011000' trisa 00 trisb B' 00101000' TMRO status,rpO /порт А настраивается в соответствии с /вышеприведенной структурой /выдача всех разрядов порта В /настройка TMR0 на внешний вход, /положительный фронт, предварительный /делитель не используется /поскольку мы в банке 1, команда адресует OPTION /выбор банка 0 loop movlw movwf movf movwf goto end 04 porta TMRO,0 portb loop /переключатель на светодиод "вне игры" для /демонстрации того, что питание включено /непрерывно отображаем таймер 0 на порт В УПРАЖНЕНИЕ НА ИМИТАЦИЮ 6.4 Скопируйте программу Cntr_Demo с компакт-диска, прилагаемого к этой книге, в MPLAB и создайте вокруг нее проект. Скомпонуйте проект и запустите имитатор. Откройте окно Watch (Наблюдение), выведя переменные portb и tmro. Запустите контроллер стиму- лирующих воздействий и настройте штырек RA4 на импульсный сигнал логической 1 (при ширине импульса, равного 1 периоду). Анимируйте программу, запустите входной импульс и наблюдайте, как изменится содержимое порта В и СФР таймера 0. 6.4.2. Временные задержки, сгенерированные аппаратными средствами В оригинальном варианте программы пинг-понга программно-сгенерированные вре- менные задержки используются для задания времени, в течение которого светодиоды должны светиться. Это приемлемо только в простых программах, поскольку при исполь- зовании программно-сгенерированных временных задержек ЦП не делает ничего полезного в течение всего времени отсчета временных задержек. Теперь же, когда мы имеем в нашем распоряжении счетчик/таймер, мы можем использовать его для того, чтобы генерировать временные задержки, а ЦП в это время, при необходимости, может заниматься другими делами. Это кажется совершенно простым, но есть небольшая проблема: как мы узнаем, когда истечет период временной задержки? Если нам придется проверять значение таймера, то наш прогресс будет крайне незначительным. Вот почему на сцене появляется прерыва- ние по переполнению. Если все будет настроено так, чтобы по окончании временной за- держки генерировалось прерывание, то мы получим мощное средство создания эффектив- ных временных задержек. В качестве первого шага давайте заменим в программе пинг-понга подпрограмму 5-мил- лисекундной временной задержки временной задержкой, управляемой таймером 0. Внут- ренняя тактовая частота в случае электронного пинг-понга приблизительно равна 800 кГц, а частота командных циклов (Fosc/4), следовательно, будет равна 200 кГц. Т.е. мы будем иметь период, равный 5 мкс. При этой тактовой частоте таймер 0 досчитает до своего мак- симального значения за 255 х 5 мкс или за 1275 мкс, а переполнится на следующем цикле, то есть после 1280 мкс. Мы можем, однако, использовать в этом случае предварительный делитель. Если частота входного сигнала будет делиться на 4 (т.е. биты PS2, PSI, PS0 (или,
152 Глава 6. Работа со временем: прерывания, счетчики и таймеры что то же самое, разряды 2-0 регистра OPTION) будут установлены в состояния, соответс- твенно, 001), то таймер 0 переполнится после 4 х 1280 мкс или 5,12 мс. Это очень близко к задержке в 5 мс, к которой мы стремимся, хотя и не совсем точно. Хотя электронный пинг-понг и не нуждается в точной синхронизации, однако предпо- ложим, что мы крайне нуждаемся во временной задержке, очень близкой к 5 мс. Давайте будем делить входную тактовую частоту на 8, вместо 4, что даст результирующую часто- ту в 25 кГц или же период, равный 40 мкс. Теперь 125 входных циклов таймера 0 дадут временную задержку, равную 125 х 40 мкс или 5,00 мс, что в точности соответствует тре- буемой задержке. Если мы соответствующим образом настроим предварительный делитель, а в начале каждой задержки будем загружать в таймер 0 значение 256 - 125 = 13Id, то станет возможной отработка точной временной задержки, завершаемой прерыванием по переполнению. Реализация данного подхода иллюстрируется программными секциями в примере про- граммы 6.7. Она охватывает как секцию инициализации, так и пересмотренную подпро- грамму отработки временной задержки. Прерывания не разрешены и подпрограмма опре- деляет, когда задержка завершена посредством проверки состояния флага прерывания по переполнению. Преимуществом, с точки зрения программиста, является то, что привязка ко времени теперь осуществляется посредством манипулирования настройками таймера 0, а не настройкой подпрограммы. “Прерывание по переполнению” не разрешено, ибо в этом случае оно дало бы мало преимуществ. В более требовательных программах, однако, пре- рывание может быть разрешено, а время, потраченное на работу с задержками, могло бы быть израсходовано на иные виды активности ЦП. Пример программы 6.7. Использование таймера 0 в подпрограмме delays ;Инициализация org 0010 start bsf status,5 /выбор банка памяти 1 movlw movwf B'00011000' trisa /установка порта А в соответствии с movlw movwf 00 trisb /вышеприведенной структурой /выдача всех битов порта В movlw B'00000010 ' /установка TMR0 на внутренний вход, movwf TMR0 /предварительно деленный на 8 /поскольку мы в банке 1, bcf status,5 /это адресует OPTION /выбор банка 0 ;введение задержки, приблизительно равной 5 мс delay5 movlw D11311 /предварительная загрузка счетчика, с тем чтобы /125 циклов, каждый в 40 мкс, отрабатывались /до переполнения счетчика movwf TMR0 dell btfss intcon,2 /проверка флага переполнения таймера goto dell /цикл, если флаг не установлен bcf intcon,2 /сброс флага переполнения таймера return [УПРАЖНЕНИЕ НА ИМИТАЦИЮ 6.5 Измените программу электронного пинг-понга так, чтобы включить в нее изменения, приведенные в примере программы 6.7. Использовав Debugger (Отладчик) > Settings (Установки), обеспечьте, чтобы тактовая частота была установлена на 800 кГц. Исполь- зуйте функцию Stopwatch (Таймер с остановом) для того, чтобы проверить продолжи- тельность временного периода задержки, обеспечиваемого новой подпрограммой вре-
6.5. Сторожевой таймер 153 менной задержки. Сколько команд call и return, а также загрузок таймера добавля- ется к задержке? Можете ли вы осуществить точную настройку, чтобы повысить точ- 6.5. Сторожевой таймер В 16F84А имеется и другой таймер, о котором мы должны знать даже при том усло- вии, что он обычно не используется в простых приложениях. Это сторожевой таймер (WDT). Большая опасность для любой компьютерной системы связана с тем, что каким- либо образом произойдет программный сбой и система заблокируется или перестанет реа- гировать. В случае настольного компьютера такая ситуация может раздражать — обычно компьютер приходится перезагружать. В случае встроенной системы возникновение та- кой ситуации может означать катастрофу, поскольку может не оказаться пользователя, ко- торый бы заметил, что что-то не так; да и пользовательский интерфейс может вообще от- сутствовать. WDT предлагает довольно грубое “решение” этой проблемы. Он представляет собой внутренний счетчик микроконтроллера, который непрерывно считает. Если он когда- либо переполняется, то это приводит к его принудительному сбросу (см. рис. 2.11). Про- граммист должен обеспечить, чтобы внутри программы WDT неоднократно очищался. Это выполняется командой clrwdt. Таким образом, только тогда, когда программа перестает работать правильно, эта команда больше не будет выполняться и произойдет переполнение. Сброс WDT в общем случае не является хорошей новостью для встроенной системы — все текущие настройки, конечно же, уничтожаются, и программа перезапускается с самого начала. Это, однако, гораздо лучше, чем программа, которая не работает вообще. Обрати- те внимание, что WDT оставляет след своей работы — это бит ТО в регистре состояния (см. рис. 2.3). Является возможным проверить состояние этого бита в самом начале про- граммы и, следовательно, отличить сброс по включению питания и сброс WDT. WDT в 16F84A активируется одним из битов конфигурации, которые показаны на рис. 2.6. Таким образом, в течение всего времени, когда микроконтроллер включен, WDT либо работает, либо не работает. Он управляется внутренним RC-генератором, который обеспечивает номинальный период тайм-аута, равный 18 мс. Он, однако, до некоторой степени зависит от температуры, напряжения питания и вариаций параметров внутренних устройств. Период тайм-аута может быть расширен посредством применения к WDT пред- варительного делителя таймера 0. В этом случае названный период может быть расширен до 128 х 18 мс, или приблизительно до 2,3 секунды. 6.6. Режим бездействия Хотя в этой главе мы рассматриваем вопросы синхронизации, сейчас, скорее всего, подходящий момент для того, чтобы рассмотреть еще один аспект работы микроконтрол- лера, когда время почти остановлено — это режим бездействия. Этот режим представляет собой существенный способ экономии электроэнергии. Микроконтроллер может войти в этот режим, выполнив команду SLEEP, см. Приложение 1. Войдя в режим бездействия, микроконтроллер начинает работать почти как в замедленном кинофильме. Генератор синхроимпульсов выключен, WDT сброшен, выполнение программы приостановлено, все порты сохраняют свои текущие настройки, а биты PD и ТО регистра состояния (рис. 2.3) очищены и соответственно установлены. Если WDT активирован, то он продолжает свою работу. В этих условия потребляемая мощность падает до незначительной величины — приблизительно до 1 мкА при специфических идеальных эксплуатационных условиях. Войдя в режим бездействия, микроконтроллер может выйти из него только в случае возникновения определенных событий. 16F84A выходит из режима бездействия в следу- ющих ситуациях:
154 Глава 6. Работа со временем: прерывания, счетчики и таймеры • Подача сигнала внешнего сброса через штырек MCLR. Хотя это событие и выводит микроконтроллер из режима бездействия, однако оно также сбрасывает микроконтрол- лер, следовательно, использование этого события ограничено случаями, когда нужно полностью перезапустить программу. Возможно, однако, программно обнаружить, что микроконтроллер только что был в режиме бездействия по состоянию бита PD в ре- гистре состояния. • Активирование по WDT. Функция WDT в режиме бездействия выполняется несколько иначе. Если внимательно посмотреть на рис. 2.10, то можно увидеть, что WDT в режиме бездействия заблокирован от выполнения сброса. Вместо этого по своему переполне- нию он просто выводит микроконтроллер из состояния бездействия, после чего про- должается выполнение программы с команды, следующей после той, на которой мик- роконтроллер вошел в состояние бездействия. • Возникновение прерывания. Как видно из рис. 6.2, любое индивидуально разрешенное прерывание может вывести микроконтроллер из состояния бездействия, вне зависимо- сти от состояния флага глобального разрешения прерываний. Таймер 0 не может, одна- ко, сгенерировать прерывание, поскольку внутренняя тактовая частота заблокирована. После выхода микроконтроллера из состояния бездействия схема генератора переза- пускается. Для любого режима кварцевого генератора это означает, что таймер TOst, пока- занный на рис. 2.11, также активируется. Он должен завершить цикл своих отсчетов пре- жде, чем выполнение программы сможет продолжаться. Следовательно, как и у человека, у 16F84A уходит некоторое время на то, чтобы пробудиться и быть готовым к действию. Режим бездействия — это чрезвычайно мощное средство для изделий, которые про- ектируются на экономный расход электроэнергии. Многие устройства не всегда непре- рывно активны, когда на них подается напряжение питания. Если бы на период неак- тивности они переводились в режим бездействия, то потребляемая ими мощность зна- чительно бы снизилась. 6.7. Что делают другие Прерывания — это весьма важная функция почти всех микроконтроллеров, однако их архитектура может значительно изменяться. Одним из отличий является, например, спо- соб, которым применяются вектора прерываний. Микроконтроллер 8051, базовая модель фирмы Atmel, имеет, как это показано в табл. 6.1, шесть прерываний. При этом вместо разделения одного вектора прерывания, как в семейст- ве PIC 16, каждое прерывание имеет свой собственный вектор. Таким образом, например, подпрограмма обработки прерываний для внешнего прерывания 0 запускается по адресу 0003н, в то время как подпрограмма обработки прерывания по переполнению таймера 0 запускается по адресу 000Вн. Поскольку каждое прерывание имеет свой собственный век- тор, то отпадает необходимость опроса флагов прерываний в начале подпрограммы обра- ботки прерываний с целью определения источника прерывания, как это делалось в при- мере программы 6.2. Но поскольку существует много векторов прерываний, то очень важно иметь средство выбора между несколькими прерываниями, если такие прерывания воз- никнут одновременно. В силу этого микроконтроллер Atmel использует приоритеты пре- рываний, как это показано в нижеприведенной таблице. Если одновременно возникает два прерывания, то первым обслуживается то прерывание, которое имеет более высокий при- оритет. Как и 16F84A, при реакции на прерывание микроконтроллер Atmel только сохра- няет счетчик команд в стеке. Микроконтроллер Freescale 68НС08, как, конечно же, и все предыдущие изделия фирмы Motorola, использует совершенно иной подход к векторам прерываний. Вместо того чтобы вектор прерывания был начальным адресом программы обработки прерываний, он содер- жит этот адрес. В Freescale эти вектора размещаются на самом верху пространства памяти, как показано в табл. 6.2. Конечно же, для этих целей должна использоваться неразрушаемая
6.8. Двигаемся дальше — время ожидания прерывания 155 память. Каждый вектор имеет 16 разрядов, поэтому он занимает две 8-разрядных ячейки памяти. Табл. 6.1. Источники прерываний Atmel и адреса векторов прерываний Источник Символ Приоритет .Адрес вектора Внешнее прерывание 0 IE0 1 (макс.) ОООЗн Запрос прерывания таймера 0 TF0 2 000Вн Внешнее прерывание 1 IE1 3 0013н Запрос прерывания таймера 1 TF1 4 001Вн Последовательная приемо-передача RI+TI 5 0023н Переполнение таймера 2, таймер 2 — внешний TF2 + EXF2 6 (мин.) 002Вн Табл. 6.2. Источники прерываний Freescale 68НС08 и адреса векторов прерываний (не полностью) Источник Символ Приоритет Адрес вектора Вектор сброса (младшие разряды) - - FFFFH Вектор сброса (старшие разряды) - - FFFEh Программное прерывание (младшие разряды) SWI 1 FFFDh Программное прерывание (старшие разряды) SWI FFFCh Запрос прерывания (младшие разряды) IRQ 2 FFFBh Запрос прерывания (старшие разряды) IRQ FFFAh Вектор сброса всегда помещается в самую верхнюю часть карты памяти. По этому ад- ресу хранится фактический стартовый адрес программы. Вектора прерываний размеща- ются один под другим в порядке, обратном их приоритету. В вышеприведенной таблице показаны только первые несколько векторов. Преимущество для пользователей состоит в том, что они могут помещать подпрограммы обработки прерываний в те места памяти, в какие желают, но только при условии, что они правильно поместят адреса этих подпро- грамм в определенные для этого векторы прерываний. Микроконтроллер Freescale 68НС08 отличен как от семейства PIC 16, так и от Atmel в том, что при обработке прерывания он заносит в стек все регистры ЦП, а именно: аккумулятор (эквивалент регистра W в PIC), младший байт индексного регистра, счетчик команд (2 байта) и регистр кода состояния. 6.8. Двигаемся дальше — время ожидания прерывания Цель прерывания состоит в том, чтобы как можно быстрее привлечь внимание ЦП. Но как быстро это фактически происходит? Время между появлением прерывания и реакцией на него ЦП называется временем ожидания прерывания. Время ожидания зависит от нес- кольких аспектов аппаратных средств и, в конечном счете, может также зависеть и от харак- теристик работающих программ. Временная диаграмма, показанная на рис. 6.10, демонст- рирует, как средние микроконтроллеры семейства PIC реагируют на разрешенное внешнее прерывание. Само по себе прерывание может наблюдаться в виде положительного импуль- са на линии штырька INT. Это вызовет установку флага INTF. Этот флаг опрашивается с интервалом Q1, заданным внутренним тактовым генератором. Как только это будет сдела- но, ЦП распознает прерывание, после чего запустится последовательность событий, пока- занная на рис. 6.4. Два холостых цикла необходимы для того, чтобы сохранить счетчик ко- манд в стеке, перезагрузить его адресом 0004н и осуществить выборку команды по этому адресу.
156 Глава 6. Работа со временем: прерывания, счетчики и таймеры OSC1 CLCOUT ® Штырек прерывания (INT) Флаг прерывания INTF (INTCON<1>) Бит GIE (INTCON<7>) ПОТОК КОМАНД Счетчик команд Загруженная команда Выполненная Команда Q1 | Q21 Q3 | 04 I Q1 | 021 03 | 04 i Q1 | Q2j 03 | 04 Q1 | 021 Q3 | 04 Q1 | 021 03 | 04 Inst(PC) lnst(PC-1) jc PC-И ти+т М«ЭД1Я ИФМЛ lnst(PC+1) lnst(0004h) Inst(PC) ' Холостой цикл Холостой цикл Inst(OOOSh) lnst(0004h) ж X X Примечания: 1. Флаг INTF опрашивается здесь (каждый Qj). 2. Время ожидания прерывания равно 3-4 Tcy, где Tcy — время командного цикла; время ожидания будет одинаковым, независимо от того, будет ли команда по адресу счетчика команд одно- или двухцикловой командой. 3. CLKOUT доступен только в режиме RC-генератора. 4. Для получения сведений о минимальной ширине импульса прерывания обращайтесь к спецификациям по управлению доступом. 5. INTF может быть выставлен в любое время на протяжении циклов Q4—Qv Рис. 6.10. Время ожидания 16F84A для внешнего прерывания УПРАЖНЕНИЕ НА ИМИТАЦИЮ 6.6 Вновь работая с программой int_demol, установите тактовую частоту на 4 МГц, ис- пользуя команду Debugger (Отладчик) > Settings (Настройки). Разверните окно Stop- watch (Таймер с остановом) (под управлением отладчика) и пошагово пройдите через программу. Наблюдайте, как в окне Stopwatch (Таймер с остановом) предсказуемо обновляется значение истекшего времени. Теперь активируйте прерывание. Обратите внимание на то, как в окне Stopwatch (Таймер с остановом) будет зарегистрировано время ожидания, соответствующее двум командным циклам. В конце отработки про- граммы обработки прерываний наблюдайте, как команда retfie также займет два ко- мандных цикла. Резюме • Прерывания и счетчики/таймеры являются важными аппаратными принадлежностями почти всех микроконтроллеров. • В обоих этих понятиях заложены важные аппаратные и программные концепции, ко- торые нужно понимать. • В этой главе были изложены базовые сведения относительно методов использования прерываний и счетчиков/таймеров. Способы их применения значительно усложняются по мере роста сложности приложений.
ЧАСТЬ 3. БОЛЬШИЕ СИСТЕМЫ И PIC®16F873A В этой части книги, также состоящей из пяти глав, основное внимание уделено формированию глубокого понимания периферийных устройств микроконтроллеров и основных принципов, лежащих в их основе. При рассмотрении используется ядро микроконтроллера, рассматриваемое в предыдущих главах, но при этом рассматривается “большой” микроконтроллер из семейства PIC 16. Все рассмотренные периферийные устройства непосредственно применимы и к семейству PIC 18. Ударение делается на понимании работы периферийных устройств и их использовании в сложных приложениях. Приводятся примеры программ на Ассемблере.
ГЛАВА 7. БОЛЬШИЕ СИСТЕМЫ И PIC® 16F873A На протяжении предыдущих пяти глав в качестве примера рассматривался микрокон- троллер PIC® 16F84A. Он и другие микроконтроллеры, подобные ему, являются прекрас- ными устройствами, предназначенными для использования в малых системах. Однако есть много задач, которые они не могут выполнять, и поэтому для более требовательных при- ложений мы должны подыскивать более мощный микроконтроллер. Но что, фактически, означает “более мощный”? Вспомните то, что говорилось в Главе 1, а именно то, что микроконтроллер по существу состоит из: ядра микропроцессора плюс память, плюс периферийные устройства. Больше “мощности” может быть добавлено к микроконтроллеру посредством нара- щивания мощности любой из названных компонент. Ядро, содержащее ЦП, может быть сделано более мощным, если оно станет быстрее, усовершенствуется его внутренняя ар- хитектура или же будет доработан набор команд. Память может быть сделана более “мощной” посредством усовершенствования техно- логии ее изготовления, повышения ее емкости и быстродействия. В качестве альтернативы, или как дополнение, может быть добавлено большее количество периферийных устройств или же могут быть усовершенствованы уже имеющиеся периферийные компоненты. В большинстве случаев во встроенных системах наиболее радикальные усовершенст- вования касаются не ядра. Вместо этого основной смысл имеющегося прогресса заключа- ется в наращивании периферийных устройств, возможно сопровождаемого обновлением памяти. За счет добавления соответствующих периферийных устройств, спорадическое ана- лого-цифровое преобразование, последовательная связь или сложные функции синхрони- зации становятся легкодоступными. В этой части книги, в Главах 7-11, мы останемся с семейством PIC 16. Однако мы будем двигаться от менее функциональных членов семейства к более продвинутым их родствен- никам, т.е. например к PIC 16F873A. Как и 16F84A, так и 16F873A являются членами одно- го семейства, ядро и набор команд у них остается постоянным, однако способность к кон- центрации функций управления встроенной системой у 16F873A значительно возрастает благодаря добавлению великолепного набора “новых” периферийных устройств. В упомянутых главах материал иллюстрируется реализацией устройства, которое на- зывается “Автономно управляемый самодвижущийся механизм Derbot” (АУСМ Derbot). Если вы никогда не собирали Derbot, то не волнуйтесь — излагаемый материал послужит прекрасным практическим пособием, который выведет на ряд новых концепций, с кото- рыми, рано или поздно, вы все равно столкнетесь. Мы будем продолжать программировать на Ассемблере, однако уже начнем испытывать некоторые ограничения как со стороны возможностей Ассемблера, так и со стороны аппаратных возможностей семейства PIC 16. Это логически подведет нас к последней части книги, в которой мы попытаемся ответить на вызов со стороны передовых микроконтроллеров, программируя на С и разрабатывая сложные многозадачные программы. Поскольку мы начали двигаться к большим системам, то во все большей мере будет важным умение не только заставить их работать, но и обеспечить, при этом, чтобы они работали достаточно надежно. В силу этого в данной главе представляются новые и важные
7.1. Основная идея — PIC 16F87XA 159 диагностические инструментальные средства, а также методы, которые будут применяться для этих целей в этой и последующих главах. К концу этой главы вы должны получить хорошее понимание: • архитектуры семейства 1687ХА, членом которого является микроконтроллер 16F873A; • карты памяти 1687ХА и структуры его прерываний; • некоторых из более совершенных инструментальных средств, используемых для тес- тирования и ввода в эксплуатацию встроенных систем; • использования внутрисхемного отладчика Microchip. Если вы собираете АУСМ Derbot, то эта глава одновременно даст вам рекомендации о первых шагах поэтапного конструирования, которое будут излагаться на протяжении не- скольких последующих глав. 7.1. Основная идея — PIC 16F87XA Используемый нами в качестве примера, микроконтроллер 16F873A является членом группы, входящей в семейство, которое было кратко представлено в начале Главы 2. Эта группа включает 16F873A, 16F874A, 16F876A и 16F877A. В общем, мы можем говорить о них, как о 16F87XA. Каждый микроконтроллер из этой группы имеет также свою LF-вер- сию, например 16LF873A, который может работать при более низком напряжении питания, чем стандартное устройство. Характеристики этой группы сведены табл. 2.1. Если посмотреть на эту таблицу, то лег- ко заметить, что четыре члена этой группы отличаются просто размерами памяти и раз- мерами микросхем, при этом больший размер микросхем позволяет использовать больше параллельных портов ввода-вывода. Это иллюстрируется схемой разводки штырьков, показанной на рис. 7.1. “Дополнительные” штырьки на больших устройствах охвачены пунктиром. Можно видеть, что основное различие заключается в появлении портов D и Е в микроконтроллерах группы 874А/877А. Описания, которые приводятся в этой главе, а также во всех последующих главах вплоть до Главы 11, имеют тенденцию к тому, чтобы использовать в качестве базового уст- ройства микроконтроллер 16F873A, поскольку он используется в проекте АУСМ Derbot, который мы будем изучать. Другие члены группы, однако, также время от времени вспо- минаются, особенно если они имеют свойства, отсутствующие в ‘873А. 7.2. Блок-схема 16F873A и его ЦП Блок-схема как 16F873A, так и 16F876A показана на рис. 7.2. Различие между двумя этими микроконтроллерами заключается в размерах памяти, как это указано в таблице, приведенной в нижней части схемы. Эту схему стоит тщательно изучить и сравнить ее де- тали с блок-схемой 16F84A, приведенной на рис. 2.2. Такое сравнение покажет, что име- ются некоторые области, в которых микропроцессоры являются идентичными, другие области, в которых имеются небольшие количественные изменение, а также третьи облас- ти, в которых схема, по сути, та же, но вычерчена несколько иначе. Кроме того, большие микроконтроллеры отличаются большим количеством дополнений. 7.2.1. Обзор ЦП и ядра Прежде всего, давайте обратим внимание на структуру ЦП, который, по существу, со- стоит из АЛУ, рабочего регистра и регистра состояния, которые остались, чего и можно было ожидать, такими же, как и в ‘F84A. Прибавление на этой схеме трех линий, идущих от АЛУ на регистр состояния — это просто квитирование трех битов состояния в регистре
160 Глава 7. Большие системы и PIC 16F873A состояния, а именно: битов Z, DC и С, которые управляются АЛУ. Соответствующие ли- нии могли бы быть приведены и на рис. 2.2. (а) MCLR/VPP---<“1 RA0/AN0*—< RA1/AN1 —* Е RA2/AN2/VHtF-7CVntF -»-»-Е RA3/AN3/VHEF+ ♦-* С RA4/T0CKI/C1OUT —— Е RA5/AN4/SS/C2OUT —• С VSS—»-Е OSC1/CLKI---< OSC2/CLKO RCORTOSOnTCKI RC1/T1OSI/CCP2 С RC2/CCP1 RC3/SCK/SCL Е <10 12 13 14 О —• RB7/PGO ' □ R06/PGC 28 27 26 25 24 23 _ 22 □ —— RB1 21 □ —— RBO/INT 20 □ 19 3 ЮЗ 17 3 юЗ 15 3 RC4/SDVSDA RB4 RB3/PGM VDO VSS RC7/RX/OT RCS/TX/CK RC5/SDO (Ь) _____ MCLR/Vpp----► RA0/AN0 «—» RA1/AN1 —» RA2/AN2/VREF-/CVREF —». RA3/AN3/VREF+ -«—► RA4/T0CKI/C1OUT —» RA5/AN4/SS/C2OUT ► :‘reo/rd7an5 • RE1/WR/AN6 *—* ; RE2/CS/AN7 —* ; Voo----» .........ySs OSC1/CLKI----► OSC2/CLKO ----- RC0/T1OSO/T1CKI —- RC1/T1OSI/CCP2 RC2/CCP1 *—- RC3/SCK/SCL *—► :”RDb7PSPo"41< ; RD1/PSP1 <—- 36 35 34 33 32 31 :'зо : 29 : 28 :..27. 26 ,18.............23 19.............22 20 21 □ —-► RB7/PGD □ RB6/PGC □ RBS □ *—- RB4 □ RB3/PGM □ —— RB2 □ - RB1 □ *—► RBO/INT □ VDD □ —--- Vss □ «’RD7/PSP7’; □ - RD6/PSP6 : □ RD5/PSP5 • .RD4/PSP4 : □’^24,"rc77rx/dt □ ► RC6/TX/CK □ RC5/SDO 3-*— RC4/SDI/SDA □ <1^"RD37PSP3 • □ RD2/PSP2 • 3 5 6 8 £ Обозначения: RAO: штырек 0 порта A RCO: штырек 0 порта С REO: штырек 0 порта Е ANO, AN1 и т.д: аналоговый входной канал ССР: сбор данных/сравнение/ШИМ OSO/OSI: выход/вход генератора таймера 1 SS: выбор подчиненного устройства VREF: опорное напряжение RB0: штырек 0 порта В RD0: штырек 0 порта D PSP0: штырек 0 параллельного порта па режиме “slave” C1OUT, C2OUT: выходы компаратора INT: внешнее прерывание OSC1/OSC2: основные подключения генератора T0CKI/T1CKI: тактовый вход таймера 0/1 CVREF: компаратор опорного напряжения DT/СК: синхронные последовательные данные/симхронизация (USART) MCLR: сброс ведущего устройства PGC/PGD: синхроимпульсы и данные для внутрисхемного последовательного программирования PGM: программа для внутрисхемного последовательного программирования RD/WR/CS: чтение, запись, выбор микросхемы (параллельный подчиненный порт) RX/TX: асинхронная последовательная приемо-передача (USART) SCK/SDI/SDO: последовательные синхроимпульсы, последовательные входные данные, последовательные выходные данные (синхронный последовательный порт как последовательное периферийное устройство SPI) SCL/SDA: последовательные синхроимпульсы, последовательные данные (синхронный последовательный порт как последовательное периферийное устройство 1гС) Рис. 7.1. Схема разводки штырьков PIC 16F87XA: (а)— 16F873A/876A; (Ь)— 16F874A/877A (“дополнительные” штырьки заключены в пунктирные прямоугольники) Одно различие, которое все же присутствует в ЦП, относится к регистру состояния. В регистре состояния 16F84A (см. рис. 2.3), старшие два разряда не используются, в то время как разряд 5 используется для того, чтобы выбирать между двумя банками памяти данных. Рис. 7.3 показывает регистр состояния для 16F87XA. При наличии намного боль- шей памяти данных, все три старших разряда теперь используются для выбора необходи- мого банка памяти. Если этого не считать, то регистр состояния остался без изменений. 7.2.2. Краткий обзор памяти Помимо того, что ЦП рассматриваемого микроконтроллера подобен 16F84A, легко заметить, что структура памяти в целом также осталась той же, только с небольшими из- менениями. 13 программных адресных линий от счетчика команд, которые могут адресо- вать 213 (т.е. 8192) ячеек памяти, теперь полностью используются в 16F876A с его 8 кило- байтами памяти программ, в то время, как только половина их используется в ‘873 А.
7.2. Блок-схема 16F873A и его ЦП 161 RAO/ANO RA1/AN1 RA2/AN2/VREF-/CVREF RA3/AN3/VREF+ RA4/T0CKI/C1OUT RA5/AN4/SS/C2OUT RBO/INT RBI RB2 RB3/PGM RB4 RB5 RB6/PGC RB7/PGD RC0/T1OSO/T1CKI RC1/T1OSI/CCP2 RC2/CCP1 RC3/SCK/SCL RC4/SDI/SDA RC5/SDO RC6/TX/CK RC7/RX/DT MCLR Vdd, Vss Устройство Флеш-память программ Память данных ЭСППЗУ данных PIC16F873A 4Кслов 192 байт 128 байт PIC1GF878A 8Кслов 368 байт 256 байт Примечание 1. Старшие разряды берутся из регистра состояния Обозначения: периферийные устройства A/D - аналогоцифровой преобразователь ССР - сбор данных/сравнение/модуль ШИМ USART - универсальный синхронный/асинхронный приемопередатчик Рис. 7.2. Блок-схема 16F873A/876A Размерность шины “Прямой адрес” изменилась — на рис. 7.2 показано, что она теперь стала 7-разрядной. Это сделано с целью обеспечения возможности работы с оперативной памятью намного большего объема, — мы будем рассматривать ее в следующем подраз- деле. Это очевидное изменение, однако, “не создало напряжения” в структуре семейства PIC 16. Эти 7 разрядов извлекаются из командного слова (см. рис. 4.13). Из этого рисунка
162 Глава 7. Большие системы и PIC 16F873A мы можем видеть, что 7 разрядов зарезервированы для “адресов файловых регистров”, так что больший микроконтроллер просто использует то, что ему уже доступно. R/W-0 R/W-0 R/W-0 R-1 R-1 R/W-x R/W-x R/W-x IRP RP1 RP0 ТО PD Z DC С разряд 7 разряд 0 разряд 7 IRP. бит выбора банка регистров (используется дня косвенной адресации) 1 = банк 2, 3 (100h-1 FFh) разряды 6-5 0 = банк 0, 1 (OOh-FFh) RP1-RP0: биты выбора банка регистров (используются для прямой адресации) 11 = банк 3(180h-1FFh) 10 = банк 2 (100h-17Fh) 01 = банк 1 (80h-FFh) 00 = банк 0 (00h-7Fh) Каждый банк содержит 128 байт. разряд 4 ТО: бит тайм-аута 1 = после включения питания, команды CLRWDT или команды sleep разряд 3 0 = тайм-аут сторожевого таймера PD: бит отключения электропитания 1 = после включения электропитания или выполнения команды CLRWDT 0 - после выполнения команды sleep разряд 2 Z: бит нуля 1 = результат арифметической или логической операции равен 0 0 = результат арифметической или логической операции не равен 0 разряд 1 DC: бит знака переноса/не-заимствования числа (команды addwf, addlw, sublw, subwf) (для не-заимствования полярность реверсируется) 1 = имел место перенос из 4-го младшего разряда результата разряд 0 0 = не было переноса из 4-го младшего разряда результата С: бит переноса/не-заимствования числа (команды addwf, addlw, sublw, subwf) 1 = имел место перенос из самого старшего разряда результата 0 = не было переноса из самого старшего разряда результата Примечание. Для не-заимствования полярность реверсируется. Вычитание выполняется посредством сложения дополнения до двух второго операнда. Для операций циклического сдвига (RRF, RLF) этот бит загружается либо старшим, либо младшим разрядом регистра-источника. Рис. 7.3. Регистр состояния 16F873A 7.2.3. Краткий обзор периферийных устройств 16F84A и 16F873A используют три периферийных устройства, которые являются для них одинаковыми (или почти одинаковыми). Это таймер 0, порт А и порт В. Существен- ное различие между двумя микроконтроллерами, конечно же, заключается в дополнитель- ных периферийных устройствах, перечисленных в табл. 2.1 и показанных на рис. 7.2. За исключением параллельных портов, которые описываются в этой главе, мы будем рассмат- ривать все эти периферийные устройства в последующих главах. Увеличиваемое число периферийных устройств несет с собой два важных вызова: как обеспечить их взаимодействие с ЦП и как обеспечить их взаимодействие с внешним ми- ром? Мы уже знаем предварительный ответ на второй из этих вопросов, заключающийся в большем количестве штырьков в микроконтроллере 16F873A и повышении степени раз- деления функций многих штырьков. Для обеспечения же интерфейса с ЦП мы вправе ожи- дать значительного увеличения числа специальных функциональных регистров (СФР) и ис- точников прерываний. Три важные дополнительные функции, присутствующие в 16F873A и показанные на рис. 7.2, это обнаружение частичной потери напряжения питания, внутрисхемный отладчик и низковольтное программирование. Все они будут рассматриваться долее в этой главе.
7.3. Память 16F873A и карты памяти 163 7.3. Память 16F873A и карты памяти 16F873A имеет структуру памяти, очень похожую на структуру памяти 16F84A. Од- нако, она значительно увеличена по объему, как уже отмечалось. Кроме того, в ней име- ются некоторые очень важные технические усовершенствования, особенно в терминах внутрисхемного программирования. 7.3.1. Память программ 16F873A Карта памяти программ показана на рис. 7.4. При сравнении ее с рис. 2.4 мы видим, что она отличается от 16F84A только размером. Поскольку уже было отмечено, что I3- разрядное слово счетчика команд может адекватно адресовать все пространство памяти, удивляет нахождение на рисунке двух “страниц” памяти программы. Ситуация еще хуже для контроллеров 16F876A/877A, каждый из которых имеет по четыре страницы памяти программ. Рис. 7.4. Карта памяти программ PIC 16F873A/874A и стек Причина того факта, что память программ должна разделяться именно таким образом, лежит в способе, которым адрес программы, содержащийся в счетчике команд, генериру- ется в разных ситуациях. Счетчик команд имеет длину, равную 13 битов. Его младшие 8 разрядов формируют содержимое регистра PCL, который является одним из специальных
164 Глава 7. Большие системы и PIC® 16F873A функциональных регистров. К нему можно обращаться и им можно манипулировать так, как и любой другой ячейкой памяти данных. Старшие 5 разрядов счетчика команд не могут считываться, но могут быть записаны в младшие 5 разрядов регистра PCLATII — другого специального функционального регистра (СФР). Содержимое СФР PCLATH записывается в старшие разряды счетчика команд всякий раз, когда в него записывается содержимое PCL. При нормальном выполнении программы счетчик команд увеличивается на 1 после вы- полнения каждой команды. Однако имеются еще три способа, с помощью которых про- грамма может изменять значение счетчика команд. Каждый из них иллюстрируется рис. 7.5 и описан ниже. Команды, работающие с регистром PCL, например вычисляемое go to РСН эти биты переносятся из PCLATH эти биты записываются в PCL эти биты переносятся из PCLATH Команды Call и Goto О PCL эти биты включаются в команду к ____________________________—------—> Все биты переносятся из/в стек Все виды использования стека Рис. 7.5. Три способа управления счетчиком команд Перенос стека Стек имеет длину, равную 13 битам. Следовательно, любая команда (подобная return), которая использует стек, вызывает перенос полного 13-разрядного значения стека в счет- чик команд — нет необходимости волноваться относительно поиска в дальнейшем каких- либо потерянных битов. Использование команд call и goto Как показывает формат командного слова, приведенный на рис. 4.13, эти две команды форматируются на обеспечение только 11-разрядной адресации. Эти 11 разрядов могут адресовать диапазон 211 или 2К слов и, таким образом, отображать страницы, показанные на рис. 7.4. Когда эти команды используются, два “потерянных” бита адреса берутся из раз- рядов 4 и 3 регистра PCLATH. В сферу ответственности программиста входит распо- знать, нужен ли переход через страницу, и если да, то соответственно установить биты. Выполнение записи на регистр PCL Непосредственная запись в PCL производится в ситуациях, подобных “вычисляемому go to”, как это было описано в подразделе 5.4. В настоящее время только младшие 8 раз- рядов счетчика команд в PCL корректируются непосредственно и это то же самое, как если бы программист работал со страницами по 256 слов. Если адресная граница должна быть пересечена при результате выполнения команды “вычисляемое go to”, то PCLATH должен
7.4. “Специальные” операции с памятью 165 быть установлен в правильное значение. Для поисковых таблиц большого размера это мо- жет представлять собой вызов. 7.3.2. Память данных 16F873A и специальные функциональные регистры Карта памяти данных 16F873A/874A, включая все специальные функциональные ре- гистры, показана на рис. 7.6. Вид всех этих специальных функциональных регистров по- началу может привести к расстройству. Еще больше может расстроить мысль о том, что большая их часть содержит все 8 активных битов, каждый из которых имеет функцию, которую необходимо понимать. Однако, как и всегда, мы обнаружим, что тщательно орга- низованный подход обеспечит нам формирование хорошего понимания. Большинство этих СФР будут рассмотрены и использованы, в правильном контексте, на протяжении следу- ющих нескольких глав. Структурно память разделена на четыре банка, которые выбираются набором значений в разрядах 6 и 5 регистра состояния (см. рис. 7.3). 7-разрядный “прямой адрес” по рис. 7.2 формируется по любой из двух командных структур рис. 4.13. Он обеспечивает потенциал адресации 27 или 128 ячеек памяти, которые составляют каждый банк. Этот 7-разрядный адрес, конкатенированный с битами 6 и 5 регистра состояния, формирует 9-разрядный “Ад- рес оперативной памяти”, показанный на рис. 7.2 и эквивалентный “Адресу файла” по ри- сунку 7.6. Первые два банка памяти данных полностью используют свой диапазон памяти. Первый из них, например, размещает 32 специальных функциональных регистра и 96 яче- ек памяти общего назначения. Верхние два банка памяти в 16F873A/874A имеют ограни- ченное использование. В них отсутствуют ячейки памяти общего назначения, а большин- ство специальных функциональных регистров просто отображаются в эти банки из других банков памяти. Посмотрите внимательно на рис. 7.6. Какие специальные функциональ- ные регистры являются уникальными для банков 3 и 4. Перечислите их. 7.3.3. Слово конфигурации Слово конфигурации микроконтроллеров семейства PIC .16 определяет некоторые из программируемых возможностей микроконтроллера, которые могут быть изменены толь- ко тогда, когда устройство программируется. Слово конфигурации 16F87XA показано в обобщенной форме на рис. 7.7. Оно позволяет оценить некоторые из основных возможно- стей микроконтроллера. С младшими 4 разрядами, а также со старшими, мы уже знакомы по слову конфигурации для 16F84A (см. рис. 2.6). Два “новых” операционных режима — внутрисхемное программирование и внутрисхемная отладка — разрешаются через слово конфигурации, как и новая функция гибкой кодовой защиты, а также функция распознава- ния частичной потери питания, разрешаемая битом BOREN. Эти функции описаны в по- следующих подразделах. 7.4. “Специальные” операции с памятью Стандартный микроконтроллер читает команды из энергонезависимой памяти програм- мы и использует энергозависимую оперативную память для сохранения временных данных. С появлением флеш-памяти различия между традиционными использованиями памяти сни- жаются. Это происходит потому, что технология флеш-памяти энергонезависима и, сле- довательно, используется для памяти программы. Однако она может очень легко перезапи- сываться, поэтому появляется искушение использовать ее и для других видов памяти. Вследствие использования технологии флеш-памяти, 16F87XA позволяет — с неко- торыми ограничениями — осуществлять запись в память программ во время выполнения
166 Глава 7. Большие системы и PIC® 16F873A программы. Этот микроконтроллер также допускает, в случае необходимости, последо- вательное программирование памяти программ уже в то время, когда интегральная мик- росхема установлена по месту своего использования. Естественно, он также обеспечивает возможность доступа к памяти данных ЭСППЗУ через специальные управляющие регист- ры. Именно эти функции памяти рассматриваются в данном подразделе. Адрес файла Адрес файла Адрес файла Адрес файла Косвенный адрес f) QQh Косвенный адрес И ggg Косвенный адрес ЮОЛ Косвенный адрес П j ggg TMRO 01 h OPTION_REG 81h TMRO 101h OPTION_REG 181h PCL 02h PCL 82h PCL 102h PCL 182h STATUS 03h STATUS 83h STATUS 103h STATUS 183h FSR 04 h FSR 84h FSR 104h FSR 184h PORTA 05h TRISA 85h 105h 185h PORTB 06h TRISB 86h PORTB 106h TRISB 186h PORTC 07h TRISC 87h 107h 187h PORTD® 08h TRISD® 88h 108h 188h PORTE® 09h TRISE® 89h 109h ________ 189h PCLATH OAh PCLATH 8Ah PCLATH 1OAh PCLATH 18Ah INTCON OBh INTCON 8Bh INTCON 1OBh INTCON 18Bh PIR1 OCh PIE1 8Ch EEDATA 1OCh EECON1 18Ch PIR2 ODh PIE2 8Dh EEADR 1ODh EECON2 18Dh TMR1L OEh PCON 8Eh EEDATH 1OEh Reserved^ 18 Eh TMR1H OFh 8Fh EEADRH 1OFh Reserved® 18Fh T1CON 10h 90h . noh 190h TMR2 11 h SSPCON2 91 h T2CON 12h PR2 92h SSPBUF 13h SSPADD 93h SSPCON 14h SSPSTAT 94h CCPR1L 15h 95h CCPR1H 16h 96h CCP1CON 17h 97h RCSTA 18h TXSTA 98h TXREG 19h SPBRG 99h RCREG 1Ah 9Ah CCPR2L 1Bh ' ’ 9Bh CCPR2H iCh CMCON 9Ch CCP2CON 1Dh CVRCON goh 'О tгй ADRESH 1Eh ADRESL gEh ADCONO 1Fh ADCON1 9Fh 120h 1AOh 20h AOh Регистр Регистр общего общего назначения назначения Доступ Доступ 20h-7Fh AOh - FFh 96 байт 96 байт 16Fh 1EFh 170h 1F0h 7Fh FFh 17Fh 1FFh БанкО Банк1 Банк 2 БанкЗ Ш нереализованные ячейки памяти, считываются как 0; * не является физическим регистром. Примечания: 1. Эти регистры не реализованы в PIC16F873A. 2. Эти регистры зарезервированы; они должны быть пустыми. Рис. 7.6. Карта регистров файлов PIC 16F873A/874A
7.4. “Специальные” операции с памятью 167 R/P-1 U-0 R/P-1 R/P-1 R/P-1 R/P-1 R/P-1 R/P-1 U-0 U-0 R/P-1 R/P-1 R/P-1 R/P-1 СР DEBUG WRT1 WRTO CPD LVP BOREN явив PWRTEN WDTEN Fosci FoscO разряд 13 разряд О Разряд 13 Разряд 12 Разряд 11 Разряды 10-9 СР: бит кодовой защиты флеш-памяти программы Не реализован: читается как “1” DEBUG: бит режима внутрисхемного отладчика WRT1, WRT0: биты разрешения записи во флеш-память программы Эти биты определяют, какие секции памяти программы могут записываться во время выполнения программы: WRT1 :WRT0 P1C16F876A/877A PIC16F873A/874A Эта область защищена от записи Эта область может записываться Эта область защищена от записи Эта область может записываться 11 никакая вся никакая вся 10 от 0000h до OOFFh от 0100h до 1 FFFh от 0000h до OOFFh от 0100h до OFFFh 01 от 0000h до 07FFh от 0800h до 1 FFFh от 0000h до 03FFh от 0400h до OFFFh 00 от ООООбдо OFFFh от 1000h до 1 FFFh от 0000h до 07FFh от 0800h до OFFFh Разряд 8 Разряд 7 CPD: биг кодовой защиты памяти данных ЭСППЗУ LVP: бит разрешения низковольтного внутрисхемного последовательного программирования (один источник питания) Разряд 6 Разряды 5-4 Разряд 3 Разряд 2 Разряды 1-0 BOREN: бит разрешения сброса по частичной потере питания Не реализованы: читаются как “Г PWRTEN: бит активирования таймера включения питания WDTEN: бит активирования сторожевого таймера FOSC1, FOSCO: биты выбора генератора. 11= RC, 10 = HS, 01 = XT, 00 = LP. Примечание: стертое состояние всех битов соответствует логической 1. Рис. 7.7. Слово конфигурации PIC 16F87XA 7.4.1. Осуществление доступа к ЭСППЗУ и памяти программ Способность записывать в память программ, как уже упоминалось, управляется уста- новками битов WRT1 и WRT0 в слове конфигурации. Имеет смысл вернуться к рис. 7.7 и еще раз посмотреть на это слово. Можно заметить, что упомянутые биты разрешают дос- туп для записи к различным блокам памяти программы. Взаимодействие с памятью программы выполняется через те же самые регистры дан- ных и адресов, которые используются для ЭСППЗУ (EEDATA и ЕЕ ADR) — они были описаны в подразделе 2.4. Однако эти регистры всего лишь 8-ми разрядные, а память про- грамм содержит 14-разрядные слова. Кроме того, требуется 13-разрядный адрес для того, чтобы обратиться ко всем 8К слов (в 16F876A и ‘877А), или же 12 разрядов, чтобы обра- титься к 4К слов (в 16F873A и ‘874А). Поэтому к каждому значению EEDATA и ЕЕ ADR добавляется регистр “старшего байта”. Эти дополнительные регистры называются, соответ- ственно, EEDATH и EEADRH и используются только для доступа к памяти программы. Схема записи в память программ и ЭСППЗУ показаны на рис. 7.8, при этом память про- грамм изображена в верхней части схемы, а ЭСППЗУ — в нижней. Регистровая пара, сфор- мированная EEADRH и EEADR, адресует память программ, в то время как один регистр ЕЕ ADR адресует ЭСППЗУ. Ситуация подобна передаче данных в/из памяти программ при помощи EEDATH и EEDATA, при этом один регистр EEDATA используется при работе с памятью данных ЭСППЗУ. Если разрешается доступ для записи к секции памяти программ, то одновременно дол- жны записываться блоки из четырех слов. Считывание одного слова, однако, возможно. Все операции передачи данных управляются регистром EECON1, который показан на рис. 7.9. Сразу можно увидеть, что самый старший разряд этого регистра управляет тем, будет ли осуществляться доступ к ЭСППЗУ или же к памяти программ. Другие разряды
168 Глава 7. Большие системы и PIC® 16F873A подобны тем, которые приведены на рис. 2.7 и, следовательно, вам знакомы. Главное раз- личие, однако, заключается в том, что разряд флага прерывания EEIF был перемещен и теперь находится на регистре PIR2 (см. рис. 7.13). Память данных ЭСППЗУ Рис. 7.8. Запись в память программ и ЭСППЗУ R/W-x U-0 U-0 U-0 R/W-x R/W-0 R/S-0 R/S-0 EEPGD WRERR WREN WR RD разряд 7 разряд О разряд 7 EEPGD: бит выбора ЭСППЗУ программы/данных 1 = доступ к памяти программы О = доступ к памяти данных Считывается 0 после POR; этот бит не может быть изменен во время выполнения операции записи. разряды 6-4 Не используются: считывается О разряд 3 WRERR: бит флага ошибки ЭСППЗУ 1 = операция записи завершена преждевременно (MCLR или сброс WDT в течение нормальной работы) 0 = операция записи О = операция записи завершена разряд 2 WREN: бит разрешения записи ЭСППЗУ 1 = разрешение циклов записи О = запрет записи в ЭСППЗУ разряд 1 WR: бит управления записью 1 = инициализирует цикл записи. Бит очищается аппаратно по завершении цикла записи. Бит WR программно может только устанавливаться (не сбрасываться) О = цикл записи в ЭСППЗУ завершен разряд О RD: бит управления чтением 1 = инициализирует готовность ЭСППЗУ; RD Бит очищается аппаратно. Бит RD программно может только устанавливаться (не сбрасываться) О = чтение ЭСППЗУ не инициализируется Рис. 7.9. Регистр EECON1
7.4. “Специальные” операции с памятью 169 Доступ к ЭСППЗУ и памяти программ на самом деле не столь уж прост и требует ос- торожности в обеспечении правильной последовательности действий. Так, запись требует выдачи в виртуальный регистр EECON2 кода 55н, за которым должен следовать код ААц. Это повышает безопасность процесса, имея целью предотвращение возможности случай- ной записи. Если бит СР слова конфигурации очищен, то невозможно осуществлять внешнее считы- вание из памяти программ, например при использовании программатора типа PICSTART® Plus. Это защищает интеллектуальную собственность разработчика или изготовителя изде- лия. Этот бит, однако, не воздействует на внутренний доступ к памяти программ. Подоб- ные особенности относятся и к памяти ЭСППЗУ, которая защищена от внешнего доступа битом CPD слова конфигурации. 7.4.2. Внутрисхемное последовательное программирование (ICSP™) Все микроконтроллеры 16F87XA могут программироваться, будучи установленными по месту. Это имеет большое значение. В среде разработки это означает, что тестовые про- граммы могут быть загружены в микроконтроллер, уже установленный в целевую систему, без необходимости вынимать его и помещать в программатор. В промышленной обста- новке это свойство позволяет программировать микроконтроллер, установленный по мес- ту использования и непосредственно перед тем, как изделие покинет предприятие-изгото- витель. Как результат, всегда имеется возможность записывать самые последние версии программного обеспечения. А если изделие уже находится в эксплуатации, то упомянутое свойство делает возможным осуществлять обновление программ через Internet и, в прин- ципе, даже без уведомления пользователя по конкретному случаю! Недостаток внутрисхемного программирования заключается в том, что некоторые штырьки должны быть выделены для этой функции или, по крайней мере, должны быть тщательно спроектированы для двойного назначения таким способом, чтобы нормальная работа штырька не препятствовала бы, в случае необходимости, функции программирова- ния. ICSP использует штырьки, показанные в табл. 7.1. АУСМ Derbot также использует ICSP — мы далее еще увидим, как эта функция вписана в схему. В обычном режиме программирования высокое напряжение, приблизительно равное 13 В, подается на штырек MCLR. Однако специальный вид ICSP обходится без этого, отно- сительно высокого напряжения. Он называется “Низковольтным режимом программиро- вания” (LVP). Этот режим разрешается битом LVP в слове конфигурации — он позволяет программировать память с использованием только нормального напряжения электропита- ния Vdd. Недостаток этого режима заключается лишь в том, что должен использоваться дополнительный штырек — RB3, как это отмечено в табл. 7.1. Данный штырек использу- ется только для активации соответствующего режима и выхода из него. Кроме аппаратных межсоединений, ICSP требует использования очень специфичного программного обеспечения для последовательной передачи данных в микроконтроллер. Далее этот вопрос не рассматривается, однако полная информация может быть найдена в соответствующей документации на устройство. Табл. 7.1. Штырьки, используемые при внутрисхемном последовательном программировании Штырек Описание RB3 Вход сигнала управления в режиме низковольтного программирования (бит конфигурации LVP в состоянии логической 1) RB6 Вход тактовой частоты RB7 Ввод/вывод данных MCLR Выбор режима программирования, подключение напряжения программирования Vdd Электропитание Vss Земля
170 Глава 7. Большие системы и PIC 16F873A 7.5. Прерывания в 16F873A 7.5.1. Структура прерываний Будучи членом семейства микроконтроллеров PIC 16, 16F873A, как ожидается, впи- шется в структуру этого семейства. Местами эта проектная стратегия работает хорошо, однако в ряде случаев она демонстрирует и ограничения семейства 16. Пример этого — структура прерываний 16F873A, показанная на рис. 7.10. Здесь мы видим минимальную структуру 16F84A (см. рис. 6.2), находящуюся в правой части схемы. Прерывание завер- шения записи ЭСППЗУ заменено, однако, линией, возникшей в результате повышенных требований для “большого” микроконтроллера — к этой линии подключены не менее 11 дополнительных источников прерывания. Все они, в конечном счете, подключаются через один вектор прерывания, с которым мы уже знакомы, — он показан в карте памяти про- грамм, приведенной на рис. 7.4. | Запись ЭСППзГ} Параллельный подчиненный PSP1F(1) порт PSPIE(1) АЦП порт Приам УСАПП RCIF. RCIE [внешнее прерывание! \[ ТаЙмерО | TMR0IF TMR0IE Синхронный последовательный порт {ведущий) [Таймер 2 [сбор данных/сравнение 21)------------- [Конфликт на шине)^]^ )----------------- —i ~CMIF ч I Компаратор jcMiE -|_J--------------- | Передача УСЛПП | ™е SSPIF SSPIE [Сборданных/сравнение 1| £££} PEIE GIE Изменение порта В RBIF RBIE Активирование периферийного устройства Активирование (если ЦП -► в режиме бездействия) Примечание: PSP-прерывание реализовано только в устройствах PIC16F874A/877A Рис. 7.10. Структура прерываний в PIC 16F87XA (дополнительные метки в затененных полях добавлены автором) 7.5.2. Регистры прерываний При наличии 15 источников прерываний, один регистр INTCON, представленный на рис. 6.3 для меньших моделей микроконтроллеров семейства 16, может теперь содержать только малую часть от всего числа флагов и битов разрешения. Его версия для 16F87XA показана на рис. 7.11. По существу он остался без изменений, за исключением того, что бит EEIE (разрешение сигнала окончания записи в ЭСППЗУ) заменен битом PEIE, показан- ным на рис. 7.10. PEIE — бит разрешения прерывания от периферийных устройств, дей- ствует как вспомогательный сигнал глобального разрешения, стробируя через логический элемент “И” магистраль прерываний от всех источников прерываний. Он будет установ- лен в 1, если должно использоваться любое из “магистральных” прерываний.
7.5. Прерывания в 16F873A 171 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-x GIE PEIE TMR0IE INTE RBIE TMROIF INTF RBIF разряд 7 разряд О разряд 7 GIE: бит глобального разрешения прерывания 1 = разрешаются все немаскированные прерывания О = запрещаются все прерывания разряд 6 PEIE: биг разрешения прерываний от периферийных устройств 1 = разрешаются все немаскированные прерывания от периферийных устройств О = запрещаются все прерывания от периферийных устройств разряд 5 TMR0IE: бит разрешения прерывания по переполнению TMR0 1 = разрешается прерывание от TMR0 О = запрещается прерывание от TMR0 разряд 4 INTE: бит разрешения внешнего прерывания RB0/INT 1 = разрешается внешнее прерывание RB0/INT О = запрещается внешнее прерывание RB0/INT разряд 3 RBIE: бит разрешения прерывания по изменению порта RB 1 - разрешается прерывание по изменению порта RB О = запрещается прерывание по изменению порта RB разряд 2 TMR0IF: биг флага прерывания по переполнению TMR0 1 = регистр TMR0 переполнился (должен быть очищен программно) О = регистр TMR0 не переполнялся разряд 1 INTF: бит флага внешнего прерывания RB0/INT 1 = имело место внешнее прерывание RB0/INT (должно быть сброшено программно) О = внешнее прерывание RB0/INT не возникало разряд О RBIF: бит флага прерывания по изменению порта RB 1 = по крайней мере, один из штырьков RB7:RB4 изменил свое состояние; состояние неопределенности может привести к продолжению установки бита. Считывание PORTB положит конец состоянию неопределенности и позволит очистить бит (должен быть очищен программно). О = ни один из штырьков RB7:RB4 не изменил свое состояние Рис. 7.11. Регистр INTCON PIC 16F87XA В дополнение к регистру INTCON введены четыре новых специальных функциональ- ных регистра — PIE1 и PIE2, которые содержат биты разрешения, размещенные в банке памяти 1, а также PIR1 и PIR2, которые содержат биты флагов, находящиеся в банке па- мяти 0. Они показаны на рис. 7.12 и 7.13 в обобщенном виде. Можно видеть, что регистры PIE1 и PIR1 имеют ту же структуру, что PIE2 и PIR2. Как можно было и ожидать, все активные биты сбрасываются в 0 при любой форме включения напряжения питания. разряд 7 разряд О PIE1 PIR1 (биты разрешения) (биты флагов) Переполнение таймера 1 TMR1IE TMR1IF* Переполнение таймера 2 TMR2IE TMR2IF* Сбор данных/сравнение 1 CCP1IE CCP1IF* Синхронный последовательный порт SSPIE SSPIF* Передача USART TXIE TXIF Прием USART RCIE RCIF Аналого-цифровой преобразователь ADIE ADIF Чтение/запись параллельного PSPIE PSPIF* подчиненного порта” * е г * должен очищаться программным способом ** только для 16F874/7. В16F873/6 зарезервирован Рис. 7.12. Регистры PIE1/PIR1 в 16F87XA (Разрешение/Запрос прерываний от периферийных устройств)
vn Глава 7. Большие системы и PIC® 16F873A разряд 7 разряд О PIE2 (биты разрешения) 1.Сборданных/сравнение2 CCP2IE _______Нереализован _______Нереализован _______Коллизия шины _______Запись ЭСППЗУ _______Нереализован _______Компаратор _______Нереализован Считывается как О Считывается как О BCLIE EEIE Считывается как О CMIE Считывается как О PIR2 (биты флагов) CCP2IF Считывается как О Считывается как О •BCLIF EEIF* Считывается как О CMIF* Считывается как О ‘должен очищаться программным способом Рис. 7.13. Регистры PIE2/PIR2 в 16F87XA 7.5.3. Идентификация прерываний сохранение контекста Если разрешен более чем один источник прерывания, то программа обслуживания пре- рывания должна будет в своем начале включать программную секцию, идентифицирую- щую, какой именно источник вызвал прерывание. Это в точности подобно случаю 16F84A, и принципы проиллюстрированные примером программы 6.2 могут с успехом применять- ся для того, чтобы удовлетворить эту потребность. Когда дело доходит до сохранения контекста, то 16F87XA вновь действует подобно 16F84A, сохраняя в стеке только адрес возврата, когда вызывается программа обслужива- ния прерывания. В область ответственности программиста входит сохранение при запуске программы обслуживания прерывания любых других регистров, которые необходимы, — обычно это регистр W и регистр состояния. Программист же должен обеспечить восста- новление этих регистров по завершении выполнения программы обслуживания прерыва- ния. Пример программы 6.4 может быть адаптирован для этих целей. 7.6. Генератор в 16F873A, сброс и электропитание 7.6.1. Генератор синхроимпульсов 16F87XA имеет точно ту же структуру генератора и диапазон опций, как и 16F84A, описанный в подразделе 3.5. Тип генератора выбирается, опять-таки, установками битов в слове конфигурации (рис. 7.7). Сейчас же может оказаться интересным посмотреть на рис. 7.19 и его сопроводительное описание, чтобы увидеть фактические осциллограммы сигналов генератора. 7.6.2. Сброс и электропитание Структура прохождения сброса подобна таковой в 16F84A (рис. 2.10), за исключением того, что был добавлен новый источник — сброс по частичной потере питания. Частичная потеря питания — это существенное падение напряжения питания. Такая форма потери мощности особенно опасна, потому что она может проходить незамеченной. Часть схемы или системы может продолжать нормально работать, в то время как другая ее часть может временно отказать или же потерять данные. Этот сброс предназначен для того, чтобы га- рантировать, что устройство полностью приведено в исходное состояние, если произошла частичная потеря питания. Этот сброс разрешается битом BOREN слова конфигурации.
7.7. Параллельные порты в 16F873A 173 Если BOREN установлен в 1 и произошла частичная потеря питания, то микроконтроллер принудительно сбрасывается. В спецификациях на рассматриваемые устройства указыва- ется уровень 4 В, как типичное напряжение, которое запускает эту форму сброса. Во всем остальном 16F87XA имеет требования к электропитанию, почти идентичные требованиям 16F84A, отображенным на рис. 3.16. Различие заключается лишь в том, что теперь мини- мальное рабочее значение напряжения питания четко определено активированием сброса по частичной потере питания, если этот сброс разрешен. При наличии множественных источников сброса, которые теперь доступны, может ока- заться полезным знать при программировании, какая форма сброса отрабатывалась самой последней. Сброс сторожевого таймера индицируется битом ТО регистра состояния (см. рис. 7.3). Дальнейшая информация обеспечивается битами POR и BOR регистра PCON (который не имеет других активных битов). Первый из них устанавливается в 0, если про- изошел сброс по включению электропитания, второй — если произошел сброс по частич- ной потере питания. 7.7. Параллельные порты в 16F873A Как можно видеть на рис. 7.2, PIC 16F873A имеет три порта: А, В и С. Порты А и В подобны портам 16F84A, за исключением того, что большее количество альтернативных функций поставлено в соответствие их штырькам. При этом порт А теперь 6-разрядный — на 1 разряд больше, чем 5-разрядный порт А в 16F84A. При сбросе все разряды порта устанавливаются на ввод. Выходные характеристики штырьков портов 16F87XA для на- пряжения питания, равного 5 В, показаны на рис. 7.14. Можно показать, придерживаясь той же процедуры, что и в подразделе 3.4.3, что “типичное” выходное сопротивление для логической единицы будет равно приблизительно 430 Ом, а для логического нуля — 22 Ома. Далее характеристики выводов портов будут рассматриваться по очереди. 7.7Л. Порт Ав 16F873A 6 разрядов порта А выведены на штырьки 2-7 16F873A, как можно видеть на рис. 7.1. Стоит также еще раз ознакомиться со списком обозначений, приведенным на рис. 7.1, чтобы выработать представление о разводке штырьков. Порт А может использоваться для универсальной двунаправленной передачи цифровых данных. Он также разделяется ана- логовыми функциями, а именно — модулем аналого-цифрового преобразователя (АЦП) и компараторами. Хотя обе эти функции мы будем рассматривать в Главе 11, очень важно обратить внимание на то, что после включения электропитания разряды данного порта устанавливаются как аналоговые входы. С целью использования данного порта для циф- рового информационного обмена, регистр ADCONO, описываемый в Главе 11, должен быть установлен соответствующим образом. Как и в случае с 16F84A, важный вход от таймера 0 управляется разрядом 4 порта А. Две схемы управления штырьками порта А показаны на рис. 7.15. Их полезно сравнить с эквивалентными схемами в 16F84A, показанными на рис. 3.11. При увеличенных функ- циональных возможностях большинства штырьков, интересно видеть, как периферийные устройства, совместно использующие штырьки, начинают “вторгаться” в схему управле- ния штырьком. Простой пример приведен на рис. 7.15 (а). Этот рисунок почти повторяет рис. 3.11 (а), за исключением того что АЦП периферийного устройства через линию “Ре- жим аналогового входа” может отключать цифровой вход порта. Более экстремальный слу- чай иллюстрируется рис. 7.15 (Ь). Здесь в линии цифрового вывода присутствует мульти- плексор. Теперь периферийное устройство, в данном случае схема компаратора, может отключать нормальный выход порта и использовать эту линию для своих собственных це- лей. В данном случае штырек микроконтроллера может быть сконфигурирован как выход компаратора 2 (C2OUT), а не как выход разряда порта.
174 Глава 7. Большие системы и PIC 16F873A (а) (Ь) lOL (-mA) Рис. 7.14. Выходные характеристики портов PIC 16F87XA: (а) — типичная Voh от IOh (Vdd = 5 В, от -40 до 125°С); (Ь) — типичная Vol от IOl (VDd = 5 В, от -40 до 125°С) Схема управления штырьком 4 не показана. Она основана на схеме по рис. 3.11 (Ь), од- нако в выходной линии к ней добавлена цепь мультиплексора, как это было описано для компаратора 1. Он держит в открытом состоянии выход стока по рис. 3.11 (Ь). В этом исследовании схем управления штырьками имеется один важный момент: штырьки портов управляются не только регистрами портов TRIS. Ряд специальных функ- циональных регистров также могут оказывать значительное влияние, отключая или пере- распределяя ресурсы. Это может привести к значительному усложнению программирования.
7.7. Параллельные порты в 16F873A 175 Так, например, может оказаться, что порт А не работает потому, что установки специаль- ного функционального регистра периферийных устройств перераспределили его функции. Берегись, программист! (а) (Ь) voo Сигнал записи в порт Сигнал записи в TRIS Штырек ввода/ вывода'' Шина Триггер данных данных ' Входнг й Триггер TRIS Режим аналогового входа Сигнал чтения из TRIS Сигнал чтения из порта На АЦП или компаратор Примечание. Штырьки ввода/вывода имеют диодную защиту no Voo и Vss Мультиплексор в выходной цепи выбирает источник данных CMCQN<2:0> - о 11_ог1_О1 C2OUT_________ГЪо— Шина данных Сигнал записи впорт Сигнал записи в TRIS АЦП или вход SS ►с к4-а Триггер данных —lb Q Штырек ввода/вывода' -►СК’’-Q Сигнал чтения из порта Сигнал чтения из TRIS Режим аналогового vss входа _|___ Триггер TRIS - D Q Примечание. Штырьки ввода/вывода имеют диодную защиту по Voo и Vss Входной «Р Периферийные устройства I могут блокировать 1 входы порта I Рис. 7.15. Выходные характеристики порта A PIC 16F87XA: (а) — штырьки RA0, 1,2 и 3; (Ь) — штырек RA5 (дополнительные метки в затененных полях добавлены автором) 7.7.2. Порт В в 16F873A Назначение выводов порта В в 16F873A (выводы 21-28) показано на рис. 7.1. Он ос- тается простым портом, почти идентичным одноименному порту 16F84A. Используемые схемы управления штырьками являются фактически теми же, как показанные на рис. 3.10 для 16F84A. Как можно видеть из рис. 7.1 и табл. 7.1, разряды 3, 6 и 7 используются для внутрисхемного последовательного программирования (ICSP). Если должно использовать- ся ICSP, то разработчик или не должен применять соответствующие штырьки для любых иных целей, или применять их так, чтобы они оставались доступными для функции ICSP. 7.7.3. Порт С в 16F873A Назначение выводов порта С в 16F873A (выводы 11-18) также показано на рис. 7.1. Это наиболее сложный из портов 16F873A. Его штырьки могут просто использоваться для цифрового ввода-вывода общего назначения. Интересно, что все его входы теперь имеют характеристики триггера Шмитта. Помимо универсального цифрового ввода-вывода, штырь- ки порта С совместно используются некоторыми из более сложных периферийных уст- ройств микроконтроллера, включая устройства, связанные с организацией последователь- ной связи. Электрические схемы контуров управления штырьками порта С приведены на рис. 7.16. Можно заметить, что в основе обоих из них все еще лежит функция порта стандартного цифрового ввода-вывода, которую мы видели в простых схемах управления штырьками в 16F84A. Помимо этого в выходной цепи добавлен мультиплексор, как мы это видели для порта А. Также добавлена возможность, связанная с тем, что периферийные устройства
176 Глава 7. Большие системы и PIC® 16F873A теперь могут брать на себя функцию регистра TRIS через линию Periferal ОЕ (Разреше- ние выхода от периферийного устройства) и логический элемент ИЛИ, которым она управ- ляет — это отмечено на электрической схеме. Последняя модификация стандартной схе- мы управления штырьком порта показана на рис. 7.16 (Ь). Вследствие того, что SMBus (системная управляющая шина) имеет определенные входные характеристики, теперь име- ются альтернативные входные пути — один со стандартным входом на триггере Шмитта и другой — с характеристиками SMBus. Это еще не конец увеличения сложности после- довательного ввода-вывода. На этих штырьках имеется (не отраженная на рис. 7.15 (Ь), но доступная в случае необходимости) возможность формирования полного интерфейса вво- да-вывода в соответствии со стандартом последовательной межсхемной связи 12С. Этот стандарт мы будем рассматривать чуть позже — он иллюстрируется рис. 10.19. (Ь) Разрешение вывода от Выбор порта/периферийного устройства® грийного устройства Vdd Шина данных. ►CK\_Q Запись в порт Триггер данных Запись в TRIS - ►СК“Ч_О Триггер TRIS Чтение TRIS D Q D Q Штырьки ввода/ вывода11' Периферийное устройство может JZT подавить настрой- Lp ки регистра TRIS vdo вывода от периферийного устройства!3) Чтение порта Ввод данных от периферийного устройства Примечания: Штырьки ввода/вывода имеют диодную защиту по Voo и Vss. Сигнал выбора порта/периферийного устройства выбирает между данными порта и выходом периферийного устройства. Сигнал разрешения вывода от периферийного устройства активиру- ется, если только активен сигнал выбора периферийного устройства. 2. 3. Выбор порта/периферийного устройства® Вывод данных от .] периферийного устройства \ Шина данныхR" Q •СК'-Q - ьскЧ-О Триггер TRIS Запись в TRIS Чтение TRIS Штырьки ввода/ вывода11 Чтение порта 2. 3. Триггер Шмитта СКЕ SSPSTAT<6> Триггер Шмитта с уровнями SMBus ЗаписЁ в порт Разрешение Триггер данных BxoflSSP Примечания: 1. Штырьки ввода/вывода имеют диодную защиту по Voo и Vss. * Сигнал выбора порта/периферийного устройства выбирает между данными порта и выходом периферийного устройства. Сигнал разрешения вывода от периферийного устройства активируется, если только активен сигнал выбора периферийного устройства. Мультиплексор выбирает входные характеристики разряда порта Рис. 7.16. Блок-схема контуров управления штырьками порта С: (а) — штырьки от RC7 до RC5, от RC2 до RC0; (Ь) — штырьки RC4 и 3 (дополнительные надписи в затененных полях добавлены автором) 7.8. Инструментальные средства тестирования, диагностики и ввода в эксплуатацию Поскольку мы двигаемся в сторону явно более сложного семейства микроконтролле- ров, отсюда следует, что мы будем разрабатывать более сложные системы. Следовательно, необходимо уделить время рассмотрению того, как мы будем тестировать и вводить в экс- плуатацию такие системы. В следующих подразделах будет проанализировано оборудова- ние и методы, которые могут использоваться для таких целей, и которые будут применять- ся по мере того, как мы будем разрабатывать проект АУСМ Derbot.
7.8. Инструментальные средшва тестирования, диагностики и ввода в эксплуатацию 177 7.8.1. Вызов, связанный с тестированием встроенной системы В подразделе 4.1.3 был рассмотрен процесс разработки программы, который включает использование программного имитатора. Однако, когда программа загружается в аппарат- ные средства, то круг наших проблем может значительно расшириться. Это особенно отно- сится к случаю, когда как аппаратные средства, так и программы не прошли тестирование. В этом случае разработчик может оказаться в неудачном положении, в котором иногда оказываются почти все разработчики встроенных систем, — он сталкивается с полностью неработающей системой, при отсутствии гипотез относительно того, в чем заключается проблема. В общем случае в ходе процедуры тестирования разработчик может сталкиваться с двумя типами проблем: • Проектные проблемы. Это проблемы, связанные с конструкцией аппаратных средств или проектом программы, они приводят к частичной или полной нефункциональности системы. • Проблемы реализации. Они связаны со способом, которым реализуется проект, кото- рый сам по себе может быть совершенно хорошим. В крут этих проблем могут входить разрушенные печатные проводники на плате, некачественная выгрузка программы либо невыполнение установки разрядов конфигурации в процессе выгрузки программы. Эти проблемы могут также приводить к частичной или полной нефункциональности системы. Названные типы проблем могут иметь одни и те же симптомы, однако очень важно уметь их отличать, поскольку решение для каждого типа проблемы может быть совершенно другим. Давайте, следовательно, попытаемся установить иерархию ввода системы в действие — с тем, чтобы мог быть разработан системный подход к тестированию и вводу ее в экс- плуатацию. На рис. 7.17 неформальным способом показаны уровни взаимозависимости, которые существуют между разными компонентами встроенных систем. В общем случае в ходе процедуры тестирования отрабатывается перемещение из нижней части показанной схемы к ее верхней части. Если автомобиль не будет иметь бензина, то он не поедет. Ана- логичным образом, если микроконтроллер не имеет правильного электропитания, он не будет работать, однако при этом программа и схемы могут быть в полном порядке. Он не будет также работать ни под каким видом, если, например, не функционирует тактовый генератор или активен штырек сброса (MCLR для PIC) или же если программа не была правильно загружена. Как только эти четыре необходимых условия удовлетворены, есть шанс, что программа начнет выполняться. Если система полностью неактивна, то пере- численные состояния должны контролироваться в первую очередь. Наиболее вероятно, что отказы, связанные с перечисленными состояниями, имеют своей причиной реализацию, — например, или некачественная запайка кварцевого генератора в печатную плату, или неправильная загрузка программы, произошедшая по какой-либо причине. Как только эти фундаментальные условия были удовлетворены, применяется следую- щий набор условий, если система работает непрерывно и демонстрирует умеренный уро- вень функциональных возможностей. Как отмечено на схеме, эти условия включают на- дежные схемные и программные проекты, правильную сборку аппаратных средств, а также надлежащее, в соответствии с ситуацией, конфигурирование периферийных устройств. Здесь слово “надежный” используется в том смысле, что проект не имеет фатальных де- фектов, хотя он может иметь некоторые черты, нуждающиеся в доработке. Когда назван- ные условия выполнены, система должна приближаться к стадии оптимизации. Теперь она должна демонстрировать хороший уровень функциональных возможностей, хотя все еще не идеальный в некоторых областях. Вероятно, что с этого момента все последующие тесты будут сопровождаться продолжающейся пошаговой доработкой проекта, которая может быть связана как с аппаратными, так и программными средствами. И, наконец, мы
178 Глава 7. Большие системы и PIC 16F873A вправе ожидать, что увидим систему, функционирующую в полном соответствии с ожида- емым уровнем эффективности. Система не функционирует вообще Рис. 7.17. Уровни зависимости во встроенной системе Итак, при понимании уровней зависимости во встроенной системе, как процедура тес- тирования должна быть реализована, если базисные тесты индицируют, что состояние нижнего уровня, согласно рис. 7.17, было пройдено? На практике идентифицируются три “золотых правила” тестирования. Вот они: • Разделяй и властвуй. Разделите систему — как аппаратные средства, так и программу — на модули или подсистемы, которые могут быть изолированы друг от друга в мак- симально возможной степени, и тестируйте их раздельно. Затем система может быть вновь собрана вместе из “заведомо исправных” подсистем. • Виновен, пока не доказано противное. Не делайте никаких предположений относитель- но того, что какая-либо часть системы работает правильно, если только вы достовер- но не убедились, что так оно и есть. Другими словами, принимайте, что компоненты системы работают не правильно, пока не сможете подтвердить противоположное. Это полная противоположность судебному закону, который предполагает, что обвиняемый невиновен, пока не доказана его виновность. • Работайте систематически, все документируйте. Этот тезис можно расширить: о Планируйте процедуру тестирования таким образом, чтобы тестирование выпол- нялось в ясном и логическом порядке. Стартовая точка последовательности дей- ствий обозначена, в некотором смысле, на рис. 7.17. Всегда начинайте с нижней части схемы и двигайтесь вверх. о Используйте при работе только качественные документы, обновляйте их по мере необходимости. При работе со встроенной системой перед вами всегда должны лежать последние версии электрической схемы и листинга программы. Всегда. Убе- дитесь в этом по надписям. В пределах легкой досягаемости у вас должны быть
7.8. Инструментальные средства тестирования, диагностики и ввода в эксплуатацию 179 соответствующие спецификации (особенно на используемый микроконтроллер). Обновляйте схемы по мере необходимости. Убеждайтесь, что на каждой новой вер- сии указана дата ее пересмотра. о Записывайте результаты тестов. Важность этого возрастает по мере роста сложно- сти систем. На самом деле, при проведении серии тестов очень легко забыть, каков был результат одного из предшествующих. Какой бы хорошей не была ваша па- мять, через неделю или две вы все равно что-нибудь забудете. Вместе с результатом записывайте данные о версии схемы и программы, которые вы использовали. Чтобы добиться успеха в процессе тестирования, нам понадобятся инструменты, ко- торые позволят контролировать и наблюдать то, что происходит. Сейчас мы перейдем к рассмотрению ряда таких инструментов. 7.8.2. Осциллографы и логические анализаторы Осциллограф — наиболее мощный универсальный прибор, доступный в мире элек- троники. Он позволяет просто и приемлемо точно замерять напряжения и времена, осо- бенно, если изучаемые сигналы являются сигналами постоянного напряжения или носят периодический характер. Стандартный осциллограф значительно расширяет свои воз- можности, если к нему добавить память. В этом случае становится возможным исследо- вать апериодические сигналы или одиночные события с приемлемой простотой. Осцил- лограф имеет существенное значение в мире встроенных систем — он служит для ис- следования базисных условий электропитания, генераторов и простых видов активности портов. Располагая опытом и хорошим осциллографом, вы сможете их использовать для контроля и более сложных сигналов. Логический анализатор обладает некоторыми характеристиками осциллографа в том, что он также может отображать значение входного сигнала в зависимости от времени. Предполагается, однако, что входной сигнал логического анализатора носит цифровой характер, так что индикатор может отображать только одно из двух значений сигнала: ло- гический 0 или логическую 1. Применяемый порог определяется логическим анализато- ром и во многих приборах он является настраиваемым. Обычной характерной чертой логического анализатора является то, что он имеет много входов, например 16, 32 или 48. Таким образом, он может использоваться для контроля активности на шинах данных и/или адресов. Логические анализаторы обычно имеют широкий диапазон дополнительных воз- можностей, включая ЗУ, которое может сохранять историю изменения входных значений, а также сложные переключательные функции, которые позволяют идентифицировать оп- ределенные комбинации входных сигналов и инициализировать переключение. Логиче- ские анализаторы были наиболее популярны в те времена, когда системы собирались из большого количества интегральных схем и имелась потребность исследования активности шин. Теперь же во многих системах интегральные схемы очень сложны, а шины более вообще недоступны. Однако логические анализаторы могут все еще быть очень полезны при просмотре сложных цифровых процессов, например сигналов параллельных портов или последовательных потоков данных. Эта книга использует замечательный прибор, который объединяет возможности как осциллографа, так и логического анализатора. Это комбинированный осциллограф от фирмы Agilent модели 54622D, который показан на рис. 7.18. Он имеет два стандартных входа осциллографа и 16 входов логического анализатора. Любая комбинация входных сигналов может отображаться одновременно. Этот “осциллограф” имеет просто фанта- стический потенциал анализа сигналов и переключательных функций, кроме того он снабжен памятью. Реализованная в нем комбинация аналоговых и цифровых функций отражает смесь аналоговых и цифровых сигналов, характерную для большинства встроен- ных систем. Он, таким образом, представляет собой естественный прибор, предназначен- ный для проведения исчерпывающего диапазона тестов в среде встроенных систем.
180 Глава 7. Большие системы и PIC 16F873A Рис. 7.18. Комбинированный осциллограф фирмы Agiient модели 54622D, подсоединенный к Derbot Рис. 7.19. Осциллограммы 16F873A: (а) — RC-генератор, номинальная частота 1 МГц; (Ь) — кварцевый генератор, 4 МГц Два снимка экрана для случая контроля сигналов от генератора, подаваемых на анало- говые входы осциллографа Agilent, показаны на рис. 7.19. Как можно видеть из информа- ции на рамке экрана, вертикальный масштаб для обоих каналов (1 и 2) составляет 2 В/см, а горизонтальный масштаб равен 1 мкс/см. Две маленькие стрелки, появляющиеся слева на экране, указывают позицию опорного нулевого напряжения для каждой осциллограммы. Первый экран — это сигнал с RC-генератора, использующего схему по рис. 3.14 (Ь). Верхняя осциллограмма показывает вывод OSC1 микроконтроллера, т.е. точку соединения
7.8. Инструментальные средства тестирования, диагностики и ввода в эксплуатацию 181 REXT и СЕХТ. Видны кривые подъема напряжения при зарядке конденсатора через ре- зистор, за которыми следует быстрый разряд конденсатора, когда выход генератора на триггере Шмитта переключается в состояние логической 1. Как показывает рис. 3.14 (Ь), сигнал на штырьке OSC2 имеет частоту, равную Fqsc/4. Это видно на нижней осцилло- грамме. Номиналы компонент выбраны как RExt = 8,2 кОм и Сехт “ 100 пФ, они дают номинальную частоту генератора, равную 700 кГц (т.е. период, равный 1,43 мкс). Факти- чески же сигнал, как можно видеть, имеет период, близкий к 1,4 мкс (т.е. частота немного выше 700 кГц), а период Fqsc/4 равен 5,6 мкс. Это приемлемо хорошее соответствие с тем, что ожидается. Необходимо отметить, однако, что когда щуп осциллографа был уда- лен от штырька OSC1, то период Fqsc/4 упал до 5,0 мкс. Здесь мы видим некую ловушку, связанную с использованием осциллографа — щуп плюс вход осциллографа добавляют емкость (и сопротивление) нагрузки в проверяемую схему. Какое это имеет значение, за- висит от самой тестируемой схемы. В данном случае нагрузка приблизительно в 15 пФ помещается непосредственно в параллель Rext, увеличивая его значение более чем на 10 процентов! В данном случае само измерение внесло погрешность. Вторая осциллограмма относится к микроконтроллеру в режиме синхронизации HS, при котором используется кварцевый генератор с применением схемы по рис. 3.14 (а). Оба штырька микроконтроллера имеют подобные, приблизительно синусоидальные сигналы той же самой частоты. Каждый сигнал представляет собой инверсию другого. Можно ви- деть, что сигнал имеет отчетливый период, равный 125 нс, подтверждающий частоту в 4 МГц. 7.8.3. Внутрисхемные эмуляторы Осциллографы и логические анализаторы очень хороши для тестирования сигналов, которые доступны при работающей системе. Однако имеется много ситуаций, когда мы должны быть способными предпринять тот же самый вид тестов, который мы в Главе 5 выполняли с программным имитатором, например, протестировать специфические секции программного кода или пошагово выполнить программу, но теперь уже с программным кодом, выполняющимся в целевых аппаратных средствах. Решением в этом случае будет использование внутрисхемного имитатора (ICE). Это устройство, которое заменяет микроконтроллер в схеме, воспроизводя его действия на- столько близко, насколько это возможно, однако оставаясь связанным с хост-компьюте- ром. Хост-компьютер в данном случае имеет возможность контролировать выполнение программы почти тем же способом, которым это делает программный имитатор. Внутрисхемные эмуляторы олицетворяют один из наиболее мощных способов тести- рования и ввода в эксплуатацию встроенных систем. Однако они имеют и некоторые не- достатки: • Они являются очень сложным оборудованием и, следовательно, дороги; • Они только воспроизводят один тип микроконтроллера или процессора и в силу этого для каждого другого микроконтроллера нужен другой внутрисхемный эмулятор; • Имеются области, где их действие неидеально, например они обычно не очень хороши при воспроизведении работы микроконтроллера в терминах генератора синхроимпуль- сов, и они могут иметь требования по электропитанию, которые являются менее гиб- кими, чем требования самого микроконтроллера; • Они не позволяют полностью воспроизвести конечные рабочие условия системы — в конце концов, ведь вынут сам микроконтроллер. 7.8.4. Встроенные отладчики Учитывая преимущества ICE, а также их недостатки, было бы естественно для разра- ботчиков ИС спросить себя, не могут ли они встроить функции ICE в сам микроконтрол- лер. Ведь значительная часть ICE, в конце концов, является точной копией схемы самого
182 Глава 7. Большие системы и PIC 16F873A микроконтроллера. Таким образом, возник целый ряд встроенных тестовых средств. Фирма Motorola (теперь Freescale) использовала технологию фонового режима отладки (BDM), в то время как фирма Microchip использовала для этого термин внутрисхемный отладчик (ICD). Мы рассмотрим эти средства подробнее, поскольку сейчас они доступны на многих микроконтроллерах PIC, включая и 16F873A. Подход ICD имеет следующие преимущества'. • Тестирование выполняется без внесения искажений в целевую систему. • ICD может также работать как программатор, выгружая программный код в целевой микроконтроллер. • Подход ICD является более гибким - подключения, тестирование и последующая выгрузка могут выполняться как “на месте”, так и в проектной лаборатории. В то же время подход ICD имеет следующие недостатки: • Некоторые ресурсы микроконтроллера используются функцией ICD; в их состав вхо- дят несколько штырьков ввода-вывод а, часть памяти программ, а также другие внут- ренние ресурсы. • Целевой микроконтроллер и его тактовый генератор должны работать; • В общем случае ICD менее мощное устройство, чем полностью экипированная ICE- система. • Некоторые виды тестирования могут быть недостаточно совершенными. Например, когда работа микроконтроллера останавливается ICD, периферийные устройства мо- гут продолжать работать, что приводит к ошибочным результатам. 7.9. Внутрисхемный отладчик Microchip (ICD 2) Возможности системы Microchip ICD 2 иллюстрируются в схематической форме на рис. 7.20; хост-компьютер связан с целевой системой через специальный модуль адаптера или адаптерную приставку. Это видно на реальной системе, показанной на рис. 7.21, где адаптерная приставка ICD 2 показана подключенной к АУСМ Derbot. ICD управляется из хост-компьютера, который должен работать под управлением MPLAB®. Адаптерная при- ставка ICD 2 соединяется с хост-компьютером через кабель USB. Связь через RS232 мо- жет также использоваться. Она затем соединяется с целевой системой через другой кабель, имеющий пять подключений. Эти подключения показаны на электрической схеме, они те же, что и для ICSP (Внутрисхемное последовательное программирование), за исключением того, что штырек низковольтного программирования — разряд 3 порта В — не использу- • ется. Внутренние ресурсы микроконтроллера, необходимые ICD, также показаны на схе- ме, они включают часть памяти программ, память данных и стек. ICD 2 может использоваться как отладчик, в этом случае он может программировать микроконтроллер, в то же самое время выгружая свою собственную “операционную сис- тему отладки”, которая загружается в верхнюю часть памяти программ. Будучи запущен- ной из MPLAB, она может затем выполнять все функции имитатора MPLAB, описанного в Главах 4 и 5, с тем отличием, что теперь программа фактически выполняется в целевых аппаратных средствах. ICD 2 может также использоваться просто как программатор — в этом случае он копирует работу программатора, подобного PICSTART Plus и описанно- му в Главе 4. Режим работы выбирается из MPLAB. Нормальное использование ICD 2 в цикле разработки связано с загрузкой тестируемой программы в микроконтроллер с ICD в режиме отладки. Затем программа отлаживается, используя все средства ICD. Когда полностью функционирующая версия программы бу- дет сформирована, ICD переключается на режим отладчика. Затем программа выгружается снова, на этот раз без использования специальных функций отладчика, и микроконтроллер может работать в нормальном рабочем режиме. Использование ICD 2 будет описано в ходе простого Derbot-базированного практиче- ского занятия, излагаемого после описания первой сборки Derbot.
7.10. Применение 16F873A: АУСМ Derbot 183 Рис. 7.20. Система ICD 2 и ее потребности во внутренних ресурсах Рис. 7.21. Система ICD 2, подключенная к АУСМ Derbot 7.10. Применение 16F873A: АУСМ Derbot После описания, изложенного ранее в этой главе, сейчас мы рассмотрим то, как 16F873A применяется в практической ситуации, например в проекте АУСМ Derbot. Блок схема Der- bot приведена на рис. 1.5, а схема электрическая — на рис. АЗ. 1. Некоторые из особеннос- тей проекта и применения Derbot описаны в Приложении 4. 7.10.1. Источник электропитания, генератор и сброс Потребности в электропитании Derbot двояки — необходимо подать электропитание на электромотор и запитать схемы микроконтроллера и все связанные с ним датчики и ин- дикаторы. В то время как доступны низковольтные двигатели, работающие от 2 или 3 В, не так просто собрать необходимые переключательные схемы, работающие с этим напряже- нием. Эксперименты с несколькими электромоторами, однако, показали, что адекватный
184 Глава 7. Большие системы и PIC 16F873A вращающий момент и итоговая скорость вращения могут быть получены от электромотора, работающего от напряжения, приблизительно равного 9 В при приемлемом токе потребле- ния. Это напряжение хорошо подходит к доступным в настоящее время интегральным схе- мам электромоторных интерфейсов, подобным L293D, которая и была использована. Вто- рая потребность в электропитании связана со схемами микроконтроллера. В то время как соответствующий блок питания мог бы быть нестабилизированным, как в проекте электрон- ного пинг-понга, однако имеется ряд элементов, особенно фоторезисторов и отражатель- ных оптических датчиков, которые требуют устойчивых рабочих условий для получения правильных результатов. В силу этого был выбран стабилизированный источник питания. Таким образом, Derbot запитывается от шести щелочных аккумуляторных элементов размера “АА”, дающих общее номинальное напряжение 9 В. Это же напряжение исполь- зуется “сырым” для запитывания электромотора. Для запитывания микроконтроллера и связанных с ним схем данное напряжение доводится до уровня 5 В с использованием ма- ломощного стабилизатора напряжения LP2950 фирмы National Semiconductors. Правильная работа ряда системных элементов, например оптических датчиков, зависит от качества стабилизации этого напряжения. Поскольку в рассматриваемом приложении имеются требования по точной синхрони- зации, то был выбран кварцевый генератор; в качестве тактовой частоты была выбрана час- тота, равная 4 МГц, позволяющая сформировать простые функции временной привязки на базе результирующего периода командного цикла, равного 1 мкс. 7.10.2. Использование параллельных портов Как можно видеть, Derbot имеет обширные потребности во вводе-выводе, хотя не все они могут реализоваться в какой либо конкретной версии разработки. Они перечислены в табл. 7.2. Некоторые из них просто требуют использования параллельного ввода-вывода общего назначения. Другие же, как указывается, являются специальными функциями, ко- торые привязаны либо к конкретным периферийным устройствам, либо вводу-выводу через уникально идентифицируемые штырьки. Таким образом, эти функции сразу же привязы- ваются к соответствующим штырькам специального назначения. Как и сами штырьки пор- тов, имеются некоторые разделяемые функции, отмеченные в таблице. Эти функции в ос- новном кратковременно используются в демонстрационных целях. Универсальный ввод-вывод Derbot может быть распределен с некоторой степенью гибкости. На выбор повлияют только возможности входов на триггере Шмитта, внутрен- ний нагрузочный резистор (порт В) и, конечно же, физическое расположение штырьков на интегральной схеме микроконтроллера. В данной главе будет рассмотрена реализация интерфейсов переключателей и светодиодов Derbot; другие виды интерфейсов будут рас- сматриваться в последующих главах. Интерфейсы переключателей АУСМ Derbot использует переключатель режимов, управляемый пользователем (ко- торый заставляет АУСМ переключаться между двумя режимами) и пару микропереклю- чателей, которые используются для реализации сенсоров препятствий. Электрически эти переключатели одинаковы, относящиеся к типу SPST (Однополюсная группа замыкающих/ размыкающих контактов). В силу этого они могут подсоединяться с использованием элек- трической схемы, приведенной на рис. 3.7 (Ь). Может использоваться обычный нагрузоч- ный резистор или нагрузка порта В. Стоит отметить, что в последнем случае нагрузки бу- дут включаться для всех разрядов порта В, используемых как входы, вне зависимости от того, нужны они или нет. Поскольку требуется всего три нагрузочных резистора, то было решено использовать внешние компоненты и не использовать нагрузочные резисторы порта В.
7.10. Применение 16F873A: АУСМ Derbot 185 Табл. 7.2. Потребности во вводе-выводе АУСМ Derbot Функция Направление данных . Используемые периферийные устройства Распределение портов и штырьков Внутрисхемный отладчик Двунаправленный Параллельный порт Порт В, 6 и 7 “Толчковые” микропереключатели Вход Параллельный порт Порт В, 4 и 5 Привод сервомотора Выход Параллельный порт Порт В, 3 Сигнал разрешения оптического датчика Выход Параллельный порт Порт В, 2 Пъезоэхолот Выход Параллельный порт Порт В, 1 Прерывание Вход Прерывание параллельного порта Порт В, 0 Переключатель режима, также USART RX Вход Параллельный порт Порт С, 7 Диагностический светодиод, также ультразвуковое эхо, также USART ТХ Выход Вход Выход Параллельный порт Порт С, 6 Диагностический светодиод, также ультразвуковой импульс Выход Параллельный порт Порт С, 5 1 С, последовательные данные Двунаправленный Синхронный последовательный порт Порт С, 4 12С, последовательная тактовая частота Двунаправленный Синхронный последовательный порт Порт С, 3 Привод правого электромотора с ШИМ, также ШИМ-демонстрация, TPs 1 и 2 Выход ШИМ Порт С, 2 Привод левого электромотора с ШИМ Выход ШИМ Порт С, 1 Отражательный оптический датчик Вход Таймер 1 Порт С, 0 Активирование левого электромотора Выход Параллельный порт Порт А, 5 Отражательный оптический датчик Вход Таймер 0 Порт А, 4 Световой датчик, задний Вход Аналого-цифровой преобразователь (АЦП) Порт А, 3 Активирование правого электромотора Выход Параллельный порт Порт А, 2 Световой датчик, левый Вход АЦП ПортА, 1 Световой датчик, правый Вход АЦП Порт А, 0 Управление светодиодами В схему включены два универсальных диагностических светодиода. Они могут ис- пользоваться для любой цели по усмотрению программиста. Красный светодиод высоко- эффективного типа дает превосходный результат при очень низком потреблении тока. Тесты показали, что приемлемая видимость может быть получена при токе, приблизи- тельно равном 3,5 мА. При использовании характеристик по рис. 3.8 (а), можно сказать,
186 Глава 7. Большие системы и PIC 16F873A что прямое напряжения на светодиоде для этого тока будет равно около 1,88 В, а из рис. 7.14 (а) можно определить, что выходное напряжение соответствующего разряда порта будет приблизительно равно 4,7 В. Отсюда, применив уравнение (3.1), получим: 4,7-1,88 R = ---------= 806 Ом 0,0035 806 Ом близко к “предпочтительному значению”, и опыт показал, что оно обеспечи- вает хорошую видимость свечения. 7.10.3. Сборка аппаратных средств Если вы собираете АУСМ Derbot, то используйте электрическую схему расположения компонентов, имеющуюся на компакт-диске, прилагаемом к этой книге. Соберите и уста- новите следующие элементы: • все компоненты в линии электропитания, включая конденсаторы развязки; • переключатель сброса и нагрузочный резистор; • кварцевый генератор и нагрузочные конденсаторы; • диагностические светодиоды с токоограничивающими резисторами; • два передних микропереключателя с нагрузочными резисторами; • переключатель режима и нагрузочный резистор; • (необязательно) пьезоэхолот и управляющий транзистор; • соединитель ICD, если имеете модуль ICD. Сделав это, вы получите печатную плату, на которой набрана схема, показанная на рис. 7.22. 7.11. Выгрузка, тестирование и выполнение простой программы с использованием ICD 2 Теперь давайте попробуем запустить программу для нового аппаратного проекта и ICD 2, если вы имеете к нему доступ. 7.11.1. Первая программа для Derbot Пример программы 7.1 — это очень простая тестовая программа для только что соз- данного АУСМ Derbot, находящегося пока в эмбриональном состоянии. Она просто про- веряет состояние передних микропереключателей и включает или выключает, соответст- венно, диагностические светодиоды. Если оба переключателя нажаты, то включается эхолот. Обратите внимание, что про- грамма использует включаемый файл 16F873A в строке: include pl6f873a.inc При использовании большого микроконтроллера непрактично рассматривать адреса всех регистров при входе в программу, как мы это делали, например, в заголовке примера программы 4.2. Ошибки, допущенные на этой стадии, также могут быть очень трудны в об- наружении. Использование включаемого файла должно стать вашей обычной практикой, если это еще не так. В MPLAB создайте проект Dbt_sw21ed (или используйте иное имя по вашему выбо- ру) и скопируйте программу Dbt_sw21ed. asm с компакт-диска, прилагаемого к этой кни- ге, или введите ее вручную; в напечатанном примере она приведена полностью. Скомпо- нуйте проект обычным способом. Если вы не располагаете ICD 2, то выгрузите программу в Р1С, используя обычный программатор, например PICSTART Plus, как описано в Главе 4.
7.11. Выгрузка, тестирование и выполнение простой программы с использованием ICD 2 187 6хАА (щелочных аккумуляторных элементов) LP2950 RB6 __ RB5 __ RB4 __ RB3 _ RB2 _ RB1 __ RBO _ Vdd __ Vss __ RC7 __ RC6___ RC5 __ RC4 _ __ МС|УнВ7 _ RAO _ RA1 __ RA2 _ RA3 _ RA4 __ RA5 __ Vss __ Osc1 __ Osc2 _ RCO _ RC1 _ RC2 _ RC3 o j UCD2 (*> о; Соединительный "° : разъем 06i(nc) 04,5 4MHz 16F873A АУСМ Derbot Промежуточная стадия сборки 1 R13 J ((__I 24k Переключатель режима Пъезоэхолот ZVN4206 TR1 TJW Rev.30.10.05 Рис. 7.22. Промежуточная стадия сборки Derbot Пример программы 7.1. Простой перенос бита для Derbot ;Dbt_sw21ed /Переносит состояние передних микропереключателей при диагностике ;светодиодов. /Если включены оба переключателя, то включается эхолот. /TJW 24.03.05 Тестировано и запущено 20.08.05 list p=16f873a include pl6f873a.inc /Специфицируем метки ОЗУ delcntrl equ 20 /используется при задержке SR delcntr2 equ 21
188 Глава 7. Большие системы и PIC 16F873A Пример программы 7,1, Продолжение______________________________________________ /Устанавливаем слово конфигурации: кварцевый генератор в режиме HS, WDT выкл, /таймер включения питания вкл, кодовая защита выкл, программа LV выкл CONFIG _HS_OSC & _WDT_OFF org 00 & _PWRTE_ON & _LVP_ OFF ;Инициализация start bsf status,5 /выбор банка памяти 1 movlw movwf movlw movwf movlw movwf movlw B'00000011 ' trisa B' 11111000' trisb B'10000000 ' trisc B' 00000110' /все разряды порта Л /разряды порта В /разряды порта С . устанавливаем на выход movwf adconl bcf status,5 /устанавливаем порт /выбор банка памяти А на цифровую 0 функцию /Здесь начинается "главная" программа /выключаем все выходы clrf porta clrf portb clrf portc /диагностика — включаем светодиоды на пол секунды bsf portc,6 bsf portc,5 call delay500 bcf portc,6 bcf portc,5 call delay500 /переносим состояние микропереключателя на диагностические светодиоды loop bcf portc,6 /предварительно очищаем порт С, разряд 6 (светодиод выкл.) btf sc portb,4 /переход, если переключатель нажат bsf portc,6 /светодиод вкл., если переключатель не нажат bcf portc,5 /предварительно очищаем порт С, разряд 5 f (светодиод выкл.) btf sc portb,5 /переход, если переключатель нажат bsf portc,5 /светодиод вкл., если переключатель не нажат Г btf sc portb,4 goto loopl btf sc portb,5 goto loopl bsf portb,1 /включение эхолота, если оба нажаты goto loop loopl bcf portb,1 /выключение эхолота goto loop /ПОДПРОГРАММЫ /вносит задержку, приблизительно равную 1 мс delayl movlw D'250' /задаются 250 циклов, /по 4 мкс каждый movwf delcntrl dell nop /в этом цикле 4 командных цикла, т.е. 4 мкс decfsz delcntrl,1
7.11. Выгрузка, тестирование и выполнение простой программы с использованием ICD 2 189 Пример программы 7.1. Окончание goto dell return ;задержка в 500 мс (приблизительно 500 вызовов delayl) delay500 movlw D'250' movwf delcntr2 de 15 call delayl call delayl decfsz delcntr2,1 goto return end de 15 7.11.2. Применение ICD 2 Нижеизложенное предполагает, что вы располагаете ICD 2, или более поздней версией этого внутрисхемного отладчика. Это очень краткое введение, написанное в предположе- нии, что вы уже имеете определенные знания, касающиеся имитатора MPLAB, возможнос- ти которого используются в ICD 2. Дальнейший опыт может затем быть получен в резуль- тате экспериментирования и чтения полного руководства на ICD 2. Прочитав подраздел “Начало работы” руководства, убедитесь в том, что ICD 2 скон- фигурирован правильно для вашего компьютера и операционной системы. Выполните со- единения между компьютером и АУСМ, как было показано на рис. 7.20. Запустите MPLAB и откройте проект, содержащий пример программы 7.1, который вы создали. Настройте ICD так, чтобы первоначально он работал в режиме отладки, щелкая на Debugger (Отлад- чик) > Select Tool (Выбор инструмента) > MPLAB ICD 2. Затем завершите соединение с АУСМ, щелкнув на Debugger (Отладчик) > Connect (Соединение). ICD выполнит само- проверку, которая проверит присутствие электропитания, а также способность применить правильные напряжения к контролируемым линиям. Если целевая система запитана и ра- ботает, ICD 2 должен пройти самопроверку и прийти в состояние готовности к идентифи- кации микроконтроллера. Он отображает сообщение, указывающее о прохождении теста, и выдает текст MPLAB ICD 2 Ready (Готовность MPLAB ICD 2). Затем раскрывающееся меню под позицией Debugger (Отладчик) становится активным, как и панель инструмен- тов, показанная на рис. 4.9 и повторенная на рис. 7.23. Дополнительная инструментальная панель, специфичная для ICD 2, также появится. Она показана в правой части рисунка и позволяет пользователю читать память программы, выгружать в нее программу и сбрасы- вать ICD. Однако обратите внимание, что если на основной инструментальной панели выбрать Programmer (Программатор) > Select Programmer (Выбрать программатор), то в развернувшемся меню будет указано, что никакой программатор не выбран. Это имеет место потому, что в этом режиме способность к программированию доступна только внут- ри функции отладчика ICD. Убедитесь, что Derbot включен, загрузите память программ, используя или соответст- вующую кнопку на инструментальной панели, показанную на рис. 7.23, или же выберите Debugger (Отладчик) > Program (Программа). Откройте окно Watch (Наблюдение), как это описано в Главе 4, и отобразите регистры PCL, PORTB и PORTC. Затем начните по- шаговое продвижение через программу, используя функцию Step Over (Перейти), чтобы пропустить подпрограммы временной задержки. Один раз в основном цикле попробуйте нажимать по очереди микропереключатели и, по мере пошагового продвижения, наблю- дайте реакцию значений портов в окне Watch (Наблюдение). В отличие от использования имитатора, именно фактические значения, снятые с аппаратных средств, передаются на дисплей. Попробуйте с компьютера устанавливать или очищать разряды порта и наблю- дайте, как вы можете таким образом включать и выключать светодиоды Derbot. Как и с
190 Глава 7. Большие системы и PIC 16F873A имитатором, контрольные точки могут устанавливаться в программе двойным щелчком на любой строке программы. !> Программировать целевое устройство Читать целевое устройство Сброс и подсоединение к ICD Рис. 7.23. Инструментальные панели отладки для ICD 2 — стандартная отладка, с дополнительными возможностями программы ICD Выход из сброса qa т | Удержание сброса j | Сброс и подключение к ICD | ___ И ’$•4 4^'. Programmer Toe Io £onfigutc Window Help Select Programmer ► MPLAB ICD 2 Setup Wizard. Program Read Verify Erase Part Blank Check Release from Reset Connect Download ICD2 Operating System Settings.. Рис. 7.24. Функции программатора для ICD 2 — разворачивающееся меню и инструментальная панель Чтобы окончательно запрограммировать систему, ICD 2 должен быть переключен в режим программатора. На верхней инструментальной панели выберите: Programmer (Про- грамматор) > Select Programmer (Выбрать программатор) > MPLAB ICD 2, а затем Programmer (Программатор) > Connect (Соединение) (автоматический режим соедине- ния также возможен). Меню Debugger (Отладчик) покажет, что в настоящее время не име- ется никакого выбранного отладчика. Теперь можно программировать и читать память. Раз- ворачивающееся меню и инструментальная панель программиста будут доступны, как показано на рис. 7.24. Обратите внимание, что операция сброса может управляться с экрана. Когда программирование будет завершено, состояние сброса останется активным. Оно мо- жет быть отключено с использованием кнопки, показанной на рис. 7.24 инструментальной панели, после чего программа сразу же запустится. 7.11.3. Установка битов конфигурации внутри программы 16F873A имеет больше битов конфигурации, чем 16F84A, и при установке их в окне MPLAB очень просто совершить ошибку. Неправильные установки могут привести к очень необычному поведению целевой встроенной системы или вообще к отсутствию поведения! Является, однако, возможным установить биты конфигурации в программе, используя ди- рективу ассемблера „CONFIG. Эта директива использует символы, которые определены во включаемом файле микроконтроллера. Соответствующая секция программы для 16F873A
7.11. Выгрузка, тестирование и выполнение простой программы с использованием ICD 2 191 показана в примере программы 7.2. Можно видеть, что каждое шестнадцатеричное значе- ние, к которому приравнивается символ, получено из настроек слова конфигурации, по- казанных в обобщенном виде на рис. 7.7. Поскольку их комбинации логически умножа- ются, то формируется окончательная настройка слова конфигурации. Используемая уста- новка, приведенная в нижеследующем примере программы, может применяться ко всем программам Derbot, основанным на 16F873A. /Установка слова конфигурации: кварцевый генератор в режиме HS, /сторожевой таймер откл., /таймер включения питания вкл, кодовая защита выкл., программа LV откл. __CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _LVP_OFF Даже при этих настройках в программе, имеется опасность того, что по невниматель- ности будет сделано изменение в окне Configuration Bits (Биты конфигурации) MPLAB. Вы можете убедиться в этом, скомпоновав пример программы 7.1. Посмотрите на установ- ки битов конфигурации, отображаемые в окне — они правильны. Однако и на этой стадии можно внести ошибку, выполнив изменение в окне. Все, что сейчас отображается в окне, будет выгружено в память программ в следующем сеансе выгрузки. Эта опасность может быть снята, если выбрать Configure (Конфигурировать) > Settings (Настройки) > Program Loading (Загрузка программы) и отметить позицию Clear configuration bits upon loading the program (Очистить биты конфигурации при загрузке программы). Теперь при загруз- ке программы, настройки окна очищаются и выгружаются биты конфигурации, опреде- ленные в программе. Пример программы 7.2. Определение битов конфигурации во включаемом файле 16F873A / Биты конфигурирования CP_ALL EQU H'1FFF' CP_OFF EQU H'3FFF' DEBUG_OFF EQU H'3FFF' ^DEBUG_ON EQU H'37FF' WRT_OFF EQU H'3FFF' /Нет защиты от записи памяти программы WRT_256 EQU H'3DFF' /Первые 256 битов памяти программ защищены /от записи WRT_1FOURTH EQU H'3BFF' /Первая четверть битов памяти программ защищена /от записи WRT_HALF EQU H'39FF' /Первая половина памяти защищена от записи CPD_OFF EQU Н'3FFF' _CPD_ON EQU Н'3EFF' LVP_ON EQU Н'3FFF' LVP_OFF EQU Н'3F7F' "bODEN_ON EQU Н'3FFF' *BODEN_OFF EQU Н'3FBF' "PWRTE_OFF EQU Н'3FFF' PWRTE_ON EQU Н' 3FF7 ' WDT_ON EQU Н'3FFF' ”wDT_OFF EQU Н'3FFB' RC_OSC EQU Н'3FFF' hs_osc EQU Н'3FFE' ’xt_osc EQU Н'3FFD' ’lp osc EQU H'3FFC'
192 Глава 7. Большие системы и PIC 16F873A 7.12. Двигаемся дальше -16F874A/16F877A: порты D и Е Если посмотреть на рис. 7.1 (Ь), то можно увидеть, что 16F874A и 16F877A имеют два дополнительных порта— 8-разрядный порт D и 3-разрядный порт Е. Любой из этих пор- тов может быть использован для ввода-вывода общего назначения, как и любой из других портов. Блок-схема порта D, когда он сконфигурирован на обычный цифровой ввод-вывод, показана на рис. 7.25 (а). Альтернативной функцией порта Е является предоставление грех дополнительных аналоговых входов. По этой причине порт Е находится еще и под управ- лением одного из регистров управления АЦП — ADCON1. Его настройки определяют, Рис. 7.25. Блок-схема управления штырьком порта D: (а) — в режиме ввода-вывода; (Ь) — как параллельный подчиненный порт (дополнительные метки в затененных полях добавлены автором) Вместе порты D и Е могут также формировать параллельный подчиненный порт. Пор- ты вводятся в этот режим установкой бита PSPMODE в регистре TRISE (рис. 7.26). Цель этого режима состоит в том, чтобы позволить микроконтроллеру связываться с помощью интерфейса в качестве подчиненного устройства с шиной данных, управляемой, возможно, микропроцессором. Разряды порта Е должны быть установлены как входы (в цифровом режиме, выбранном в ADCON1); состояние TRISD, однако, несущественно. Затем порты D и Е конфигурируются, как показано на рис. 7.25 (Ь). На схеме показан разряд 1 порта D, вместе с тремя линиями управления — CS, WR и RD. Это 3 разряда порта Е, которые теперь сконфигурированы для этой цели. Обратите внимание, что имеется выходной и входной триггеры для каждого разряда порта D. Пример применения параллельного подчиненного порта показан на рис. 7.27. Здесь порт соединен с шиной данных и линиями управления, которые формируют часть боль- шей системы, управляемой микропроцессором. Программа 16F874A может записывать данные в порт, когда бит OBF регистра TRISE установлен. Если CS и RD переводятся в значение логического нуля внешней схемой, то порт выводит данные, записанные в выход- ных триггерах, на внешнюю шину. Это действие очищает OBF. Если же CS и WR прини- мают значение логического 0, то порт переписывает данные с шины во входные триггеры, при этом бит IBF TRISE установлен в состояние логической 1. IBF очищается, когда порт
7.12. Двигаемся дальше - 16F874A/16F877A: порты D и Е 193 считывается программой микроконтроллера. Если, однако, внешняя схема вновь произ- водит запись в порт, прежде чем предыдущее слово было считано, то устанавливается бит IBOV TRISE. Флаг прерывания PSPIF (рис. 7.10) устанавливается, когда операция записи или чтения подчиненного устройства завершаются внешней схемой. Этот флаг должен быть очищен программно. R-0 R-0 R/W-0 R/W-0 U-0 R/W-1 R/W-1 R/W-1 IBF OBF IBOV PSPMODE Разряд 2 Разряд 1 Разряд 0 разряд 7 разряд 0 Разряды состояния/управления параллельного подчиненного порта: разряд 7 IBF: бит состояния заполнения входного буфера 1 - слово было получено и ожидает, чтобы быть считанным ЦП О = никакое слово не было получено разряд 6 OBF: бит состояния заполнения выходного буфера 1 = буфер вывода все еще содержит ранее записанное слово О = буфер вывода был считан разряд 5 IBOV: бит обнаружения переполнения входного буфера (в режиме микропроцессора) 1 = запись произошла, когда предыдущее входное слово не было считано (бит должен быть сброшен программно) О = переполнения не было разряд 4 PSPMODE: бит выбора режима параллельного подчиненного порта 1 = PORTD функционирует в режиме параллельного подчиненного порта О = PORTD функционирует в режиме порта ввода-вывода общего назначения разряд 3 Нереализован: считывается как О Разряды направления данных для порта Е: разряд 2 Разряд 2: бит управления направлением для штырька RE2/CS/AN7 1 = вход О = выход разряд 1 Разряд 1: бит управления направлением для штырька RE1/WR/AN6 1 = вход О = выход разряд 0 Разряд 0: бит управления направлением для штырька RE0/RD/AN5 1 = вход О = выход Рис. 7.27. Параллельный подчиненный порт, соединенный с системной шиной
194 Глава 7. Большие системы и PIC® 16F873A Резюме • Группа микроконтроллеров 16F87XA — важное подмножество семейства PIC 16. Ее увеличенные функциональные возможности достигнуты в результате включения мощного набора периферийных устройств, наряду с модернизацией памяти. • Ядро архитектуры группы 16F87XA является таким же, как и у других микроконтрол- леров семейства PIC 16 с тем же самым набором команд. • Тестирование встроенной системы должно выполняться на систематической основе с применением самых лучших из доступных соответствующих инструментальных средств. • Внутрисхемная отладка — это мощная методика для тестирования и ввода в действие как программных, так и аппаратных средств, обеспечивающая минимум необходимо- го вмешательства.
ГЛАВА 8. ЧЕЛОВЕКО-МАШИННЫЕ И ФИЗИЧЕСКИЕ ИНТЕРФЕЙСЫ Рис. 1.1 иллюстрирует типичную встроенную систему. На этом рисунке можно видеть, что встроенный компьютер считывает значения сигналов, выдает управляющие сигналы и взаимодействует с человеком-пользователем, а также, возможно, с внешней системой через сеть. Все эти формы активности становятся возможными благодаря использованию широкого спектра интерфейсов, которые составляют значительную часть аппаратного про- екта встроенных систем. В этой главе мы рассмотрим некоторые аспекты организации ин- терфейсов, включая организацию как человеко-машинных, так и физических интерфейсов. Для того чтобы спроектировать интерфейс, нам нужно кое-что знать о датчиках и ис- полнительных устройствах, которые могут использоваться. Эта область знаний лежит между знаниями о системах в целом и знаниями о собственно электронных схемах микро- контроллера. Она охватывает входные устройства — датчики для измерений либо устрой- ства ввода данных человеком, а также выходные устройства — индикаторы или средства подачи предупредительных сигналов, рассчитанные на восприятие человеком, а также электромоторы и другие исполнительные механизмы для работы с физическими система- ми. Без преувеличения можно сказать, что есть тысячи устройств упомянутых типов — мы рассмотрим только несколько примеров. Помимо получения знаний о самих по себе датчиках и исполнительных механизмах, мы должны будем также знать, как их можно подключить к микроконтроллеру. Например, может потребоваться усиление сигналов с датчиков до того, как их можно будет подать на микроконтроллер; или может потребоваться, чтобы выходные сигналы управления элек- тромотором поступали на ключевые схемы управления питанием силовых цепей, чтобы электромотор срабатывал — в нужное время и на нужных оборотах. И, наконец, важнейший момент: имеется необходимость понимания того, как могут быть написаны программы, реализующие упомянутый интерфейс. Таким образом, в данной главе вы узнаете: • о требованиях к человеко-машинному интерфейсу и некоторых простых средствах для удовлетворения этих требований; • о некоторых простых примерах датчиков; • о некоторых способах формирования интерфейса между сигналами датчиков и мик- роконтроллером; • о некоторых простых примерах исполнительных механизмов; • о некоторых способах формирования интерфейса между микроконтроллером и ис- полнительными механизмами; • об использовании, применительно к АУСМ Derbot, некоторых датчиков и исполни- тельных механизмов. Многие из названных тем будут проиллюстрированы примерами на базе АУСМ Derbot. Важно отметить, что многие важные элементы формирования интерфейсов в этой главе не рассматриваются. Так, процессу ввода аналоговых сигналов в целом посвящена Глава 11. А сетевые концепции, с точки зрения последовательного информационного об- мена, рассматриваются в Главе 10.
196 Глава 8. Человеко-машинные и физические ингерфейсы 8.1. Основная идея человеко-машинного интерфейса Человек должен взаимодействовать с машиной, с которой он работает. Почти неиз- бежно такое взаимодействие приобретает форму бесконечного цикла итераций. Пользо- ватель оценивает текущее состояние системы и, возможно, рабочей среды в целом. В процессе этой оценки он получает информацию от системы. Затем, основываясь на том, какие последующие события он считает предпочтительными, пользователь взаимодей- ствует с системой, чтобы инициализировать определенные изменения в ее поведении. Это взаимодействие может носить форму чистого информационного обмена. Например, поль- зователь холодильной установки может увидеть на индикаторе текущую температуру, затем решить, что он желает: например, чтобы температура была ниже и ввести с клавиа- туры новую желаемую температуру. В качестве альтернативы, пользовал ель в принципе мог бы применять и какие-либо иные физические воздействия. Это очень похоже на то, что происходит при управлении автомобилем, когда водитель считывает информацию с приборной доски и реагирует посредством физических действий, носящих форму пово- рота рулевого колеса, нажатия на педаль тормоза или газа. Рис. 8.1. Человеко-машинный интерфейс некоторых знакомых изделий: (а) — домашнего холодильника; (Ь) — фотокопировального устройства; (с) — приборной доски автомобиля (фрагмент) Рис. 8.1 демонстрирует примеры человеко-машинных интерфейсов, присутствующих в привычных для нас изделиях, которые также являются той или иной формой встроенной системы. Так, холодильник может работать в одном из двух режимов: “супер” и “эко”. Он отображает фактические температуры морозилки и основного отделения. Обе требуемые
8.2. От ключей к малым клавиатурам 197 температуры могут задаваться. Если температура в морозилке поднимется выше опреде- ленной величины, то будет подан акустический предупредительный сигнал. Этот акусти- ческий предупредительный сигнал может быть, однако, отключен. Все вводы управляю- щих воздействий выполняются простым нажатием кнопок, в то время как выходная ин- формация отображается двумя двухразрядными цифровыми индикаторами, а также ин- дикаторами знака. Управление фотокопировальным устройством является несколько более сложной про- цедурой. В нем имеется широкий диапазон режимов работы с использованием различных источников бумаги, имеются также различные возможности настройки изображения. Ин- формация выводится на специализированный дисплей. Поскольку этот дисплей имеет сен- сорный экран, то он также служит для ввода управляющей информации. Более привычная обычная клавиатура позволяет осуществлять ввод числовой информации, типа управ- ляющих кодов и требуемого числа копий. Показанный фрагмент приборной доски автомобиля отражает дальнейший рост слож- ности. Одной из основных функций приборной доски является индикация скорости дви- жения автомобиля. Поскольку в данном случае автомобиль стоит на месте, то этот факт индицируется большим нулем. Вокруг показаний скорости мы можем видеть обширный диапазон информации о состоянии автомобиля, включая такие различные параметры, как число оборотов двигателя, выбранная радиостанция, температура, состояние дверей, уровень горючего и т.д. Несмотря на сложность и разнообразие информации, вся она отображается в простой форме. Опять-таки, в случае приборной доски наблюдается зна- чительный уровень использования цифровых индикаторов. К ним также добавлены инди- каторы столбцовых диаграмм, простые подсвечиваемые символы и простая схематическая информация. При этом на последнем приведенном изображении отсутствуют какие-либо устройства ввода информации пользователем. Что впечатляет в каждом из этих трех во многом различных интерфейсов — это нити, которые их объединяют. Каждый из них имеет значительную необходимость передать человеку численную информацию, а также информацию о состоянии; оба эти вида инфор- мации отображаются простыми способами. Основной упор делается на зрительное вос- приятие. Звук также используется, особенно в аварийных ситуациях. В последующем разделе данной главы мы будем исследовать средства информацион- ного обмена между встроенной системой и пользователем. Это будет выполнено через ана- лиз малой клавиатуры, семисегментного светодиодного индикатора и ЖК-индикатора, поскольку в простых встроенных системах они носят более-менее вездесущий характер. Они будут иллюстрироваться на примере пульта ручного управления (ПУ) АУСМ Derbot. Это необязательный модуль, который может держаться в руке или устанавливаться над батарейным отсеком, как показано на рис. АЗ.З. Пульт управления доступен в двух испол- нениях — светодиодном и жидкокристаллическом. Эти исполнения показаны на рис. 8.2. Пульт управления разработан как “бесхитростный терминал”, который связывается с по- мощью интерфейса непосредственно с ЦП АУСМ Derbot. Он может, однако, использо- ваться и в автономной форме — в данной главе мы рассмотрим это применение. В Главе 10 мы будем рассматривать связь ПУ с АУСМ, используя ее для иллюстрации последователь- ной связи. Электрическая схема ПУ АУСМ Derbot приведена на рис. АЗ.2. 8.2. От ключей к малым клавиатурам Скромный ключ, основа столь большого числа человеко-машинных интерфейсов, был представлен в Главе 3. Ключи хороши для передачи информации дискретного характера — они имеют два состояния, однако может использоваться несколько ключей, при этом каждый из них может представлять один бит порта. Вместе с тем в более сложных ситуа- циях использование дополнительных ключей становится нецелесообразным. С одной сто- роны, использование битов порта становится все более интенсивным, а с другой — дво- ичная природа ключей часто уже не соответствует потребностям ввода информации.
198 Глава 8. Человеко-машинные и физические интерфейсы (а) (Ь) Рис. 8.2. Пульт управления АУСМ Derbot: (а) — светодиодное исполнение; (Ь) — жидкокристаллическое исполнение 8.2.1. Малая клавиатура Полезный шаг вперед от простого ключа олицетворяется малой клавиатурой, которая присутствует в интерфейсе фотокопировального устройства и пульте управления АУСМ Derbot, показанных на рис. 8.2. Малая клавиатура позволяет осуществлять ввод как чис- ловой, так и алфавитно-цифровой информации. Она широко используется в фотокопи- ровальных устройствах, сторожевых сигнальных системах, контроллерах центрального отопления и так далее. Малая клавиатура также основана на ключах, однако, если бы каждому из этих ключей был бы поставлен в соответствие бит порта, то использование такого ресурса было бы чрез- мерно интенсивным. Вместо этого, для обеспечения хорошего использования ресурсов, ключи соединены по схеме матрицы. Рис. 8.3 показывает электрические соединения для малой клавиатуры по рис. 8.2, которая имеет 12 клавиш. Теперь можно видеть, что кла- виши размещаются в форме матрицы 4 х 3, с четырьмя строками и тремя столбцами. В результате необходимо только семь межсоединений, а не 12. Всякий раз, когда нажима- ется клавиша, она соединяет строку матрицы со столбцом. Рис. 8.3. Схема электрическая малой клавиатуры с нагрузочными резисторами В среде встроенных систем малая клавиатура обычно подсоединяется к битам порта ввода-вывода микроконтроллера. Пример подсоединения битов порта показан на рис. 8.3,
8.2. От ключей к малым клавиатурам 199 наряду с необходимыми нагрузочными резисторами. Теперь самое “трудное” — эффек- тивно определить, какая клавиша нажата. Методика, обычно используемая для того, чтобы считывать состояние малой клавиату- ры, соответствует блок-схеме, приведенной на рис. 8.4 (а). Сначала разряды столбцов ус- танавливаются как выходы, а разряды строк — как входы. Затем выходные разряды столб- цов устанавливаются в 0. Если никакая клавиша клавиатуры не нажата, то все входы ли- нии строки будут считываться как 1, вследствие действия нагрузочных резисторов. Если, однако, клавиша нажата, то соответствующий ключ соединит линию столбца и линию стро- ки. Значит, соответствующая линия строки перейдет в состояние 0. Если этот процесс будет мгновенно повторен, но с выходами, замененными на входы, то линия столбца для нажатой клавиши также может быть найдена и, значит, клавиша — полностью идентифицирована. (а) (Ь) Клавиша Считываемое значение 1 0111 011Х 2 0111 101Х 3 0111 110Х 4 1011 011Х 5 1011 101Х 6 1011 110Х 7 1101 011Х 8 1101 101Х 9 1101 110Х * 1110011Х 0 1110101Х # 1110110Х Рис. 8.4. Считывание клавиатуры портом микроконтроллера: (а) — блок-схема; (Ь) — выходы малой клавиатуры по рис. 8.3 Выходные значения для малой клавиатуры, соединенной по схеме согласно рис. 8.3, показаны на рис. 8.4 (Ь). Например, предположим, что была нажата клавиша 7. В первой фазе отработки блок-схемы, когда подсоединения строк установлены как входы, третья линия строки (разряд 5 порта) считывалась бы как 0. Во второй фазе отработки блок- схемы, когда разряды столбцов установлены как входы, первый столбец (разряд 3 порта) считывался бы как 0. На рис. 8.4 приведена конечная считываемая структура, при этом состояние ее бита 0 не имеет значения и не используется, оно отмечено символом “X”. 8.2.2. Пример проектной разработки: использование малой клавиатуры в ПУ АУСМ Derbot Только что описанная блок-схема — это только отправная точка для работы с клавиа- турами. Как, например, мы определим, когда клавиша клавиатуры нажата на самом деле, и что в результате нам делать с кодами, показанными в вышеприведенной таблице? Пример программы 8.1 иллюстрирует практическое применение алгоритма считывания клавиатуры в программе, называемой keypad_test. Данная программа используется для иллюстрации использования клавиатуры и ЖК-индикатора. Эта программа слишком длинна, чтобы приводить ее полный листинг в этой книге, поэтому воспроизводится только
200 Глава 8. Человеко-машинные и физические интерфейсы секция программы, относящаяся к работе с клавиатурой. На компакт-диске, прилагаемом к этой книге, имеется полная версия данной программы. Рис. 8.5. Блок-схема для примера программы 8.1 Блок схема программы показана на рис. 8.5. Для определения факта нажатия клавиши клавиатуры эта программа использует функцию “прерывание по изменению состояния”, доступную для старших четырех битов порта В. После инициализации вся работа програм- мы связана с отработкой подпрограммы обслуживания прерывания (ПОП), которая на- зывается kpad_to_lcd. По сути, эта подпрограмма делает четыре вещи: считывает код с клавиатуры, преобразует его в кодировку ASCII, посылает код на ЖК-индикатор, а затем ожидает отпускания клавиши клавиатуры, чтобы после этого выйти из ПОП. Попытайтесь пошагово проанализировать программу, сопоставляя ее с приведенной блок-схемой. В начальной части секции инициализации порт В устанавливается таким образом, что разряды строк матрицы являются входами, а разряды столбцов — выходами. Мы могли бы начать выполнение программы и другим способом, однако для того чтобы использовать “прерывание по изменению состояния”, старшие 4 разряда должны быть установлены как входы. Все выходные разряды последовательно устанавливаются в ноль, после чего “прерывание по изменению состояния” разрешается. На этой стадии мы уже начали реализовывать блок-схему по рис. 8.4 (а). Прерывание возникает, когда нажимается клавиша на клавиатуре и вызывается ПОП с именем kpad_to_lcd. Эта подпрограмма немедленно вызывает подпрограмму kpad_rd, которая продолжает отработку блок-схемы по рис. 8.4 (а), начав выполнение секции инициа- лизации. Значение порта В считывается и сохраняется в ячейке памяти с именем kpad_pat. Затем роли строк и столбцов меняются, и выполняется считывание разрядов строк. Резуль- таты логически складывается в kpad_pat, гарантируя, что любые нежелательные разря- ды будут удалены в результате логического умножения на 0. Затем подпрограмма сбра- сывает порт В в его исходное состояние, приводя в готовность к следующей операции счи- тывания клавиатуры. Значение, хранимое в kpad_pat после завершения работы подпрограммы kpad_rd, имеет не очень полезный формат. Это 7-разрядное число, возможные значения которого показаны на рис. 8.4 (Ь). По этой причине программа вызывает подпрограмму кр_со- de_conv, которая преобразует это число в код клавиши клавиатуры, которому оно со- ответствует. То, как это делается, описано в следующем параграфе. Затем этот код вы- дается на ЖК-индикатор с использованием подпрограммы lcd_write. Эта операция не показана в приведенном примере программы, однако далее описывается в этой главе.
8.2. От ключей к малым клавиатурам 201 Теперь программа входит в цикл ожидания отпускания клавиши клавиатуры, после чего вновь вызывает подпрограмму kpad_rd. Это происходит вследствие того, что когда поль- зователь отпускает клавишу клавиатуры, он также инициализирует “прерывание по изме- нению состояния”, которое могло бы привести ко второму, уже нежелательному, считы- ванию состояния клавиатуры. Пример программы 8.1. Считывание клавиатуры ПУ АУСМ Derbot /keypad_test /Проверяет клавиатуру, /ПУ АУСМ Derbot /TJW 23.06.05, передавая код нажатой клавиши на ЖК-дисплей тестировано 24.06.05 (начальные секции программы опущены) ; Инициализация bsf status,rpO /выбор банка памяти 1 movlw В'11110000' movwf trisb bcf status,rpO /первоначально биты строк порта В устанавливаются /как входы, биты столбцов — как выходы /(порт В не используется) / выбор банка памяти 0 (инициализация ЖК-индикатора опущена) clrf portb /инициализация значения клавиатуры /разрешение прерывания bcf intcon,rbif bs f intcon,rbie bsf intcon,gie loop goto loop /ожидание ввода с клавиатуры Подпрограмма обслуживания прерывания (ПОП). /Было распознано нажатие клавиши на клавиатуре через прерывание по /изменению состояния” порта В. Получаем код с клавиатуры /преобразуем его в код символа, сохраняем его в kpad_char, /затем передаем на ЖК-индикатор и ожидаем отпускания клавиши клавиатуры kpad_to_lcd call kpad_rd /теперь преобразуем код клавиатуры в код символа, /формируя адрес с использованием поисковой таблицы call kp_code_conv /посылаем код символа на ЖК-индикатор /проверяем на rel test bs f portc,lcd_RS /установка на вывод символа movwf call lcd_op lcd_write отпускание клавиши call kpad_rd movf kpad_pat,0 клавиатуры andlw Ofe /подавляем младшие биты, которые не исполь sublw btf ss goto Ofe /проверка status, z rel_test на неактивность bcf retfie intcon,rbif / clear interrupt flag зуются
202 Глава 8. Человеко-машинные и физические интерфейсы Пример программы 8.1. Продолжение /ПОДПРОГРАММЫ /Считывает клавиатуру, помещает /сбрасывает интерфейс клавиатуры код клавиатуры в kpad_pat и kpad_rd movf portb,w /считывает значение portb — /это должен быть код строки andlw B' 11110000' /обеспечивает подавление /нежелательных разрядов movwf kpad_pat bsf status,rpO /устанавливает строку как выход, /на столбец — вход movlw B' 00001110 ' movwf trisb bcf status,rpO movlw 00 movwf portb /гарантирует нулевые значения выходных /значений movf portb,w /считывает значение portb — это должен /быть код столбца andlw B' 00001110 ' /обеспечивает подавление нежелательных /разрядов iorwf kpad pat,1 /логическое сложение результатов /сброс интерфейса клавиатуры bsf status,rpO /устанавливает строку как вход, /столбец — как выход movlw B'11110000' movwf trisb bcf status,rpO clrf return portb /гарантирует нулевые выходные значения /Преобразование коде клавиатуры, содержащегося в kpad_pat, в код символа /ASCII character, сначала формируется адрес (в kpad_add), который /используется для обращения к поисковой таблице. Возврат при символе, /сохраненном в kpad char kp code conv bcf status,c rr f kpad_pat,1 /подавление бита 0, /который не используется clrf kpad_add /определяем строку btfsc kpad_pat,6 goto kpl goto col_find /если строка 1, /kpad add остается без изменений kpl btfsc kpad pat,5 goto kp2 movlw B' 00000100' /сюда, если строка 2 iorwf kpad_add,1 /формируем адрес таблицы goto col find kp2 btfsc kpad_pat,4 goto kp3 movlw B' 00001000' /сюда, если строка 3 iorwf kpad add,1 /формируем адрес таблицы goto col find kp3 btfsc kpad pat,3 goto kp4
8.2. От ключей к малым клавиатурам 203 Пример программы 8.1 . Окончание movlw В' 00001100' /сюда, если строка 4 iorwf kpad_add,1 /формируем адрес таблицы goto col find kp4 movlw D' 16 ' /строка не распознана, /возврат с ошибкой через таблицу goto keypad_op ;теперь определяем столбец col_find btfsc kpad_pat,2 goto cfl goto keypad_op /сюда, если столбец 1, /kpad add остается без изменений cfl btfsc kpad pat,1 goto cf2 movlw B'00000001 ' /сюда, если столбец 2 iorwf kpad__add, 1 /формируем адрес таблицы goto keypad_op /предполагаем, что столбец 3 cf2 movlw В'00000010' iorwf kpad add,1 /формируем адрес таблицы keypad__op movf kpad add,0 call kp table movwf kpad_char /сохраняем символ return /Таблица, вызываемая для преобразования кода, считанного с клавиатуры, /в код реального символа. Обратите внимание, что будет возвращен ASCII-код ;символа в десятичном формате kp_table addwf pci, 1 retlw ' 1 ’ /строка 1 retlw '2 ' retlw ' 3 ' retlw 'A' /Код ошибки retlw ' 4 ' /строка 2 retlw ' 5 ' retlw ' 6 ' retlw 'B ' /Код ошибки retlw ' 7 ' /строка 3 retlw ' 8 ' retlw ' 9 ' retlw 'C ' /Код ошибки retlw । * । /строка 4 retlw ' 0 ' retlw '#' retlw ' D' /Код ошибки retlw 'E ' /Код ошибки Подпрограмма kp_code_conv преобразует коды, считанные с клавиатуры и при- веденные на рис. 8.4 (Ь), в ASCII-коды нажатых клавиш. Она делает это, извлекая адрес, хранящийся в ячейке памяти kpad_add, который используется для доступа к поисковой таблице kp_table. Этот адрес имеет формат, показанный на рис. 8.6. Подпрограмма по очереди проверяет разряды считанного кода, определяя, какая строка и какой столбец яв- ляются активными. По результатам проверки она устанавливает адрес. Затем вызывается поисковая таблица, как это было описано в Главе 5.
204 Глава 8. Человеко-машинные и физические интерфейсы Строка Row 1 = 00 Row 2 = 01 Row 3 = 10 j Row 4 = 11 Столбец i Col. 1 = 00 I Col. 2 = 01 ; Col. 3 = 10 kp. add He используются Рис. 8.6. Формат адреса поисковой таблицы 8.3. Светодиодные индикаторы В первой части этой главы было показано, насколько важными являются индикаторы почти во всех системах, имеющих человеко-машинный интерфейс. Теперь же мы рас- смотрим два наиболее часто используемых типа индикаторов: семисегментный светоди- одный индикатор и ЖК-индикатор. 8.3.1. Светодиодные матрицы: семисегментный светодиодный индикатор Так же, как и ключи, простые светодиоды были представлены в Главе 3. Мы видели, что светодиоды являются визуально привлекательным и эффективным источником света. Они могут управляться от логических элементов или выходов порта и, следовательно, мо- гут быть весьма полезными при отображении простой информации. Все же один светоди- од или даже группа светодиодов очень ограничены с точки зрения информации, которую они могут предоставить. При этом по мере увеличения их количества управлять ими ста- новится все сложнее. Таким образом, имеется ряд стандартных конфигураций, в которых пакетируются светодиоды, включая столбцовые диаграммы, семисегментные индикаторы, точечные матрицы и структуры “звездного взрыва”. Семисегментные индикаторы — это особенно универсальная конфигурация, мы ее уже видели на рис. 8.1 (а, с), а также рис. 8.2 (а). Мы рассмотрим светодиодную реализа- цию этой конфигурации несколько более подробно. Одна цифра, сформированная свето- диодами фирмы Kingbright, показана на рис. 8.7. Именно такой индикатор используется в ПУ АУСМ Derbot (см. рис. 8.2 (а)). Подсвечивая различные комбинации из семи сегмен- тов, можно высветить все числа, а также множество других алфавитно-цифровых симво- лов. Совместно с числом также может высвечиваться десятичная точка, как это показано на рисунке. Однако в индикаторе этого типа возникает проблема, связанная с тем, что если каждый сегмент будет подсвечиваться своим светодиодом, то потребуется 14 соединений — и это только для одной цифры! Если требуется выводить несколько цифр, то количе- ство соединений становится очень большим. В силу этого применяются две простые и разумные методики, направленные на снижение количества необходимых соединений. Соединение с общим анодом/катодом При использовании нескольких светодиодов в простых конфигурациях почти навер- няка одна “сторона” выводов всех светодиодов будет соединена с другими такими же вы- водами. Другими словами, вероятно, что аноды или катоды всех светодиодов будут объе- динены вместе. Это именно то, что делается в разряде семисегментного индикатора, как показано на рис. 8.7 (Ь). Разряд светодиода может иметь форму либо с общим катодом, либо с общим анодом. В разряде индикатора имеется восемь светодиодов (включая деся- тичную точку), однако вместо 16 соединений, которые требовались ранее, сейчас их только
8.3. Светодиодные индикаторы 205 девять — по одному на каждый сегмент и один для общего вывода. Фактическая разводка выводов в показанном примере выполняется в два ряда — по одному ряду вверху и внизу числа. В сумме имеются 10 выводов, при этом общий анод/катод имеет два вывода. Рис. 8.7. Семисегментный индикатор: (а) — семисегментный разряд (светодиоды Kingbright, 12.7 мм); (Ь) — электрические соединения (вверху — общий анод; внизу — общий катод). Воспроизводится с разрешения фирмы Kingbright Elec. Со. Ltd Мультиплексирование разрядов За счет использования общего анода или общего катода количество соединений для одного разряда снижается. Однако отображение одной единственной цифры использу- ется редко, а отображение нескольких разрядов все еще требует большого количества соединений. Четырехразрядный индикатор, например, использующий десятичную точку в каждом разряде, потребует использования 36 соединений. Более того, многоразрядный индикатор может предъявить такие требования к электропитанию, что они окажутся чрезмерными. Так, если будут светиться все сегменты и каждый из них будет потреблять ток в 5 мА, то это приведет к потреблению тока в 180 мА. По этой причине был приме- нен второй важный метод, а именно — мультиплексирование разрядов. С одной стороны, этот метод позволяет нам создать практически-приемлемый индикатор, с другой же — он ставит определенные вопросы, связанные с отработкой некоторых моментов, относящих- ся к работе в реальном времени. Применяемые методы иллюстрируются примером раз- работки, который рассматривается далее. 8.3.2. Пример разработки: семисегментный индикатор ПУ АУСМ Derbot Электрическая схема ПУ АУСМ Derbot, приведенная на рис. АЗ.2, относительно сложна, поскольку ПУ может использоваться как в варианте со светодиодами, так и в ЖК- варианте (однако не в обеих сразу). Одна секция семисегментного светодиодного индика- тора показана на рис. 8.8 (а), на ее основе может быть сформировано понимание мультип- лексирования разрядов. Можно видеть, что все эквивалентные линии сегментов соедине- ны вместе — так, например, сегмент 'а' разряда 1 соединен с сегментом 'а' разряда 2 и т.д. Каждая из этих линий сегментов подсоединяется через резистор (1,2 кОм, не показан) к биту порта. В нашем случае используются индикаторы фирмы Kingbright с общим като- дом на основе светодиодов типа “высокоэффективный красный”.
206 Глава 8. Человеко-машинные и физические интерфейсы (а) Схемы управления разрядами Схемы управления < сегментами Сегмент Разряд порта Сегмент Разряд порта Сегмент Разряд порта а С, 6 е А,2 1 0,0 b с, 7 t А,3 2 С.1 с А, 0 g А,4 3 С.5 d А, 1 d.p. А.5 4 В,0 (Ь) Структура сегментов Структура сегментов для разряда 1 для разряда 3 Структура сегментов для разряда 4 Схемы управления сегментами Структура сегментов для разряда 4 / Разряд 1 / \______________________________t \ Схемы Разряд 2 _______________________________/ \______________________________/ управления ₽11₽ял1“" Разряд! \[ Д Разряд 4 J Рис. 8.8. Блок семисегментного индикатора ПУ АУСМ Derbot: (а) — деталь схемы электрической индикации; (Ь) — временная диаграмма управления разрядами Каждая из линий общего катода разряда подсоединена к “совместимому с логикой” полевому МОП-транзистору. Когда напряжение на затворе транзистора становится высо- ким, транзистор переходит в проводящее состояние и потенциал вывода общего катода становится низким. (Дальнейшие детали, касающиеся переключения транзистора, приво- дятся далее в этой главе.) В результате этого любой сегмент, анод которого находится в состоянии логической единицы, начинает светиться. Значения добавочных резисторов
8.3. Светодиодные индикаторы 207 были подобраны экспериментально с целью минимизации тока при обеспечении прием- лемой видимости. Из опытных данных можно определить, что каждый светодиод имеет прямое напряжение, соответствующее его проводящему состоянию, равное примерно 1,9 В, при этом ток I, проходящий через сегмент, может быть вычислен как: I = (5,0 - 1,9)/( 1200) I = 2,58 мА Этот расчет не принимает во внимание сопротивление “включенного” переключатель- ного транзистора, а также выходное сопротивление порта. Обе эти величины являются пре- небрежимо малыми, по сравнению со значением в 1,2 кОм последовательного резистора. Способ, которым управляется этот индикатор, иллюстрируется временной диаграммой (рис. 8.8 (Ь)). Разряды активируются последовательно в порядке очереди. Если этот про- цесс выполнять с правильной скоростью, то в силу инерционности человеческого зрения, будет казаться, что все цифры разрядов индикатора светятся одновременно. Приведенная временная диаграмма показывает установленные сегменты разряда 4, а также линию об- щего катода разряда 4, установленную в состояние логической 1. Таким образом, разряд 4 включен, в то время как все другие разряды выключены. Это состояние удерживается в течение некоторого периода времени (в общем случае приблизительно равного 5-20 мс), затем разряд 2 высвечивается аналогичным образом. Каждый разряд подсвечивается по очереди и цикл повторяется. Если индикатор управляется от микроконтроллера, то должна быть написана соот- ветствующая программа, отрабатывающая нужную временную диаграмму. Давайте по- смотрим в примере программы 8.2, как это делается на практике. Это очень простая про- грамма, которая управляет светодиодным вариантом ПУ АУСМ Derbot. Она ничего не делает, кроме отображения на разрядах индикатора слова HELP (Помогите). Рис. 8.7 (а) показывает, что для буквы Н должны подсвечиваться сегменты b, с, e,fng. После про- стой инициализации битовая структура для буквы Н устанавливается в портах А и С, посредством установки в состояние логической 1 каждого из разрядов, подсоединенных к “включенному” сегменту. Общий катод разряда 1 также устанавливается в состояние логической 1, после чего вызывается подпрограмма временной задержки в 5 мс. Затем сегменты буквы Н и управление общим катодом разряда 1 заменяются сегментами буквы Е и управлением общим катодом разряда 2. Программа продолжает выполняться для всех четырех букв, после чего опять возвращается в начало цикла. Пример программы 8.2. Управление семисегментным светодиодным индикатором ПУ АУСМ Derbot ;led_disp_tst /Тестирует семисегментный 4-х разрядный светодиодный индикатор ПУ АУСМ /АУСМ Derbot посредством вывода на него слова "HELP" / Т JW 17.06.05 включения /Тактовая частота приблизительно равна 1 МГц /Слово конфигурации: сторожевой таймер выкл., таймер /питания вкл. , кодовая защита i Порт В ЗЫКЛ . , RC-генератор / 1 Порт A Порт C /0 led seg c led cc digit 4 led cc digit 2 /1 led seg d keypad col 3 led cc digit 1 /2 led seg e keypad col 2 Interrupt op /3 led seg f keypad col 1 SCL ; 4 led seg g keypad row 4 SDA /5 led seg dp keypad row 3 led cc digit 3 / 6 - keypad row 2 led seg a /7 - keypad row 1 led seg b
208 Глава 8. Человеко-машинные и физические интерфейсы Пример программы 8.2, Продолжение _______________________________ list p=16F873A ♦include pl6f873A.inc /специфицируем ОЗУ delcntrl equ 20 /используется в delay5 /специфицируем некоторые биты портов /Порт С digl_cc equ 1 /управление разрядом с общим катодом dig2_cc equ 0 dig3_cc equ 5 /Порт В dig4_cc equ 0 org 00 Инициализация bcf status,rpl bsf status,rpO /выбор банка памяти 1 movlw B'00000000' /установка всех разрядов порта на выход movwf trisa movwf trisb movwf trisc bcf status,rpO /выбор банка памяти 0 /установка разряда 1 loop bcf portb,dig4_cc movlw B'00011101' включение сегментов для H movwf porta bcf portc,6 bsf portc,7 bsf portc,digl_cc/ активирование разряда после r установки сегментов call । delay5 /разряд 2 bcf portc,digl cc movlw B'00011110' /включение сегментов для Е movwf porta bsf portc,6 bcf portc,7 bsf portc,d ig2 cc /активирование разряда call delay5 / разряд 3 bcf portc,dig2_cc movlw B"00001110 ' /включение сегментов для L movwf porta bcf portc,6 bcf portc,7 bsf portc,dig3 cc /активирование разряда call delay5 / разряд 4 bcf portc,dig3_cc movlw B" 00011100' /включение сегментов для Р movwf porta bs f portc,6 bsf portc,7 bsf portb,dig4 cc /активирование разряда call delay5 goto loop
8.4. ЖК-индикаторы 209 Пример программы 8.2. Окончание /ПОДПРОГРАММА: отрабатывает задержку, приблизительно равную 5 мс delay5 movlw D'250 ' /запуск 250 циклов movwf delcntrl dell nop ;в этом цикле 5 командных циклов, т.е. 20 мкс пор decfsz delcntrl,1 goto dell return end сегмент a сегмент b сегмент c сегмент d сегмент e сегмент I сегмент g сегмент “точи" Разряд 1 Разряд 2 Разряд 3 Разряд 4 Разряд 1 активен Разряд 2 активен Разряд 3 активен Разряд 4 ! активен 5 мс/дел Рис. 8.9. Выходные сигналы для семисегментного индикатора — отображается слово “HELP” Рис. 8.9 показывает снимок экрана при использовании секции логического анализато- ра комбинированного осциллографа фирмы Agilent, снятый при работающей программе. Показаны все линии сегментов совместно с четырьмя схемами управления разрядами. Ко- гда линия управления общим катодом какого либо разряда находится в состоянии логиче- ской 1, то связанное с ним само соединение катодов будет находиться в состоянии логи- ческого 0 и разряд будет активирован. Так, легко видеть, что для разряда 1 сегменты Ь, с, е, fug включены, формируя букву “Н”. Аналогичным образом, в разряде 2 сегменты a, d, e,f и g формируют букву “Е” и т.д. Процесс повторяется непрерывно, в результате чего высвечивается слово “HELP”. Можно видеть, что сегменты е и/все время включе- ны, в то время как десятичная точка все время выключена. Светодиоды чрезвычайно полезны, однако им присущ ряд недостатков: во-первых, они потребляют значительный ток, что очень чувствительно, по крайней мере, в конструкциях с батарейным питанием, во-вторых, очень трудно, если не невозможно, формировать из них сложные многоразрядные или графические индикаторы. Следовательно, если имеется по- требность в более сложных индикаторах, то одним из решений может быть использование технологии жидких кристаллов (ЖК). 8.4. ЖК-индикаторы ЖК-индикаторы или дисплеи (ЖКД) стали одной из технологий, которые сделали возможной современную революцию в электронике. Они являются существенной частью каждого мобильного телефона, каждого ноутбука и каждого персонального органайзера.
210 Глава 8. Человеко-машинные и физические интерфейсы Жидкий кристалл — это органическое соединение, которое поляризует свет, проходя- щий через него. Жидкий кристалл также реагирует на приложенное к нему напряжение, меняя ориентацию своих молекул, и таким образом изменяя направление создаваемой им поляризации света. Жидкий кристалл может быть помещен между двумя параллельными стеклянными пластинами с соответствующими структурами прозрачных электродов на каждой пластине. Когда к электродам будет приложено напряжение, оптический характер жидкого кристалла изменится, отражая воздействие электродов на кристалл. Был разрабстан широкий диапазон конструкций ЖК-индикаторов и ЖК-дисплеев, включая те, которые базируются на использовании формата семисегментных разрядных и точечных матриц, а также целого ряда графических форм. Многие ЖК-дисплеи общего назначения доступны на коммерческой основе, в то же время для крупногабаритных изде- лий создаются специализированные дисплеи. ПУ АУСМ Derbot использует очень популяр- ный и полезный универсальный формат, который иллюстрируется на рис. 8.2 (Ь). Пока- занный индикатор имеет две строки по восемь разрядов каждая. При этом каждый разряд представляет собой точечную ЖК-матрицу. Распространены также большие индикато- ры, использующие этот формат, — они имеют больше разрядов и больше строк. Непосредственно управлять жидкими кристаллами не так уж и просто. Вместе с тем сейчас мы не будем слишком углубляться в этот вопрос — на данном этапе нам будет дос- таточно знать, что большинство ЖК-индикаторов, в том числе и показанный на рис. 8.2 (Ь), содержат свои собственные электронные схемы управления, спроектированные так, что они совместимы с микроконтроллером. Наша задача состоит в том, чтобы понять, как подсоединить эти управляющие схемы. 8.4.1. Микросхема управления ЖК-индикатором HD44780 и ее производные Несколько лет назад гигант электроники Hitachi разработал микроконтроллер, специ- ально спроектированный для управления алфавитно-цифровыми ЖК-модулями такого же типа, что и показанный на рис. 8.2 (Ь). В свою очередь он имел простой интерфейс, кото- рый мог подключаться к микропроцессорам и микроконтроллерам общего назначения. Этот микроконтроллер, HD44780, определил интерфейс, который стал неформальным стандар- том для индикаторов этого типа. Многие изготовители индикаторов интегрировали его в свои изделия. Сейчас существует целое поколение производных устройств от HD44780, которые заменили эту микросхему Hitachi, однако сохранили большую часть ее свойств. В их состав входят микросхемы S6A009 и KS0066U от Samsung. Все эти производные де- монстрируют тенденцию быть настолько похожими на оригинальный микроконтроллер Hitachi, что будут описываться свойства именно HD44780. Однако при разработке кон- кретных систем с индикаторами весьма важно гарантировать, что вы будете работать с корректными техническими данными устройств. Интерфейс HD44780 имеет некоторые особенности, частично связанные с временным масштабом, который определяется самими индикаторами. Основными чертами интер- фейса являются такие характеристики. • Данные передаются по 4- или 8-разрядной шине данных, что определяется пользова- телем. Эти данные могут быть либо командами, либо символьной информацией. Ис- пользование 4-разрядного режима позволяет ограничить весь интерфейс 7-ю разряда- ми, однако процесс передачи данных будет немного более медленным. Разряд 7 шины данных дублирует “флаг занятости”, указывающий, готово ли устройство принять но- вые данные. Это очень важно, поскольку многие операции HD44780 занимают ощути- мое время и должны быть завершены до приема следующей команды. • Управление выполняется с использованием трех линий управления: о линия “выбор регистра” (RS), которая определяет, будут передаваться команда или символьные данные;
8.4. ЖК-индикаторы 211 о линия “чтение/не-запись” (R/W), которая определяет направление перемещения данных; о линия “разрешение” (Е), которая выполняет функцию тактирования с целью син- хронизации передачи данных. • Имеется простой набор команд, который позволяет управлять рабочими характери- стиками. В их состав входят команды инициализации и сброса индикатора, управле- ния положением и характеристиками курсора и т.д. • Пользователь имеет доступ к двум регистрам, в зависимости от состояния линии RS: о регистру команд, используемому для передачи команд (RS = 0); о регистру данных, используемому для передачи отображаемых данных, например кодов символов (RS ~ 1). • Внутренние ресурсы микроконтроллера включают 80 байт ОЗУ индикатора и ПЗУ генератора символов. После включения напряжения питания HD44780 должен выполнить очень специфич- ный процесс инициализации. Очень важно выполнить его абсолютно правильно, иначе индикатор, управляемый HD44780, может просто не работать. Соответствующая после- довательность команд, основанная на рассматриваемом интерфейсе, обычно приводится в спецификациях на индикаторы, доступные на коммерческой основе. Первые команды инициализации зависят от того, работает ли индикатор в 4- или 8-разрядном режиме, флаг занятости в начале выполнения последовательности инициализации не является доступ- ным. В силу этого команды инициализации обычно разделяются вызовами подпрограмм временной задержки соответствующей длительности, что гарантирует окончание одного действия до начала следующего. RS ..................................................../ R/W Г~ \ Шина не Занятость4 DB7 Занятость Код команды Код символа Счетчик адреса Счетчик Счетчик адреса адреса _ Считывание флага Запись занятости и счетчика команды адреса Запись символа Рис. 8.10. Временная диаграмма работы HD44780, 8-разрядный интерфейс HD44780 ограничивается временными требованиями самих ЖК-индикаторов, посколь- ку они демонстрируют тенденцию к тому, чтобы работать медленнее, чем большинство микроконтроллеров. Взаимодействие с ними, следовательно, несет в себе некоторые уни- кальные задачи привязки ко времени. Пример временной диаграммы для 8-разрядного интерфейса показан на рис. 8.10. Все передачи данных на ЖК-контроллер выполняются с синхронизацией по импульсам на шине Е. При шине RS, первоначально установленной в состояние логического нуля, данные, размещенные на шине данных, интерпретируются микроконтроллером как команды, которые HD44780 принимает и начинает выполнять. Микроконтроллер должен знать, когда передача команды завершится. В силу этого шина
212 Глава 8. Человеко-машинные и физические интерфейсы R/W переходит в состояние логической единицы с тем, чтобы в следующем Е-цикле ЖК- контроллер выдал на шину данных слово, содержащее флаг занятости в качестве стар- шего разряда, а в качестве младших разрядов — значение счетчика адресов внутреннего ОЗУ. Никакие другие данные не могут посылаться на ЖК-контроллер до тех пор, пока флаг занятости не будет сброшен, поэтому он постоянно проверяется. Когда флаг переходит в состояние логического 0, линия RS в данном примере переходит в состояние логической единицы, после чего линия R/W переходит в состояние логического 0, что говорит о том, что следующим будет передаваться код символа. 8.4.2. Пример разработки: использование ЖК-индикатора в ПУ АУСМ Derbot ПУ АУСМ Derbot в своей ЖК-версии использует ЖК-индикатор Powertip РС0802-А. Этот индикатор имеет две строки по восемь символов каждая. Он управляется микро- контроллером ЖК-индикаторов S6A0069, который имеет только что описанные свойства HD44780. Он использует 8-разрядный режим интерфейса. Полная электрическая схема приведена на рис. АЗ.2, детали ЖК-индикатора показаны на рис. 8.11. +5 В 20k L VDD ltj Vo ОВ I VSS Порт С разряд 6 DBO Порт С разряд 7 — 2 x 8-Digit Порт А разрядО — LCD display Порт А разряд 1 — DB3 J Порт А разряд 2 J?®* Powertip PC0802-A Порт А разряд 3 — DB5 H Порт А разряд 4 — DB6 Порт А разряд 5 — DB7 Порт С разряд 5 R/W Порт С разряд 1 E Порт С разряд 0 — RS Рис. 8.11. Подсоединения к ЖК-индикатору Powertip РС0802 с указанием подключений к ПУ АУСМ Derbot Программой, используемой для демонстрации применения дисплея на жидких крис- таллах, является программа keypad_test, которая уже цитировалась в примере про- граммы 8.1. Когда клавиша малой клавиатуры нажата, эта программа идентифицирует нажатую клавишу и передает ASCII-код нажатой клавиши на ЖК-индикатор. Подпро- грамма, предназначенная для того чтобы занести команду или код символа в контроллер дисплея — lcd_write, а также подпрограмма проверки флага занятости — busy_check, показаны в примере программы 8.3. Процесс инициализации можно увидеть, если про- смотреть полный листинг программы, имеющийся на компакт-диске, прилагаемом к этой книге. Подпрограмма IccLwrite начинает свою работу с вызова подпрограммы busy_check с тем, чтобы не предпринимались попытки записи в контроллер индикатора, когда он не будет готов к приему информации. Затем подпрограмма переводит линию R/W в состоя- ние логического 0, чтобы индицировать начало процесса записи. Подпрограмма становится несколько более сложной вследствие того, что аппаратные средства делят 8-разрядную шину, ведущую к контроллеру ЖК-индикатора, между двумя портами (рис. 8.11), по этой причине в подпрограмме должны выполняться две операции сдвига вправо. Как только корректные данные будут установлены в портах, линия разрешения, помеченная как lcd_E, переходит в состояние логической 1, индицируя завершение передачи данных.
8.4. ЖК-индикаторы 213 Подпрограмма busy_check сначала устанавливает порт А как выход. Значение RS, которая может быть в любом логическом состоянии, сохраняется. Затем эта линия пере- водится в состояние, соответствующее логическому 0, a R/W устанавливается в состоя- ние логической 1, что создает условия считывания состояния флага занятости. Затем линия Е стробируется логической 1 и выполняется проверка состояния флага занятости. Подпрограмма будет циклить до тех пор, пока флаг занятости не будет сброшен. Пример программы 8.3. Программа тестирования малой клавиатуры и подпрограммы управления ЖК-индикатором___________________________________________________ /Ожидает, пока флаг занятости не будет сброшен и выдает слово, /содержащееся в lcd_op, на ЖК-индикатор. /RS должна быть предварительно установлена в требуемое состояние, /это состояние сохраняется lcd_write call bcf busy_check portc,lcd_rw bcf status,c rrf lcd_op,l /формирование выходных разрядов, выходное /слово задает состояние портов А и С bcf portc,6 /устанавливает значение разряда 0 шины btfsc status,с bsf portc,6 bcf status,с rrf lcd_op,1 bcf portc,7 /устанавливает значение разряда 1 шины btfsc status,с bsf portc,7 movf lcd_op,0 movwf porta bsf portc,lcd_E bcf portc,lcd_E return /Проверяем флаг занятости и ожидаем, пока он не сбросится busy_check bsf status,грО /выбор банка памяти 1 busy_loop movlw В'00111111' /установка всех разрядов порта А на вход movwf trisa bcf status,грО bcf flags,0 btfsc portc,lcd_RS /сохраняем бит RS в переменной flags bsf flags,0 bcf portc,lcd_RS /доступ к регистру команд bsf portc,lcd_RW /установка на чтение bcf portc,lcd_E bsf portc,lcd_E btfsc porta,lcd_busy /проверка флага занятости, /цикл, если он еще установлен goto busy_loop bcf portc,lcd_E bsf status,грО /выбор банка памяти 1 movlw В'00000000' /установка всех разрядов порта А на выход movwf trisa bcf status,грО bcf portc,lcd_RS btfsc flags,0 /восстановление бита RS bsf portc,lcd_RS return
214 Глава 8. Человеко-машинные и физические интерфейсы ЖК-индикаторы, например, только что описанного типа, чрезвычайно полезны в мире малых и средних встроенных систем. Они потребляют мало электроэнергии и сравнитель- но гибки в использовании. К их недостаткам следует отнести то, что формирование с ни- ми интерфейса может вызывать определенные затруднения, при этом даже выдача на них минимальных сообщений может потребовать выполнения объемных блоков программно- го кода. Вследствие того, что их интерфейс работает медленно, ЖК-индикаторы могут стать ограничительным фактором в высокоскоростных системах. 8.5. Основная идея — формирование интерфейса с физическим миром Независимо от того, имеет ли встроенный микроконтроллер человеко-машинный интерфейс, он, конечно же, будет взаимодействовать с физическим миром. Для того что- бы это делать, он должен обладать способностью определять состояние физических пере- менных величин и, кроме того, он должен иметь возможность управлять этими перемен- ными. Такое взаимодействие с физическим миром выполняется через использование раз- личных преобразователей, которые сами по себе представляют обширное поле для изуче- ния и исследования. Входные преобразователи, которые называются датчиками или сен- сорами, воспринимают и преобразуют физические переменные величины в электрические переменные. Примерами датчиков могут быть оптические датчики, датчики температуры, а также позиционные датчики, включительно с датчиками расстояния или кругового сме- щения. Выходные преобразователи преобразуют электрические переменные в физиче- ские переменные. Преобразователи, которые создают физическое перемещение, называ- ются исполнительными механизмами или силовыми приводами. Именно они будут пред- ставлять для нас основной интерес. Примерами исполнительных механизмов могут быть соленоиды и электромоторы. В нашем исследовании встроенных систем нам необходимо знание того, какие преобразователи имеются, что они могут делать и как можно органи- зовать с ними интерфейс. Таким образом, в оставшейся части этой главы мы рассмотрим некоторые методы формирования интерфейса, которые всегда являлись довольно важ- ными для встроенных систем. Мы рассмотрим также преобразователи, используемые в АУСМ Derbot. Хотя это и может показаться произвольным выбором, однако следует заметить, что выбор именно этих преобразователей в качестве учебного примера хорош настолько же, как и любой другой — в данной книге просто невозможно привести ис- черпывающий обзор всех существующих преобразователей. 8.6. Некоторые простые датчики В настоящее время имеется обширный диапазон видов датчиков — одни из них имеют длительную историю, а другие основаны на самых новейших технологиях. В их составе имеются “интеллектуальные датчики”, которые интегрированы в интегральные схемы и обладают встроенным потенциалом обработки сигналов. Все они базируются на каких-либо физических явлениях, приводящих к преобразованию физических перемен- ных в электрические сигналы, иногда через промежуточные переменные. Здесь мы будем рассматривать электромеханические, оптические и ультразвуковые датчики. Некоторые из них показаны на рис. 8.12. 8.6.1. Микропереключатель Использование микропереключателей было основным способом распознавания ме- ханической позиции на протяжении многих лет и вполне вероятно, что такое положение сохранится в ближайшие годы. Обычно они имеют форму однополюсного двухходового
8.6. Некоторые простые датчики 215 переключателя с рычажком или роликом, приводящим микропереключатель в действие. Существующие микропереключатели имеют диапазон от сверхминиатюрных до больших и массивных, предназначенных для интенсивного использования в промышленной обста- новке. Электрически их можно подключать почти как обычные двухпозиционные пере- ключатели, используя одну из схем, показанных на рис. 3.7. В промышленных примене- ниях могут приниматься дополнительные меры с целью минимизации электрических по- мех. В АУСМ Derbot два микропереключателя используются в качестве “датчиков толчка”, один из которых виден на рис. 8.12. Рис. 8.12. Некоторые из датчиков и исполнительных механизмов АУСМ Derbot: ультразвуковой датчик расстояния, смонтированный на сервоприводе фирмы Futaba позади фотосопротивления и переключателя 8.6.2. Фотосопротивления Фоторезистор (ФР) изготавливается из полупроводникового материала, открытого для воздействия света. Когда на него попадает свет, он создает в материале электронно-ды- рочные пары, которые увеличивают его проводимость. Когда источник света удаляется, электронно-дырочные пары рекомбинируют и проводимость падает. Общий эффект заклю- чается в том, что по мере увеличения освещенности ФР его сопротивление падает. В АУСМ Derbot используется ФР NORP12, изготовленный фирмой Silonex, сопротив- ление которого в условиях полной темноты приблизительно равно 20 МОм, а при ярком освещении его сопротивление падает приблизительно до нескольких сот Ом. Он может быть соединен в простой делитель напряжения с целью формирования выходного напря- жения, как это показано на рис. 8.13. АУСМ Derbot имеет три сенсора этого типа, которые он использует в режиме поиска света. Эти датчики можно видеть на схеме, приведенной на рис. А3.1. Они подсоединены к входам аналого-цифрового преобразователя, как это будет описано в Главе 11. 8.6.3. Оптическое обнаружение объектов Оптические методы очень полезны при распознавании объектов и поверхностей. В одной конфигурации присутствие объекта можно распознать, если он разбивает пучок
216 Глава 8. Человеко-машинные и физические интерфейсы света, в другой — если он отражает пучок света. Имеется большое количество датчиков, в которых источник света и собственно датчик объединены в одном корпусе. АУСМ Derbot использует отражательные оптические датчики типа ОРВ608А, изготовленные фирмой Optek. 10k OB (а) ОТРАЖАЮЩАЯ ПОВЕРХНОСТЬ Анод Катод Коллектор Эмиттер Рис. 8.14. Отражательный оптический датчик: (а) — принцип работы; (Ь) — электрические соединения Рис. 8.13. ФР NORP12, подсоединенный по схеме делителя напряжения, указаны типичные выходные напряжения Принцип работы данного датчика иллюстрируется на рис. 8.14 (а). Датчик состоит из инфракрасного светодиода и фототранзистора, которые смонтированы в одном пласт- массовом корпусе. Материал корпуса пропускает инфракрасные лучи, однако отфильт- ровывает окружающий видимый свет. Если на соответствующем расстоянии перед дат- чиком поместить отражающую поверхность, то некоторая часть излучаемого света будет отражаться, попадая на фототранзистор, который переходит в проводящее состояние. Если датчик подсоединен к схеме по рис. 8.14 (Ь), то выход схемы Vo соответствует логической 1, когда отраженный свет отсутствует, и переходит в состояние логического 0, если отра- жающая поверхность присутствует. Значения резистора зависят от характеристик датчи- ка; значения, приведенные на рисунке, следует рассматривать только как пример. Рассто- яние между датчиком и отражающей поверхностью является критическим параметром для многих датчиков такого типа. При этом наиболее распространенным является значе- ние, приблизительно равное 3 мм.
8.6. Некоторые простые датчики 217 8.6.4. Использование оптического датчика в качестве датчика поворота В АУСМ Derbot только что описанные оптические датчики используются для форми- рования очень простых датчиков поворота, как показано на рис. 8.15. Картонная лента с очень простым черно-белым рисунком (см. рис. АЗЛ) прикреплена к колесу, при этом лицевая сторона датчика позиционирована приблизительно на расстоянии 3 мм от нее. Когда колесо поворачивается, датчик формирует приблизительно прямоугольный сигнал с переходом в логическую единицу всякий раз, когда мимо него проходит черная секция. (Фактическая форма сигнала показана на рис. 8.20, требования по выделению сигнала будут исследоваться далее.) Если эти импульсы считать, то они могут использоваться как базис для замеров рас- стояния в АУСМ Derbot. Эта тема будет развиваться далее в последующих главах. Необ- ходимо также отметить, что использованный нами датчик поворота очень груб, по сравне- нию с коммерчески-доступными устройствами. В то время как датчик поворота АУСМ Derbot генерирует 16 импульсов на один оборот колеса, коммерчески-доступные устрой- ства могут генерировать сотни импульсов на один поворот вала, обеспечивая намного более высокое разрешение. Рис. 8.15. Отражательный оптический датчик, используемый в АУСМ Derbot в качестве датчика поворотов 8.6.5. Ультразвуковой датчик объектов Ультразвук широко используется в датчиках и измерительных устройствах — от про- стого замера расстояния до получения сложных изображений в медицинских применени- ях. АУСМ Derbot использует ультразвуковой отражательный датчик для того, чтобы об- наружить препятствия на своем пути или обеспечить возможность АУСМ двигаться па- раллельно стенке. Соответствующий датчик, Devantech SRF04 виден на рис. 8.12. Датчик состоит из передатчика и приемника и, в той мере, в которой он основан на принципе отражения, данный датчик изначально подобен отражательному оптическому датчику. Однако большое различие между ними связано с фактом того, что источник ультразвука является импульсным, кроме того измеряется время, необходимое для того, чтобы эхо-сигнал возвратился от препятствия; по этому времени вычисляется расстояние до объекта. Временная диаграмма работы ультразвукового датчика показана на рис. 8.16. Логический импульс подается на вход модуля триггера. Это инициализирует генерацию пакета ультразвуковых импульсов, состоящего из восьми импульсов. Эхо-выход модуля затем переходит в состояние логической единицы и остается в этом состоянии, пока не будет распознан эхо-сигнал. После чего этот выход переходит в состояние логического
218 Глава 8. Человеко-машинные и физические интерфейсы 0. Если замерить длительность эхоимпульса, то можно вычислить расстояние до объекта, вызвавшего отражение ультразвука. Вход I триггера Ультразвуковые импульсы, _____________I посылаемые модулем Эхо-импульс____________ Принятый эхо-сигнал Рис. 8.16. Упрощенная временная диаграмма работы ультразвукового дальномера SRF04 8.7. Больше о дискретных входах Если микроконтроллер должен получать логические сигналы, то необходимо, чтобы эти сигналы имели уровни напряжения, которые были бы распознаны как логический 0 или логическая 1. Эти уровни напряжения обычно определяются семейством логических микросхем, например ТТЛ (транзисторно-транзисторная логика) или КМОП-структуры (комплементарная МОП-структура). Когда одно устройство соединено с другим, оба они запитываются одинаковым напряжением и содержат микросхемы одной и той же серии, то обычно будет безопасно предположить, что логические уровни будут безопасно и на- дежно передаваться. Однако если сигналы были сгенерированы источником, построенным не на логических микросхемах, а, например, датчиком, или же если они были получены после прохождения длинной линии связи, а также если они были объектом воздействия помех, то может оказаться, что они не будут правильно интерпретироваться приемником. 8.7.1. Входные характеристики 16F873A Для того чтобы определить, будет ли сигнал правильно принят устройством, собран- ным на основе логических схем, необходимо прежде всего понимать входные характе- ристики этого устройства. Характеристики для одного разряда порта 16F873A схематично показаны на рис. 8.17. Из этого рисунка можно видеть, что любое входное напряжение, лежащее между 0 и 0,8 В, интерпретируется как логический 0, а любое входное напряже- ние, лежащее между 2 и 5 В, интерпретируется как логическая 1. Входное напряжение, лежащее между указанными двумя областями, не определено. Если входное напряжение превысит 5 В, то имеется опасность повреждения устрой- ства. Логические входные цепи, однако, почти неизменно имеют внутренние защитные диоды, один из которых соединен между входом и землей, а другой — между входом и шиной питания. Соответствующие схемы приведены на рис. 8.19 (а). Оба диода подсое- динены так, чтобы при нормальной работе они были смещены в обратном направлении. Однако если входное напряжение превысит напряжение на шине питания на величину, способную вызвать переход диода в проводящее состояние, то диод, соединенный между шиной питания и входом, начнет проводить и входное напряжение будет зафиксировано на уровне напряжения питания. Точно так же, если входное напряжение упадет ниже 0 В на достаточную величину, то другой диод также начнет проводить. Этот механизм обес- печивает определенную защиту на входных цепях.
8.7. Больше о дискретных входах 219 Т Невосстановимое повреждение устройства — 5В , ч . и.. (Напряжение питания) Логическая 1 Значение “абсолютного максимума” Значение “абсолютного минимума” 2 В ________________________ Неопределенный логический уровень 0,8 В ---------------------- Логический 0 0 В _________________________ -0,3 В ---------------------- Невосстановимое повреждение устройства Рис. 8.17. Уровни входного напряжения для одного бита порта, напряжение питания равно 5 В В случае 16F873A защитные диоды срабатывают при +5,3 или -0,3 В. Однако они не имеют неограниченных возможностей; максимум фиксированного входного тока опреде- лен как ±20 мА. Если абсолютные максимальные напряжения будут значительно пре- вышены, то произойдет повреждение входных цепей, которое, вероятно, начнется с раз- рушения защитного диода. 8.7.2. Обеспечение корректных логических уровней и защиты входных цепей В круг ответственности разработчика входит гарантировать то, что устойчивое состо- яние входного напряжения всегда соответствует одному из двух распознаваемых логиче- ских уровней, то есть его значение должно всегда соответствовать одной из затемненных зон, показанных на рис. 8.17. Уровень входного напряжения может быстро проходить через промежуточную зону неопределенности, но он не должен там задерживаться. Оно, напря- жение, никогда не должно выходить за пределы допустимого диапазона. При этом, оно всегда будет соответствовать этим условиям, если сигналы генерируются локально дру- гим логическим устройством, относящейся к той же серии. Если же, однако, сигнал был передан на “большое” расстояние, возможно от удаленного датчика, или, например, если имеются помехи либо сигнал изначально не имел “логической” природы, то могут воз- никнуть проблемы. На рис. 8.18 приведены эскизы ряда форм, которые может принимать нарушенный сигнал. Сигнал (а) имеет положительные выбросы, которые потенциально могут повре- дить входные схемы. Сигнал (Ь) аналогично имеет выбросы напряжения. В то время как они не на том уровне, который повреждает входные схемы, они все же могут привести к получению неверных результатов, особенно если сигнал должен подаваться на вход счет- чика, либо же он представляет собой последовательный тактовый сигнал или сигнал дан- ных. Сигнал (с) имеет очень пологие фронты, возможно из-за эффекта фильтрации в длин- ном кабеле или же потому, что источником сигнала является датчик. И, наконец, сигнал (d) походит на приемлемо корректный логический сигнал, однако он смещен вверх в ре- зультате наличия напряжения смещения. Причиной этого могла бы быть передача сиг- нала на большое расстояние при наличии разности опорных потенциалов земли между передатчиком и приемником.
220 Глава 8. Человеко-машинные и физические интерфейсы Рис. 8.18. Различные формы искажения сигнала: (а) — всплески сигнала, потенциально опасные для входа устройства; (Ь) — помехи в сигнале; (с) — чрезмерно пологие фронты; (d) — постоянное смещение сигнала Имеется целый ряд методов, при помощи которых можно попробовать исправить про- блемы, подобные выше описанным, и гарантировать корректные логические уровни сиг- налов. Они рассматриваются в любом хорошем учебнике по электронике. Рис. 8.19 иллю- стрирует три таких метода. Рис. 8.19. Некоторые простые методы кондиционирования дискретного входа: (а) — использование защитных диодов; (Ь) — фильтрация выбросов напряжения при помощи триггера Шмитта; (с) — изоляция сдвига уровня при помощи оптического изолятора
8.7. Больше о дискретных входах 221 Ограничение выбросов напряжения при помощи токоограничивающих резисторов Уже было упомянуто, что если через защитные диоды будет протекать слишком силь- ный ток, то диоды перегорят. Следовательно, если имеется возможность повреждения защитных диодов, то стоит включить последовательно с ними добавочные резисторы, что- бы ограничить ток, который может через них протекать. Соответствующие схемы при- ведены на рис. 8.19 (а). Этот метод позволил бы подкорректировать искаженный сигнал, показанный на рис. 8.18 (а), если величина выбросов не будет слишком большой. Предположим, рассматривая рис. 8.18 (а), что максимально допустимый ток через диод равен 20 мА, Rprot равно 1 кОм, а верхний защитный диод начинает проводить, когда вход- ное напряжение становится равным 5,3 В. В этом случае максимально допустимый выброс напряжения будет иметь пиковое значение, равное [(20 мА х 1 кОм) + 5,3], т.е. около 25 В. Триггер Шмитта Триггер Шмитта был описан в Главе 3. Он обеспечивает простое и надежное средст- во формирования фронтов для логического сигнала, показанного на рис. 8.18 (с). Аналоговая фильтрация входных сигналов Иногда логический сигнал искажается помехами, которые не несут потенциальной опасности повреждения микроконтроллера, но могут вызывать проблемы в работе систе- мы. Например, если сигнал поступает на вход счетчика, то может иметь место ложное сра- батывание счетчика, если в сигнале будут присутствовать выбросы напряжения. Простой RC-фильтр, показанный на рис. 8.19 (Ь), иногда достаточен, чтобы удалить низкоуровне- вые помехи. Фронты сигнала, которые будут сглажены фильтром, могут быть восстанов- лены посредством использования триггера Шмитта. Этот подход может решить проблемы с сигналом, показанным на рис. 8.18 (Ь). Рис. 8.20 показывает осциллограмму сигнала на выходе одного из отражательных оп- тических датчиков АУСМ Derbot. Соединения с ним выполнены поблизости от электро- мотора, который, будучи электромотором постоянного тока со щетками, является сильным источником помех. Сигналы от датчика соединены с входами таймера 0 и таймера 1. В то время как сигнал не выглядит серьезно искаженным, однако небольшие выбросы на- пряжения, которые присутствуют в нем, вполне достаточны для того, чтобы вызвать не- правильное срабатывание счетчика. Рис. 8.20. Сигнал отражательного оптического датчика АУСМ Derbot
222 Глава 8. Человеко-машинные и физические интерфейсы Как показывает электрическая схема, приведенная на рис. А3.1, RC-фильтр, имеющий значения компонент R = 11 кОм, С = 10 нФ (т. е. его частота среза близка к 1,4 кГц) вве- ден в цепь сигнала. Его частота среза много выше максимальной частоты в 40 Гц, ожи- даемой от датчика поворота вала, вместе с тем она адекватна для устранения эффектов выбросов напряжения. А входы на триггерах Шмитта обоих таймеров служат для того, чтобы исправить замедленную скорость изменения входного сигнала. Оптическая изоляция Оптический изолирующий элемент, показанный на рис. 8.19 (с), является очень полез- ным средством защиты логического входа, особенно, когда сигнал был получен со значи- тельного расстояния. Входной сигнал управляет светодиодом, световой выход которого активизирует фототранзистор. Между входом и выходом нет электрических соединений, в силу чего такая проблема, как разность потенциала земли, показанная на рис. 8.18 (d), может быть разрешена. Фильтрация дискретного входа Многие интегральные схемы, разработанные для того чтобы принимать сигналы и могущие нести помехи, реализуют некоторую форму цифровой фильтрации входных сиг- налов, встроенную в их входные цепи. Также обстоит дело и с микроконтроллером 'F873A, имеющим, как мы будем видеть в Главе 10, асинхронный последовательный вход. Простая стратегия цифровой фильтрации заключается в трехкратной последовательной выборке входного сигнала с последующим использование мажоритарной схемы для определения логического значения, которое будет принято. Таким образом, если будут распознаны две логические единицы и один логический ноль, то будет принято логическое значение, со- ответствующее 1. Ноль же, возможно представляющий собой результат сбоя из-за помех, будет отброшен. Осуществление выборки должно, конечно же, производиться с большей частотой, чем любая ожидаемая частота изменения входного сигнала. 8.7.3. Устранение дребезга контактов переключателя Специфическая проблема, связанная с механическими переключателями, заключается в том, что их контакты в буквальном смысле дребезжат в момент замыкания. Это приво- дит к возникновению короткого периода времени, обычно меньшего 10 мс, когда состоя- ние переключателя “прыгает” между разомкнутым и замкнутым состояниями. При вклю- чении обычной электрической нагрузки, например электролампочки, это не проблема и мы даже ничего не замечаем. Когда же переключатель соединен с цифровой схемой, осо- бенно с такой, которая имеет быструю реакцию или же является счетчиком, то эффект может оказаться бедственным. Существует ряд стандартных методов устранения эффекта дребезга контактов пере- ключателя. Описание аппаратных методов, в общем случае основанных на использовании обычных триггеров или же триггеров Шмитта, может быть найдено в любом хорошем учебнике по электронике. Здесь же нам представляется интересным кратко исследовать программные методы, ибо они могут быть без дополнительных издержек реализованы в системе. Рис. 8.21 показывает две имеющиеся возможности. На рис. 8.21 (а) и (Ь), переклю- чаемый вход опрашивается (то есть периодически считывается) с периодом опроса, боль- шим, чем период дребезга контактов переключателя. Если, как это показано на рис. 8.21 (а), состояние переключателя изменится, а дребезг будет иметь место между опросами, то по- лученный входной сигнал будет носить чисто переключательный характер. Если же вход будет опрошен во время дребезга контактов переключателя, как показано на рис. 8.21 (Ь), то считанное логическое значение окажется непредсказуемо до следующего опроса. Либо будет распознано предшествующее логическое значение, которое и будет сохранено в течение следующего интервала опроса (пунктирная линия), либо будет распознано новое
8.7. Больше о дискретных входах 223 логическое значение (сплошная линия), которое и будет сохраняться в течение следую- щего интервала опроса. В любом случае сигнал переключения будет чистым. Иногда программист не захочет опрашивать вход, а вместо этого предпочтет исполь- зовать прерывание. Если прерывание вызывается одним переключателем, переходящим в известное состояние (например, всегда переходящим из состояния логической 1 в со- стояние логического 0), то дребезг контактов вряд ли может вызвать проблему. Однако прерывание может вызываться одним из нескольких переключателей, например как при чтении малой клавиатуры, описанной ранее в этой главе. Если состояние переключателя будет считываться немедленно после возникновения прерывания, имеется вероятность, что считывание произойдет во время дребезга контактов переключателя. В данном слу- чае после, первого обнаружения изменения состояния переключателя, можно ввести ко- роткую программную временную задержку. Т. о. состояние переключателя можно полу- чить по окончании временной задержки, когда дребезг контактов уже завершится. (а) V'o Выход 14- переключателя Периодический опрос входа Распознанный 1 входной сигнал' 0 (Ь) V'o Выход Vs- переключателя Периодический опрос входа Распознанный -| входной сигнал Дребезг контактов переключателя t t Дребезг контактов переключателя 1. t Рис. 8.21. Устранение дребезга контактов переключателя посредством периодического опроса состояния входного сигнала: (а) — периодический опрос состояния входного сигнала пропускает период дребезга; (Ь) — момент опроса совпадает с периодом дребезга
224 Глава 8. Человеко-машинные и физические интерфейсы 8.8. Исполнительные механизмы: электромоторы и сервоприводы Общим требованием к встроенным системам, как правило, является их способность инициировать физическое перемещение. Обычно это либо линейное движение, то есть дви- жение по прямой линии, или же вращательное движение. Многие из исполнительных механизмов, используемых для того чтобы создать эти движения, имеют электрическую природу. Так, соленоиды могут использоваться для создания линейного движения, сер- воприводы — только углового, а электромоторы постоянного тока или шаговые элек- тродвигатели — для углового или вращательного. Другие методы создания исполни- тельных механизмов, особенно для больших усилий, включают использование пневма- тики и гидравлики. 8.8.1. Электродвигатели постоянного тока и шаговые электродвигатели Электродвигатели постоянного тока и шаговые электродвигатели очень широко ис- пользуются во встроенных системах. Будучи основанными на различных принципах ра- боты, они, тем не менее, демонстрируют тенденцию конкурировать за использование в сходных приложениях. Если создать для них правильную рабочую среду, то оба эти вида исполнительных механизмов могут быть использованы как для создания непрерывного вращательного движения, так и обеспечения точных угловых смещений. Электромоторы постоянного тока имеют диапазон своего различия — от чрезвычайно больших и мощных до очень маленьких и экономных. Так электромоторы постоянного тока приводят в движение, например, огромные электропоезда и, в то же время, приво- дят в действие крошечные механотронные системы. Причины их популярности заклю- чаются в их широком диапазоне скоростей, способности управлять этими скоростями, а также потенциально высокой эффективностью. Если их использовать с измерительным потенциометром обратной связи или датчиком поворота вала, то они могут обеспечить точное угловое позиционирование. Маленькие электромоторы постоянного тока, того же типа, что и применяемые во встроенных системах, имеют обычно постоянные магниты — т.е. магнитное поле, внутри которого вращается якорь, обеспечивается одним или боль- шим числом постоянных магнитов. Это приводит к одному из привлекательных свойств электромоторов постоянного тока — простоте работы. Должна управляться только об- мотка якоря. Большая притягательная черта шаговых электромоторов — это их способность не- посредственно взаимодействовать с цифровыми системами. Каждый цифровой импульс, посланный на контроллер шагового электромотора, может использоваться для того, что- бы сместить позицию вала электромотора на заранее известный угол. Следовательно, в теории, микропроцессор или микроконтроллер может управлять скоростью вращения и угловым положением вала электромотора с высокой степенью точности и без обратной связи. На практике такая выгодная позиция полностью не достигается. Шаговые электро- двигатели имеют не очень хорошие пусковые характеристики, демонстрируют тенденцию к механическому резонансу в отдельных диапазонах скоростей, а также теряют вращатель- ный момент на высоких скоростях, что ограничивает скорость их работы. Любая из наз- ванных особенностей может привести к тому, что электромотор потеряет синхронизацию с дискретным приводом. И, что важнее всего, — шаговые электродвигатели имеют тенден- цию быть менее эффективными и более сложными в управлении, чем электромоторы по- стоянного тока. Выбор между шаговым электромотором и электромотором постоянного тока не всегда очевиден. В общем случае, если требуется точное и ограниченное вращательное движение, а потребляемая мощность не имеет первостепенной важности, то, как правило, используют
8.8. Исполнительные механизмы: электромоторы и сервоприводы 225 шаговые электромоторы. Если же требуется более низкая точность и, возможно, более высокое быстродействие и/или более высокая эффективность, то наилучшим выбором будет использование электромоторов постоянного тока. В АУСМ Derbot необходимо обеспечить управляемое вращательное движение колес. Эти колеса выполняют функцию управления движением, при этом важно обеспечить кон- троль расстояния и скорости. Все эти функции могли бы быть реализованы посредством использования шаговых электромоторов. Однако простота управления электромоторами постоянного тока, совместно с их хорошей эффективностью, что имеет большое значение для АУСМ Derbot, работающего от батареек, привела к выбору именно этого типа электро- мотора. Для эффективного управления необходимо использовать какую-то форму обратной связи. Для этого был реализован простой датчик поворота вала, который ранее уже был описан. Исполнение АУСМ Derbot, описанное в этой книге, использует электромотор с редуктором, изготовленный фирмой MFA/COMO Drills. Этот электромотор изображен на рис. 8.22, а его основные технические данные приведены в таблицах А3.1 и АЗ.2. Рис. 8.22. Электромотор с редуктором АУСМ Derbot, изготовленный фирмой MFA/Como, индекс для ссылок: RE280/1 8.8.2. Угловое позиционирование: сервопривод Сервопривод — это устройство, которое в силу своей популярности претендует на исключительное использование обобщенного названия “сервомеханизм”! Широко ис- пользуемое в радиоуправляемом моделировании и робототехнике, оно позволяет осуще- ствить точное угловое позиционирование. Выход сервопривода — это вал, который может занимать угловую позицию в диапазоне, равном примерно 180 . Входом сервопривода яв- ляется поток импульсов, в общем случае имеющих частоту повторения 50 Гц (т.е. период следования импульсов равен 20 мс). Ширина входного импульса определяет угловую по- зицию выходного вала. В примере, показанномона рис. 8.23, ширина импульса в 1,25 мс ведет к позиционированию выходного вала на 0, а 1,5 мс — к позиционированию выход- ного вала на 90 , а 1,75 мс — к позиционированию выходного вала на 180. Это пример ши- ротно-импульсной модуляции, которую мы будем рассматривать в последующих главах. В некоторых конфигурациях АУСМ Derbot используется сервопривод Futaba S3003 с тем, чтобы вращать ультразвуковой датчик, обеспечивая, таким образом, возможность одному и тому же датчику выполнять замеры в различных направлениях.
226 Глава 8. Человеко-машинные и физические интерфейсы 90 градусов ' 1,5 мс 1,75 мс О Рис. 8.23. Входные и выходные характеристики сервопривода 180 градусов 8.9. Организация интерфейса с исполнительными механизмами 8.9.1. Простое переключение постоянного тока Только очень малые электрические нагрузки, подобные светодиодам, могут управ- ляться непосредственно битом порта микроконтроллера. Большие же нагрузки, потребля- ющие выше 10 или 20 мА, а также запитываемые напряжениями (более высокие, чем на- пряжение питания логических микросхем), должны подключаться через силовые комму- тационные устройства. Транзисторные ключи обеспечивают простой способ переключения нагрузок посто- янного тока. Рис. 8.24 показывает два используемых типа таких ключей: полевой МОП- транзистор и биполярный транзистор, связывающие бит порта контроллера или выход логического вентиля с резистивной нагрузкой RL. В обеих схемах значение логической единицы, поступающее от микроконтроллера, заставляет течь ток в нагрузке. Как и в слу- чае выхода открытого стока, показанного на рис. 3.6, напряжение питания нагрузки Vs не обязательно должно быть таким же самым, как напряжение питания микроконтроллера. Во многих случаях оно бывает выше, например микроконтроллер, запитываемый от 5 В, может управлять нагрузкой, запитываемой напряжением, равным 12 или 24 В. Биполярный транзистор (рис. 8.24 (а)) требует малого тока базы для переключения намного большего тока коллектора. Полевые МОП-транзисторы (рис. 8.24 (Ь)) требуют скромного напряжения затвора, при ничтожном токе, для включения большого тока стока. Поскольку МОП-устройство управляется чисто напряжением, то его затвор может быть со- единен непосредственно с выходом бита порта. Этот выход должен несколько превышать пороговое напряжение срабатывания затвора, необходимое для включения полевого МОП- транзистора. Эта простота подсоединения делает полевые МОП-транзисторы очень при- влекательным вариантом для переключения нагрузки в микроконтроллерной среде (при условии, что только упомянутое пороговое напряжение может быть превышено).
8.9. Организация интерфейса с исполнительными механизмами 227 (а) (Ь) (с) Рис. 8.24. Транзисторное переключение нагрузок постоянного тока: (а) — резистивная схема, биполярный транзистор; (Ь) — резистивная схема, полевой МОП-транзистор; (с) — индуктивная схема, полевой МОП-транзистор В настоящее время доступны специальные семейства полевых МОП-транзисторов, разработанных для прямого интерфейса с уровнями сигналов логических микросхем. Ха- рактеристики двух примеров таких полевых МОП-транзисторов, выпускаемых компа- нией Zetex, приведены в табл. 8.1. Для любого из перечисленных в таблице транзисторов можно видеть, что если их напряжение “затвор-исток” VGs превысит 3 В, то их сопротив- ление “сток-исток” упадет почти от бесконечности до низкой величины. Насколько низким оно станет, зависит от типа транзистора и его внутренней конструкции. ZVN4306A имеет более низкое максимальное сопротивление “включенного” состояния, равное 0,33 Ома. Его входная емкость, однако, равна 350 пФ. Немного более дешевый ZVN4206A имеет со- противление “включенного” состояния, равное 1,5 Ом, но зато обладает меньшей вход- ной емкостью, равной 100 пФ. Эта входная емкость должна заряжаться цепью управления, когда транзистор переключается из состояния логического 0 в состояние логической 1. Для сильноточных полевых МОП-транзисторов входная емкость становится важным фак- тором, в ряде случаев обуславливающим необходимость использования специальных схем управления. Если нагрузка носит индуктивный характер, подобно электромотору постоянного тока, обмотке шагового электродвигателя, соленоиду или электромеханическому реле, то дол- жны быть предприняты специальные меры предосторожности. Индуктивность сохраняет энергию, когда ток течет в ее магнитном поле. Если приложенное напряжение выключает- ся, необходимо существенно обеспечить путь для тока, идя по которому оно, напряжение,
228 Глава 8. Человеко-машинные и физические интерфейсы упало бы до нуля — в ходе этого процесса индуктивность возвращает сохраненную энер- гию в контур. Обычно это выполняется включением “гасящего” диода, как показано на рис. 8.24 (с). Табл. 8.1. Характеристики двух популярных совместимых с логическими микросхемами полевых МОП-транзисторов Характеристика ZVN4206A ZVN4306A Максимальное напряжение сток-исток, VDS (В) 60 60 Максимальный порог затвор-исток VGS (В) 3 3 Максимальное сопротивление сток-исток во включенном состоянии Rds(oii) (Ом) 1,5 0,33 Максимальный непрерывный ток истока ID, А 0,6 1,1 Максимальное рассеивание мощности (Вт) 0,7 1,1 Входная емкость (пФ) 100 350 8.9.2. Простое выполнение переключений в АУСМ Derbot В АУСМ Derbot транзисторные переключатели используются в ряде мест для вклю- чения и отключения нагрузок — как в основном блоке АУСМ, так и в ПУ. Два из них показаны на рис. 8.25 — они взяты из схемы принципиальной основного блока АУСМ Derbot, приведенной на рис. А3.1. Рис. 8.25. Фрагмент схемы принципиальной АУСМ Derbot — оптические датчики и пьезо-зуммер Пьезо-зуммер потребляет номинальный ток в 9 мА, и запитывается напряжением от 3 до 20 В. В силу этого он может управляться непосредственно от напряжения питания в 5 В, не требуя своего собственного управляющего транзистора. Однако, чтобы миними- зировать нагрузку на микроконтроллере, было решено использовать один такой транзис- тор. Оптические датчики демонстрируют тенденцию к потреблению несколько большей мощности. Для минимизации потребляемого тока, светодиоды двух датчиков соединены последовательно, как показано на схеме. Экспериментальным путем было установлено, что датчики работают хорошо, если сопротивление резистора, включенного последовательно со светодиодами, равно 91 Ом. Приняв (из технических данных на устройства), что прямое напряжение на каждом диоде равно примерно 1,7 В, можно получить, что ток будет равен: I = (5-3,4) /91 = 17,6 мА
8.9. Организация интерфейса с исполнительными механизмами 229 Как и в случае с пьезо-зуммером, выход порта микроконтроллера PIC® смог бы обес- печить переключение такого тока, хотя его значение приближается уже к значению “аб- солютного максимума” в 25 мА. Опять-таки, было принято решение использовать транзи- сторное переключение с целью минимизации нагрузки на микроконтроллер. 8.9.3. Реверсируемое переключение: Н-образный мост Как мы уже знаем, если ток всегда идет в одном направлении, то включение и выклю- чение нагрузки выполняется довольно легко. Однако некоторые нагрузки, например элек- тромоторы постоянного тока или шаговые электродвигатели, нуждаются в том, чтобы к ним прикладывалось напряжение реверсируемой полярности, даже если доступно только однополярное напряжение питания. Способ, которым обычно это достигается, заключает- ся в использовании простой, однако остроумной схемы, называемой Н-образным мостом — эта схема показана на рис. 8.26. В Н-образном мосте две пары переключательных устройств, обычно транзисторов, подключены между шиной питания и О В. Для простоты переключательные устройства на приведенной схеме показаны как ключи, при этом предполагается, что ключ замыкается, когда управляющий сигнал имеет значение, соответствующее логической 1. Пары ключей помечены как А и В. Каждая пара имеет ключ “высокой стороны” и ключ “низкой сторо- ны”. Нагрузка подключается между двумя парами для формирования общей Н-образной конфигурации. Ясно, что ключи в паре никогда не должны одновременно находиться во включенном состоянии, иначе источник питания будет закорочен на землю. Таким обра- зом, обычно они управляются через логический инвертор, как это показано на схеме, с тем, чтобы одновременно только один из них мог быть включен. Рис. 8.26. Принцип работы Н-образного моста Если вход X переключается в состояние, соответствующее логическому 0, а вход Y — логической единице, то состояния ключей будут такими, как показано на схеме, при зам- кнутых правом верхнем и нижнем левом ключах, другие два ключа будут в разомкнутом состоянии. Таким образом путь тока будет пролегать через ключ “высокой стороны” пары В, через нагрузку и через ключ “низкой стороны” пары А. Если два входа будут реверси- рованы, то все ключи изменят свое состояние на противоположное и ток в нагрузке нач- нет протекать в противоположном направлении. Так реализуется реверсное управление током. Если нагрузка является индуктивной, то гасящие диоды должны быть подключены, как показано на схеме. Эта схема, а также ее производные, используется во многих приме- нениях — как маломощных, так и в приложениях, связанных с переключением очень больших токов.
230 Глава 8. Человеко-машинные и физические интерфейсы Маломощная практическая реализация Н-образного моста доступна в форме микро- схемы L293D, изготовляемой фирмой ST Microelectronics. Эта микросхема содержит 4 полумоста, из которых могут быть сформированы 2 полных Н-образных моста. Упрощен- ная схема L293D приведена на рис. 8.27. Она вычерчена таким образом, что каждый по- лумост изображен как логический буфер. Это может показаться не очевидным, однако рассмотрим предыдущую схему, когда вход X находится в состоянии логической 1, тогда выход напряжения от транзисторной пары А будет соответствовать состоянию логической 1, либо состоянию логического 0, когда вход X будет находиться в состоянии логического 0. Буферы 1 и 2 могут формировать завершенный Н-образный мост, то же самое справед- ливо и в отношении буферов 3 и 4. Используются два источника питания — Vls и Vos. Первый запитывает входные логические схемы, а второй — сам мост. Эти два напряже- ния, запитывающие цепи управления электромотором, могут иметь различные значения, при этом Vos не должно быть меньше, чем Vls- Напряжение питания логических схем мо- жет, например, быть равно 5 В, в то время, как напряжение питания нагрузки может быть равно 12 В. Сигнал разрешения поступает сразу на пару буферов, поэтому все ключи моста могут быть легко выключены. В микросхеме имеются внутренние гасящие диоды. Мик- росхема L293D имеет четыре земляных вывода, которые могут быть подпаяны к медной пластинке на печатной плате, обеспечивая возможность ограниченного отвода тепла. Выход 2 Выход 4 ОВ Основные рабочие условия: Выходной ток каждого канала 600 мА, защита от перегрева; Пиковый выходной ток (нерегулярный) равен 1,2 А на канал, устойчивость к высокочастотным помехам (входное напряжение логического 0 - до 1,5 В) Рис. 8.27. Двойной Н-образный мост на микросхеме L293D 8.9.4. Переключение электромоторов в АУСМ Derbot В АУСМ Derbot используются две микросхемы L293D для управления его двумя элек- тромоторами, при этом детали схемы показаны на рис. 8.28. Вместо отдельной схемы уп- равления на каждый логический вход, между ними используется инвертор. Таким образом,
8.10. Сборка АУСМ Derbot 231 электромотор работает либо в одном направлении, либо в другом. Однако каждая из ли- ний разрешения управляются от бита порта, поэтому каждый электромотор может быть заблокирован. Шина питания логических схем подсоединена к шине блока питания 5 В, в то время как шина питания нагрузки подсоединена непосредственно к батарейкам питания — предполагается, что для запитывания электромоторов доступно напряжение, равное 9 В. Внутреннее падение напряжения на интегральных схемах, однако, снижает эту величину, делая ее близкой к 7 В. Каждая из линий разрешения имеет нагрузочный резистор, сопро- тивление которого примерно равно 10 кОм, соединенный между линией и землей, кото- рые не показаны на данной схеме (однако приведены на схеме в Приложении 3). Эти ре- зисторы несут важную функцию блокировки электромоторов, когда микроконтроллер не выполняет управления этими линиями, например во время инициализации. Рис. 8.28. Микросхема L293D, использованная в АУСМ Derbot 8.10. Сборка АУСМ Derbot Если вы собираете АУСМ Derbot, то сейчас вам рекомендуется добавить электромо- торы и их схемы управления, основанные на L293D, получив в результате схему, пока- занную на рис. 8.29. Если вы хотите запустить АУСМ, то вам также потребуется устано- вить пакет батарей, используя отдельную печатную плату и промежуточные подставки. Дальнейшие указания по сборке АУСМ Derbot приводятся на компакт-диске, прилагае- мом к этой книге. Сейчас вы можете одновременно установить плату ПУ в ее светодиодном либо ЖК- исполнении. Программы, которые рассматривались в первых подразделах данной главы, могут быть загружены и протестированы. Эти программы, однако, не обеспечивают воз- можности взаимодействия ПУ с АУСМ — этот вопрос будет рассматриваться в после- дующих главах. 8.11. Применение датчиков и исполнительных механизмов — программа “слепой” навигации АУСМ Derbot При собранном АУСМ Derbot, как только что описывалось, можно запустить програм- му Dbt„blind_Nav, которая находится на компакт-диске, прилагаемом к этой книге, и
232 Глава 8. Человеко-машинные и физические интерфейсы основные свойства которой рассмотрены в примере программы 8.4. Эта программа иници- ализирует движение АУСМ вперед вплоть до момента, когда он наткнется на препятст- вие, факт чего обнаруживается микропереключателями. После этого АУСМ разворачива- ется и двигается вперед в новом направлении. Рис. 8.29. Промежуточная стадия сборки АУСМ Derbot номер 2 Главная программа запускается с метки start, заставляя электромоторы вращаться в прямом направлении. Это легко выполняется простым включением электромоторов. Однако они начинают работать с приличной максимальной скоростью, которая является чрезмерной для такого простого приложения, поэтому используется широтно-импульсная модуляция для установки более медленной скорости. Детали описанного процесса скры- ты в подпрограммах leftmot_fwd и rtmot_fwd, которые вызываются по очереди. Они не включены в пример программы, приведенный ниже, однако отражены в полном лис- тинге, присутствующем на компакт-диске, прилагаемом к этой книге. Эти подпрограммы будут детально рассмотрены в следующей главе. Затем программа входит в цикл по метке loop. Начиная с этого момента, она в повторяющемся режиме проверяет состояние мик- ропереключателей и до тех пор продолжает циклить, пока какой-либо из микропереклю- чателей не будет активирован. Когда микропереключатель сработает, АУСМ остановит- ся, включится приблизительно на 1,5 секунд пьезо-зуммер, после чего будет вызвана
8.11. Применение датчиков и исполнительных механизмов — программа “слепой" навигации АУСМ Derbot 233 подпрограмма широтно-импульсной модуляции. Затем АУСМ развернется за счет того, что один электромотор будет вращаться в прямом направлении, а другой — в обратном. После этого АУСМ возобновит движение вперед, отрабатывая цикл главной программы. Пример программы 8.4. “Слепая” навигация АУСМ Derbot (фрагмент) ;Dbt blind Nav ;АУСМ Derbot перемещается в режиме "слепой" навигации. /Двигается вперед, переключается и поворачивается после соударения. /Для установки приемлемых скоростей используется ШИМ с фиксированной /частотой ,-TJW 05.05.05 Тестировано 09.05.05 (Секции выделения памяти и инициализации опущены) /запуск электромоторов start call leftmot_fwd ; запуск левого электромотора вперед call rtmot_fwd / запуск правого электромотора вперед /проверка на столкновения — реверс и поворот, /проверка замыкания контактов loop btfss portb,us_rt / проверка левого микропереключателя goto rev_rt btfss portb,us left / проверка левого микропереключателя goto rev left call delaylOO goto loop t rev_rt bsf portc,led rt bcf porta,mot en left / остановка электромоторов bcf porta,mot en rt bsf portb,sounder / короткий звуковой сигнал высокого тона от зуммера call delay200 bcf portb,sounder /реверс обеих электромоторов call leftmot rev call rtmot rev call delay500 call delay500 call delay500 call leftmot fwd левый электромотор вперед на поворот call delay500 call delay500 bcf portc,led rt goto start t rev_left bsf portc,led left bcf porta,mot en rt остановка электромоторов bcf porta,mot_en_left bs f portb,sounder короткий звуковой сигнал высокого тона от зуммера call delay200 bcf portb,sounder /реверс обеих электромоторов call leftmot_rev
234 Глава 8. Человеко-машинные и физические интерфейсы Пример программы 8.4. Окончание_________________________________________ call rtmot_rev call delay500 call delay500 call delay500 call rtmot_fwd /правый электромотор вперед на поворот call delay500 call delay500 bcf portc,led_left goto start (подпрограммы опущены) Резюме • Встроенный микроконтроллер должен обладать возможностью взаимодействовать с физическим миром и, возможно, с миром людей. • Большинство функций взаимодействия с людьми могут быть реализованы посредством использования переключателей, клавиатур и индикаторов. • Для взаимодействия с физическим миром микроконтроллер должен быть способен взаимодействовать с широким диапазоном преобразователей. Разработчики должны понимать природу основных существующих датчиков и исполнительных устройств, а также должны быть готовы идти в ногу с прикладной современной технологией. • Формирование интерфейсов с датчиками требует приемлемого уровня знаний в области методов выделения полезных сигналов. • Формирование интерфейсов с исполнительными устройствами требует приемлемого уровня знаний в области методов переключения напряжения питания.
ГЛАВА 9. ДАЛЬНЕЙШЕЕ ИССЛЕДОВАНИЕ ВОПРОСОВ СИНХРОНИЗАЦИИ Мы уже видели в Главе б, какое важное место занимают подсчет и синхронизация в среде встроенных систем. Мы также видели, как просто выполняется подсчет в цифровой форме и как можно преобразовать эту способность к счету в способность измерять время. Теперь мы должны продвинуть эти возможности намного дальше, особенно в области син- хронизации. Как только мы получим хорошие инструментальные средства синхронизации, то сможем использовать их, чтобы подкрепить другие функции микроконтроллера, подоб- ные генерации последовательных данных или широтно-импульсной модуляции. Также мы сможем использовать эти инструментальные средства синхронизации для того, чтобы об- легчить выполнение сложных внешних действий, например генерирование сигналов син- хронизации для системы управления двигателем. Эта глава исследует потребности в счете и синхронизации, имеющиеся во внедренной среде, а также в ней исследуются возможности удовлетворения этих потребностей при приемлемом уровне сложности применяемых методов. В то время как подсчет остается основной методикой, его функция временной привязки проявляется как преобладающий вид активности. Центральной темой этой главы будет исследование усложненных структур счетчиков/ таймеров. Их использование приведет к тому, что микроконтроллер сможет передавать многие из своих привязанных ко времени действий этим аппаратным средствам. При этом программа может продолжать выполняться, делать другие вещи, в то время как аппарат- ные средства будут заботиться о вопросах синхронизации. Упомянутые действия микро- контроллера включают: • поддержание непрерывных функций счета; • регистрацию (“фиксацию”) аппаратными средствами таймера времени произошед- шего события; • использование аппаратных средств таймера для инициализации событий в конкретное время; • такая настройка среды, при которой могут генерироваться повторяющиеся время-ори- ентированные события; • измерение частоты и, следовательно, значений физических переменных, которые могут быть выражены через эту частоту, например количество оборотов мотора. Будут исследоваться структуры, имеющиеся в микроконтроллере 16F873A. Это даст как увеличение знаний в отношении использования этого устройства, а также близких к нему устройств, так и понимание концепций, относящихся к любой микроконтроллерной системе. Многие аспекты будут иллюстрироваться на примере АУСМ Derbot. Необходи- мые указания по соответствующей сборке АУСМ Derbot приведены в заключительном подразделе этой главы. Обратите внимание, что фирма Microchip демонстрирует тенденцию к тому, чтобы применять термин “таймер” к своим модулям счетчиков/таймеров. В этой главе термины “таймер” и “счетчик/таймер” будут рассматриваться как более или менее равнозначные.
236 Глава 9. Дальнейшее исследование вопросов синхронизации 9.1. Основная идея — углубленное исследование вопросов, связанных со счетом и временной привязкой Основываясь на материале Главы 6, сейчас мы переходим к исследованию более слож- ных применений счетчиков и таймеров, как это отмечено в вышеприведенном списке. Способность выполнить это в значительной степени зависит от имеющихся аппаратных средств счетчиков/таймеров. В силу этого в данной главе каждый новый метод счета или временной привязки будет сопровождаться описанием соответствующих аппаратных средств. Таймер 0 семейства PIC® 16 рассматривался в подразделе 6.3 Главы б. Уделите не- сколько минут тому, чтобы еще раз посмотреть на рис. 6.8 и вспомнить о принципиальных функциях, которые он иллюстрирует, если вы чувствуете, что их подзабыли. Его центром является отображаемый на пространство памяти цифровой счетчик, с которым можно вы- полнять операции записи и считывания. Тактовый вход счетчика может браться из двух источников. Может быть выбран либо внешний вход — в этом случае часто говорят, что данный модуль работает в режиме “счетчика”. Альтернативно на счетчик может быть по- дан сигнал от внутреннего генератора — в этом случае говорят, что модуль работает в режиме “таймера”. Может быть использован предварительный делитель частоты, кото- рый делит частоту входного тактового сигнала. Когда счетчик досчитывает до своего мак- симального значения, то происходит его переполнение со сбросом в ноль — в этом случае может генерироваться прерывание. PIC 16F873A имеет три таймера с некоторыми важными дополнительными цепями, которые мы сейчас и рассмотрим. Относительно простые структуры, которые мы уже рас- сматривали, формируют основу более сложных конструкций, к рассмотрению которых мы сейчас также перейдем. 9.2. Таймер 0 и таймер 1 в 16F87XA 9.2.1. Таймер О 16F873A использует стандартный среднего уровня модуль таймера 0. Это та же кон- струкция счетчика/таймера, которая использована в 16F84A. Следовательно, к нему пол- ностью подходит описание, приведенное в подразделе 6.3.3 Главы 6. 9.2.2. Таймер 1 Среднего уровня модуль таймера 0 в PIC ограничен тем, что он имеет всего 8 разрядов. Таймер 1, показанный на рис. 9.1, построен полностью на концепциях таймера 0, однако имеет ряд важных отличий. Прежде всего, он 16-разрядный. Как видно из рисунка, он сформирован из двух 8-разрядных регистров — TMR1H и TMR1L. Это специальные функ- циональные регистры (СФР), которые читаются и записываются обычным способом. Их можно увидеть на карте регистров файлов, приведенной на рис. 7.6. Вместе они обеспечи- вают возможность счета от 0000 до FFFFH или 65536d- Когда счетчик сбрасывается от FFFFH в 0, устанавливается флаг прерывания TMR1IF (виден на схеме структуры преры- ваний, приведенной на рис. 7.10). При соответствующем разрешении прерывания он может использоваться для генерирования прерывания по переполнению. Таймер 1 управляется регистром T1CON, показанным на рис. 9.2. Таймер включается и выключается битом TMR1ON. Таймер имеет три различных источника синхроимпуль- сов, которые показаны на рис. 9.1. При использовании функции счета, внешний вход T1CKI, разделяемый со штырьком 0 порта С, должен использоваться. Для функций синхронизации имеется возможность использования внутреннего генератора синхроим- пульсов Fosc/4. Выбор между этими двумя источниками синхроимпульсов делается
9.2. Таймер 0 и таймер 1 в 16F87XA 237 битом TMR1CS регистра управления. Третий возможный источник синхроимпульсов делается доступным благодаря возможности установки специализированного внешнего генератора таймера 1, подключенного к двум внешним штырькам, показанным на блок- схеме. Это устраняет зависимость работы таймера от частоты основного генератора. Внеш- ний генератор может работать на частоте, полностью отличной от частоты основного гене- ратора, и может также продолжать работать, когда основной генератор блокируется в ре- жиме бездействия. Использование внешнего генератора разрешается битом T1OSCEN. Вход генератора для таймера 1 идентичен входу основного генератора LP (подраздел 3.5.3 Главы 3). Он предназначен для более низких тактовых частот, приблизительно до значения в 200 кГц. Обычно он используется с кварцевым генератором, работающим на частоте 32,768 кГц, которая может быть поделена с целью формирования односекундной временной базы. Примечание 1. Когда бит T10SCEN сброшен, инвертор выключается. Это устраняет ненужный расход электропитания. Рис. 9.1. Блок-схема таймера 1 в 16F87XA (дополнительные метки в заштрихованных полях добавлены автором) U-0 U-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 I — | — | T1CKPS1 | T1CKPS0 | T1OSCEN | T1SYNC | TMR1CS | TMR1ON | Разряд 7 разряды 7-6 разряды 5-4 Разряд 0 Не реализован: читается как “0" T1CKPS1:T1CKPS0: биты выбора предварительного деления входной синхропоследовательности таймера 1 11 = коэффициент предварительного деления 1:8 10 = коэффициент предварительного деления 1:4 01 = коэффициент предварительного деления 1:2 00 = коэффициент предварительного деления 1:1 разряд 3 T1OSCEN: бит управления разрешением генератора таймера 1 = генератор разрешен 0 = генератор выключен (инвертор генератора выключается для устранения ненужного расхода электроэнергии) разряд 2 T1SYNC: бит управления синхронизацией входа внешнего тактирования таймера 1 Когда TMR1CS= 1: 1 = не синхронизовать внешний тактовый вход 0 = синхронизовать внешний тактовый вход Когда TMR1CS = 0: Этот бит игнорируется. Когда TMR1CS = 0, таймер 1 использует внутренний синхрогенератор разряд 1 TMR1CS: бит выбора источника синхропоследовательности таймера 1 1 = внешняя синхропоследовательность от штырька RC0/T10SO/T1CKI (по набегающему фронту) 0 = внутренняя синхропоследовательность (Fosc/4) разряд 0 TMR1ON: бит включения таймера 1 1 = включение таймера 1 0 = выключение таймера 1 Примечание. В одноименном регистре семейства 18 разряд 7 называется RD16. Если он устанавливается в 1, то включается режим “16-ти разрядного чтения/записи”. Рис. 9.2. Регистр T1CON управления таймера 1 (адрес 10ц)
238 Глава 9. Дальнейшее исследование вопросов синхронизации Какой бы источник синхроимпульсов не был выбран, имеется возможность применения предварительного делителя. При использовании только двух битов управления, T1CKPS1 и T1CKPS0, не реализуется использование всего диапазона опций масштабирования, пред- лагаемого таймером 0 — можно использовать только три значения коэффициента деления: 2, 4 и 8. И, наконец, синхронизация внешнего входа разрешается битом T1SVNC — при работе как в режиме сбора данных, так и в режиме сравнения, которые будут описаны в последующих разделах, таймер должен работать синхронно. Однако при работе в асин- хронном режиме он может также продолжать работать, когда микроконтроллер находится в режиме бездействия. Когда выбран внешний источник синхроимпульсов, счетчик всегда инкрементируется по нарастающему фронту сигнала (в таймере 0 может выбираться либо нарастающий фронт, либо срез импульса). При этом для того, чтобы счетчик начал считать, он сначала должен получить срез импульса. Таким образом, имеется опасность того, что первый им- пульс может быть потерян. Мы увидим в приведенной далее программе для АУСМ Derbot, как справиться с этой небольшой проблемой. 9.2.3. Применение таймеров 0и1 в качестве счетчиков для замера пройденного расстояния в АУСМ Derbot Хоть мы и заявили, что основной темой данной главы будет синхронизация, однако наш первый программный пример будет связан со счетом. Фундаментальной потребно- стью любого транспортного средства является способность измерить, как далеко оно прое- хало — методика, известная как одометрия. В АУСМ Derbot такой замер осуществляется с использованием самодельного оптического датчика поворотов колеса, как это было опи- сано в подразделе 8.6.4 Главы 8. Считая импульсы от датчика поворотов, и вычисляя, основываясь на геометрических параметрах колеса, расстояние, которому соответствует один импульс, можно определить общее расстояние, пройденное АУСМ Derbot. Пример программы 9.1 использует датчик поворота колеса для того, чтобы реализо- вать простую одометрию в АУСМ Derbot. Выходы от двух оптических датчиков соедине- ны в АУСМ Derbot с входами таймеров 0 и 1 PIC-микроконтроллера, как показано на рис. А3.1. Оба эти входа используются в счетном режиме. При диаметрах колес, исполь- зованных в прототипе АУСМ Derbot, а также применяемых датчиков поворота колес, описанных в Приложении 3, программа перемещает АУСМ Derbot вперед на 1 метр. Затем она отрабатывает поворот на 180 и вновь выполняется перемещение вперед на 1 м. Про- грамма будет непрерывно циклить описанным способом. Как и раньше, для экономии места, полный листинг программы в книге не воспроиз- водится, однако он есть на компакт-диске, прилагаемом к этой книге. Читателям будет весьма поучительно разобраться со к#югими функциями этой программы. Биты порта ус- танавливаются обычным способом, отражая подход к использованию портов, принятый в АУСМ Derbot. ADCON1 управляет тем, будут ли биты порта А использоваться для ввода аналоговых сигналов или для ввода-вывода дискретных сигналов. Он инициализируется на ожидаемое аналого-цифровое распределение битов порта А, хотя в данной программе аналоговый вход не используется. Сверяясь со схемой регистра опций, приведенной на рис. 6.9, можно проверить ус- тановки таймера 0, описанные в комментариях программы. Точно так же, сверившись с рис. 9.2, можно проверить установки таймера 1. В программной секции opto_move оба таймера сбрасываются в ноль. Однако вход таймера 1 контролируется. Если он имеет нулевое значение, то значение таймера увеличи- вается на единицу, поскольку первый нарастающий фронт не был обнаружен аппаратны- ми средствами. Затем два электромотора устанавливаются на движение вперед, используя те же самые подпрограммы, что и в примере программы 8.4. Затем программа начинает выполнять цикл opto_loop. В нем значения таймера непрерывно проверяются. Значе- ние счетчика, равное 91, соответствует пройденному расстоянию в 1 м для кодирующей
9.2. Таймер 0 и таймер 1 в 16F87XA 239 структуры, имеющей 16 черно-белых переходов на 1 оборот колеса, как это описано в При- ложении 3. Когда значение счетчика достигнет 91, то соответствующий бит разрешения пуска электромотора сбрасывается и электромотор останавливается. Когда оба электромотора остановятся, АУСМ Derbot выполняет поворот на месте за счет вращения электромоторов в противоположных направлениях. Расстояние, которое каждое колесо должно покрыть, было вычислено с использованием геометрических пара- метров, описанных в Приложении 4, при этом было найдено, что оно эквивалентно значе- нию счетчика, равному 23, которое и используется в программе. При выполнении про- граммы, дуга, проходимая каждым колесом на развороте, замеряется датчиками поворо- тов колес, и электромоторы останавливаются, когда нужное расстояние пройдено. Затем АУСМ проходит то же самое фиксированное расстояние обратно, к отправной точке, и процесс снова повторяется. Пример программы 9.1. Использование одометрии в АУСМ Derbot ;odometry_test /Перемещает АУСМ вперед на фиксированное расстояние, поворачивает ;на 180 градусов и возвращается в режиме бесконечного цикла /TJW 19.05.05 Тестировано 20.05.06 (комментарии и выделение памяти опущены) org 00 /установка СФР в банке памяти 1 (установка регистров Tris А, В, С) movlw В’01000100' movwf adconl /настройка порта А на правильную /комбинацию аналоговых/цифровых входов movlw В'11101000' /настройка таймера 0: внешний вход, /переключение из 0 в 1, без /предварительного деления movwf option_reg movlw D'250' /установка периода ШИМ movwf pr2 /установка СФР в банке памяти 0 bcf status,rpO /выбор банка памяти 0 movlw В'00000011' /установка таймера 1: без предварительного /деления, генератор выкл., внешний синхровход movwf tlcon дальнейшая инициализация и вводная секция программы /прогон вперед на фиксированное расстояние, /затем поворот и возврат opto_move clrf tmrO clrf tmrll clrf tmrlh clrf flags btfss portc,0 /сброс таймеров /если вход нулевой, инкрементирование Т1 /поскольку первый нарастающий фронт не /был распознан
240 Глава 9. Дальнейшее исследование вопросов синхронизации Пример программы 9.1. Продолжение incf tmrll call leftmot fwd /старт работы электромотора call rtmot fwd opto_loop call opto_to_led /передача состояния оптических датчиков /на диагностические светодиоды /перемещение вперед на установленное расстояние (1 м) movlw D'91' /проверка достижения счетчиком данного значения subwf tmrO,0 btfsc status,z bcf porta,mot_en_left /остановка электромотора, /если значение достигнуто movlw D' 91' subwf tmrll,0 btfsc status,z bcf porta,mot_en_rt /если оба электромотора остановлены, переход на поворот, /в противном случае отработка цикла btfsc porta,mot_en_left goto opto_loop btfsc porta,mot_en_rt goto opto_loop /теперь поворот call delay500 /гарантируем, что АУСМ стоит movlw movwf movwf btf ss incf call call /отработка поворота opt_loopl call 00 tmrO tmrll portc,0 tmrll leftmot_fwd rtmot_rev opto_to_led /сброс таймеров и флагов /инкрементируем Т1, если он в нуле /поворот на месте, левый электромотор — /вперед, правый — назад /передача состояния оптических датчиков /поворот на 180 градусов movlw D'23' subwf tmrO,0 btfsc status,z bcf porta,mot_en_ /на диагностические светодиоды /проверка достижения счетчиком данного /значения left /остановка электромотора, /если значение достигнуто movlw D'23' subwf tmrll,0 btfsc status,z bcf porta,mot_en_rt /если оба электромотора остановлены, переход на поворот, /в противном случае отработка цикла btfsc porta,mot en left goto opt loopl btfsc porta,mot en rt goto opt_loopl call delaybOO /гарантируем, что АУСМ стоит goto opto move / * * * * * ★★★★ ★ ****************************
9.2. Таймер 0 и таймер 1 в 16F87XA 241 Пример программы 9.1. Окончание /ПОДПРОГРАММЫ подпрограммы управления электромоторами и отработки временной задержки /передача состояния оптических датчиков на светодиоды opto_to_led bcf portc,led_left /предварительно сбрасываем левый btf ss porta,4 /светодиод bsf portc,led_left /однако включаем его, если /оптический датчик сработал bcf btf ss portc, led__rt portc,0 /предварительно сбрасываем правый /светодиод bs f return end portc,led_rt /однако включаем его, если /оптический датчик сработал Эта программа показывает, как приложение работает при подсчете одометрии, одно- временно выявляя его слабости. Разрешение замера расстояния, использующего простой самодельный датчик поворота колес, является недостаточно точным и может служить толь- ко для целей демонстрации — интересно, но и только. АУСМ может выполнять только приблизительный поворот на 180, также только приблизительно он возвращается в ис- ходную позицию. Если дать ему возможность продолжать ездить туда-сюда, то можно будет увидеть, что в результате накопления погрешностей его возвраты станут все менее и менее точными. Кроме того, в электромоторах отсутствует регулирование частоты вра- щения. Хотя на оба электромотора и подается одно и то же напряжение, однако редко можно найти два абсолютно идентичных электромотора, поэтому АУСМ демонстрирует тенденцию двигаться по кривой, хотя и не очень ярко выраженную. Мы сможем решить эту проблему в этой главе несколько позже, когда реализуем измерение скорости, а затем, в Главе 11, — реализуем управление этой скоростью. 9.2.4. Использование таймеров 0и1 для генерирования повторяющихся прерываний Часто важное использование счетчика/таймера связано с генерированием непрерывной серии точно привязанных ко времени прерываний. Они могут использоваться для многих применений синхронизации, включая формирование базиса сложной программной струк- туры, которая называется операционной системой реального времени, однако говорить о ней мы будем в Главе 18\ Иногда такую серию прерываний называют синхроимпульсами сигналов времени. Это может немного ввести в заблуждение — ведь у нас уже есть гене- ратор синхроимпульсов, а сейчас мы говорим о чем то, совершенно другом. Однако такие импульсы сигналов времени могут стать почти настолько же фундаментальными, как и сам тактовый генератор микроконтроллера. Они могут стать базисом почти всех время- базированных операций. Таймеры 0 и 1 могут легко использоваться для того, чтобы генерировать такие импуль- сы сигналов времени, поскольку оба они могут генерировать прерывание по переполнению. Принцип иллюстрируется на рис. 9.3. Таймер настроен так, чтобы непрерывно работать в режиме таймера с разрешенными прерываниями. Изменение его значений представляется ступенчатой линией на диаграмме. Он в повторяющемся режиме считает до своего макси- мального значения, после чего переполняется и сбрасывается в ноль. Всякий раз, когда он это делает, генерируется прерывание.
242 Глава 9. Дальнейшее исследование вопросов синхронизации Значение таймера Переполнение таймера со сбросом в ноль, при этом генерируется прерывание Прерывания * ^int ► Рис. 9.3. Генерирование синхроимпульсов сигналов времени — серии повторяющихся прерываний. В общем случае, если таймер имеет п разрядов, то он будет считать до Т единиц — от одного нулевого состояния до другого. Время между прерываниями, Tint таким образом может быть получено по формуле: Tmt = 2" X Zcik — это период тактовых импульсов, подаваемых на таймер. ПРИМЕР РАЗРАБОТКИ 9.1 Предположив частоту тактового генератора, равную 4 МГц, какую самую медленную последовательность импульсов сигналов времени можно получить от таймера 0 и таймера 1? Какая частота следующей более быстрой последовательности в каждом В отношении таймера 0 смотрите рис. 6.8 и 6.9. Чтобы достигнуть самой медленной скорости следования прерываний, предварительный делитель устанавливается на коэффициент деления 256. Таким образом, входная тактовая частота самого таймера будет равна 1 МГц / 256, или 3,906 кГц. Действие же самого 8-разрядного таймера за- ключается в том, что он также будет делить эту частоту на 256, порождая последова- тельность импульсов сигналов времени с частотой, равной 3,906 кГц / 256, или 15,26 Гц. Следующую болёе быструю частоту мы получим, если установим предварительный делитель на коэффициент деления, равный 128. В этом случае частота прерываний была бы равной 30,52 Гц. Для случая таймера .1 обратитесь к рис. 9.1 и 9.2. Максимальный коэффициент деле- ния в этом случае будет равным 8. При использовании этого коэффициента деле- ния, входная тактовая частота таймера будет равна 125 кГц. Сам же таймер будет делить эту частоту на 216, что приведет к частоте следования прерываний, равной Т£1Тц. Следующей более высокой частотой была бы частота, которая получается, если установить предварительный делитель на коэффициент деления, равный 4 — это приведет к частоте следования прерываний, равной 3,81 Гц. Интересно видеть, что нет разительного отличия между самыми медленными часто- тами прерываний, обеспечиваемыми каждым из таймеров. Хотя таймер 0 имеет только 8 разрядов, однако факт того, что он имеет очень эффективный предвари- тельный делитель частоты, компенсирует его меньшую разрядность в применениях этого типа. . . Пример использования прерывания по переполнению приведен в примере програм- мы 9.3.
9.3. Таймер 2 в 16F87XA, компаратор и регистр PR2 243 9.3. Таймер 2 в 16F87XA, компаратор и регистр PR2 9.3.1. Таймер 2 Таймер 2 в 16F87XA — это простое 8-разрядное устройство. Он показан в форме блок- схемы на рис. 9.4. Только два компонента этой блок-схемы — регистр TMR2 и предвари- тельный делитель частоты, фактически, имеют отношение к стандартным функциям тай- мера. Таймер 2 — это чистый таймер, поэтому он управляется только от внутреннего так- тового генератора, показанного в правой части блок-схемы. Никакой внешний ввод сигна- лов невозможен. 8-разрядный регистр таймера может читаться и записываться, его можно видеть по адресу памяти 11н на рис. 7.6. Имеются также скромные возможности пред- варительного деления частоты. Регистр управления таймером 2, T2CON, показан на рис. 9.5. Объяснения, приведенные на этом рисунке, дают хорошее описание роли каждого бита данного регистра. Рис. 9.4. Блок-схема таймера 2 в 16F87XA (дополнительные надписи в затененных прямоугольниках добавлены автором) — TOUTPS3 TOUTPS2 TOUTPS1 TOUTPSO TMR2ON T2CKPS1 T2CKPS0 Разряд 7 Разряд О разряд 7 Не реализован: читается, как “О” разряды 6-3 TOUTPS3:TOUTPSO: биты выбора постделения частоты выхода таймера 2 0000 = постделение 1:1 0001 = постделение 1:2 0010 = постделение 1:3 1111= постделение 1:16 разряд 2 TMR2ON: бит включения таймера 2 1 = таймер 2 вкл. 0 = таймер 2 выкл. разряды 1-0 T2CKPS1 :T2CKPS0: биты установки коэффициента предварительного деления тактовой частоты таймера 2 00 = коэффициент предварительного деления 1 01 = коэффициент предварительного деления 4 1х = коэффициент предварительного деления 16 Рис. 9.5. Регистр управления таймером 2, T2CON
244 Глава 9. Дальнейшее исследование вопросов синхронизации Несмотря на свою кажущуюся простоту, таймер 2 начинает выступать в качестве мощ- ного аппаратного модуля, когда задействуются его дополнительные элементы, которые и будут сейчас рассмотрены. Его полезность еще в большей степени возрастает, когда ис- пользуется регистр сравнения и сбора данных с его функцией широтно-импульсной мо- дуляции (ШИМ). 9.3.2. Регистр PR2, компаратор и постделитель Таймер 2 имеет регистр периода PR2 по адресу 92н в карте памяти (см. рис. 7.6), кото- рый может предварительно устанавливаться программистом. Когда таймер работает, его значение непрерывно сравнивается компаратором с содержимым регистра PR2. Когда их значения сравняются, таймер сбрасывается в 0 на следующем тактовом цикле. Этот процесс иллюстрируется на рис. 9.6. Значение PR2 показано фиксированным, хотя оно может быть изменено программно. Изменения значений таймера 2 на рисунке представлены как пилообразные сигналы, хотя на самом деле эти изменения имеют сту- пенчатый характер (как показано на рис. 9.3) и этот характер необходимо учитывать. Счет происходит до значения, хранящегося в PR2. Когда значения таймера и PR2 сравни- ваются, генерируется сигнал сброса и таймер 2 сбрасывается в ноль. Это происходит на цикле инкрементирования после обнаружения равенства, поэтому имеется (PR2 + 1) так- товых циклов между каждым сбросом. Рис. 9.4 показывает, что этот сигнал сброса фор- мирует выходной сигнал модуля, помеченный как “выход TMR2”. Этот сигнал может быть выбран как тактовый сигнал информационного обмена синхронным последовательным портом (SSP), как это будет описано в следующей главе. Значение в регистре PR2 \ Значение -- таймера 2 z. Значение таймера 2, пока компаратор не сработал Выход компаратора (= выход TMR2) Прерывание TMR2IF (постделитель установлен на коэффициент деления 4) Рис. 9.6. Работа регистра PR2 и компаратора ПРИМЕР РАЗРАБОТКИ 9.2 АУСМ Derbot имеет частоту тактового генератора, равную 4 МГц. Какова самая мень- шая частота прерываний, которую таймер 2 может генерировать? Чтобы достигнуть самой малой частоты прерываний, PR2, а также предварительный делитель и постделитель должны быть установлены на максимумы. Если предвари- тельный делитель установлен на коэффициент деления 16, то тактовая частота тай- мера 2 будет равна 1 МГц /16, или 62,5 кГц. Если PR2 установлен на 255, то таймер 2 будет способен считать до своего максимального значения (т.е. до 255) перед сбросом в 0. Следовательно, частота сброса будет равна 62,5 кГц / 256 или 244,14 Гц. Если эта частота подвергнется делению в постделителе, установленном на коэффициент деления 16, результирующая частота прерываний будет 15,26 Гц. Это минимально возможная частота прерываний для этого источника. Ряд только что описанных сбросов также формирует входную последовательность пост- делителя, выход которого может использоваться как источник прерываний. Постделитель
9.4. Модули сбора данных/сравнения/ШИМ (ССР-модули) 245 управляется битами TOUTPSX регистра управления. Обратите внимание, что он может устанавливаться на любое значение коэффициента деления вплоть до 16 — он не ограни- чен только степенями двойки. Рис. 9.6 показывает случай, когда постделитель установлен на коэффициент деления, равный четырем. Результатом этого является поток прерываний, частота которого может настраиваться в целом диапазоне значений. 9.4. Модули сбора данных/сравнения/ШИМ (ССР-модули) 9.4.1. Краткий обзор вопросов сбора данных/сравнения/ШИМ В начале Главы 6 было высказано соображение о том, что встроенные системы имеют потребности синхронизации, которые являются до некоторой степени эквивалентными различным потребностям привязки ко времени, возникающим в нашей ежедневной жизни. Встроенная система нуждается в эквиваленте настройки будильника и в записи времени, когда произошло событие. Эти и другие потребности встроенной системы адекватно реша- ются добавлением одного или большего числа регистров к базовому счетчику/таймеру. Регистр, который может записывать время события, называется регистром “сбора данных”. Регистр, который может генерировать предупредительный сигнал, делает это, удерживая предварительно установленное значение и сравнивая его со значением работающего тай- мера (как мы уже рассматривали это для PR2). Предупредительный сигнал подается, когда два упомянутых значения равны. Такие регистры называются регистрами “сравнения”. Микроконтроллеры семейства PIC 16 объединяют эти функции, а также многие другие, в модулях, которые называются модулями сбора данных/сравнения/ШИМ (ССР-модулями). ССР-модули очень универсальны, они взаимодействуют как с таймером 1, так и с тай- мером 2. 16F873A имеет два таких модуля, и их работу стоит понять. Каждый модуль имеет два 8-разрядных регистра, называемых CCPRxL и CCPRxH, где х — это 1 или 2. Вместе они формируют 16-разрядный регистр, который может использоваться для сбора данных, сравнения или же формирования рабочего цикла ШИМ-потока. ССР-модули управляются соответствующими регистрами CCPxCON (рис. 9.7). Их младшие 4 бита определяют режим работы модуля. Можно видеть, что модуль может быть выключен, установлен на ШИМ или настроен на одну из четырех возможных конфигураций (либо в режиме сбора данных, либо в режиме сравнения). Мы исследуем все названные режимы работы по очереди. 9.4.2. Режим сбора данных Регистр сбора данных работает, в каком-то роде, как секундомер. Когда происходит событие, значение, отражаемое работающим таймером, записывается. Затем в обычном секундомере часы останавливаются. В случае же регистра сбора данных таймер продол- жает работать, однако его значение на момент, когда событие произошло, остается запи- санным. Модуль ССР1 в режиме сбора данных показан на рис. 9.8. Модуль ССР2 будет рабо- тать в этом режиме так же, как и ССР1, но при этом его вход совместно используется и для разряда 1 Порта С. Так как входной штырек разделен с портом С, он должен быть уста- новлен как вход в TRISC. Внешний сигнал, представляя “событие”, соединен со штырь- ком микроконтроллера RC2/CCP1. Цель режима сбора данных состоит в том, чтобы за- писать в CCPR1L и CCPR1H значение таймера 1, когда происходит внешнее событие. В отношении гибкости можно добавить, что внешний сигнал может быть предварительно поделен на 4 или 16, а также может быть выбран либо возрастающий фронт, либо срез сиг- нала. Возможные устанавливаемые опции можно увидеть на рис. 9.7. Также как и активи- рование режима сбора данных, возникновение события вызывает прерывание, представ- ляемое флагом CCP1IF, показанным на схеме структуры прерываний по рис. 7.10. Мо- дуль ССР2 имеет эквивалентное прерывание, представляемое флагом CCP2IF.
246 Глава 9. Дальнейшее исследование вопросов синхронизации U-0 U-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 — — ССРхХ CCPxY ССРхМЗ ССРхМ2 CCPxMl CCPxMO разряд 7 разряды 7-6 разряды 5-4 разряды 3-0 Не реализован: читается как “0" CCPxX:CCPxY: младшие разряды ШИМ Режим сбора данных: Не используется Режим сравнения: Не используется Режим ШИМ: Эти биты являются двумя младшими битами, задающими рабочий период-ШИМ. Восемь старших битов находятся в CCPRxL CCPxM3:CCPxMO: биты выбора режима ССРх разряд 0 0000 = сбор данных/Сравнение/ШИМ запрещены (сброс модуля ССРх) 0100 = режим сбора данных, по каждому срезу 0101 = режим сбора данных, по каждому нарастающему фронту 0110 = режим сбора данных, по каждому 4-му нарастающему фронту 0111= режим сбора данных, по каждому 16-му нарастающему фронту 1000 = режим сравнения, установка выхода по совпадению (бит CCPxlF установлен) 1001 = режим сравнения, сброс выхода по совпадению (бит CCPxlF установлен) 1010 = режим сравнения, генерирование программного прерывания по совпадению (бит CCPxlF устанавливается, нет воздействия на штырек ССРх) 1011 = режим сравнения, переключение специального события (бит CCPxlF установлен, нет воздействия на штырек ССРх); ССР1 сбрасывает TMR1; ССР2 сбрасывает TMR1 и запускает аналого-цифровое преобразование (если модуль АЦП активирован) 11 хх = режим ШИМ Рис. 9.7. Регистры CCP1CON/CCP2CON (адреса 17н и 1DH, соответственно) Рис. 9.8. Блок-схема для режима сбора данных (ССР1) (дополнительные метки в заштрихованных полях добавлены автором) 9.4.3. Режим сравнения Модуль ССР1, сконфигурированный на режим сравнения, показан на рис. 9.9. Здесь цифровой компаратор работает совместно с аппаратными средствами, которые непрерыв- но сравнивает значение таймера 1 и 16-разрядного регистра, составленного из CCPR1H и CCPR1L. Таймер 1 должен работать в режиме таймера или в режиме синхронизованного счетчика. Модуль соединен с внешним штырьком, который должен быть сконфигурирован
9.5. Широтно-импульсная модуляция (ШИМ) 247 как выход в TRISC. Когда происходит совпадение, может происходить одно из нескольких событий — это зависит от установок регистра управления (рис. 9.7). Соответствующий выходной бит может быть установлен или же сброшен (при установке флага прерывания в обоих случаях). Это позволяет запускать либо останавливать внешние события. В каче- стве альтернативы флаг прерывания может быть установлено без изменений выхода. И, наконец, может инициализироваться “специальное событие”. Для обоих модулей это включает сброс таймера 1 и отсутствие изменений на выходном штырьке. Модуль ССР2 также инициализирует аналого-цифровое преобразование, если преобразователь акти- вирован. Триггер специального события сбросит таймер 1, однако не установит бит флага прерывания TMR1IF (PIR1 <0>), а также установит бит GO/DONE (ADCONO<2>) Рис. 9.9. Блок схема для режима сравнения (ССР1) (дополнительные метки в заштрихованных полях добавлены автором) 9.5. Широтно-импульсная модуляция (ШИМ) Широтно-импульсная модуляция — это очень мощная методика, которая позволяет цифровым выходом управлять аналоговыми переменными при использовании для пере- дачи данных только одного соединения. 9.5.1. Принцип ШИМ Понимание типичного приложения ШИМ требует некоторого знания в области элек- троники, используемой для реализации ШИМ. Это настолько важно, что мы кратко рас- смотрим соответствующие вопросы, иллюстрируемые рис. 9.10. Связь между током и напряжением в катушке индуктивности задается уравнением: V=Ldi/dt Где V— напряжение на катушке индуктивности, i — ток через катушку индуктивности, a L — ее индуктивность. Из этого уравнения можно получить, что в случае, когда будет иметь место ступенчатое изменение в напряжении, приложенном к катушке индуктив- ности, то ток через нее будет расти по экспоненте, переходя к своему значению устойчи- вого состояния V/R, где R — сопротивление катушки индуктивности. Скорость роста тока зависит от параметра схемы, который называется постоянной времени, которая для катушки индуктивности задается как L/R. Можно показать, что для ступенчатого измене- ния приложенного напряжения ток повышается с 10 до 90 процентов от своего устано- вившегося значения за время 2,2L/R. Если напряжение будет снято, то время, необходимое
248 Глава 9. Дальнейшее исследование вопросов синхронизации для того, чтобы ток упал (в предположении, что имеется цепь, по которой он может про- текать), будет таким же. (а) Рис. 9.10. Принцип ШИМ: (а) — пример электронной цепи; (Ь) — постоянная времени мала, по сравнению с “временем включения”; (с) — постоянная времени велика, по сравнению с “временем включения", узкий импульс; (d) — постоянная времени велика, по сравнению с “временем включения", широкий импульс. Давайте вообразим, что индуктивная нагрузка включается и выключается транзистор- ным ключом, как это показано на рис. 9.10 (а). Когда транзистор выключен, затухающий ток течет через гасящий диод. Если продолжительность времени, когда транзистор на- ходится во включенном состоянии, намного больше, чем постоянная времени цепи, то время роста и падение тока будет соответствовать незначительной пропорции от общего времени, и форма тока будет иметь вид, показанный на рис. 9.10 (Ь). Однако если пере- ключения будут носить повторяющийся характер и с периодом, меньшим, чем постоянная времени катушки индуктивности, то у тока не будет времени достигнуть своего устойчи- вого состояния. Он будет повышаться немного, когда ключ замыкается и немного падать (протекая через гасящий диод), когда ключ размыкается. Если переключения будут идти непрерывно, то ток вырастет до своего усредненного значения, которое зависит от коэф- фициента заполнения сигнала переключения. Сказанное иллюстрируется рис. 9.10 (с, d). Важным моментом в этом процессе есть то, что средний ток, текущий в катушке ин- дуктивности, может управляться коэффициентом заполнения переключающего сигнала. В этом и заключается принцип широтно-импульсной модуляции.
9.5. Широтно-импульсная модуляция (ШИМ) 249 Сигнал ШИМ в общем случае имеет фиксированный период следования Т при пе- ременной ширине импудьса ton. Можно показать, что для схемы по рис. 9.10 (а) средний ток, текущий в катушке индуктивности, Iave определяется как: /ave-aon/Л Х(^) (9-1) 9.5.2. Генерирование ШИМ-сигналов аппаратными средствами — 16F87XA ШИМ Великолепие ШИМ заключается как в ее простоте, так и в способе, которым она играет роль ворот между цифровым и аналоговым мирами. Сигнал ШИМ очень просто генериру- ется цифровыми аппаратными средствами. Мы используем семейство PIC 16 в качестве примера, чтобы это объяснить. Хотя сам принцип является простым, однако некоторые по- лезные “дополнения”, введенные Microchip, добавляют немного сложности к его реализа- ции. Поэтому целесообразно уделить некоторое время для наилучшего их понимания. Упрощенная блок-схема модуля ССР, сконфигурированного на генерирование ШИМ- сигналов, показана на рис. 9.11, примеры сигналов — на рис. 9.12. Можно заметить, что рис. 9.11 содержит основные компоненты блок схемы, показанной на рис. 9.4, с работаю- щими вместе таймером 2, компаратором и регистром PR2. Хотя теперь и не показанный, таймер 2 все еще управляется от встроенного генератора через собственный предваритель- ный делитель. При постоянно работающем таймере 2 можно ожидать, что сигналы ШИМ будут иметь вид, показанный на рис. 9.6. Это действительно имеет место — сигналы по рис. 9.6 расширяются и приобретают вид сигналов, показанных на рис. 9.12. Выход ком- паратора, однако, теперь управляет R-S триггером. Когда значение в PR2 сравнивается со значением таймера 2, то компаратор сбрасывает таймер и переводит в единичное состо- яние триггер, выход которого переводится в состояние логической 1. Это можно видеть на рис. 9.12. Таким образом задается период ШИМ. Итак, задав период ШИМ, давайте теперь рассмотрим, как устанавливается ширина импульса. Для того чтобы сделать это, используется второй регистр сравнения. При этом используется регистр CCPR1H плюс второй компаратор. Как показывает логика схемы, всякий раз, когда компаратор распознает равные входные значения, он сбрасывает выход- ной триггер, переводя его выход в состояние логического нуля. Именно этот компаратор определяет ширину импульса. Опять-таки, это отражено на рис. 9.12. Для изменения ши- рины импульса программист записывает значение в регистр CCPR1L, который работает как буфер. Это значение перемещается в CCPR1II только тогда, когда цикл ШИМ завер- шен, чтобы избежать ошибок вывода. Блок-схема становится более сложной, потому что три регистра “растянуты” с тем, что- бы сделать их потенциально 10-разрядными вместо 8-разрядных. Это увеличивает разре- шение. CCPR1L использует 2 бита регистра CCP1CON (как уже показывалось на рис. 9.7). CCPR1H расширен за счет внутреннего 2-разрядного триггера, в то время как расширение таймера 2 описано в Примечании 1 к рис. 9.11. Из-за этих двух дополнительных битов, в 10-разрядной версии он эффективно синхронизуется непосредственно сигналом внутрен- него генератора, частота которого не подвергается делению. Если используется предвари- тельный делитель, то он работает с этой частотой, а не с обычной Fosc/4. Обратите внима- ние, однако, что регистр PR2 остается 8-разрядным. Это означает, что период ШИМ имеет только 8-разрядное эквивалентное разрешение. Период Т ШИМ определяется взаимодействием регистра PR2 и 8-ю разрядами тай- мера 2. Он может быть вычислен следующим образом: Т = (PR2 + 1) х (период входной тактовой частоты таймера 2) = = (PR2 + 1) х {Tosc х 4 х (коэфф, предварительного деления таймера 2)} (9.2)
250 Глава 9. Дальнейшее исследование вопросов синхронизации Рис. 9.11. Упрощенная блок-схема ШИМ (для модуля ССР1, для модуля ССР2 она такая же) (дополнительные метки в заштрихованных полях добавлены автором) Рис. 9.12. Пример сигналов ШИМ-генератора 16F873A Ширина импульса ШИМ tOfl определяется взаимодействием расширенного регистра CCPR1H (всех его 10 разрядов) и расширенного (10-разрядного) таймера 2. Она может быть вычислена следующим образом: t0« = (регистр ширины импульса) х (период входной тактовой частоты таймера ШИМ) где “период входной тактовой частоты таймера ШИМ” — это период сигнала на тактовом входе расширенного таймера 2, а “регистр ширины импульса” — это значение, находяще- еся в расширенном регистре CCPR1H. Следовательно:
9.5. Широтно-импульсная модуляция (ШИМ) 251 ton = (регистр ширины импульса) х х {Tosc х (коэф, предварительного деления таймера 2)} (9.3) Обратите внимание, что, как объяснено выше, здесь к терму Tosc не применяется ко- эффициент деления 4. 9.5.3. Применение ШИМ для управления электромоторами в АУСМ Derbot Теперь исследуем приложение ШИМ 16F873A к АУСМ Derbot. Прежде всего, мы нуж- даемся в том, чтобы понять, как ШИМ применяется при проектировании схем. Мы уже ви- дели в Главе 8, как Н-образный мост мог бы использоваться для включения/выключения реверсивного электромотора. Если на Н-образный мост подать не сигнал от управляющей цепи включения/выключения, а сигнал ШИМ, то мы получим непрерывно управляемый реверсивный электропривод. Принципиальная схема для левого электромотора АУСМ Derbot показана на рис. 9.13 (а). Половина интегральной схемы L913D (рис. 8.27) используется для того, чтобы сформиро- вать Н-образный мост, выходы которого управляют электромотором. Два входа Н-образ- ного моста соединены между собой через логический инвертор так, чтобы всякий раз, когда на одном из них присутствует сигнал логической единицы, на другом был логиче- ский ноль, и наоборот. Если на вход подать сигнал логической 1, то электромотор будет вращаться в одном направлении, а если сигнал логического 0 — в другом. Если теперь вход управления мостом соединить с источником ШИМ, то произойдет интересная вещь: если сигнал ШИМ будет иметь точно прямоугольную форму, и будет идти на достаточно высокой частоте, то электромотор будет стоять, поскольку средний ток будет нулевым. Это иллюстрируется рис. 9.13 (Ь). Если сигнал на входе управления мос- том выйдет на отметку, когда коэффициент заполнения будет меньшим 1, то средний ток управления будет иметь отрицательное среднее значение. Если же коэффициент запол- нения будет большим 1, то средний ток управления будет иметь положительное среднее значение. Это также видно на рис. 9.13 (Ь). Т.о. меняя ширину импульса ШИМ в полном диапазоне его изменения — от абсолютного минимума до абсолютного максимума — скорость электромотора можно непрерывно изменять в обоих направлениях. При просмотре полной принципиальной схемы, приведенной на рис. А3.1, можно видеть, что ССР1 управляет правым электромотором, в то время как ССР2 управляет левым. Сигналы разрешения поступают от битов 2 и 5 порта А. Простейшей программой, которой мы располагаем для того чтобы посмотреть, как используется ШИМ в АУСМ Derbot,.является программа “слепой навигации’’, рассмот- ренная в главе 8. Она является частью примера программы 8.4. Те части этой программы, которые имеют отношение к ШИМ и ранее были опущены, сейчас приведены в примере программы 9.2. Приведенные в примере программные секции начинаются с инициализации ШИМ. Посредством осуществления записи в регистр T2CON (см. рис. 9.5), включается таймер 2, при этом ни пред- ни пост-деление частоты не используются (см. рис. 9.4). Используя ре- гистры CCPxCON, два регистра управления ССР настраиваются на режим ШИМ. И, на- конец, регистр PR2 загружается значением 249d- Учитывая, что частота тактового генера- тора равна 4 МГц, мы можем получить по уравнению (9.2), что период ШИМ будет равен: Т = (PR2 + 1) х {Tosc х 4 х (коэффициент предварительного деления таймера 2)} = = 250 х (250 нс х 4 х 1) = = 250 мкс т.е. частота ШИМ = 4,00 кГц Это удобное значение частоты, которое мы уже ранее использовали для других целей. Оно сохраняет почти полное разрешение системы ШИМ.
252 Глава 9. Дальнейшее исследование вопросов синхронизации (а) ССР2 (Порт С, разряд 1) Порт А, разряд 5 (Ь) Управление ШИМ Положи- тельные значения 4. О тельные значения Рис. 9.13. Использование ШИМ с Н-образным мостом в АУСМ Derbot — достигается непрерывно изменяющееся управление в обоих направлениях: (а) — принципиальная схема (левый электромотор); (Ь) — пример сигналов В примере программы 9.2 приведены также подпрограммы, используемые для на- стройки электромоторов на прямое либо обратное вращение — это подпрограммы leftmot_fwd rtmot_fwd и т.д. Каждая из этих подпрограмм начинается с активирования линии управления соот- ветствующего мотора посредством установки бита mot_en_rt или mot_en_lef t в со- стояние логической единицы. Затем в CCPR1L либо CCPR2L загружается значение, ко- торое определяет ширину импульса ШИМ. Для простоты два младших разряда значения настройки ширины импульса, хранимые в CCPxCON, предварительно устанавливаются в ноль и в дальнейшем в данной программе не используются. Следовательно, настройка ширины импульса, имеющая диапазон от 00 до 250Dj загружается в CCPRxL, при этом значение 00 дает полный реверсный ход, 250d — полный прямой ход, a 125d дает отсут- ствие вращения электромотора. Числа, которые фактически загружаются в программе — 176d и 80d, были определены экспериментальным путем — они дают мягкое движение как вперед, так и назад. Позже в этой главе, а затем далее в книге мы создадим другие
9.5. Широтно-импульсная модуляция (ШИМ) 253 программы для получения переменной скорости вращения электромоторов, полностью использующие возможности ШИМ. Пример программы 9.2. Связанные с ШИМ секции программы “слепой навигации” Dbt_blind_Nav АУСМ Derbot перемещается в режиме "слепой" навигации. Перемещается вперед и назад, поворачивается по соударению. Для установки скорости используется ШИМ с фиксированной частотой следования импульсов; TJW 05.05.05 Тестировано 09.05.05 (вступительные секции программы опущены) Специфицируем некоторые разряды портов ;для порта А mot_en_rt equ 2 /разрешение ввода для правого электромотора, /установка значения L293D mot_en_left equ 5 /разрешение ввода для левого электромотора, /установка значения L293D bcf status,грО /выбор банка памяти 0 /настройка ШИМ movlw B'00000100' /включение таймера 2, без пред- и ;пост-масштабирования movwf movlw movwf movwf movlw movwf t2con В'00001100' /активирование ШИМ ccplcon сср2соп 0f9 рг2 (главная программа опущена — ее можно видеть в примере программы 8.4) /подпрограммы управления электромоторами leftmot_fwd /настраивает левый электромотор на движение вперед bsf porta,mot_en_left movlw D'176' movwf CCPR2L return rtmot_fwd bsf porta,mot_en_rt movlw D'17 6' movwf CCPR1L return leftmot_rev bsf porta,mot_en_left movlw D'80' movwf CCPR2L return rtmot_rev bsf porta,mot_en_rt movlw D'80' movwf CCPR1L return
254 Глава 9. Дальнейшее исследование вопросов синхронизации 9.6. Программная генерация сигналов ШИМ В то время как аппаратные источники сигналов ШИМ надежны и просты в исполь- зовании, они не всегда доступны. Вполне может быть, что в недорогих применениях ис- пользуется микроконтроллер без источника ШИМ. В альтернативе, приложение уже мо- жет задействовать все доступные источники ШИМ, а ему требуются еще источники ШИМ. ШИМ — это классический случай функции, которая может выполняться как аппаратно, так и программно. При использовании программного подхода единственным аппаратным ресурсом, который потребуется, будет один штырек порта ввода-вывода, который будет настроен на вывод. Выходные сигналы ШИМ могут генерироваться только на основе использования про- граммного цикла задержки, аналогичного описанному в Главе 5. Возможная блок-схема соответствующей программы приведена на рис. 5.4. Этот подход, однако, почти полно- стью связывает ЦП “по рукам и ногам“, поэтому, скорее всего, что на практике он найдет только ограниченное применение. Альтернативой использованию чисто программного похода к генерированию потока ШИМ-сигналов, все еще не требующим аппаратного модуля ШИМ, является использова- ние прерывания таймера для задания периода следования сигналов. Это может упростить сложность программирования и обеспечить возможность использования ЦП в других процессах. Все, что необходимо — это установить прерывание по переполнению таймера, работающего на необходимой скорости, как это было описано в подразделе 9.3.3 данной главы. По каждому прерыванию выход ШИМ должен устанавливаться в состояние логи- ческой единицы и должна инициализироваться программная задержка. В конце задержки выход ШИМ сбрасывается. Этот процесс иллюстрируется на рис. 9.14. Прерывания ' по переполнению таймера 7"pwm Рис. 9.14. Генерирование ШИМ по прерыванию от таймера 9.6Л. Пример программного генерирования ШИМ Хороший пример применения только что описанной методики можно видеть в примере программы 9.3. Соответствующая подпрограмма управляет сервоприводом АУСМ Derbot, который используется для поворота ультразвукового детектора. 16F873A имеет только два источника ШИМ и они используются для управления электромоторами. Сервопривод тре- бует формирования импульсных сигналов, показанных на рис. 8.23. Это особенно подхо- дит для метода программного генерирования сигналов ШИМ, поскольку ширина импуль- сов будет всегда малой в сравнении с периодом, поэтому ЦП будет загружаться на срав- нительно короткий отрезок времени. Программа перемещает вал сервопривода пошагово от 0 до 180 градусов, отрабатывая 45 шагов. Вследствие того, что при непрерывном поша- говом перемещении вала сервопривода потребление тока будет очень большим, между пошаговыми позициями вала сервопривода генерируется линейный переход.
9.6. Программная генерация сигналов ШИМ 255 В силу того, что таймеры 0 и 1 загружены выполнением функции кодирования пово- рота колес, только таймер 2 может быть использован для генерирования прерываний по переполнению. Однако он уже загружен выполнением ШИМ-функции. Сейчас мы увидим, как один таймер может использоваться для выполнения двух, на вид несвязанных между собой действий. Таймер может продолжать выполнять свою ШИМ-роль, однако прерыва- ния по его переполнению через постделитель (см. рис. 9.4) могут использоваться в дан- ном, дополнительном применении. Названные два применения до некоторой степени кон- фликтуют — сервопривод требует периода следования сигналов в 20 мс, в то время как сигналы ШИМ должны оставаться в диапазоне нескольких килогерц. В этом случае свою положительную роль играет гибкость постделителя. Как и в случае настройки ШИМ для электромоторов, можно видеть, что если содержимое PR2 будет установлено на 249D, то частота переполнения таймера 2 будет равна 4 кГц. Теперь, если для таймера 2 установить коэффициент деления постделителя на 16, то частота прерываний станет равной 250 Гц, т.е. будет обеспечен период в 4 мс. Это не 20 мс, которые мы хотим, однако программно легко обеспечить, чтобы выходной импульс выдавался по каждому пятому прерыванию. Только что описанные настройки можно видеть в примере программы. Регистр PR2 загружается значением 249D, а постделитель таймера 2 устанавливается на коэффициент деления, равный 16. Затем устанавливаются три программных счетчика — int_cntr, который считает поступающие прерывания, pulse_cntr, считающий количество им- пульсов, посланных для каждой ширины импульсов, а также past_pulse, содержащий ширину предыдущего импульса — это значение используется для того, чтобы определить, нужно ли формировать линейный переход между предыдущей шириной импульса и сле- дующей. Затем разрешается прерывание от таймера 2 и программа входит в цикл ожида- ния. Все последующие действия программы выполняются в ISR (подпрограмма обслу- живания прерываний). В ISR сначала декрементируется значение int_cntr с тем, чтобы определить, дол- жен ли выдаваться выходной импульс. Если это так, то значение pulse_cntr декре- ментируется с целью определения того, должна ли изменяться ширина импульса. Если да, то инкрементируется значение servo_dirn. Оно используется как указатель на просмот- ровую таблицу, из которой берется новое значение ширины импульса. По метке ISR1 выполняется доступ к просмотровой таблице и считывается требуемое значение ширины импульса. Оно сохраняется в ячейке памяти pw_cntr. Это сохраненное значение опре- деляет то, сколько раз должна вызываться подпрограмма 20-микросекундной задержки, формируя требуемую ширину импульса. Теперь генерируется переход, если он нужен. Значение в pw_cntr сравнивается с предшествующим значением, хранимым в ячейке памяти past_pulse. Если они равны, то импульс сразу же выдается. Если же нет, то выполняется проверка состояния флага переноса, с целью определения того, какое из значений больше. Затем значение pw_cntr соответствующим образом инкрементируется или декрементируется для установки новой ширины импульса. Затем импульс выдается с использованием простого цикла задержки. Пример программы 9.3. Программное генерирование сигналов ШИМ Dbt_servo_tst Пошагово поворачивает вал сервопривода от 0 до 180 градусов при общем количестве шагов, равном 45. Период ШИМ для управления сервоприводом генерируется по переполнению таймера 2 с программной установкой ширины импульса. Генерируется переход между шагами. TJW 26.05.05 Тестировано 30.08.05 (Вводные комментарии опущены) cblock 20
256 Глава 9. Дальнейшее исследование вопросов синхронизации Пример программы 9.3. Продолжение delcntrl delcntr2 /используется в подпрограммах delay5 и delayADC temp /временная ячейка памяти, используется только ;в последовательных командах int_cntr /считает приходящие прерывания pulse_cntr /считает, сколько импульсов ШИМ посланы на сервопривод /перед переходом в следующую позицию pw_cntr /счетчик, /импульса используемый для задания ширины , подаваемого на сервопривод servo_dirn /счетчик, который используется как указатель ;на просмотровую таблицу past_pulse endc /содержит значение последней ширины импульса, /используется /таблицы, для со значением, полученным из просмотровой определения фактической ширины импульса org goto 00 begin org 04 goto ISR /инициализация /установка СФР в банке памяти 1 begin bcf status,rpl bsf status,rpO /выбор банка памяти 1 movlw movwf В' 11110001' trisb /установка разрядов порта В, /разряд 3 — выход ШИМ на сервопривод movlw movwf / установка bcf movlw D'249' /установка периода переполнения таймера 2 рг2 СФР в банке памяти 0 status,грО /выбор банка памяти 0 В'01111100' /включение таймера 2, без предварительного /деления, постделение на 16, что дает период /прерываний в 4 мс (при рг2 = 250) movwf t2con /инициализация значений счетчиков movlw D'5' /предварительная установка счетчика прерываний movwf int_cntr movlw D'200' movwf pulse_cntr /предварительная загрузка счетчика импульсов movlw D' 60 ' /начало с промежуточной шириной импульса movwf past_pul.se (вступительные секции подпрограммы опущены) /разрешение прерываний bcf pirl,tmr2if /очистка ожидающих прерываний bsf status,rpO /выбор банка памяти 1 bsf piel,tmr2ie /разрешение прерывания от таймера 2 bcf status,rpO /выбор банка памяти 0 bsf intcon,peie /разрешение прерываний от периферийных устройств bsf intcon,gie
9.6. Программная генерация сигналов ШИМ 257 Пример программы 9.3. Продолжение wait goto wait /переход на ожидание — работает подпрограмма t /обслуживания прерываний /Это подпрограмма обслуживания прерывания. Прерывания возникают ;каждые 4 мс. Считает 5 и по пятому выдает импульс на сервопривод. ;Длительность импульса зависит от установок servo_dirn ISR decfsz int_cntr /декрементирует счетчик прерываний. /Действия выполняются если только он в нуле goto intend decfsz pulse_cntr /переход сюда, если импульс должен быть выдан, /проверка, должна ли измениться ширина импульса goto ISR1 incf servo_dirn,1 /сюда, если ширина импульса меняется, /указатель — на новую длительность movlw D'200 ' /перезагрузка счетчика импульсов, /200 импульсов будет выдано при новой /ширине импульса movwf pulse_cntr ;теперь определяем ширину /значение перехода импульса, вычисляя, если необходимо, ISR1 movf servo_dirn,0 /получаем требуемую ширину импульса /из таблицы andlw 07 /используем только три /младших разряда servo_dirn call int table movwf pw_cntr /это требуемое значение, может /потребоваться сформировать на него переход /определяем значение перехода, если нужно subwf past_pulse, 0 /сравниваем требуемое значение /с самым последним импульсом btfsc status,z goto pulse_op /если они равны, переход к выдаче импульса btfsc status,c /если флаг переноса не установлен, /требуемое больше последнего goto $ + 3 incf past_pulse,1 /сюда, если требуемое больше последнего, /переход в сторону большего goto $+2 decf past_pulse,1 /сюда, если требуемое меньше последнего, /переход в сторону меньшего movf past_pulse,0 /сохраняем новое значение /для следующего раза movwf pw_cntr /теперь выдаем импульс pulse_op bsf portb,3 /устанавливаем единичное значение /импульса pw_loop call delay20u decfsz pw cntr goto pw_loop bcf portb,3 /сброс импульса movlw D' 5 ' /перезагрузка счетчика прерываний movwf int cntr intend bcf pirl,tmr2if /очистка флага прерывания retfie
258 Глава 9. Дальнейшее исследование вопросов синхронизации Пример программы 9.3. Окончание____ /таблица позиций вала сервопривода int_table addwf pci retlw D'20 ' /задержка 400 мкс, 0 градусов retlw D' 40 ' /задержка 800 мкс, 45 градусов retlw D' 60 ' /задержка 1200 мкс, 90 градусов - retlw D' 80 ' /задержка 1600 мкс, 135 градусов retlw D'100' /задержка 2000 мкс, 180 градусов retlw D' 80 ' /задержка 1600 мкс, 135 градусов retlw D' 60 ' /задержка 1200 мкс, 90 градусов retlw D' 40 ' /задержка 800 мкс, 45 градусов /ПОДПРОГРАММЫ /вносит задержку в 20 мкс delay20u movlw 5 /вызывается 5 циклов, каждый по 3 мкс, плюс вызов, /возврат (2 командных цикла) и 2 команды move /теряется меньше одного цикла, когда /отрабатывается последняя команда goto movwf delcntrl dela decfsz delcntrl,! /3 командных цикла, т.е. 3 мкс goto dela return (другие подпрограммы временных задержек опущены) end Опытным путем было установлено, что эта небольшая программа работает хорошо, изменение позиции вала сервопривода происходило гладко. 9.6.2. Дополнительные директивы Ассемблера для распределения памяти и осуществления ветвления программ Обратите внимание на использование в вышеприведенной программе двух полезных дополнений к уже освоенному нами инструментарию программирования на Ассемблере. Так, в начале программы используется пара директив Ассемблера: cblock и endc. Эти директивы используются для определения списка ячеек памяти. Это заменяет использо- вание длинного списка операторов equ. В подпрограмме обслуживания прерываний ветв- ление достигается следующим образом: btfsc status,с /если флаг переноса не установлен, /требуемое больше последнего goto $+3 incf past_pulse,1 /сюда, если требуемое больше последнего, /переход в сторону большего goto $ + 2 Здесь символ доллара ($) представляет текущее значение счетчика команд. Его ис- пользование в строке goto $ + 3 инициализирует переход вперед на три строки. Отри- цательные значения также могут использоваться. Эта методика неоценима для локаль- ных переходов на несколько строк вперед или назад, снижая потребность в использова- нии меток строк. Она менее полезна при организации более длинных переходов, так как изменение программы может привести к тому, что количество строк в ней изменится и указанные ранее значения переходов окажутся неверными.
9.7. Использование ШИМ для цифро-аналогового преобразования 259 9.7. Использование ШИМ для цифро-аналогового преобразования В то время как ШИМ, возможно, чаще всего используется для управления нагрузками, она также позволяет реализовать простой и очень эффективный цифро-аналоговый пре- образователь. (ЦАП). Если поток сигналов ШИМ фиксированной частоты пропустить через фильтр нижних частот (ФНЧ) с соответствующей частотой отсечки, то поток дис- кретных импульсов превращается в постоянное напряжение с небольшими остаточными пульсациями. Если сигналы ШИМ модулировать, то может быть получено изменяющееся выходное напряжение. Эта идея иллюстрируется в простой форме на рис. 9.15. Поток сигналов ШИМ про- пускается через RC-фильтр, который оказывает сглаживающий эффект, видимый на ри- сунке. Характеристика фильтра, показанная на рис. 9.15 (Ь), выбрана таковой, что час- тота ШИМ лежит в полосе затухания фильтра. Если частота модуляции лежит в полосе пропускания фильтра, то частота ШИМ будет блокироваться, а проходить будет только модулирующая частота. Эффект может быть достаточно впечатляющим. (а) JWL (Ь) Рис. 9.15. Фильтрация потока сигналов ШИМ с целью получения аналогового напряжения: (а) — фильтр нижних частот с входным и выходным сигналами; (Ь) — итоговая характеристика фильтра 9.7.1. Пример использования ШИМ для цифро-аналогового преобразования АУСМ Derbot имеет в своем составе две секции RC-фильтров нижних частот, выхо- дами которых являются ТР1 и ТР2 (рис. А5.1). Они установлены просто для того, чтобы продемонстрировать генерирование аналогового напряжения с использованием ШИМ — никакого участия в функционировании АУСМ они не принимают. При их эксперименталь- ном использовании для названной цели биты активирования электромоторов должны на- ходиться в нулевом состоянии. Программа dbt_PWM_qrtr_sinwave, находящаяся на компакт-диске, прилагаемом к этой книге, является простой иллюстрацией рассматриваемой методики. Частично она воспроизводится в примере программы 9.4. Программа использует полное 10-разрядное значение, доступное для установки периода ШИМ. Она генерирует четверть синусоиды, по очереди беря значения из просмотровой таблицы, которая называется Sin_Table. Ячейка памяти с меткой pointer указывает место просмотровой таблицы, в которой прог- рамма в данный момент находится. Имеется 45 точек кривой, хранимых как 16-разрядные значения — в 2 байтах каждое. Это формирует отмасштабированные точки синусоиды для 0,2,4 и так далее вплоть до 90. Однако используются только два старшие бита млад- шего байта. Как только инициализация будет завершена, программа входит в простой цикл, начи- нающийся по метке sin_loop. Старший байт координаты точки переносится непо- средственно в ccprll. Младший байт при этом должен быть трансформирован, чтобы
260 Глава 9. Дальнейшее исследование вопросов синхронизации заполнить два целевых бита в сер Icon. В то же самое время другие биты сер Icon не должны при этом трансформироваться. Вы можете проследить по листингу программы то, как это делается. Задержка в 1 мс вводится для каждой координаты точки, используя подпрограмму delayl. Это, совместно со временем выполнения оставшейся части про- граммы, формирует частоту следования синусоидального сигнала. Пример программы 9.4. использованием ШИМ Генерирование четверти синусоидальной волны с ; dbt_IIU4M_qrtr_sinwave к-****************************** /Демонстрирует выход одной четверти синусоидальной волны на ССР1 /Используются все десять разрядов установки периода ШИМ /TJW 09.07.05 *************< Тестировано 11.07.05 (все вступительные с секции программы опущены) clrf pointer sin_loop movf pointer,0 call sin table /получение старшего байта координаты точки movwf ccprll / перемещение ее на выход ШИМ incf pointer,1 /инкрементирование указателя movf pointer,0 call sin table /получение младшего байта andlw B'11000000 ' /мы используем только 2 старших разряда movwf temp bcf status,c /настройка CCP1CON rr f temp,1 rrf temp,0 ior Iw B'00001100 ' /гарантируем, что другие разряды CCP1CON /установлены правильно, т.е. режим ШИМ /остается выбранным movwf ccplcon /и организован вывод сигналов incf pointer,1 movf pointer,0 sublw D' 92 ' /проверка на конец таблицы btfsc status,z clrf pointer /сброс указателя call delayl goto sin_loop Sin Table addwf pci, 1 retlw 00 /0 градусов, старший байт retlw 00 /0 градусов, младший байт retlw 03 /2 градуса, старший байт retlw 5A /2 градуса, младший байт retlw 06 /4 градуса, старший байт retlw 0B2 /4 градуса, младший байт Также на компакт-диске, прилагаемом к этой книге, находится программа с именем dbt_PWM_full_sinwave. Эта программа использует ту же самую просмотровую таб- лицу для генерирования полного синусоидального сигнала, однако она несколько более сложна, чем версия для четверти синусоидальной волны. Она складывает все координа- ты со средним значением, равным 125d- Это значение представляет собой смещение си- нусоидального сигнала относительно нуля. В первом квадранте она пошагово последо- вательно перебирает просмотровую таблицу, во втором — она осуществляет перебор в
9.7. Использование ШИМ для цифро-аналогового преобразования 261 обратном направлении, в третьем — она вновь перебирает таблицу в прямом направле- нии, однако вычитает координаты из 125D. В четвертом она вновь перебирает координа- ты в обратном направлении и продолжает вычитать их из 125D- Все это можно видеть в полном листинге программы. Выход программы dbt_PWM_full_sinwave можно видеть на рис. 9.16 (а), при этом выходной сигнал пропускается через секцию RC-фильтра 100 нФ / 20 кОм (с частотой отсечки, приблизительно равной 80 Гц). Обратите внимание на горизонтальные и вер- тикальные настройки в каждом случае. Канал 2 в обоих случаях отображает синусои- дальную волну. Изображение (а) демонстрирует весьма удовлетворительную на вид си- нусоидальную волну. Изображение (Ь) показывает детали того же самого сигнала со- вместно с потоком сигналов ШИМ, которые его создают. Период ШИМ, как можно ви- деть на изображении (Ь), равен точно 250 мкс (т.е. частота сигналов равна 4 кГц). Ха- рактерная (однако, небольшая) зубчатая рябь присутствует на аналоговом сигнале, при этом также заметен постепенный общий рост напряжения сигнала. При частоте сигна- лов ШИМ, равной 4 кГц, а также использовании подпрограммы delayl, будет всего четыре или пять ШИМ-циклов на каждую дискрету. Общий период синусоидальной волны, как можно видеть, будет приблизительно равен 3,8 делений по 50 мс каждое, т.е. 190 мс. Эта величина соответствует 180 дискретам, формирующим синусоидальную волну, при этом к каждой дискрете применяется задержка в 1 мс плюс дальнейшее вре- мя выполнения программы. (а) (Ь) Рис. 9.16. Синусоидальная волна, сгенерированная с использованием ШИМ: (а) — выходная синусоидальная волна; (Ь) — внизу поток сигналов ШИМ. Вверху — крупный масштаб аналогового выходного сигнала Использование ШИМ для цифро-аналогового преобразования, как было чуть выше описано, может оказаться простым и эффективным. Однако, этому методу присущи не- которые недостатки, которые необходимо понимать, если предполагается его использо- вать. Ниже эти недостатки кратко перечислены: • Выходное аналоговое напряжение прямо зависит от логических уровней потока сиг- налов ШИМ. Они, в свою очередь, зависят от точности напряжения питания, качества заземляющих цепей и использованной технологии логических схем. В общем случае точного цифро-аналогового преобразования от этой методики ожидать не следует. • Влияние фильтра нижних частот таково, что данный метод малопригоден для генери- рования быстроизменяющихся сигналов. Ситуация может быть улучшена посредст- вом использования фильтра более высокого порядка и/или повышения частоты ШИМ. Это может быть достигнуто уменьшением значения, хранящегося в регистре PR2. Од- нако при повышении частоты ШИМ, таким образом, следует заметить, что разрешение падает. В общем случае мы можем видеть, что любое требование о повышении час- тоты ШИМ конфликтует с требованием о повышении разрешения. • Всегда в аналоговом выходном сигнале будет присутствовать определенный уровень остаточной ряби.
262 Глава 9. Дальнейшее исследование вопросов синхронизации 9.8. Измерение частоты 9.8.1. Принцип измерения частоты Измерение частоты — это очень важное применение как счета, так и синхрониза- ции. В своей основе измерение частоты — это определение того, сколько раз нечто про- исходит в течение заданного периода времени, как иллюстрируется на рис. 9.17. Диапа- зон замеров может простираться от того, как много срабатываний счетчика Гейгера было получено за минуту, как много колебаний за секунду (т.е. Герц) имело место в электрон- ных или акустических измерениях, либо сколько поворотов колеса за единицу времени имело место при измерениях скорости. В этих измерениях необходим как таймер, так и счетчик — таймер для измерения опорного периода времени, а счетчик — для подсчета числа событий за этот период времени. Измеряемая частота Фиксированный известный ___ период времени Должны быть подсчитаны все входные циклы на этом отрезке времени Рис. 9.17. Принцип измерения частоты 9.8.2. Измерения частоты (скорости) в АУСМ Derbot В АУСМ Derbot методика измерения частоты применяется к измерениям скорости перемещения АУСМ, в дальнейшем эта же методика будет применена для управления скоростью. Как показывает рис. 9.17, прежде всего, требуется точная временная база, относительно которой могут делаться измерения. Хотя для этих целей может использо- ваться любой из таймеров 16F873A, у нас оба таймера (0 и 1) уже используются в режиме счета в датчиках поворота колес, поэтому они недоступны. Таймер 2 на первый взгляд будет занят выполнением функции ШИМ, однако в случае программного генерирования ШИМ, описанного в подразделе 9.6, более пристальный взгляд показывает, что этот тай- мер все еще может использоваться. Чуть ранее в этой главе было показано, как может быть получен период прерывания, равный 4 мс, без создания препятствий для выполне- ния функции ШИМ. Этот период слишком мал для большинства замеров частоты, однако если мы сформируем период измерения, основываясь на определенном количестве итера- ций названного периода следования импульса сигнала времени, то получим основу фор- мирования временного периода для замеров частоты. Пример программы 9.5 демонстрирует секции программы Dbt_speed_meas — про- стой программы для измерения скорости, которая в полном варианте приведена на ком- пакт-диске, прилагаемом к этой книге. Эта программа просто включает электромоторы и обеспечивает их вращение с использованием фиксированной частоты сигналов ШИМ. Данная программа структурирована в соответствии с упрощенной блок-схемой по рис. 9.18. Система инициализируется, после чего активируются электромоторы и разрешаются пре- рывания от таймера 2. Прерывания от таймера 2 генерируются каждые 4 мс, при этом каждое 250-е вхождение этого прерывания (т.е. каждую секунду), считываются значе- ния, аккумулированные в таймерах 0 и 1. Использованные настройки таймеров могут быть изучены посредством просмотра листинга программы. Настройки таймеров 0 и 1 — те же, что и в примере программы 9.1, а настройки таймера 2 — те же, что и настройки для примера программы 9.3. Можно
9.8. Измерение частоты 263 видеть, что после инициализации в программе выполняется активирование прерываний и электромоторов, а также установка счетчика прерываний int_cntr. Электромоторы настраиваются на движение вперед на средней скорости. В начале программы обработки прерываний, прежде всего, декрементируется зна- чение int__cntr. Если оно не является нулевым, то программа обработки прерываний прекращает свою работу. Однако если после декрементирования значение счетчика стало нулевым, то по истечении ровно одной секунды значения таймеров 0 и 1 считываются и сохраняются. Таким образом выполняется измерение частоты. В этой простой демонст- рационной программе с результатом измерения ничего не делается. Однако эта програм- ма будет использоваться в следующем подразделе данной главы для реализации управ- ления скоростью в АУСМ Derbot. Рис. 9.18. Программа замера скорости АУСМ Derbot: упрощенная блок-схема Пример программы 9.5. Измерения частоты в применении к АУСМ Derbot ;dbt_speed_meas /Скорость вращения колес АУСМ Derbot замеряется путем подсчета частоты. /Это демонстрационная программа. /Концепция измерения частоты может быть включена в большую программу, /предназначенную, например, для управления скоростью. /TJW 07.07.05 Тестировано 07.07.05 #include p!6f873A.inc (вступительные секции программы опущены) /инициализация /установка СФР в банке памяти 1 main bcf status, rpl bsf status,грО /выбор банка памяти 1 movlw В111101000' /установка таймера 0: внешний вход, /предварительного деления нет
264 Глава 9. Дальнейшее исследование вопросов синхронизации Пример программы 9.5. Продолжение_______________________________________ movwf option_reg /переключение из нуля в единицу, movlw D'249' /установка периода ШИМ movwf рг2 bsf piel,tmr2ie /разрешение прерывания таймера 2 /установка СФР в банке памяти О bcf status,rpO /выбор банка памяти О movlw В'00000011' /установка таймера 1: предварительное /деление не используется, генератор /блокирован, внешний синхровход movwf tlcon movlw В'01111100' /включение таймера 2, /предварительное деление не используется, /используется постделение с коэффициентом 16 movwf t2con movlw В'00001100' /выбор ШИМ movwf ccplcon movwf ccp2con (дальнейшая инициализация и запуск опущены) ;сброс таймеров clrf tmrO clrf tmrll clrf tmrlh /разрешение прерываний movlw D'250' /загрузка счетчика прерываний movwf int_cntr bcf pirl,tmr2if /очистка очереди прерываний bsf intcon,peie /разрешение прерываний /от периферийных устройств bsf intcon,gie /разрешение глобального прерывания /начло движения, ожидание прерывания от таймера movlw D'200' /установка частоты ШИМ на приемлемую скорость /движения вперед movwf ccprll movwf ccpr21 bsf portb,2 /включение оптических датчиков bsf porta,mot_en_left /активирование электромоторов bsf porta,mot—en_rt wait goto wait /Это подпрограмма обслуживания прерываний. Прерывания возникают /через каждые 4 мс. Идет счет до 250 (т.е. до 1 с), а затем замеряется количество импульсов от каждого колеса. Timer2_Int bsf portc,5 de с f s z int_cntr goto int_end /сюда для выполнение [ измерений movf tmrO,0 movwf tmrO—temp movf tmrll,0 movwf tmrl—temp clrf tmrO clrf tmrll / диагностика /очистка счетчиков /сохранение значений счетчиков
9.9. Управление скоростью в применении к АУСМ Derbot 265 Пример программы 9.5. Окончание btfss portc,0 /однако инкрементирование Tl, /если он в нуле, поскольку первый /нарастающий фронт не был распознан incf tmrll movlw D'250' /перезагрузка счетчика прерываний movwf int_cntr int_end bcf pirl,tmr2if bcf portc,5 /диагностика retfie 9.9. Управление скоростью в применении к АУСМ Derbot Встроенные системы часто должны выполнять управление, и сейчас мы впервые при- меним некоторые принципы управления для замкнутого контура. Программа Dbt_spe- ed_control, частично показанная в примере программы 9.6, использует только что обсу- ждавшееся измерение частоты для реализации управления для замкнутого контура в при- менении к электромоторам АУСМ. Оно основано на принципах простых систем управле- ния по замкнутому контуру в том, что выходная переменная (скорость электромотора, отображаемая частотой сигнала с датчика поворота вала колеса) сравнивается с требуе- мым значением. Разница между двумя величинами усиливается для модифицирования управляющего воздействия на электромоторы. Алгоритм управления является идентич- ным для каждого электромотора и встроен в подпрограмму обслуживания прерываний — соответствующая секция следует после строки комментария “настройка скорости левого электромотора”. Пример программы 9.6. Программа управления скоростью передвижения АУСМ Derbot ;dbt_speed_control /Скорость вращения колес АУСМ Derbot замеряется посредством /замера частоты. АУСМ Derbot двигается вперед на фиксированной /скорости — демонстрируется простое управление скоростью /TJW 07.07.05 bs f Тестировано, .24.07.05 status,rpO /выбор банка памяти 0 movlw В'11101000' /настройка таймера 0: внешний вход, /инкрементирование по переключению /с 0 в 1, предварительный делитель /не используется movwf option_reg movlw Off /установка периода ШИМ на максимум movwf рг2 bsf piel,tmr2ie /разрешение прерывания от таймера 2 /установка СФР в банке памяти 0 bcf status,rpO /выбор банка памяти 0 movlw В'00000011' /настройка таймера 1: предварительный /делитель не используется, генератор /заблокирован, movwf tlcon /вход внешний, синхронизация внутренним /тактовым генератором
266 Глава 9. Дальнейшее исследование вопросов синхронизации Пример программы 9.6. Продолжение ___________________,____________________ movlw В'01111100' /включение таймера 2, предварительный /делитель не используется, постделитель /установлен на коэфф, деления, равный 16 movwf t2con /период внутр, таймера равен 4,096 мс, /частота равна 244,14 Гц /Это подпрограмма обработки прерываний. Прерывания происходят каждые /4,096 мс. Счет до 125 (0,512 с), затем считывается отсчет импульсов /для каждого колеса и вычисляются новые настройки ШИМ Таймер2_Int bsf portc,5 /диагностика /это проверка decfsz int_cntr goto int_end скорости movf tmrO,0 /сохраняем значения счетчиков movwf movf movwf clrf clrf btf ss tmrO—temp tmr11,0 tmrl_temp tmrO tmrll portc,0 /очистка счетчиков /инкрементирование Т1, если он incf tmrll /в нуле, поскольку первый нарастающий /фронт не был распознан /Настраиваем скорость левого электромотора. Находим вычитанием /"погрешность" частоты movf tmrO—temp,0 sublw D'10' /это требуемая скорость movwf tmr0—temp btf ss status,с /проверка знака результата, пропуск /если +ve goto left_err_neg bcf status,с /сюда, если результат положителен, "усиливаем" результат за счет сдвига влево. Проверка на выход за диапазон, бит 7 изначально в 0 /(из-за используемых чисел) btf ss tmrO—temp,6 /проверка на возможный выход /за диапазон, не сдвигать, /если бит 6 установлен rlf tmrO temp,f bcf status,c btf ss tmrO temp,6 /повторный сдвиг rlf tmrO temp,f bcf status,c btf ss tmrO temp,6 /повторный сдвиг rlf tmrO temp,f movf tmrO temp,w addwf ccpr21,0 /добавить в текущее значение ШИМ, /результат в W movwf tmrO—temp /тестирование на выход за /диапазон и корректировка btfsc status,c goto set 1 max /флаг переноса установлен, поэтому /устанавливаем максимальный выход movf tmrO—temp,0 /выдача вычисленного результата на
9.9. Управление скоростью в применении к АУСМ Derbot 267 Пример программы 9.6. Окончание movwf ccpr21 goto rt_adj /и обработка set_l_max movlw D' 255 ' ;сюда, если значение выхода максимально, movwf ccpr21 /выдача максимального значения goto rt adj /и обработка left_err_neg comf tmr0_temp,0 /здесь хранится отрицательное число, addlw 1 /следовательно, выполняем коррекцию, /взяв дополнение до 2 movwf tmr0__temp btfss tmr0_temp,6 /проверка на возможное переполнение rlf tmrO temp,f /не сдвигаем, если бит 6 установлен bcf status,c btfss tmrO temp,6 /повторный сдвиг rlf tmrO temp,f bcf status,c btfss tmrO temp,6 /повторный сдвиг rlf tmrO temp,f movf tmr0_temp,w subwf ccpr21,1 /и вычитание из текущего значения ШИМ /Тестирование на выход за диапазон не /включено ;теперь настраиваем скорость правого электромотора Данная программа является, по сути, расширением примера программы 9.5, за исклю- чением того, что содержимое регистра PR2, управляющего максимальным периодом ШИМ, было изменено на 255d- Это просто упрощает манипуляции с данными и понимание про- граммы. Это, однако, означает, что период прерываний от таймера 2 теперь будет равен 4,096 мс, а не 4,000 мс, поэтому измерения частоты не будут точно соответствовать поло- вине секунды либо секунде. Но поскольку эта информация все равно не отображается в дружественной для человека форме, то, фактически, это не имеет значения. Для понимания настроек внутри программы необходимо понимание того, как скорость вращения электромотора связана с частотой сигнала, снимаемого с датчика поворота вала колеса. Использованный датчик поворотов вала колеса обеспечивает генерирование 16-ти импульсов на каждый поворот вала. При напряжении питания в 9 В, приложенном к ин- тегральной схеме управления электромотором L293, замеренная скорость холостого хода на выходе редуктора была приблизительно равной 154 оборота в минуту. Это значение находится в приемлемом соответствии с табл. А3.1, если принять во внимание потери в управляющих электронных схемах. Эта скорость преобразуется в максимальную частоту сигналов с датчика поворотов вала колеса как (154 х 16) / 60 или 41 Гц. Для тестирования этой программы была выбрана скорость, равная приблизительно половине названного максимума. Это означает, что на отрезке времени, равном 0,512 с, ожидается отсчет в 10 единиц (ближайшее целое число). Это значение приведено в про- грамме. Сам по себе алгоритм управления соответствует блок-схеме, приведенной на рис. 9.19. Ее рекомендуется изучать совместно с листингом программы. Частота ШИМ управления электромоторами устанавливается на середину диапазона (т.е. устанавливается нулевая скорость) в начале программы, после чего впоследствии подпрограмма обработки преры- ваний настраивает ее. Листинг программы показывает, что таким образом настраивается только левый электромотор. Настройки правого электромотора можно увидеть в полном листинге данной программы, имеющейся на компакт-диске, прилагаемом к этой книге. Опытным путем было установлено, что данная программа работает хорошо, при этом управляемая скорость сначала замерялась “на стенде” посредством контроля частоты выходных сигналов отражательных оптических датчиков. Когда АУСМ Derbot двигался
268 Глава 9. Дальнейшее исследование вопросов синхронизации по полу, сразу было видно, что он двигается по приемлемо прямой линии, а не по легкой кривой, по которой он двигался, когда оба электромотора работали без использования управления скоростью. Стоить еще раз напомнить себе, что все функции данной программы — от задания скорости электромотора до ее измерения и коррекции — были достигнуты только за счет использования методов счета и синхронизации. Рис. 9.19. Блок-схема алгоритма управления электромотором 9.10. Когда нет таймера В то время как мы уже видели большой потенциал аппаратного таймера, все же возни- кают ситуации, когда таймера нет или он недоступен. Может оказаться, что в используе- мом микроконтроллере таймеров нет или же все они уже задействованы. Именно послед- ний случай возникает в АУСМ Derbot, где уже все таймеры используются, хотя в случае применения ультразвукового датчика требуется еще один таймер. В этом случае было при- нято решение возвратиться к использованию программного цикла синхронизации, кото- рый описывался в Главе 5. Недостатком такого цикла является то, что он полностью загру- жает ЦП. Однако в данном случае, поскольку замеры ультразвуковых импульсов непре- рывно не выполняются, а их временные промежутки относительно малы, то загрузка про- цессора будет относительно невелика. Пример программы 9.7 демонстрирует часть программы, которая измеряет расстояние между ультразвуковым датчиком, описанным в подразделе 8.6.5 Главы 8 и объектом, на- ходимся в радиусе его действия. Когда мы перейдем к Главе 77, то будем рассматривать отображение расстояния в сантиметрах на ЖК ПУ АУСМ, при этом мы увидим, что элек- тронные цепи могут быть настроены таким образом, что будут осуществлять роль ультра- звуковой измерительной рулетки. Соответствующая вторая секция программы в данном примере не приведена, поскольку она находится в подпрограммах манипулирования дан- ными, которые описываются в Главе 11. Полностью программа приведена на компакт- диске, прилагаемом к этой книге. Ультразвуковой датчик разделяет штырьки с диагно- стическими светодиодами. Следовательно, если этот датчик используется, то светодиоды больше не могут независимо использоваться, хотя они и будут реагировать на выдачу ульт- развуковых импульсов.
9.10. Когда нет таймера 269 Главная программа реализует временную диаграмму, приведенную на рис. 8.16, она структурирована в форме непрерывного цикла, начинающегося по метке us_loop. Ульт- развуковой импульс инициализируется импульсом от разряда 5 порта С. Далее следует пе- риод молчания, позволяющий нарастание эхо-импульса. Затем программа входит в цикл синхронизации, внутри которого счетчик echo_time инкрементируется в каждой ите- рации цикла. Этот цикл спроектирован таким образом, что его длительность равна точно 30 мкс. При скорости звука, равной 1 мм/3 мкс, это означает, что звук пройдет 10 мм за вре- мя каждого прохода цикла. Поскольку звук должен пройти до объекта и отразиться от него, то это, в свою очередь, означает погрешность измерений, равную 5 мм. Состояние эхо-им- пульса проверяется на каждой итерации цикла и если обнаружено, что эхо-импульс упал до нуля, то выполнение цикла прекращается. Если же счетчик переполнился, то это означает, что объект не обнаружен. Краткий звуковой сигнал от зуммера АУСМ подается, если объект обнаружен и длинный звуковой сигнал — если объект не обнаружен. Полная версия этой программы продолжает выполняться, преобразуя отсчеты в echo_time в значение расстояния, выраженное в сантиметрах. Пример программы 9.7. Программная синхронизация ультразвукового датчика ;Dbt_US_tst /Тестирование ультразвукового датчика АУСМ Derbot. /Замеряет расстояние между датчиком и объектом, преобразует и /передает значение измеренного расстояния на ЖК-индикатор /Звук проходит 1 мм за 3 мкс. Для радиуса действия в 1 м требуется /отсчет времени до б мс, для 2м— до 12 мс. ,-TJW 10.0 9.05 Тестировано 12.09.05 /Спецификация ОЗУ cblock 20 echo time /измеренное время возврата эхо-сигнала endc org 00 goto begin / (вступительные секции программы опущены) Главный цикл начинается здесь us_loop clrf echo_time /очистка счетчика, используемого /для измерения времени bsf portc,5 /выдача ультразвукового импульса /минимальная длительность равна 10 мкс call delay20u bcf portc,5 call delay300u /пауза для установки единичного значения /выхода, т.е. пропуск 5 см /отработка этого цикла занимает 30 мкс на итерацию, /т.е. 10 мм туда и обратно, или 5 мм в одну сторону, /следовательно, 8-битный диапазон равен 255 х 5 мм = 1275 мм. /Максимальная длительность отработки циклов равна 30 х 255 = 7,6 мс echo call delay24u incf echo time,1
270 Глава 9. Дальнейшее исследование вопросов синхронизации Пример программы 9.7. Окончание btfsc status,z goto no_tgt btfsc portc,6 goto echo ;сюда, если обнаружен объект bsf portb,1 call delay200 bcf portb,1 call delay200 /проверка на переполнение, которое /указывает, что объект не обнаружен /проверка эхо-импульса, пропуск, если /бит сброшен (т.е. эхо-импульс принят) /индикация коротким звуковым сигналом (здесь выполняется обработка данных и передача результата на ЖК-индикатор) goto us_loop no_tgt bsf portb,1 /индикация длинным звуковым сигналом call delay500 call delay500 bcf portb,1 call delay200 goto us_loop (большинство подпрограмм опущены) /Эта подпрограмма вносит задержку в 24 мкс delay24u movlw 6 /устанавливается б циклов, каждый по 3 мкс, /плюс вызов (2) и 2 команды открытия (2) / + 2 командных цикла в конце /менее одного цикла теряется, когда /отрабатывается последняя команда goto movwf delcntrl del21 decfsz delcnti :1,1 /3 командных цикла в этом цикле, т.е. 3 мкс goto nop return del21 Рекомендуется, чтобы на данный момент времени эта программа рассматривалась только как теоретический пример, поскольку подпрограммы, необходимые для ее вы- полнения, будут рассматриваться в Главах 10 и 11. 9.11. Режим бездействия В Главе 6 мы вспоминали о режиме бездействия, когда время кажется почти остано- вившимся (в подразделе, посвященном синхронизации). Режим бездействия в 16F87XA в точности реализован на тех же принципах, что и режим бездействия в 16F84A, описанный в подразделе 6.6 Главы 6. Возможным ограничением режима бездействия в 16F84A явля- ется ограниченный диапазон возможностей выхода из этого режима. Важным примером этого является отсутствие синхронизованного периодическим сигналом активирования. (Хотя и кажется, что сторожевой таймер обеспечивает такую возможность, однако час- тота его работы неопределенна, а диапазон периодов переполнения не очень широк.) По контрасту со сказанным 16F87XA предлагает широкий диапазон возможностей вывода ЦП из режима бездействия, включая ряд возможностей, инициируемых перифе- рийными устройствами. Схема структуры прерываний, показанная на рис. 7.10, указывает, что все периферийные устройства могут инициализировать выход системы из режима без- действия. Практически же, конечно, некоторые из этих устройств в режиме бездействия
9.12. Куда двигаться дальше? 271 прекращают работу, поскольку зависят от тактового генератора, который в этом режиме выключен. Интересным является случай таймера 1, который может работать со своим собственным генератором. Он может продолжать работать, в то время как система нахо- дится в режиме бездействия, периодически активируя ее по прерываниям, полученным по переполнению этого таймера. Возможны следующие источники вывода системы из режима бездействия периферийными устройствами: • Таймер 1, когда он работает в асинхронном режиме; • Прерывание от модуля ССР, работающего в режиме сбора данных; • Триггер специального события при таймере 1, работающий в асинхронном режиме при внешней синхронизации; • Синхронный последовательный порт; • Порт USART (адресуемый универсальный синхронно-асинхронный приемопередат- чик); • Аналого-цифровой преобразователь, работающий с RC-генератором; • Завершение записи ЭСППЗУ; • Изменение состояния выхода компаратора; • Чтение либо запись параллельного подчиненного порта (для 16F874A или ’877А). 9.12. Куда двигаться дальше? На нескольких последних страницах мы обсуждали ценные средства и методы, ко- торые позволяют реализовать процессы, привязанные ко времени. При этом мы старались сохранить простоту изложения — большинство примеров излагались так, как если бы рас- сматриваемый процесс был единственным в системе. На практике, конечно же, это не так — в АУСМ Derbot AGV электромоторы должны работать и в то же время должны заме- ряться их скорости, выполняться управление сервоприводом и так далее. Число привязан- ных ко времени задач, как правило, является большим и возможно, что эти задачи могут между собой конфликтовать. Мы уже рассматривали, например, случай, когда один тай- мер использовался для двух различных и потенциально конфликтующих между собой задач. Этот вызов, связанный с необходимостью упорядочить привязанные ко времени процессы, выполняющиеся во встроенных системах, является общей чертой многих сис- тем, и для того, чтобы ответить на него, необходимо использовать систематический под- ход. Такой подход реализован в операционной системе реального времени, которая бу- дет темой исследования Главы 18. 9.13. Сборка АУСМ Derbot Для выполнения большинства программ, использованных в примерах этой главы, вам потребуется смонтировать в АУСМ Derbot отражательные оптические датчики, а также установить кодирующие структуры датчиков поворота валов колес. Схема принципиаль- ная АУСМ при этом приобретет вид, показанный на рис. 9.20. Для выполнения примера программы 9.3 необходимо также установить сервопривод. Он не показан на рис. 9.20, однако его можно видеть на рис. А3.1. Резюме • Синхронизация — это важный элемент проекта встроенной системы — как сам по себе, так и в применении к другим видам активности встроенных систем, например последовательного информационного обмена или широтно-импульсной модуляции (ШИМ).
272 Глава 9. Дальнейшее исследование вопросов синхронизации • Существует целый ряд таймеров, имеющих полезные дополнительные функции, ко- торые расширяют их способность к сбору информации, сравнению, формированию повторяющихся прерываний или генерированию потока импульсов ШИМ. • В приложениях любой сложности вполне вероятно, что микроконтроллер будет иметь несколько таймеров, работающих одновременно и используемых в различных и, воз- можно, конфликтующих между собой задачах. На этой стадии остается открытым сле- дующий вопрос: как упорядочить и гармонизовать эти привязанные ко времени раз- личные виды активности встроенной системы? LP2950 Выключатель литания 6 z AAAIk. (9 x V) tant. Соединительный разъем питания 1 иг 100 и. 10 V 74HC14 uswitr.li 1 uswilch 2 R4 24k Right 2х30р 4 MHzr Левый электро- мотор VLS In3 Out3 0V 0V Out4 In4 En2 1/6 'НС14РП En1 In 1 Out1 OV OV Out2 In2 ___ VOS L293D DERBOT AGV Intermediate Build Stage 3 TJW Rev. 10.2.06 MCLBRB7 RAO RA1 RA2 RA3 RA4 RA5 Vss Osd Osc2 RCO RC1 RC2 RC3 RB6 RB5 RB4 RB3 RB2 RB1 RBO Vdd Vss RC7 RC6 RC5 RC4 100п 1002 Conn. |бк6 16F873A ТР1<Э 100n Сэ] 10п CO Переключатель режимов ____СЗ Левый T»1 I i r-e °2; ^©5° i о 6; (nc) Диагностические светодиоды Ультразвуковой импульс7 С7 2k ТР2 ZVN4206 .Пьезо- зуммер й------О J Ультразвуковой эхо-сигнал ton—I— Левый t ZVN4206 R14 Правый 5 кб Отражательные оптические датчики типа ОРВ608А т Рис. 9.20. Промежуточная стадия сборки АУСМ Derbot номер 3
ГЛАВА 10. НАЧИНАЕМ ИЗУЧАТЬ ПОСЛЕДОВАТЕЛЬНЫЙ ИНФОРМАЦИОННЫЙ ОБМЕН Важным процессом, реализуемым внутри любой микропроцессорной системы, явля- ется движение данных, например, между ЦП и памятью. Столь же важным процессом является передача данных между подсистемами, а также, например, между компьютером и клавиатурой. При передаче данных биты складываются в слова (часто в байты, но не всегда), затем эти слова посылаются. В общем случае имеются два способа передачи данных. При параллельной передаче данных все биты слова передаются одновременно, каждый бит по собственному соеди- нению. Альтернативой является посылать биты по очереди через одно соединение. Этот подход называется последовательным информационным обменом. Легко увидеть первые относительные преимущества названных методов. Параллельный информационный об- мен требует большего количества проводов и соединений, однако он быстрее. Последо- вательный информационный обмен требует меньшего количества проводов, является бо- лее медленным и требует, в общем случае, использования более сложных аппаратных средств передачи и приема информации. Таким образом, в прошлом передача данных на короткие расстояния носила преиму- щественно параллельный характер. В случае значительных расстояний, когда большое количество проводов было бы громоздким и дорогим решением, использовалась последо- вательная связь. Теперь, однако, названное различие все больше и больше ставится под вопрос — ив большей степени в области встроенных систем, где все должно быть очень маленьким. Преимущество последовательной передачи данных, с присущим ей меньшим количеством проводных связей, во многих ситуациях становится решающим фактором. Таким образом, последовательная связь стала более важной составляющей систем, при этом очень много сил и изобретательности прилагается к тому, чтобы преодолеть ее главные и очевидные недостатки: низкое быстродействие и более сложные аппаратные средства. Эта глава представляет основные идеи, на которых основан последовательный инфор- мационный обмен — как принципиальные, так и практические. Она охватывает: • описание принципов синхронной последовательной связи; • исследование реализации синхронной последовательной связи в PIC® 16F873A, осо- бенно в протоколах SPI (Последовательный периферийный интерфейс) и ГС (Меж- схемный интерфейс); • описание принципов асинхронной последовательной связи; • исследование реализации асинхронной последовательной связи в PIC 16F873A. Как и всегда, значительная часть материала иллюстрируется программным кодом при- меров npoipaMM. Эти программы написаны для АУСМ Derbot и платы его пульта ручного управления. При этом для их запуска имеет значение наличие соответствующих аппарат- ных средств. В данной главе приведен целый ряд осциллограмм передачи последователь- ных данных. На момент написания этой книги фактически было невозможно выполнить имитацию выполнения рассматриваемых программ при помощи имитатора MPLAB , так как последовательные порты в данном имитаторе не поддерживаются.
274 Глава 10. Начинаем изучать последовательный информационный обмен 10.1. Введение в последовательный информационный обмен: основная идея Вступление, приведенное выше, только что обозначило одно из основных преимуществ последовательной связи — это тот факт, что она сохраняет пространство. Рис. 10.1 показы- вает один из методов, которым реализуется этот принцип. Обе из показанных на рисунке микросхем памяти могут хранить одинаковое количество данных. Однако та из них, кото- рая требует параллельного подключения, требует использования 13 адресных линий и вось- ми линий данных, которые доминируют в габаритах микросхемы. Аналогичная микро- схема, но использующая последовательное подключение, имеет две линии (SCL — по- следовательная тактовая частота и SDA — последовательные данные) для данных и три (SO, SI, S2) — для адреса. Это пример микросхемы с интерфейсом ГС, о котором мы ско- ро узнаем намного больше. Очевидно, что экономия пространства на уровне интегральных схем просто поразительна. К этому добавляется экономия пространства за счет проводни- ков печатной платы, ленточных кабелей и так далее. (а) (Ь) NC с 1 28 □ VCC А12 с J WE А7 С з CS2 А6 с □ А8 А5 с □ А9 А4 С 2 А11 АЗ С Ь ОЕ А2 С з А10 А1 С 3 CS1 АО с з D7 D0 с 3 D6 D1 с з D5 D2 с з D4 GND с 14 15 3 D3 SO c”l 8 □ si q з S2 Ч 3 vss d □ vcc WP SCL SDA Рис. 10.1. Пример плоских корпусов с двухрядным расположением выводов (DIP-корпусов), требуемых для памяти объемом 8 Кбайт, приблизительно в масштабе: (а) — параллельные шины адреса и данных; (Ь) — последовательные адрес и данные В то время как последовательная связь имеет ряд явных преимуществ, важно понимать и вызовы, которые она предъявляет. Если есть только один провод для передачи данных, то как мы узнаем, когда начинается или заканчивается отдельный бит, или когда начи- нается или заканчивается слово? Эти вопросы решаются различными интересными спо- собами. Два разных способа используются для идентификации отдельных битов. Простой способ состоит в том, чтобы посылать сигнал тактовой частоты, сопровождающий данные; каждый цикл тактовой частоты используется для того, чтобы определить 1 бит данных. Этот способ называется синхронным последовательным информационным обменом. При втором способе вместо того чтобы всегда посылать сигнал тактовой частоты, некоторые требования к синхронизации могут быть внедрены в сами данные. В этом случае может стать возможным обходиться вообще без тактовой частоты, а информационные биты будут при этом все же правильно идентифицироваться. Этот способ называется асинхронным последовательным информационным обменом. Мы будем до некоторой степени детально рассматривать оба эти способа информационного обмена в течение всей этой главы. Для идентификации начала и конца целого слова данные обычно упаковывают в неко- торый формат. Синхронизация и форматирование данных подразумевает использование некоторого набора правил, чтобы гарантировать согласованную связь. Эти наборы правил называются протоколами, они очень важны в мире последовательной связи. Некоторые из них сравнительно просты, в то время как другие — очень сложны. В этой главе мы рас- смотрим ряд таких протоколов.
10.2. Простые последовательные каналы связи — синхронный информационный обмен 275 В последовательном канале связи в общем случае мы используем идею о передатчике — устройстве, выдающем данные в последовательный канал связи, и приемнике — уст- ройстве, получающем эти данные. Говоря общими терминами, любое устройство в после- довательном канале связи иногда называют узлом. Чтобы иллюстрировать наш анализ последовательного информационного обмена, мы будем рассматривать возможности его организации в 16F873A. Он имеет два последова- тельных порта, как уже упоминалось в Главе 7. Оба они чрезвычайно гибки и могут кон- фигурироваться различными способами. Следовательно, оба они и достаточно сложны. Главный синхронный последовательный порт (MSSP) разработан для реализации различ- ных форм последовательной связи, в то время как адресуемый универсальный синхронно- асинхронный приемо-передатчик (USART) может функционировать как в синхронном режиме, так и в асинхронном. 10.2. Простые последовательные каналы связи — синхронный информационный обмен 10.2.1. Основы синхронной связи Чтобы понимать, как данные могут быть посланы последовательно, полезно исследо- вать используемое оборудование. Наиболее вероятно, что данные внутри микропроцессо- ра или памяти используются и форматируются в параллельном виде. Следовательно, по- следовательный передатчик должен быть способным принять данные в параллельном формате, а затем передать их в последовательном; последовательный приемник должен быть способным делать обратное действие. Классический способ реализации задуманного — использовать сдвиговый регистр. Простой 8-разрядный сдвиговый регистр показан на рис. 10.2. Он набран из восьми триггеров, соединенных вместе таким образом, чтобы Q-выход каждого был информаци- онным входом следующего. Все триггеры управляются одной и той же тактовой частотой, при этом на каждый цикл тактовой частоты данные перемещаются на один триггер вправо. Если новый бит данных будет появляться на входе на каждом цикле тактовой частоты, то за восемь циклов тактовой частоты 1 байт будет загружен в такой регистр. После этого он может читаться как параллельное слово на выходах от QA до Qh- Эта простая схема мо- жет работать как приемник последовательных данных. Рис. 10.2. 8-разрядный сдвиговый регистр— возможный приемник последовательных данных Не трудно доработать эту схему так, чтобы параллельные данные не только могли чи- таться из сдвигового регистра, но также могли бы в него загружаться в форме параллель- ного слова. Вряд ли стоит рисовать полную логическую схему такого сдвигового регистра — вместо этого мы могли бы представить его в форме блок-схемы, которая показана на рис. 10.3. В этот универсальный сдвиговый регистр мы можем засылать последователь- ные данные или выгружать их из него, кроме этого мы можем также читать из него парал- лельные данные или загружать их в него. На данном этапе мы уже имеем базис формирования последовательного канала связи. Если взять два сдвиговых регистра, показанных на рис. 10.3, и синхронизировать их от
276 Глава 10. Начинаем изучать последовательный информационный обмен одного источника, то данные из каждого из них могут перемещаться последовательно в другой, используя соединение, показанное на рис. 10.4. Фактически в этом случае два 8- разрядных сдвиговых регистра будут работать как один 16-разрядный сдвиговый регистр с выходом, поданным обратно на вход. После восьми циклов тактовой частоты данные, имеющиеся в одном сдвиговом регистре, будут перемещены в другой. Следовательно, любой из этих регистров может рассматриваться как передатчик и любой — как прием- ник. Действие передачи данных фактически управляется тактовой частотой. Такая линия называется синхронным каналом связи, потому что передача данных синхронизирована по общему сигналу т актовой частоты. Рис. 10.3. Блок-схема универсальною сдвиговою регистра Последовательный узел 1 Последовательный узел 2 Рис. 10.4. Универсальный последовательный канал связи 10.2.2. Реализация синхронного последовательного ввода-вывода в микроконтроллере Только что описанный синхронный последовательный канал связи может быть легко реализован в микроконтроллере, как показано на рис. 10.5. Источник тактовой частоты помещен в микроконтроллер, и поскольку тактовая частота управляет потоком данных, этот узел называется ведущим. Другой узел называется подчиненным. Подчиненное уст- ройство может быть другим микроконтроллером, памятью или одним из ряда других пе- риферийных устройств. Этот вид соединения является основой многих простых внедренных последователь- ных каналов связи. Сдвиговый регистр отображается на пространство памяти — из него можно считывать и в него можно записывать. 10.2.3. Microwire и SPI (Последовательный периферийный интерфейс) В недавних 1970-ых и в начале 1980-ых фирмы National Semiconductor, Motorola и другие разрабатывали микропроцессоры и микроконтроллеры, которые имели встроенную
10.2. Простые последовательные каналы связи — синхронный информационный обмен 277 функцию синхронного последовательного информационного обмена. Эти фирмы нужда- лись в том. чтобы определить связанные с этими функциями операционные характеристики с тем, ч тобы другие изготови тели могли бы производить устройства, которые могли надеж- но взаимодействовать с их изделиями. Как National, так и Motorola производили последо- вательные порты, которые работали описанным выше способом. На базе их разработок были сформированы два стандарта. National назвала свой стандарт “Microwire”, a Motorola назвала свой стандарт SPI. Эти стандарты подобны, а выполненные в соо тветствии с ними изделия могут осуществлять между собой информационный обмен. Каждый стандарт обес- печивает гибкость коррек тировки характеристик, например определения того, будут ли данные передаваться по возрастающему фронту или срезу синхроимпульсов. Оба стан- дарта применяются уже на протяжении многих лет и хорошо себя зарекомендовали. При этом и сейчас производятся новые микросхемы, совместимые с этими стандартами. Мы рассмотрим реализацию SP1 в следующих подразделах. Ведущее устройство Подчиненное устройство Обозначения: MSB — старший бит; LSB — младший бит; SDO — выход последовательных данных SDI — вход последовательных данных; SCLK — последовательные тактовые импульсы Рис. 10.5. Синхронный носледоваюльный канал связи, реализованный в микроконтроллере 10.2.4. Введение множественных узлов Схема на рис. 10.5 показывает эффективную последовательную линию передачи дан- ных, но она соединяет только два узла. Как можно было бы ее расширить? Ответ прост. Если ввести средства выбора того, с каким подчиненным устройством ведущее устройство будет обмениваться данным, то более одного подчиненного устройства смогут подклю- чаться к последовательным линиям передачи данных, как это показано на рис. 10.6. Каж- дый вход подчиненного устройства теперь требует средств его активирования, иногда соответствующую линию называют “Выбор подчиненного устройства” (SS) или “Выбор микросхемы”. Точное функциональное назначение линии SS несколько изменяется от од- ного устройства к другому, но в большей или меньшей степени можно сказать, что эта линия заставляет подчиненное устройство полностью или частично отсоединяться от по- следовательной линии передачи данных. Теперь ведущее устройство должно располагать выделенной линией для каждого подчиненного устройства, с которым оно связывается; это могут быть отдельные выходы портов.
278 Глава 10. Начинаем изучать последовательный информационный обмен 10.3. Модуль главного синхронного последовательного порта (MSSP) 16F87XA в режиме SPI Модуль MSSP разработан для обеспечения синхронной связи и может быть сконфигу- рирован как простой синхронный порт (этот режим называется режимом SPI, но он совмес- тим и с режимом Microwire) или как порт 12С (Межсхемный интерфейс). Он имеет зри вы- деленных специальных функциональных регистра — SSPCON1, SSPCON2 и SSPSTAT, которые можно видеть на карте файловых регистров, приведенной на рис. 7.6. Он также имеет регистр передачи данных, SSPBUF, и может быть источником прерываний, как было показано на рис. 7.10. В этом подразделе мы будем рассматривать данный модуль в режиме SPI. Рис. 10.6. Одно синхронное ведущее устройство с множеством подчиненных устройств 10.3.1. Краткий обзор порта Рис. 10.7 показывает MSSP, сконфигурированный как порт SPI. Он может быть скон- фигурирован как ведущий или подчиненный, при этом, если он сконфигурирован как веду- щий, то имеется возможность выбора из ряда тактовых частот. Давайте проанализируем, как он использует простые концепции последовательной связи, которые мы уже обсуди- ли. В основе последовательного порта лежит сдвиговый регистр SSPSR. Когда на него подаются тактовые импульсы, он передает последовательные данные на штырек SDO (если логический элемент буфера вывода открыт) и принимает последовательные данные со штырька SDI. Если порт установлен как подчиненный, то он будет получать тактовую частоту от ведущего устройства системы через штырек SCK. Если же порт установлен как ведущий, то он будет генерировать тактовую частоту, которую будет теперь выдавать через штырек SCK. Эта тактовая частота получается или от внутреннего тактового гене- ратора, или от таймера 2. Важной доработкой рассмотренного ранее простого последовательного порта явля- ется добавление буферного регистра SSPBUF. Он содержит байт данных, который дви- гается в или из сдвигового регистра, и является, фактически, адресуемым регистром, в который программа может или записывать, или из которого может считывать. Это делает последовательный порт намного более гибким в использовании. Данные могут переме- щаться в или из буфера, в то время как сдвиговый регистр выполняет свою работу. Это, например, позволяет временно хранить полученный байт, в то время как следующий уже загружается в сдвиговый регистр.
10.3. Модуль главного синхронного последовательного порта (MSSP) 16F87XA в режиме SPI 279 Рис. 10.7. Блок-схема MSSP для режима SPI (дополнительные метки в затененных полях добавлены автором) 10.3.2. Конфигурация порта Двумя специальными функциональными регистрами, которые управляют работой рас- сматриваемого порта в режиме SPI, являются регистры SSPCON1 и SSPSTAT. Их исполь- зование в режимах SPI и 12С несколько отличается. Эти регистры показаны для случая их использования в режиме SPI на рис. 10.8 и 10.9, соответственно. В них имеются биты, предназначенные для: • активирования и конфигурирования порта; • установки тактовой частоты и характеристик тактового генератора; • управления передачей данных и буферизацией. Порт стробируется разрядом 5 (SSPEN) регистра SSPCON1, а его режим работы уста- навливается младшими 4 разрядами этого же регистра. На рис. 10.8 можно видеть, что эти разряды определяют, должен ли порт работать как ведущий или же как подчиненный. Если он работает в режиме ведущего устройства, то доступны четыре источника синхроимпуль- сов. Это могут быть сигналы генератора синхроимпульсов, разделенные на 4, 16 или 64, или же выход таймера 2, как описано в Главе 9 и отображено на рис. 9.4. _ Если порт работает в режиме подчиненного устройства, то входной штырек SS сиг- нала выбора подчиненного устройства может быть стробирован младшими разрядами SSPCON1. В этом случае, внешний сигнал SS может управлять буфером с тремя состоя- ниями, который управляет штырьком SDO и тактовой частотой, подаваемой на сдвиго- вый регистр. Таким образом, вход SS активирует работу последовательного порта, и этот порт может использоваться в многоузловой конфигурации — например такой, какая по- казана на рис. 10.6.
280 Глава 10. Начинаем изучать последовательный информационный обмен R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 WCOL SSPOV SSPEN СКР SSPM3 SSPM2 SSPM1 SSPM0 разряд 7 разряд 0 разряд 7 WCOL. бит обнаружения коллизии записи (только режим передачи) 1 - запись тз регистр SSPBUF тз то время когда он все еще передает предыдущее слово (должен быть очищен программно) 0 - коллизии нет разряд 6 SSPOV. бит индикации переполнения при приеме Режим подчиненною устройства SPI; 1 = новый байт получен, тз то время как регистр SSPBUF все еще содержит предыдущие данные. В случае переполнения данные в SSPSR теряются. Переполнение может происходить только тз режиме подчиненною устройства. Пользователь должен считывать SSPBUF даже тз тех случаях, когда он только передает данные, чгобы избежать состояния переполнения. (Ретистр должен очищаться программно.) 0 = переполнения нет Примечание. В режиме ведущего устройства бит переполнения не устанавливается, так как каждый новый прием (и передача) инициализируются выполнением записи тз регистр SSPBUF. разряд 5 SSPEN: бит активирования синхронного последовательного порта 1 = активирует последовательный порт и конфигурирует SCK, SDO, SDI и SS как штырьки последовательного порта 0 = отключает последовательный порт и конфигурирует перечисленные штырьки как штырьки порта ввода-вывода Примечание. Когда порт активирован, названные штырьки должны быть правильно сконфитурированы как входы или как выходы. разряд 4 СКР: бит выбора полярности ситналов тактовой частоты 1 = считается неактивное состояние сигнала, когда он в состоянии логической единицы 0 = считается неактивное состояние ситнала, когда он в состоянии логического нуля разряды 3-0 SSPM3:SSPMO: биг выбора режима синхронного последовательного порта 0101 = режим нодчинеттното устройства SPI, синхронизация — штырек SCK. Управление штырька SS заблокировано. SS может использоваться как штырек ввода-вывода _ 0100 = режим подчиненного устройства SPI, синхронизация — штырек SCK. Управление нпырька SS разрешено 0011 = режим ведущего устройства SPI, синхронизация — TMR2 выход/2 0010 = режим ведущего устройства SPI, синхронизация — Fosc/64 0001 = режим ведущего устройства SPI, синхронизация — Fosc/16 0000 = режим ведущего устройства SPI, синхронизация — Fosc/4 Примечание. Не перечисленные здесь комбинации битов являются либо зарезервированными, либо используются только в режиме 12С. Рис. 10.8. Регистр SSPCON1 (адрес 14н) в режиме SPI R/W-0 R/W-0 R-0 R-0 R-0 R-0 R-0 R-0 SMP СКЕ D/A Р S R/W UA BF разряд 7 разряд 0 разряд 7 SMP: бит выборки Режим ведущего устройства SPI: 1 = выборка входных данных осуществляется в конце периода вывода данных 0 = выборка входных данных осуществляется в середине периода вывода данных Режим подчиненного устройства SPI: SMP должен быть очищен, когда используется режим подчиненного устройства SPI. разряд 6 СКЕ: биг выбора тактовой частоты SPI 1 = передача выполняется, когда сигнал тактовой частоты переходит из активного в неактивное состояние 0 = передача выполняется, когда сигнал тактовой частоты переходит из неактивного в активное состояние Примечание. Полярность состояния ситнала тактовой частоты устанавливается битом СКР (SSPCON1 <4>). Разряды от 1 до 5 в режиме SPI не используются разряд 0 BF: бит заполнения буфера (только для режима приема) 1 = прием завершен, SSPBUF заполнен 0 = прием не завершен, SSPBUF не заполнен Рис. 10.9. Ретистр SSPSTAT (адрес 94н) в режиме SPI
10.3. Модуль главного синхронного последовательного порга (MSSP) 16F87XA в режиме SPI 281 Для всех штырьков, через которые будут проходить данные или сигналы тактовой час- тоты, биты направления перемещения данных должны быть установлены требуемым об- разом. Следовательно, для штырька SDO, который разделяется с разрядом 5 порта С, раз- ряд 5 TRISC должен быть сброшен, чтобы объявить штырек выходом. Точно так же, для SCK в режиме ведущего устройства разряд 3 TRISC должен быть сброшен (чтобы объя- вить его выходом), в то время как в режиме подчиненного устройства этот бит должен быть установлен (чтобы объявить его входом). Штырек SDI, однако, находится под прямым управлением модуля MSSP. 10.3.3 . Установка тактовой частоты Рис. 10.10 показывает связь между сигналами тактовой частоты и сигналами данных, для случая, когда модуль находится в режиме ведущего устройства. Если бит СКР уста- новлен в 1, то неактивным состоянием сигнала тактовой частоты считается состояние, со- ответствующее логической единице. Фронт синхроимпульса, по которому передаются дан- ные, определяется битом СКЕ. Для входящих данных, момент, когда данные считываются, определяется битом SMP. Способ, которым они устанавливаются, может быть определен в соответствии со специфическими требованиями используемого подчиненного устрой- ства. Конечно же, очень важно обеспечивать непротиворечивость в рамках взаимосвязан- ной системы. Писать в SSPBUF SCK (СКР = о СКЕ = 0) SDI (SMP = 0) SCK (СКР = 1 СКЕ = о) SCK (скр = о СКЕ = 1) 4 режима синхронизации SCK (СКР = 1 СКЕ = 1) SDO (СКЕ = 0) SDO (СКЕ= 1) Input Sample (SMP = 0) SDI (SMP = 1) Выборка входа (SMP = 1) SSPIF SSPSR to SSPBUF Рис. 10.10. Временная диаграмма для ведущего режима SPI
282 Глава 10. Начинаем изучать последовательный информационный обмен 10.3.4 . Управление передачей данных Рассматриваемый синхронный последовательный порт может быть установлен как ведущим, так и подчиненным. В любом из названных случаев прикладное программное обеспечение может использовать порт или приемником, или передатчиком, или же, одно- временно, приемником и передатчиком. Каким бы ни было приложение, данные всегда син- хронно продвигаются из одного конца сдвигового регистра в другой. То, какие данные должны использоваться, определяется пользователем. Однако использование последовательного порта ставит разработчика перед группой интересных вызовов в терминах синхронизации и управления. Так, если порт установлен в подчиненный режим и внешнее устройство инициализирует перемещение данных, то под- чиненный порт должен быть приведен в готовность к этому перемещению. Он должен пе- реместить данные в и/или из буфера порта согласно направления, в котором данные пере- мещаются. Если же порт установлен как ведущий, то он инициализирует перемещение дан- ных и должен также переместить данные в и/или из буфера. В любом случае, аппаратные средства последовательного порта могут предпринимать перемещение данных, в то время как программа делает что-то совершенно другое. Чтобы помочь управлению процессом, порт имеет ряд битов состояния, в специальных функциональных регистрах, так же как и сигнал прерывания. Если порт установлен как ведущий, то запись в буферный регистр SSPBUF автома- тически начинает перемещение данных, выталкивая наружу любые данные, которые были загружены в SSPBUF, и загружая любые данные, присутствующие на штырьке SDI. По завершении восьми циклов тактовой частоты устанавливается флаг прерывания SSPIF, и данные, имеющиеся в сдвиговом регистре SSPSR, автоматически перемещаются в буфер SSPBUF. Флаг SSPIF может использоваться как прерывание, сообщающее ЦП о том, что передача данных завершена. Если имеется попытка записи в SSPBUF прежде, чем преды- дущее слово было полностью послано, то устанавливается бит коллизии записи WCOL. Если порт установлен как подчиненный, то когда вход SCK начинает переключаться, порт загружает данные в сдвиговый регистр SSPSR через штырек SDI. В то же самое вре- мя данные выталкиваются из другого конца регистра через штырек SDI. Это, конечно, забота разработчика системы — гарантировать, что достоверные данные будут готовы в регистре SSPSR, и/или будут доступными в соответствии с требованиями на входе SDI. Когда завершится восемь циклов, устанавливается флаг прерывания SSPIF и снова дан- ные, имеющиеся в сдвиговом регистре SSPSR, автоматически перемещаются в буфер SSPBUF. Если предыдущий байт не читался из SSPBUF, то устанавливается бит SSPOV, указывая на переполнение приема. 10.4. Простой пример использования SPI Версия АУСМ Derbot, описанная в этой книге, не использует информационный обмен через SP1. Однако пример программы 10.1 дает представление о том, как это может выпол- няться на аппаратных средствах АУСМ Derbot. Как и всегда, полный листинг этой про- граммы имеется на компакт-диске, прилагаемом к этой книге, в то время как в книге при- ведены только фрагменты программы, имеющие прямое отношение к рассматриваемой нами теме. Правда, в данном случае программа такая короткая, что почти вся она воспро- изведена. Является возможным сверить настройки инициализации со схемами регистров управления, показанными на рис. 10.8 и 10.9. Программа активирует SPI микроконтроллера АУСМ Derbot, выполняя запись в SSPCON1 (по причинам необходимости обеспечения обратной совместимости, во вклю- чаемом файле на Ассемблере этот регистр называется SSPCON) и устанавливая его веду- щим, с тактовой частотой Fosc/16. Оба бита управления тактовой частотой — SMP и СКЕ — устанавливаются в ноль. Штырек тактовой частоты и штырьки вывода данных устанав- ливаются как выходы в TRISC. Затем в режиме повторения программа передает по очереди
10.4. Простой пример использования SPI 283 2 байта в последовательную линию передачи данных, отрабатывая временную задержку в 40 мкс между передачами. Пример программы 10.1. Программа демонстрации использования SPI ;sync_ser_demo /Программа демонстрации последовательного выхода MSSP /Программа в режиме повторения передает с задержкой одни /и те же 2 числа через последовательный порт. /Последовательные данные поступают на разряд 5 порта С, /последовательная тактовая частота — на разряд 3 разряд порта С. /2.7.05. TJW Тестировано 02.07.05 (Начальные комментарии и инициализация опущены) bsf status,rpO /выбор банка памяти 1 movlw movwf B'10000000' trisc /установка битов порта С, /SDO и SCK устанавливаются как выходы /(линия SDI,6ht 4 контролируется модулем SPI, /он не устанавливается) bcf movlw movwf movlw movwf /выключение clrf clrf clrf Loop movlw movwf call movlw movwf call goto status,rpO B'00000000' sspstat B'00110001' sspcon всех выходов porta portb portc B'11010101' sspbuf delay40u B'00101010' sspbuf delay40u loop /выбор банка памяти 1 /SMP=0, СКЕ=0, другие биты не используются /активирование последовательного порта, режим /ведущего, тактовая частота равна fosc/16, /бездействие по логической 1 /Подпрограмма: вносит задержку, приблизительно равную 40 мкс delay40u movlw D'10' /запрашивается 10 циклов, каждый занимает 4 мкс movwf delcntrl dell nop /4 командных цикла в этом цикле, т.е. 4 мкс decfsz delcntrl,1 goto dell return end Рис. 10.11 показывает осциллограммы сигналов данных и сигналов тактовой частоты, соответствующих примеру программы 10.1 для СКЕ = 1 и СКЕ = 0. Они, по сути, — прак- тическое подтверждение некоторых из сигналов, приведенных на временной диаграмме, показанной на рис. 10.10. При горизонтальном масштабе, установленном на 10 мкс/деле- ние, можно видеть, что период тактовой частоты точно равен 4 мкс, то есть частота равна 250 кГц. Это соответствует установкам тактовой частоты в SSPCON1, т.е. это Fosc (4 МГц),
284 Глава 10. Начинаем изучагь последовательный информационный обмен разделенная на 16. Два байта данных — 11010101, за которым следует 00101010, четко просматриваются на осциллограммах — они передаются старшими битами вперед. При бите СКР (в SSPCON1), в обоих случаях равном логической 1, неактивным состоянием сигнал тактовой частоты считается тогда, когда сигнал находится в состоянии логической единицы. Когда бит СКЕ (в SSPSTAT) установлен в состояние логической 1, мы видим, что выходные данные изменяются по положительному набегающему фронту сигнала так то- вой частоты, то есть по переключению сигнала тактовой частоты из “активного” (в нашем случае логический 0) в неактивное состояние. Будет истинным и обратное, если СКЕ уста- новить в 0. Обратите внимание, что неактивное состояние линии данных не фиксировано. Синхронизация между байтами также представляет интерес. Обратите внимание, что программа вызывает подпро1рамму временной задержки па 40 мкс между посылками бай- тов, однако видимый на осциллограммах промежуток между посылками байтов является меньшим, чем 20 мкс. Эго происходит потому, что процесс передачи данных инициализи- руется программой тогда, когда опа записывает данные в SSPBUF. Затем программа вы- зывает подпрограмму временной задержки, значительная часть которой выполняется в то время, когда идет передача данных. (Ь) Рис. 10.11. Синхронный последовательный выход: (а) — СКР = 1, СКЕ - 1; (Ь) — СКР - 1, СКЕ = О 10.5. Ограничения, характерные для Microwire, SPI и простой синхронной последовательной передачи данных Из того, что мы пока видели, можно сделать вывод, ч то синхронные последовательные линии связи, подобные Microwire и SPI, обеспечивают простой и надежный обмен данных, однако они имеют определенные ограничения. Перечислим их: • они гге очеггь хорошо подходят для ситуаций, в которых может потребоваться больше, чем одно ведугцес устройство; • они не адресуемы; • в них не используется квитирование сообщений: передатчик просто гге знает — полу- чено ли посланное им сообщение, или нет; • они не очеггь гибки — может оказаться гге так просто добавить еще один узел, даже работающий в подчиненном режиме, поскольку для каждого ггового подчиненного устройства (по крайней мере, в конфигурации гго рис. 10.6) необходима дополнитель- ная лиггия выборки подчиненного устройства.
10.6. Расширение возможностей синхронного последовательного канала связи, шина I2C 285 10.6. Расширение возможностей синхронного последовательного канала связи, шина 12С Протокол интерфейса межехемпой связи (Г?С) был разработан компанией Philips с целью получения стандарта последовательной связи, который был бы свободен от неко- торых недостатков, присущих Microwire или SP1. Как и предполагает его название, этот стандарт призван обеспечить связь между интегральными микросхемами внутри одной сис- темы. Он должен быть гибким и толерантным к различным технологиям и скоростям. По- добно всем хорошим стандартам, его применение вышло далеко за рамки первоначально- го его предназначения. 10.6.1. Основные характеристики 12С и физические соединения Подобно SPI или Microwirc, 12С основан иа отношениях между узлами по схеме “веду- щий-подчиненный”. Ведущий узел полностью контролирует использование шины. Име- ется стандартный режим (с тактовой час тотой до 100 кГц), быс трый режим (с тактовой час- тотой до 400 кГц) и высокоскоростной режим (с максимальной тактовой частотой, рав- ной 3,4 Мбит/с). Шина ГС для организации всех межсоединений использует только две линии, назы- вающиеся SDA (последовательные данные) и SCL (последовательная тактовая частота). Выход каждого узла соединяется с шиной, используя выход открытого стока или откры- того коллектора, как показано на рис. 10.12, в то время как вход узла выполняется через буфер стандартных логических схем. Каждая из двух линий имеет нагрузочный резистор. Обе линии являются двунаправленными, по сигнал тактовой частоты, идущий по линии SCL, всегда генерируется текущим ведущим устройством. Когда нет узлов осуществляющих доступ к шине, все выходы открытых стоков неак- тивны и линии находятся в неактивном состоянии, соответствующем логической 1. Число узлов, соединенных с шиной, ограничено только числом адресов, которые являются дос- тупными (см. ниже), а также предельной суммарной емкостью нагрузки, которую увеличи- вает каждый узел. В конечном счете, слишком большая емкость будет означать, что время нарастания сигналов тактовой частоты или данных превысит специфицированное макси- мальное значение. Рис. 10.12. Основные взаимосвязи интерфейса 12С
286 Глава 10. Начинаем изучать последовательный информационный обмен 10.6.2. Нагрузочный резистор Независимо от того, имеет ли линия активную нагрузку, именно нагрузочный резистор, совместно с паразитной емкостью линии, определяет время нарастания сигнала. Специфи- кация рассматриваемого стандарта ограничивает максимальную емкость линии величиной 400 пФ, а максимальное время нарастания сигнала (из логического 0 в логическую 1) в стандартном режиме — не более 1000 нс. Значение резистора выбирается таким, чтобы достигнуть соответствия требованиям по времени нарастания сигнала, которое, в свою оче- редь, зависит от емкости линии. Низкое значение нагрузочного резистора снижает время нарастания, однако увеличивает потребление тока. Широко используемое значение сопро- тивления резистора — 4,7 кОм; однако это значение должно быть понижено при высокой емкости линии, или же увеличено, если емкость линии низкая. 10.6.3. Характеристики сигналов 12С Протокол 12С придерживается очень четкого формата передачи данных, который ил- люстрируется рис. 10.13. Передача данных инициируется стартовыми условиями, при ко- торых линия SDA переходит в состояние логического 0, в то время как линия SCL оста- ется в состоянии логической 1. Передача данных прекращается по условиям останова, при которых линия SDA переходит в состояние логической 1, а линия тактовой частоты оста- ется в состоянии логической 1. Стартовые условия и условия останова передачи устанав- ливаются текущим ведущим устройством, которое одновременно является и источником тактовой частоты. SDA Запуск Адрес Чтение/запись Подтверждение Данные Подтверждение Данные Подтверждение Останов Рис. 10.13. Характеристики сигналов 12С Между стартовым состоянием и состоянием останова данные передаются побайтно. На протяжении этого времени значение SDA может изменяться только тогда, когда SCL на- ходится в состоянии логического 0; данные должны стабильно удерживаться, когда состо- яние линии тактовой частоты соответствует логической единице. Это обеспечивает как пе- редачу данных, так и возможность определения стартового состояния и состояния останова. Первый байт любой посылки данных содержит адресную информацию. Стандарт допус- кает использование либо 7-разрядного адреса, занимающего 1 байт, либо 10-разрядного ад- реса, занимающего два байта. Рис. 10.13 демонстрирует 7-разрядную версию. В любом режиме восьмой разряд первого байта — это бит считывания/записи. Он определяет на- правление потока данных для сообщения, которое следует далее. В конце каждого байта передатчик освобождает линию SDA, а приемник должен послать бит подтверждения, пе- реводя линию SDA в состояние логического 0. Любое количество байт может быть посла- но в рамках одного сообщения (т.е. между одним стартовым и одним стоповым битами). Имеются два небольших исключения из только что описанной схемы. Допускается использование адреса “общего вызова”, в котором все биты адреса являются нулевыми. Он используется для одновременной адресации на шине всех узлов. Если ведущее уст- ройство желает начать передачу нового сообщения, когда еще не завершена передача пре- дыдущего, то оно может сформировать условия “Повторного запуска”. Важно также, что протокол 12С допускает наличие более одного ведущего устройства, при этом узел может переключаться из режима подчиненного устройства в режим ведущего устройства. Если
10.7. MSSP, сконфигурированный для I2C 287 шина находится в состоянии незанятости, то любое потенциально ведущее устройство мо- жет взять на себя управление шиной. Если два ведущих устройства попытаются одновре- менно взять на себя управление шиной, то запустится процесс арбитража. 10.7. MSSP, сконфигурированный для 12С Модуль MSSP в 16F873A может быть сконфигурирован для работы по протоколу 12С. В этом случае линия SCL будет разделяться с разрядом 3 порта С, а линия SDA — с раз- рядом 4 порта С. Для режима интерфейса 12С порт становится значительно более сложным, чем для режима SPI, поэтому необходимо приложить некоторые усилия, чтобы понять его работу. Первым признаком повышения сложности является введение дополнительного регистра управления — SSPCON2, который необходим для реализации режима 12С. Мы будем изучать эту сложную, однако интересную реализацию последовательного информационного обмена постепенно. Теоретические сведения будут иллюстрироваться программами для АУСМ Derbot AGV. 10.7.1. Регистры MSSP для режима 12С и их первичное использование Как и в случае MSSP в режиме SPI, двумя регистрами, центральными для аппаратных средств модуля, являются сдвиговый регистр SSPSR и буферный регистр SSPBUF. К ним добавляется регистр адреса SSPADD. Он используется для запоминания адреса подчинен- ного устройства, если такое устройство находится в подчиненном режиме. Когда устрой- ство находится в режиме ведущего устройства, этот регистр формирует часть генератора скорости информационного обмена. Ниже мы рассмотрим блок-схемы аппаратных средств модуля — по одной для ведущего и подчиненного устройства. Находясь в режиме I2C, MSSP использует два регистра управления, о которых мы уже говорили, — SSPCON1 и SSPSTAT. Большинство битов в этих регистрах, однако, используются для других функций, по- этому подходить к их изучению нужно очень внимательно, а трактовать их надо почти как отдельные СФР. Эти регистры схематически изображены на рис. 10.14 и 10.15. Для того чтобы справиться с возросшей сложностью модуля для I С, введен дополнительный регистр управления SSPCON2, показанный на рис. 10.16. Таким образом, в итоге имеется шесть регистров, которые программист может непосредственно использовать при работе MSSP в режиме 12С — это в дополнение к регистрам, имеющим отношение к порту С и прерываниям. Как и в режиме SPI, MSSP устанавливается на режим 12С посредством установки бита SSPEN в регистре SSPCON1. Режим функционирования, а именно — ведущее или под- чиненное устройство, а также длина используемого адреса, определяются посредством установки младших четырех битов регистра SSPCON1. Из рис. 10.14 можно увидеть, что имеются шесть возможных режимов работы с интерфейсом 12С. В то время как биты регистра SSPSTAT в основном дают информацию о текущем со- стоянии порта, биты нового регистра SSPCON2 (рис. 10.16) инициализируют тот или иной вид активности 12С. Так, например, установка бита SEN инициализирует условия старта, бита PEN — условия останова, а бита RSEN — повторного старта. Скоро мы подробнее рассмотрим примеры их использования. Чтобы лучше понять, как эти биты используются, а также разобраться с их синхрони- зацией, необходимо более-менее существенно изучить временные диаграммы, которые приводятся в спецификациях. Их достаточно много — по одной на каждый из возможных режимов работы. Две из них мы будем рассматривать далее в этой главе. Искусство соз- дания программ, управляющих MSSP в режиме 1"С, в значительной степени заключается в том, чтобы полностью поддерживать эти временные диаграммы. Хотя это не означает,
288 Глава 10. Начинаем изучать последовательный информационный обмен что каждый бит, показанный на диаграмме, должен использоваться — иногда может ока- заться, что их не будет вообще. Однако следует придерживаться изображенных на диаграм- ме последовательностей событий. Эти диаграммы не так уж и просты, поэтому во многих случаях предпочтительно использовать (или адаптировать) уже созданные программы, чем начинать написание программ с нуля. R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 WCOL SSPOV SSPEN СКР SSPM3 SSPM2 SSPM1 SSPM0 разряд 7 разряд 0 разряд 7 WCOL: бит обнаружения коллизии записи В режиме передачи ог ведущего устройства: 1 = была предпринята попытка записи в регистр SSPBUF, в то время как условия 12С не были действительными для передачи, которая должна была начаться (должен быть очищен протраммно) 0 = коллизии нет В режиме передачи от подчиненного устройства. 1 = была предпринята попытка записи в ретистр SSPBUF, в то время как он все еще передает предыдущее слово (должен быть очищен программно) 0 = коллизии нет В режиме приема (как в режиме ведущею, гак и подчиненною устройства): Эго “безразличный” бит разряд 6 SSPOV: бит индикации переполнения при приеме В режиме приема: 1 = принят байт, в то время как ретистр SSPBUF все еще содержит предыдущий байт (должен быть очищен программно) 0 = переполнения нет В режиме передачи: В режиме передачи — это “безразличный” бит разряд 5 SSPEN. бит активирования синхронною последовательного порта 1 = активирует последовательный порт и конфигурирует штырьки SDA и SCL как штырьки последовательного порта 0 = блокирует последовательный порт и конфигурирует названные шгырьки как штырьки порта ввода-вывода Примечание. После активирования штырьки SDA и SCL должны быть правильно сконфитурированы как входы или выходы разряд 4 СКР: бит управления освобождением SCK В режиме подчиненного устройства: 1 = освобождение синхрочастоты О = удержание линии синхрочасготы в состоянии лотического 0 (растяжение тактовой частоты) (используется для того, чтобы гарантировать время установки данных) В режиме ведущего устройства: В этом режиме бит не используется. разряды 3-0 SSPM3:SSPMO: биты выбора режима синхронного последовательного порта 1111= режим подчиненного устройства 12С, 10-разрядный адрес с разрешенными прерываниями по стартовому и стоповому биту 1110 = режим подчиненного устройства 12С, 7-разрядный адрес с разрешенными прерываниями но стартовому и стоповому биту 1011 = режим ведущего устройства 12С, управляемый программно-аппаратными средствами (подчиненное устройство в неактивном состоянии) 1000 = режим ведущего устройства 12С, такговая частота = Fosc/(4 ‘(SSPADDH)) 0111 = режим подчиненного устройства 12С, 10-разрядный адрес 0110 = режим подчиненного устройства 12С, 7-разрядный адрес Примечание. Комбинации битов, не перечисленные здесь, являются либо зарезервированными или использую гея только в режиме SPI Рис. 10.14. Регистр SSPCON1 (адрес 14н) в режиме 12С
10.7. MSSP, сконфигурированный для I2C 289 R/W-0 R/W-0 R-0 R-0 R-0 R-0 R-0 R-0 SMP СКЕ D/A Р S R/VV UA BF разряд 7 разряд 0 разряд 7 SMP: бит управления скоростью нарастания сигнала В режиме ведущего или подчиненного устройства: 1 = управление скоростью нарастания сигнала заблокировано для режима стандартной скорости (100 кГц и 1 МГц) 0 = управление скоростью нарастания сигнала разрешено для высокоскоростного режима (400 кГц) разряд 6 СКЕ: бит выбора SMBus В режиме ведущего или подчиненного устройства: 1 = разрешить конкретные входы SMBus 0 = запретить конкретные входы SMBus разряд 5 D/А: бит данных/адреса В режиме ведущего устройства: Зарезервирован В режиме подчиненного устройства: 1 = указывает, что последний полученный или переданный байт был данными 0 = указывает, что последний полученный или переданный байт был адресом разряд 4 Р: столовый бит 1 = указывает, что последним был распознан столовый бит 0 = указывает, что последним не был распознан столовый бит Примечание. Этот бит очищается при сбросе и очистке SSPEN. разряд 3 S:стартовый бит 1 - указывает, что последним был распознан стартовый бит 0 = указывает, что последним не был распознан стартовый бит Примечание. Этот бит очищается при сбросе и очистке SSPEN. разряд 2 R/W: информационный бит чтения/не-записи (только для режима 12С) В режиме подчиненного устройства: 1 = чтение 0 = запись Примечание. Этот бит содержит информацию по R/W после последнего соответствия адреса. Данный бит действителен только от момента соответствия адреса до следующего стартового бита, соответствия адреса или бита не-АСК. В режиме ведущего устройства: 1 = идет передача 0 = передачи нет Примечание. Логическое сложение этого бита с SEN, RSEN, PEN, RCEN или ACKEN укажет, является ли MSSP в режиме бездействия. разряд 1 UА: адрес обновления (только для 10-разрядного подчиненного режима) 1 = указывает на то, что пользователю необходимо обновить адрес в регистре SSPADD 0 = нет необходимости в обновлении адреса разряд 0 BF: бит состояния заполнения буфера В режиме передачи: 1 = прием завершен, SSPBUF полон 0 = прием не завершен, SSPBUF не заполнен В режиме приема: 1 = идет передача данных (не включая бит квитирования и столовый бит), SSPBUF полон 0 = передача данных завершена (не включая бит квитирования и столовый бит), SSPBUF не заполнен Рис. 10.15. Регистр SSPSTAT (адрес 94н) в режиме 12С
290 Глава 10. Начинаем изучаю последова!ельный информационный обмен R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 GCEN ACKSTAT ACKDT ACKEN RCEN PEN RSEN SEN разряд 7 разряд 0 разряд 7 GCEN: бит разрешения общего вызова (юлько в режиме подчиненного усгройсгва) 1 = разреши п3 прерывание, когда адрес общего вызова (OOOOh) получен в SSPSR 0 - адрес общею вызова заблокирован разряд 6 ACKSTAT: биi подпзерждения состояния (юлько в режиме передачи ведущею усгройства) 1 - подтверждение не было получено от подчиненною устройства 0 = подтверждение было получено or подчиненного усгройсгва разряд 5 ACKDT: бит подтверждения данных (юлько для режима приема ведущею устройства) 1 = отсутствие подтверждения 0 =подтверждение Примечание. Значение, которое будет передано, когда пользователь инициализирует последовательноеть подтверждения в конце приема сообщения разряд 4 ACKEN: бит разрешения последовательности подтверждения (юлько для режима приема ведущего усгройства) 1 = инициализировать последовагелытость подтверждения на титырьках SDA и SCL и передать бит данных ACKDT. Автоматически очищается аппаратными средствами 0 - последовательность подтверждения не инициализирована разряд 3 RCEN: бит разрешения приема (только режим ведущею) 1 = разрешить режим приема для 12С 0 - прием не разрешен разряд 2 PEN: бит разрешения условий останова (только режим ведущего) 1 = инициализировать условия останова на штырьках SDA и SCL. Автоматически очищается аппаратными средствами 0 = отсутствие условий останова разряд 1 RSEN: бит разрешения условий повторного старта (только режим ведущего) 1 = инициализировать усттовия повторною старта на штырьках SDA и SCL. Автоматически очищается аппаратными средствами 0 = отсутствие условий повторного старта разряд 0 SEN: бит разрешения условий старта/разрешения растяжения тактовой частоты В режиме ведущего: 1 = инициализировать условия старта на штырьках SDA и SCL. Автоматически очищается аппаратными средствами 0 = отсутствие условий повторного старта В режиме подчиненного: 1 = разрешено растяжение тактовой частоты как для передачи с подчиненного устройства, так и для приема подчиненным устройством (разрешение растяжения) 0 = разрешено растяжение тактовой частоты только для передачи подчиненным устройством (совместимость с PIC16F87X) Рис. 10.16. Регистр SSPCON2 (адрес 91н) в режиме 12С 10.7.2 . MSSP в режиме подчиненного устройства 12С Будучи сконфигурированным в режиме подчиненного устройства I2C, MSSP работает так, как это показано на рис. 10.17. Блок схема, приведенная на этом рисунке не столь уж сложна и, конечно же, имеет много схожего с блок-схемой для режима SPI, приведенной на рис. 10.7. На ней отображены основные функции сдвигового регистра SSPSR и буферного регистра SSPBUF. Тактовая частота сдвигового регистра берется от внешнего штырька SCL, а данные загружаются или выгружаются из сдвигового регистра через штырек SDA. Роль подчиненного устройства чрезвычайно проста — ожидать, пока оно будет адре- совано, а затем делать то, что ему скажут. Таким образом, специальные логические схемы определяют момент, когда возникают условия старта, а компаратор совпадения адресов проверяет, является ли адрес, который передается, внутренним адресом узла, который со- держится в регистре управления SSPADD. Если имеется соответствие адресов, то уста- навливается флаг SSPIF прерывания MSSP в регистре PIR1. Программист использует его для инициализации реакции подчиненного устройства. Она, реакция, зависит, прежде всего,
10.7. MSSP, сконфи!урированный для I2C 291 от значения бита R/W в слове адреса, которое передается в бит R/W регистра SSPSTAT и может контролироваться программно. Если распознана команда записи, то подчиненное устройство должно действовать как приемник. Соответствующая временная диаграмма для 7-разрядного адреса показана на рис. 10.18 (а). Флаг заполнения буфера BF установлен, поскольку был принят байт адреса, он должен быть сброшен холостым считыванием SSPBUF. Если флаг SSPIF используется, то он должен быть сброшен. Затем подчиненное устройство последовательно загружает байт данных под управлением тактовых синхроимпульсов, поступающих от ведущего уст- ройства. Если все работает правильно, то сигнал подтверждения автоматически генериру- ется подчиненным устройством. Рис. 10.18 (а) иллюстрирует случай, когда первый байт данных не был считан из SSPBUF. Флаг BF (в SSPSTAT) остается установленным, что приводит к тому, что устанавливается флаг переполнения SSPOV. После этого подтвер- ждение подчиненным устройством не посылается, и ведущее устройство прекращает пе- редачу, создавая условия останова. Если в первом байте сообщения передана команда чтения, то подчиненное устройство должно работать как передатчик. Соответствующая последовательность показана на рис. 10.18 (Ь). Когда подчиненное устройство распознало, что оно адресовано и от него требу- ется чтение данных, то оно должно записать байт данных в регистр SSPBUF, в результате чего автоматически установится флаг BF. Рис. 10.17. Блок схема для режима подчиненного устройства 12С Конечно же, реакция устройства может потребовать немного времени, поэтому оно удерживает линию тактовой частоты в нулевом состоянии до тех пор, пока передача не будет завершена. Это блокирует любые операции на линии последовательной связи. По- следовательная линия освобождается программно посредством установки бита СКР в со- стояние логической единицы. Аппаратные средства автоматически возвращают его в 0
292 Глава 10. Начинаем изучать последовательный информационный обмен (если BF в нуле) по завершении передачи 9-ти битов. Это пример “растягивания” такто- вой частоты — одного из нескольких способов, которыми подчиненное устройство может влиять на работу последовательной линии связи. Он автоматически реализуется в режиме передачи, в режиме приема он реализуется как дополнительная функция, посредством ус- тановки бита SEN в регистре SSPCON2. При освобожденном SCK, ведущее устройство последовательно выгружает данные, а подчиненное устройство должно в ответ сгенерировать подтверждение. Дальнейшая ин- формация о состоянии может быть получена по состояниям флагов в регистре состояния SSPSTAT. Сообщение 12С завершается, когда обнаружен стоп-бит, переданный ведущим устройством. Описанную последовательность событий можно проследить на приводи- мом далее рисунке. СКР не сбрасывается в 0, когда SEN = О (Ь) Прием адреса HW-I iWW; SSPIF (PIR1<3>) ; Выборка ' входных данных I а нуле,«в BF (SSPSTAT<0>} СКР Передача данных ААААА — Очищается программно программно Передача данных — ИЗ SSMPJ$R Из SSHFISH Очищается программно] SSPBUF записывается ; программно | _ СКР устанавливается программно СКР устанавливается программно Рис. 10.18. Временная диаграмма режима подчиненного устройства 12С, 7-разрядный адрес, SEN = 0: (а) — прием; (Ь) — передача 10.7.3 . MSSP в режиме ведущего устройства 12С Как можно видеть на рис. 10.19, MSSP в режиме ведущего устройства в целом более сложен. Ведь ведущее устройство должно, в конце концов, управлять всей работой шины. В основе конфигурации, однако, мы все еще видим сдвиговый регистр SSPSR и буферный
10.7. MSSP, сконфигурированный для I2C 293 регистр SSPBUF. Электрический интерфейс с двумя последовательными линиями демон- стрирует классическое соединение 12С, о котором мы уже говорили, с открытым стоком на выходе и триггером Шмитта на входе. Тактовая частота генерируется теперь внутренним генератором скорости передачи информации. Эта частота поступает как на сдвиговый ре- гистр, так и на внешнюю шину через штырек SCL. Узел должен быть способен генериро- вать и обнаруживать условия старта, останова и подтверждения. Он также, посредством логического элемента “Исключающее ИЛИ”, подключенного к выходу SDA, обнаруживает коллизию шины. Такая коллизия происходит, когда ведущее устройство передает данные, однако логическое состояние шины не соответствует передаваемым значениям. В случае коллизии устанавливается флаг прерывания по коллизии шины BCLIF (рис. 7.10). Веду- щий порт может также быть объектом арбитража, если он распознает, что находится в со- стоянии конкуренции с другим ведущим устройством. Рис. 10.19. Блок-схема MSSP, режим ведущего устройства 12С Генератор-контроллер скорости информационного обмена, который виден в верхнем правом углу рис. 10.19, показан детально на рис. 10.20. Он состоит из отрицательного счет- чика, который перезагружается значением, содержащимся в регистре SSPADD, когда дос- читывает до нуля. Следует четко понимать, что регистр SSPADD не имеет никакого отно- шения к адресам, когда модуль работает в режиме ведущего устройства — ведущие уст- ройства не имеют адреса. Пользователь выбирает требуемую скорость информационного обмена значением, помещаемым в SSPADD. Формула, которая определяет это значение, имеет следующий вид: [SSPADD] = (Fosc/4xFSCL) - 1 (Ю.1) где [SSPADD] — это значение, загруженное в регистр SSPADD, Fosc — это тактовая час- тота микроконтроллера, a Fscl —это требуемая тактовая частота I2С. Рис. 10.21 показывает временную диаграмму для порта, сконфигурированного как веду- щее устройство 12С при передаче байта данных. Бит SEN, как видно из рисунка, использу- ется для инициализации стартовых условий, а бит PEN — для инициализации условий ос- танова. Оба названных бита находятся в регистре SSPCON2. Бит R/W регистра SSPSTAT
294 Глава 10. Начинаем изучала последовательный информационный обмен используется для индикации того, что продолжается передача данных. Эта последователь- ность событий будет проиллюстрирована вскоре на примере программы для АУСМ Derbot. Рис. 10.20. Генератор-контроллер скорости информационного обмена 12С SDA ACKSTAT в SSPCON2 « 1 Передача данных или второй половины 10-раз рядного адреса От подчиненного устройства, очистка бита ACKSTAT SSPCON2<6> - Запись; SSPCON2<0> SEN = 1 Начало условий старта rSEN = o ,' ’ Передача адреса на подчиненное устройство FVW = о । ( SCL удерживается ' в 0, пока ЦП \ 1 реагирует на SSPIF SCL Рис. 10.21. Временная диаграмма для режима ведущего устройства 12С — идет передача, 7- или 10-разрядный адрес 10.8. Применение 12С в АУСМ Derbot 10.8.1. Ручной ПУ Derbot как узел последовательной линии связи АУСМ Derbot разработан так, чтобы взаимодействовать с пультом управления через интерфейс ГС. При этом АУСМ устанавливается как ведущее устройство, а пульт управ- ления — как подчиненное. Однако многие команды передачи данных инициализируются пультом управления, когда пользователь нажимает клавишу на вспомогательной клавиа- туре. Но ведь подчиненное устройство 12С не может инициализировать передачу! Следо- вательно, линия прерывания должна идти от контроллера ПУ до АУСМ, которая форми- рует внешний вход прерывания микроконтроллера АУСМ. В общем виде взаимодействие программируется так, чтобы в случае обнаружения нажатия клавиши на вспомогательной клавиатуре контроллер посылал бы прерывание в АУСМ, который затем запрашивает данные через канал связи 12С.
10.8. Применение I2C в АУСМ Derbot 295 Два приводимые далее примера программ — 10.2 и 10.3 — написаны, соответственно, для АУСМ Derbot, действующего как ведущее устройство, и пульта управления, действу- ющего как подчиненное устройство. При совместной их работе, нажатие клавиши на вспо- могательной клавиатуре ПУ инициализирует передачу прерывания в АУСМ. В результате инициализируется сообщение Г'С, в котором АУСМ, как ведущее устройство, запрашивает байт данных (или символ) из пульта управления. Затем, после получения символа, АУСМ отсылает его обратно в пульт управления, который посылает его на индикатор. Полная версия программы может быть найдена на компакт-диске, прилагаемом к этой книге. При- веденные программы и подпрограммы обслуживания прерываний могут использоваться как основа при организации любой связи между пультом управления, АУСМ и любыми другими периферийными устройствами 12С, которые пользователь может захотеть разра- ботать. Однако стоит заметить, что это сравнительно простые программы — они не кон- тролируют и не обрабатывают всевозможные сбойные ситуации. 10.8.2. АУСМ в качестве ведущего устройства 12С Пример программы 10.2 выполняется на АУСМ Derbot и использует порт 12С как ве- дущее устройство. Основными установками СФР являются: порт С (где биты порта 12С дол- жны быть установлены как входы), регистр SSPADD (который определяет значение такто- вой частоты) и регистр SSPCON1 (который определяет общие настройки). Для того что- бы определить значение для SSPADD используется уравнение (10.1). Детали установки SSPCON1 должны быть тщательно исследованы посредством сравнения их с описанием назначения битов регистра, приведенным на рис. 10.14. Пример программы 10.2. Информационный обмен через 12С между АУСМ Derbot (ведущее устройство) и ручным ПУ (фрагменты) ;Dbt_kybd_echo_mstr /Эта программа использует шину I2C несколькими способами: ; * посылает начальное многобайтовое сообщение на ручной ПУ ; * по прерыванию принимает одно число от ручного ПУ, ; * сохраняет его, а затем отсылает его обратно на ПУ /В любой пульт управления могут быть введены подпрограммы, /обеспечивающие пользователю возможность управлять АУСМ. /TJW 20.7.05 Тестировано и практически испытано 21.07.05 (вступительные секции программы опущены) ;выделение памяти I2C_ _RX_word equ 23 /сохраняет самое последнее слово, принятое по I2C I2C* _add equ 24 /сохраняет адрес, использованный в 12С-сообщении I2C~ _TX_word equ 25 /сохраняет слово, подлежащее передаче по I2C org 00 goto start org 04 goto Interrupt_SR /Инициализация СФР в банке памяти 1 start bcf status,rpl bsf status,rpO /выбор банка памяти 1 movlw В'10011000' /установка битов порта С, оба I2C бита / устанавливаются на вход movwf trisc
296 Глава 10. Начинаем изучать последовательный информационный обмен Пример программы 10.2. Продолжение_________________________________________ movlw 07 /устанавливаем скорость информационного /обмена на 125 кГц movwf sspadd /Инициализация СФР в банке памяти 0 bcf status,грО movlw В'00101000' ;SSPCON1:MSSP вкл, ведущее I2C movwf sspcon /посылка начальной строки clrf pointer movlw 0а4 /посылка адреса подчиненного устройства, R/W на запись movwf !2C_add call !2C_send_add loop_strl movf pointer,0 call tablel movwf I2C_TX_word sublw Off /проверка и дальнейшее выполнение, /если обнаружен признак конца btfsc status,z goto string_end call !2C_send_word incf pointer,1 call delayl /дается время на запись ЖК-индикатору call delayl call delayl goto loop_strl string_end call I2C_send_stop /разрешение прерываний bcf intcon,intf /сброс ожидающих прерываний bsf intcon,inte /разрешение внешнего прерывания bsf intcon, gie /Ожидание прерывания от ручного ПУ loop goto loop Подпрограмма обслуживания прерываний (ПОП). По внешнему прерыванию ПОП считывает байт из ручного ПУ, и возвращает его обратно, т.е. проходит два 120-сообщения. Принятый байт сохраняется в I2C_RX_word для дальнейшей обработки Interrupt_SR bsf portc,6 /диагностика /Старт нового 12С-сообщения, запрос слова из подчиненного устройства, movlw 0а5 /это адрес подчиненного устройства, /R/W на чтение movwf I2C_add call I2C send add /теперь ожидаем входящего байта call I2C_rec_word call I2C_send_stop bcf status,rpO call delay20u /Теперь возвращаем принятый байт обратно — старт нового сообщения movlw 0а4 ; это адрес подчиненного устройства, R/W на чтение movwf I2C_add call I2C send add
10.8. Применение I2C в АУСМ Derbot 297 Пример программы 10.2. Продолжение ;отправка ранее принятого символа movf I2C_RX_word,0 /перемещаем принятое слово в буфер передачи movwf !2C_TX_word call I2C_send_word call !2C_send_stop bcf status,rpO bcf portc,6 /сброс диагностических диодов bcf intcon,intf retfie ПОДПРОГРАММЫ ;инициирует I2С-сообщение, ^средством передачи слова из !2C_add, которое /должно включать бит чтения/записи. Ожидает все подтверждения и состояние /завершения. Освобождает память банка 0. I2C send add bsf status,rpO bsf sspcon2,sen /установка стартового бита btfsc sspcon2,sen /проверка на завершение goto $-1 bcf status,rpO movf I2C add,0 /загрузка битов адреса и направления movwf sspbuf /передача bcf pirl,sspif /эти биты скоро будут тестироваться bsf status,rpO btfsc sspstat,bf /проверка на завершение записи goto $-1 btfsc sspcon2,ackstat /ожидание нулевого бита подтверждения goto $-1 bcf status,rpO btf ss pirl,sspif /проверка флага прерывания по завершению goto $-1 bcf pirl,sspif return /Принимает ( одно) слово с шины I2C и сохраняет его в I2C_RX_word. /Возвращает Ack = 1, сигнализируя об этом в последнем байте. /Освобождает память в банке памяти 0 I2C rec word bsf status,rpO bsf sspcon2, rcen установка бита разрешения приема bt f ss sspstat,bf ожидание заполнения буфера goto $-1 bcf status,rpO чтение данных movf sspbuf,0 movwf I2C RX word сохранение для дальнейшего использования bcf pirl,sspif предварительный сброс флага прерывания, /поскольку мы собираемся его использовать bsf status,rpO bsf sspcon2,ackdt установка требуемого состояния подтверждения,' 1 в качестве последнего байта bsf sspcon2,acken и активируем его bcf status,rpO btf ss pirl,sspif используем флаг прерывания для проверки / на конец подтверждения goto $-1
298 Глава 10. Начинаем изучать последовательный информационный обмен Пример программы 10.2. Окончание bcf status,rpO return /Посылает слово через шину I2C и ожидает подтверждения. /Освобождает память в банке памяти 0 . I2C_send_word bcf status,rpO movf I2C_TX_word,0 получаем слово movwf sspbuf / начинаем передачу bsf status,rpO btfsc sspstat,r_w / проверяем на завершение записи goto $-1 btfsc sspcon2,ackstat проверяем на нулевой бит подтверждения goto $-1 bcf status,rpO return /Посылает столовый бит I2C и ожидает завершения передачи. /Освобождает память в банке памяти 0 . I2C_send_stop bsf status,rpO bsf sspcon2,pen / установка стоп-бита btfss sspstat,p / проверка завершения передачи стоп-бита goto $-1 bcf status,rpO return В программе все основные операции с 12С выполняются с использованием подпрограмм. Поэтому будет достаточно поучительно рассмотреть их. Программа начинается с коммен- тария посылка строки открытия” передачей символьного сообщения “Derbot” на пульт управления. Это выполняется как посылка одного многобайтового сообщения. Сна- чала посылается адрес с использованием подпрограммы I2C_send_add. Адрес 52ц выб- ран произвольно; он должен быть сдвинут влево на 1 разряд, чтобы вписаться в слово ад- реса. При бите R/W, установленном в 0, передаваемое слово становится равным А4Н. В процессе передачи 12С-сообщения, символы считываются по очереди из таблицы 1 (таблица в примере не показана, но имеется на компакт-диске, прилагаемом к этой книге) и посылаются последовательно при использовании подпрограммы I2C_send_word. Эта передача происходит в соответствии с временной диаграммой, показанной на рис. 10.21. Между каждым символом вызывается подпрограмма временной задержки с тем, чтобы предоставить ПУ время, необходимое для выдачи символа на ЖК-индикатор. Конец сим- вольной строки отмечен кодом FFh- Когда он обнаруживается, условия останова отраба- тываются подпрограммой I2C_send_stop. Все последующие действия программы связаны с отработкой подпрограммы обслу- живания прерываний, которая инициализируется получением внешнего прерывания из пульта управления. Подпрограмма обслуживания прерывания посылает 12С-сообщение, адресованное пульту управления, запрашивая чтение. Это выполняется подпрограммами I2C_send_add и I2C_rec_word. При бите R/W теперь установленном в 1, слово ад- реса будет равно А5ц. Читателям рекомендуется проследить последовательность вызова подпрограмм, а также использование ими регистров управления. Сообщение заканчива- ется созданием условий останова, формируемых подпрограммой I2C_send_s top. Об- ратное сообщение, в котором принятое слово возвращается назад в пульт управления, формируется последовательностью подпрограмм I2C_send_add, за которой следует I2C_send_word, а затем I2C_send_stop.
10.8. Применение I2C в АУСМ Derbot 299 10.8.3. Ручной ПУ как подчиненное устройство 12С Программа, приведенная в примере 10.3, выполняется в пульте управления Derbot. Она является расширением программы keypad—test, которая рассматривалась в примере про- граммы 8.1. В этой программе теперь введен информационный обмен через ГС с АУСМ. Сначала обратите внимание на способ, которым используются регистры управления, в сравнении с режимом ведущего устройства. SSPCON1 устанавливает узел как подчинен- ный, a SSPADD теперь используется для того, чтобы содержать адрес подчиненного уст- ройства. SSPADD содержит адрес подчиненного устройства, равный 52н, сдвинутый вле- во на 1 разряд в режиме циклического сдвига. Биты I2С порта С, опять-таки, должны быть установлены как входы. Разрешаются два прерывания: прерывание от порта В, по измене- нию состояния, — для обнаружения факта нажатия клавиши на малой клавиатуре, и пре- рывание MSSP, предупреждающее микроконтроллер о поступлении первого байта сооб- щения 12С. Биты управления прерываниями — GIE, PEIE, SSPIE и RBIE устанавлива- ются соответствующим образом. Прерывание MSSP происходит тогда, когда обнаружено соответствие хранимого адреса и адреса, содержащегося в байте адреса. Подпрограмма прерывания сначала определяет ис- точник прерывания. Если это прерывание 12С, то сначала проверяется бит D/А в SSPSTAT для определения того, является ли только что полученный байт адресом или данными. Если это адрес, то регистр SSPBUF (который будет содержать байт адреса) считывается — про- сто для того, чтобы очистить флаг BF в SSPSTAT. Затем выполняется проверка бита R/W в SSPSTAT. Если ведущее устройство запрашивает запись, то подпрограмма обслужива- ния прерывания возвращает управление вызывающей программе. Затем программа будет ждать следующее прерывание, которое укажет на ожидаемый входящий байт данных. Если ведущее устройство запрашивает чтение, то управление будет оставаться в подпрограмме обслуживания прерывания и перейдет на метку Send—12С. Отрабатывается временная ди- аграмма по рис. 10.18 (Ь). Байт, содержащийся в kpad_char, перемещается в SSPBUF, бит СКР, находящийся в SSPCON1, устанавливается в 1 для освобождения линии такто- вой частоты, далее выполняется контроль флага прерывания для определения факта завер- шения операции. _ Если при контроле бита D/А был обнаружен входящий байт данных, то управление вы- полнением программы передается на метку ISR1. К этому времени данные будут уже в SSPBUF. Они соответствующим образом считываются, и символ посылается на индикатор, используя подпрограмму lcd_write. Также вызывается подпрограмма dig_pntr_set — ее можно видеть только в полном листинге, приведенном на компакт-диске, прила- гаемом к этой книге. Эта подпрограмма управляет ЖК-указателем, гарантируя, что симво- лы не посланы в позиции, которые не соответствуют размерам используемого индикатора. Пример программы 10.3. Информационный обмен между АУСМ Derbot и ручным ПУ (подчиненное устройство) через интерфейс 12С (фрагменты) /dbt_kypd_echo_slave для ручного ПУ АУСМ Derbot /Считывает значение с клавиатуры, когда нажата клавиша, и посылает /прерывание в АУСМ. /Передает символ клавиатуры через I2C по запросу, затем принимает /эхо-символ. /Отображает все, что приходит от АУСМ. /TJW 13.07.05 тестировано 15.07.05 (вступительные секции программы опущены) /Инициализация СФР в банке памяти 1 main bcf status,rpl bsf status,грО /выбор банка памяти 1
300 Глава 10. Начинаем изучать последовательный информационный обмен Пример программы 10.3. Продолжение movlw movwf movlw movwf bsf B'00011000' trisc B'10100100' sspadd piel,sspie биты I2C порта С на вход адрес равен 52Н (он сдвигается на 1 в sspadd) разрешение прерывания I2C ; Инициализация СФР в банке памяти 0 bcf status,rpO выбор банка памяти 0 movlw B'00110110' SSPCON1:MSSP вкл., подчиненное устройство I2C, 7-разрядный адрес, прерывания выключены, растяжения тактовой частоты по приему нет movwf sspcon ;разрешение глобальных прерываний clrf portb инициализация значения клавиатуры bsf intcon,gie bsf intcon,peie loop goto f loop ожидание прерываний от клавиатуры и I2C . A * А А А А А А А А А А А А А А А А А А А А Л * * A ;Это подпрограмма обработки прерывания (ПОП), вызываемая нажатием клавиши ;клавиатуры или совпадением адресов I2C. ;Не обеспечивает сохранение контекста, поскольку все действия происходят /в подпрограммах обслуживания прерываний. Interrupt_SR btfsc intcon, rbif /это прерывание от клавиатуры? goto kpad_ISR ;Сюда, если это прерывание I2C, или соответствие адресов ; (подтверждение посылается автоматически) ;ИЛИ следующий принятый байт был обнаружен. ;проверка — является ли этот байт адресом или данными bsf status,rpO btfsc sspstat,d а goto ISR1 переход, если слово — данные bcf status,rpO movf sspbuf,0 холостое считывание байта адреса для сброса флага /Проверка — если чтение, то загрузка и передача байта bsf status,rpO btfsc sspstat,г w goto Send I2C bcf status,rpO в противном случае — выход из ПОП для ожидания входящего байта данных bcf pirl,sspif сброс бита прерывания и выход из ПОП retfie /Сюда, если был обнаружен байт данных, /следовательно, слово уже в буфере. ISR1 call dig_pntr_set сортировка указателя индикатора bcf status,rpO чтение слова movf sspbuf,0 movwf I2C RX word сохранение слова movwf led op подготовка к передаче слова на ЖК-индикатор bsf portc,led rs call lcd_write
10.8. Применение I2C в АУСМ Derbot 301 Пример программы 10.3. Окончание _____________________________________ /передача на ЖК-индикатор завершена, выход из ПОП. bcf pirl,sspif /сброс бита прерывания retfie /сюда, если посылка слова I2C. Посылаемый байт содержится в kpad_char Send_l2C bcf status,грО bcf pirl,sspif movf kpad_char,0 /перенос символа в sspbuf movwf sspbuf bsf sspcon,ckp /освобождение линии тактовой частоты btfss pirl,sspif /ожидание завершения передачи goto $-1 /передача завершена, выход из ПОП. bcf pirl,sspif /сброс бита прерывания retfie /Нажатие клавиши клавиатуры было распознано через прерывание /по изменению состояния порта В. /Получаем значение с клавиатуры, преобразуем его в символ, /сохраняем в kpad_char, ожидаем освобождения клавиши, /затем посылаем прерывание в АУСМ. f kpad_ISR call kpad_rd 10.8.4. Практическая оценка программ информационного обмена через 12С для АУСМ Derbot Рис. 10.22 демонстрирует некоторые из форм сигналов, снятых в процессе фактическо- го информационного обмена через гС, когда работали показанные выше программы. На рис. 10.22 (а) мы видим характеристики девяти периодов следования тактовой частоты на слово при информационном обмене через 12С. Можно видеть, что тактовая частота только немного ниже, чем ожидавшиеся 125 кГц. Ведущее устройство начинает передавать сооб- щение с байтом адреса 10100100в (т.е. А4цЛ Как мы уже знаем, самый младший разряд адреса является битом R/W, в данном случае индицирующим, что запрашивается опера- ция записи. Затем подчиненное устройство отвечает словом 00110111В (т.е. 37н или сим- волом ASCII “7”, означающим, что на малой клавиатуре была нажата клавиша “7”). Ве- дущее устройство ожидает подтверждения, а затем инициирует условия останова. Рис. 10.22. Реальные сигналы 12С: (а) — полное однобайтовое сообщение; (Ь) — крупный план, демонстрирующий фронты сигналов
302 Глава 10. Начинаем изучать последовательный информационный обмен На рис. 10.22 (Ь) показаны детали характеристик сигналов логической линии, управ- ляемой выходом с открытым стоком. Переключения с логической 1 в логический 0 явля- ется быстрым, оно вызывается включением выхода транзистора. Однако при выключении транзистора линия переходит в состояние логической 1 только благодаря действию нагру- зочного резистора. Этот процесс протекает медленнее — на осциллограмме отчетливо на- блюдается экспоненциальный рост сигнала. Только что рассмотренные две программы являются полезными и демонстрируют ис- пользование ГС в достаточно ограниченных приложениях. Стоит отметить, что эти прог- раммы не принимагот в расчет все состояния, в которые может войти узел ГС, они также не предпринимают корректирующих действий, если последовательная линия связи рабо- тает некорректно. Так, например, если программа, работающая в ведущем устройстве, гге получит подтверждения, то она просто будет циклить до бесконечности. 10.9. Оценка синхронного последовательного информационного обмена и введение в асинхронный информационный обмен Только что рассмотренный последовательный синхронный информационный обмен является чрезвычайно полезным способом обмена данными, однако остается вопрос: так ли уж необходимо передавать сигналы тактовой частоты всякий раз, когда передаются данные? Хотя последовательный синхронный информационный обмен и предоставляет нам легкий способ синхронизации данных, ему все же присущи следующие недостатки: • необходима дополнительная линия, идущая к каждому информационному узлу; • полоса частот, необходимая для тактовой частоты, в два раза шире полосы частот, необходимой для данных; следовательно, именно требования линии передачи тактовой частоты ограничивают общую скорость информационного обмена; • в случае значительных расстояний сигналы тактовой частоты и сигналы данных могут потерять синхронизацию. 10.9.1. Принципы асинхронного информационного обмена По вышеперечисленным причинам был разработан целый ряд стандартов последова- тельной связи, которые не требуют передачи сигналов тактовой частоты параллельно сиг- налам данных. Эти стандарты в общем случае называются стандартами на асинхронный последовательный информационный обмен. В этом виде информационного обмена прием- ник должен извлечь всю необходимую информацию по синхронизации непосредственно из самого сигнала. При этом к сигналам предъявляются новые и совершенно другие тре- бования, а узлы приемников и передатчиков становятся более сложными, по сравнению с узлами синхронной линии связи. Распространенный (однако, далеко не единственный) подход к организации асинхрон- ного информационного обмена базируется на следующих принципах: • Скорость передачи данных определена заранее — как передатчик, так и приемник на- строены на одну и ту же скорость информационного обмена. При этом подходе каж- дый узел нуждается в наличии точного и стабильного источника тактовой частоты, по которому будет генерироваться заданная скорость информационного обмена. Незна- чительные вариации от теоретических значений, однако, допускаются. • Каждый байт или слово обрамляются стартовым и стоповым битом. Это позволяет добиться синхронизации перед тем, как начнут передаваться данные.
10.9. Оценка синхронного последовательного информационного обмена и введение в асинхронный информационный обмен 303 Формат данных, используемый при асинхронном информационном обмене, — того же типа, что и применяемый в таких стандартах, как RS-232, показан на рис. 10.23. Состоянию незанятости линии соответствует заранее определенное логическое состояние. Начало пе- редачи слова данных инициируется стартовым битом, который имеет полярность, проти- воположную состоянию незанятости линии. Набегающий фронт сигнала стартового бита используется для синхронизации. Затем передаются восемь битов данных. Девятый бит, предназначенный для контроля паритета, иногда также используется. Затем линия возвра- щается в состояние незанятости, формируя этим самым столовый бит. Новое слово дан- ных может быть послано немедленно, после завершения передачи одного стопового бита, или же линия может оставаться в состоянии незанятости до того момента, пока она не по- требуется вновь. 10.9.2. Синхронизация последовательных данных без приходящей тактовой частоты С целью обеспечения корректного приема входного потока данных, приемник должен быть способен распознавать начало байта или слова и знать момент для каждого бита, когда данные будут достоверными. Можно было бы подумать, что при заранее заданной скорости информационного обмена это не должно быть трудной задачей, однако на самом деле раз- личные микроконтроллеры не в состоянии обеспечить в точности одинаковые тактовые частоты. Состояние незанятости Старто- вый бит Первый бит данных т Начало синхронизации Дополнительный бит “паритета” может быть вставлен здесь Наиболее ранний возможный момент передачи нового стартового бита Рис. 10.23. Распространенный формат асинхронных последовательных данных Принцип того, как упомянутая синхронизация может быть достигнута, иллюстрирует- ся рис. 10.24. В приемнике работает внутренний тактовый генератор, значение частоты которого является точным произведением ожидаемой частоты битов. Обычно выбирается значение множителя, равное 16, однако это не существенно. Приемник контролирует со- стояние входящих данных на последовательной линии приема данных. Когда он распознает стартовый бит, счетчик начинает считать циклы тактовой частоты до тех пор, пока не бу- дет достигнута срединная точка ожидаемого стартового бита, это будет 8 циклов, если ис- пользуется множитель тактовой частоты, равный 16. Затем он вновь проверяет состояние входной линии данных, чтобы убедиться в том, что стартовый бит присутствует. Если это не так, то прием прекращается. Если наличие стартового бита подтверждено, то счетчик циклов отсчитывает следующие 16 циклов — до середины первого информационного бита. В этот момент он загружает входной бит в главный сдвиговый регистр приема. Таким об- разом он продолжает загружать входные биты, ожидая всякий раз в течение времени, рав- ном времени передаче одного бита, перед тем как загрузить следующий бит. В зависимости от настроек приемника, он загружает 8 или 9 битов (это зависит от ожидаемой длины сло- ва). После этого он вновь ожидает в течение времени, равному времени передаче одного бита, и проверяет наличие стопового бита. Если присутствует корректный столовый бит,
304 Глава 10. Начинаем изучать последовательный информационный обмен то выставляется флаг успешного приема, а принятые данные переносятся в буфер. Если сто- ловый бит отсутствует, то выставляется флаг “ошибки фрейма”. Затем приемник пере- ходит в состояние готовности к приему следующего слова. Срединная точка стопового бита Срединная точка первого информа- ционного бита Состояние незанятости линии Старте- I выйбит ▼ Входящие данные Первый информ-ный бит Тактовая частота приемника, равная произведению ожидаемой частоты передачи данных на целое число Рис. 10.24. Синхронизация сигналов при асинхронном информационном обмене 10.10. Адресуемый универсальный синхронно-асинхронный приемопередатчик (USART) в 16F87XA 10.10.1. Обзор порта Вторым последовательным портом, который присутствует в семействе 16F87XA, яв- ляется адресуемый универсальный синхронно-асинхронный приемопередатчик (УСАПП или USART). Это почти непроизносимое название говорит нам о том, что этот порт может работать как в синхронном, так и асинхронном режимах, а также о том, что он может как принимать, так и передавать данные. Вставка слова “универсальный” отражает традицион- ный подход к названиям подобных устройств — оно просто означает, что порт может быть сконфигурирован на большинство необходимых режимов работы. Термин “адресу- емый” указывает режим использования, при котором входящий байт может означать адрес и интерпретироваться как таковой. USART может быть сконфигурирован как синхронное ведущее устройство, как син- хронное подчиненное устройство либо работать в асинхронном режиме. В последнем случае устройство будет полнодуплексным устройством, т.е. устройством, которое одно- временно может передавать и принимать данные. Таким образом, он имеет как сдвиговый регистр приема данных, так и сдвиговый регистр передачи данных, которые могут работать одновременно. Обе секции порта разделяют один и тот же генератор-контроллер скорости информационного обмена и имеют одинаковый формат данных. Как можно увидеть из рис. 7.10, он имеет источники прерываний как для приема, так и для передачи информа- ции. USART разделяет штырьки с портом С, при этом линия приема соответствует раз- ряду 7, а линия передачи — разряду 6. Работа USART управляется двумя регистрами — TXSTA (см. рис. 10.25) и RCSTA (см. рис. 10.26). Порт активируется битом SPEN регистра RCSTA, а выбор между синхронным и асинхронным режимами — битом SYNC регистра TXSTA. Мы рассмотрим каждый из режимов работы по очереди и проанализируем небольшой пример программы для АУСМ Derbot.
10.10. Адресуемый универсальный синхронно-асинхронный приемопередатчик (USART) в 16F87XA 305 10.10.2. Асинхронный передатчик USART Блок-схема секции передатчика USART показана на рис. 10.27. Она управляется, в ос- новном, регистром управления TXSTA. Чтобы начать со знакомого, обратим внимание на основной элемент последовательного порта, отмеченный на блок-схеме, — сдвиговый ре- гистр или регистр TSR. Обратите внимание на то, что данные, в отличие от порта MSSP, передаются младшими разрядами вперед. Сдвиговый регистр буферизуется регистром TXREG, который является адресуемым СФР, связанным с шиной данных. Именно в этот регистр программа записывает информацию. Сдвиговый регистр управляется тактовым ге- нератором-контроллером скорости информационного обмена, который активируется би- том TXEN. Тактовая частота устанавливается генератором-контроллером скорости инфор- мационного обмена в зависимости от значения, содержащегося в регистре SPBRG. Выход сдвигового регистра соединяется со штырьком микроконтроллера через схему управления и буферизации штырька. Она стробируется битом активирования последовательного пор- та SPEN в регистре управления RCSTA. Данные, подлежащие передаче, должны быть загружены в буфер TXREG программой. Они сразу же переносятся в сдвиговый регистр TSR, если в данный момент не идет пере- дача данных, или же такой перенос производится после передачи стопового бита, если в данный момент производится передача данных. Информация о состоянии обеспечивается двумя битами — флагом прерывания TXIF и битом TMRT. Первый из названных битов указывает состояние TXREG. Когда идет обмен данными между TXREG и сдвиговым ре- гистром, то устанавливается флаг прерывания TXIF (в регистре PIR1, рис. 7.12). Он не мо- жет быть сброшен программно и очищается только тогда, когда выполняется перезагрузка TXREG. Бит TRMT контролирует состояния сдвигового регистра и может быть опрошен программно. Он устанавливается, когда сдвиговый регистр пуст, т.е. передача была завер- шена. R/W-0 R/W-0 R/W-0 R/W-0 U-0 R/W-0 R-1 R/W-0 CSRC ТХ9 TXEN SYNC — BRGH TRMT TX9D разряд 7 разряд 0 разряд 7 CSRC: бит выбора источника синхронизации Асинхронный режим Бит не контролируется Синхронный режим: 1 = режим ведущего устройства (тактовая частота генерируется внутренне от BRG) 0 = режим подчиненного устройства (тактовая частота поступает от внешнего источника) разряд 6 ТХ9: бит разрешения 9-битной передачи 1 = выбор 9-битной передачи 0 = выбор 8-битной передачи разряд 5 TXEN: бит разрешения передачи 1 = передача разрешена 0 = передача не разрешена Примечание: SREN/CREN подавляет TXEN в синхронном режиме разряд 4 SYNC: бит выбора режима USART 1 = синхронный режим 0 = асинхронный режим разряд 3 Не реализован: читается как “0” разряд 2 BRGH: бит выбора высокой скорости информационного обмена Асинхронный режим: 1 = высокая скорость 0 = низкая скорость Синхронный режим: В этом режиме данный бит не используется. разряд 1 TRMT: бит состояния сдвигового регистра передачи (TSR) 1 = TSR пуст 0 = TSR полон разряд 0 TX9D: 9-й бит передаваемых данных, также может быть битом паритета Рис. 10.25. Регистр состояния передачи и управления, TXSTA (адрес 98н)
306 Глава 10. Начинаем изучать последовательный информационный обмен Девятый бит данных, TX9D, разрешаемый битом ТХ9, может быть вставлен в переда- ваемое слово. Оба эти бита присутствуют в регистре управления TXSTA. Этот девятый бит может быть использован как бит паритета. Однако в отличие от некоторых последова- тельных портов, значение паритета не генерируется автоматически аппаратными средст- вами — программист должен делать это внутри программы. Если девятый бит должен ис- пользоваться, то соответствующий признак должен быть установлен до того как соответ- ствующее слово данных будет записано в TXREG. Если этого не сделать, то запись в TXREG запустит передачу последовательных данных, в которой девятый разряд не будет правильно установлен на свое место. Альтернативное использование девятого бита — это указание адреса в сопровождающем байте, как будет описано далее в подразделе 10.10.6. R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R-0 R-0 R-x SPEN RX9 SREN CREN ADDEN FERR OERR RX9D разряд 7 разряд 0 разряд 7 SPEN: бит активирования последовательного порта 1 = последовательный порт активирован (конфигурирует штырьки RC7/RX/DT и RC6/TX/CK как штырьки последовательного порта) О = последовательный порт заблокирован разряд 6 RX9: бит разрешения 9-битного приема 1 = 9-ти битный прием выбран О = выбрант 8-битный прием разряд 5 SREN: бит разрешения однократного приема Асинхронный режим: Не контролируется Синхронный режим — ведущее устройство: 1 = разрешение однократного приема О = запрет однократного приема Этот бит сбрасывается после завершения приема Синхронный режим — подчиненное устройство: Не контролируется разряд 4 CREN: бит разрешения непрерывного приема Асинхронный режим: 1 = разрешение непрерывного приема О = запрет непрерывного приема Синхронный режим: 1 = разрешает непрерывный прием до момента сброса бита разрешения CREN (CREN подавляет SREN) О = запрет непрерывного приема разряд 3 ADDEN: бит разрешения распознавания адреса Асинхронный 9-битный режим (RX9 = 1): 1 = разрешает распознавание адреса, разрешает прерывания и загрузку буфера приема, когда установлен RSR<8> О = запрещает распознавание адреса, принимаются все байты, 9-й бит может использоваться как бит паритета разряд 2 FERR: бит ошибки фрейма 1 = ошибка фрейма (может обновляться считыванием регистра RCREG с последующим приемом следующего достоверного байта) О = нет ошибки фрейма разряд 1 OERR: бит ошибки переполнения 1 = ошибка переполнения (может быть сброшен очисткой бита CREN) О = ошибки переполнения нет разряд О RX9D: 9-й бит принятых данных (может быть битом паритета, однако его значение должно вычисляться в пользовательских программах) Рис. 10.26. Регистр состояния и управления, RCSTA (адрес 18н)
10.10. Адресуемый универсальный синхронно-асинхронный приемопередатчик (USART) в 16F87XA 307 Примечание. Биты TXIF и TXIE смотрите на рис, 7.12. Все другие биты управления расположены в регистре TXSTA (рис. 10.25), за исключением SPEN. Рис. 10.27. Блок-схема секции передачи USART (дополнительные метки в зачерненных прямоугольниках добавлены автором) 10.10. 3. Генератор-контроллер скорости информационного обмена USART Генератор-контроллер скорости информационного обмена используется как в синхрон- ном, так и в асинхронном режимах USART. Он построен на основе использования посто- янно считающего 8-разрядного счетчика, контролируемого регистром SPBRG. Счетчик син- хронизуется частотой внутреннего генератора микроконтроллера, а действие счетчика фак- тически заключается в делении этой частоты на коэффициент, задаваемый SPBRG. Затем коэффициент деления модифицируется в асинхронном режиме битом предварительного деления BRGH, расположенным в регистре TXSTA. Результирующая частота информа- ционного обмена определяется следующим образом, при этом [SPBRG] — это значение в одноименном регистре: Асинхронный режим Для BRGH = 0 Частота информационного обмена = fosc/64x([SPBRG]+l) (Ю.2) Асинхронный режим Для BRGH = 1 Частота информационного обмена = fosc/l6х ([SPBRGJ+1) (Ю.З) Синхронный режим BRGH не контроли- руется Частота информационного обмена = fosc/4x([SPBRG]+l) (Ю.4) 10.10. 4. Асинхронный приемник USART Блок-схема секции приемника USART показана на рис. 10.28. В основном она контро- лируется регистром RCSTA (см. рис. 10.26). В некотором смысле эта блок-схема является зеркальным отображением блок-схемы передатчика, приведенной на рис. 10.27. Однако ее некоторые функции являются абсолютно противоположными, ввиду того, что требо- вания, предъявляемые к приемнику и передатчику, являются различными. Данные по- ступают на 7-й штырек порта С микроконтроллера. В цепь сигнала включены схемы кор- рекции данных с целью минимизации воздействия помех. Всякий раз, когда определяется конкретное значение сигнала данных, берутся три выборки и определяется их мажори- тарное значение. Сердцем приемника является сдвиговый регистр RSR. Он тактируется
308 Глава 10. Начинаем изучать последовательный информационный обмен частотой, поступающей от генератора-контроллера скорости информационного обмена. Сдвиговый регистр буферизуется двойным буфером обратного магазинного типа, работа- ющим по принципу “первым вошел — первым вышел”. Старшим байтом этого буфера является регистр RCREG, функционирующий как адресуемый СФР. Этот двойной буфер может содержать самые последние принятые два байта данных и, следовательно, обеспе- чивать возможность загрузки в сдвиговый регистр третьего входящего байта. Активиро- вание порта выполняется битом SPEN. Этому биту подчиняется либо бит разрешения однократного приема SREN (не путайте со SPEN!), либо бит разрешения непрерывного приема CREN. Это позволяет осуществлять выбор между режимом приема одного вход- ного слова и режимом приема непрерывной последовательности слов. Когда полное слово было корректно принято, включая столовый бит, 8 информацион- ных битов передаются в обратный магазинный буфер (FIFO), если он уже очищен для приема данных и бит флага RCIF установлен. Если используется девятый бит (определя- ется состоянием RX9), то он переносится в бит RX9D. Этот бит имеет тот же уровень бу- феризации, что и приходящие информационные байты. Примечание: FIFO—первым вошел, первым вышел. Для RCIF, RCIE смотрите рис. 7.12 Все другие биты управления находятся в RCSTA (рис. 10.26); Рис. 10.28. Блок-схема секции приема USART (дополнительные метки в затененных полях добавлены автором) Если по сигналам тактовой частоты последовательно загружен входной байт данных, однако обнаружено, что стоп-бит находится в состоянии логического 0, то ошибка фрейма индицируется битом FERR. Как и в случае с RCREG и RX9D, этот бит подвергается двой- ной буферизации с тем, чтобы мог быть проверен статус фрейма каждого буферизованного байта. Если оба буфера RCREG заполнены и регистр RSR принял следующий полный байт, то устанавливается бит переполнения приема OERR. Слово в регистре RSR теряется и дальнейшее перемещение данных из регистра RSR в RCREG блокируется. Флаг OERR должен быть сброшен программно до того, как станет возможным дальнейший прием дан- ных. При считывании информационного значения, операция считывания RCREG вызывает обновление битов FERR и RX9D с установкой их новых значений. Впоследствии эти би- ты должны считываться первыми.
10.10. Адресуемый универсальный синхронно-асинхронный приемопередатчик (USART) в 16F87XA 309 10.10. 5. Пример асинхронного информационного обмена В этом подразделе мы расширим описанный ранее в этой главе пример программы 10.2 с тем, чтобы программа могла работать с асинхронной линией связи. Теперь, когда на ма- лой клавиатуре ручного ПУ АУСМ Derbot будет нажата клавиша, то соответствующий символ будет послан в АУСМ, который затем выдаст его через свой асинхронный передат- чик. В результате этот символ возвращается обратно в АУСМ через его асинхронный при- емник, и, наконец, слово данных возвращается в ручной ПУ. Наряду с тем, что упомяну- тая дополнительная последовательная линия связи не добавляет какой-либо дополнитель- ной функциональности к АУСМ, она предоставляет хорошую возможность разработать простую тестовую программу, которую впоследствии можно использовать для работы с большим объемом последовательных данных. Пример программы 10.4 демонстрирует де- тали, связанные с организацией асинхронного информационного обмена. Полная програм- ма имеется на компакт-диске, прилагаемом к этой книге. Можно проанализировать начальные установки регистров TXSTA и RCSTA, прочитав соответствующие комментарии в программе, а затем сравнить их со схемами регистров уп- равления на рис. 10.25 и 10.26. Скорость информационного обмена в 50 Кбит/с была вы- брана произвольным образом. Как и в случае с примером программы 10.2, все перемещения данных выполняются внутри основной подпрограммы обслуживания прерываний. По этой причине асинхрон- ные прерывания не используются. Подпрограмма обслуживания прерываний начинает свою работу с чтения байта, поступающего с ручного ПУ через порт 12С, и сохранения его в I2C_RX_word. Показан фрагмент программы, в котором выполняется передача данных на асинхронный передатчик. Только что принятое слово передается в регистр TXREG. По мере того, как оно будет выдаваться, асинхронный приемник одновременно с этим начнет его загружать. Программа просто ожидает установки флага прерывания приема, которая указывает на то, что слово было принято и передача завершена. Затем принятое слово воз- вращается назад в ручной ПУ через связь 12С. Пример программы 10.4. Асинхронный информационный обмен с АУСМ Derbot Dbt_kybd_echo_async Данная программа принимает число из ручного ПУ через шину I2C, сохраняет его, затем передает через асинхронный последовательный канал связи, после чего отсылает его назад через I2C. Каждое 12С-сообщение имеет длину 1 байт. Подпрограммы могут быть адаптированы для использования в любой программе для АУСМ Derbot. TJW 18.07.05 Тестировано и проверено в работе 19.07.05 (предыдущие программные секции опущены) bcf status,rpO /Инициализируем USART в обоих банках памяти movlw B' 10010000 /настройка асинхронного канала: /порт включен, 8-битная передача данных, movwf rcsta /непрерывный прием, адрес не распознается bsf status,rpO movlw B'00100100 / настройка асинхронного канала: /передача разрешена, 8-битный режим, movwf txsta /высокая скорость информационного обмена movlw 04 /устанавливаем скорость информационного обмена /на 50 Кбит в секунду movwf spbrg bcf status,rpO
310 Глава 10. Начинаем изучать последовательный информационный обмен Пример программы 10.4. Окончание (программные секции опущены) /Подпрограмма обслуживания прерываний. По внешнему прерыванию /из ручного ПУ считывается байт SSP, выдается обратно через USART, /принимается вновь через USART и вновь посылается на ПУ. /Принятый байт сохраняется в I2C_RX_word для последующего использования. • к************************]'***]'******************************************* / Interrupt_SR выдача через асинхронный канал связи bcf pir1,rcif /предварительная очистка флага прерывания приема movf l2C_RX_word,0 /получаем слово и переносим его в txreg movwf txreg btf ss pirl,rcif /проверка флага прерывания приема, /указывающего на завершение приема goto $-1 movf rcreg,0 /получаем и сохраняем принятое слово movwf async_RX_word /посылаем эхо-символ movf async_RX word/переносим слово, принятое по асинхронному /каналу, в буфер передачи movwf l2C_TX_word call I2C_send_word Осциллограммы сигналов для этого примера программы можно видеть на рис. 10.29. Рис. 10.29 (а) демонстрирует осциллограмму асинхронной передачи байта данных, снятую, когда используемый комбинированный прибор находится в режиме осциллографа. При го- ризонтальном масштабе в 50 мкс/деление, можно видеть, что период передачи бита точно равен 20 мкс, что определяется выбранной скоростью информационного обмена в 50 Кбит/с. Состояние бездействия соответствует логической 1 и начальный стартовый бит с нулевым логическим уровнем может быть отчетливо виден. Данные передаются “задом наперед” — сначала младшие биты, при этом можно видеть, что их значение равно 00110101 в или 35 в десятичном виде. Это ASCII-символ “5”, указывающий на то, что именно эта клавиша бы- ла нажата на малой клавиатуре ПУ. Столовый бит совмещается со следующим периодом незанятости линии, будучи просто ее начальным отрезком, равным 20 мкс, поэтому его нельзя видеть отчетливо. (а) (Ь) Рис. 10.29. Формы сигналов, передаваемых по последовательной линии связи: (а) — один байт, переда- ется асинхронно; (Ь) — один байт, передается от 12С на асинхронную линию связи
10.11. Реализация последовательной связи без использования последовательного порта — “битовые серии’311 Рис. 10.29 (Ь) показывает то же самое асинхронно передаваемое слово, но теперь уже с частями предшествующего и последующего I2С-сообщения. Комбинированный прибор работает теперь в режиме логического анализатора. Первое I С-сообщение демонстрирует только байт данных, опять-таки равный 00110101в, который повторяется асинхронной ли- нией связи, хотя, конечно же, в другом формате. Последующее 12С-сообщение — это просто байт адреса ручного ПУ, который может быть прочитан как 10100100b- Бит R/W находится в нулевом состоянии (т.е. ведущее уст- ройство будет записывать данные в подчиненное устройство), при этом сигнал подтвер- ждения может быть виден на девятом цикле тактовой частоты. 10.10. 6. Использование распознавания адреса в режиме приема USART USART может использоваться и таким способом, который позволяет включать адрес в принимаемые данные. Так как несколько узлов могут быть подключены к последователь- ной линии связи, то соответствующий узел сможет опознавать свой адрес. Приемник USART должен быть настроен на 9-битный режим (в регистре RCSTA бит RX9 = 1), а бит разреше- ния адреса ADDEN в этом же регистре должен быть установлен на 1. При работе в этом режиме логическая 1 в девятом бите указывает на то, что передаваемый байт является адресом. Первоначально все данные, в которых девятый бит находится в нулевом состоя- нии, игнорируются. Когда будет распознан байт, у которого есть девятый бит и он равен 1, программа может считать переданный байт и определить (программно), имеется ли сов- падение адресов. Если это так, то программа возвратит порт в режим нормального прие- ма, установив бит ADDEN в 0. При этом последующие слова будут считываться как дан- ные того устройства, адрес которого был распознан. Это будет продолжаться до тех пор, пока не будет распознано следующее слово адреса, при этом оно может предназначаться другому узлу. 10.10. 7. USARTв синхронном режиме Помимо своего значительного потенциала в асинхронном информационном обмене, USART также может быть использован в синхронном режиме, который выбирается уста- новкой бита SYNC регистра TXSTA. Порт при этом должен быть активирован битом SPEN регистра RCSTA. Теперь разряд 7 порта С может использоваться для последовательных данных, а разряд 6 — для последовательной тактовой частоты. При понимании режима SPI порта MSSP, который был описан ранее в этой главе, понимание концепций, лежащих в основе режима работы USART, рассматриваемого сейчас, не должно составлять каких ли- бо трудностей. Следовательно, если пользователь захочет использовать этот режим, то он должен самостоятельно изучить соответствующую информацию. 10.11. Реализация последовательной связи без использования последовательного порта — “битовые серии” После изучения предшествующих страниц у вас могло создаться впечатление, что для организации последовательного информационного обмена совершенно необходимо исполь- зовать микроконтроллер с его одним либо большим числом последовательных портов. Это не совсем так, поскольку имеется возможность генерировать и принимать последователь- ные информационные потоки только программным способом, используя для ввода-вывода разряды стандартного порта. Это может оказаться сравнительно простым, даже привлека- тельным (с точки зрения экономии ресурсов) вариантом реализации простой синхронной
312 Глава 10. Начинаем изучать последовательный информационный обмен линии связи, если она будет использоваться только время от времени. Также имеется тео- ретическая возможность программно реализовать и более сложные протоколы, типа 12С, однако практически воплотить эту возможность довольно трудно. В Главе 6 дано больше информации по этому вопросу, с сопровождаемым примером для микроконтроллера PIC 16F84. 10.12. Сборка АУСМ Derbot Для запуска большинства программ, использованных в примерах этой главе, вам потре- буется использовать ЖК-исполнение ручного ПУ АУСМ Derbot. Соединительный разъем “bus” (шина) на АУСМ должен быть уже установлен, также как и нагрузочные резисторы 12С. При этом принципиальная схема АУСМ станет очень близкой к схеме, приведенной на рис. А3.1 — в ней не будет только фотосопротивлений и ультразвукового детектора. Резюме • Последовательный информационный обмен становится все более важным аспектом встроенных систем. Его хорошее понимание очень важно для начинающего разработ- чика. • В общем случае имеются два типа последовательного информационного обмена: син- хронный и асинхронный. • Имеется очень большое количество различных стандартов и протоколов последователь- ного информационного обмена, имеющих диапазон от очень простых протоколов до весьма сложных. Важно выбрать тот протокол, который лучше всего соответствовал бы нуждам приложения. • Микроконтроллер 16F873A имеет два чрезвычайно гибких последовательных порта. За эту гибкость приходится платить значительной сложностью освоения их использо- вания. Следовательно, часто при использовании этих портов имеет смысл адаптировать широкодоступные программы, а не разрабатывать свои собственные, начиная с нуля.
ГЛАВА 11. СБОР И МАНИПУЛИРОВАНИЕ ДАННЫМИ В предыдущих главах этой книги мы ограничили свое рассмотрение миром, который был почти полностью дискретным. В то время как мы хотим извлечь пользу из преиму- ществ, которые дискретные сигналы могут нам предоставить, нам необходимо признать, что большинство реальных переменных по своей природе являются аналоговыми. Они из- меняются непрерывно и могут принимать значения из диапазона, границы которого не яв- ляются четко определенными, если мы говорим о таких переменных, как температура, сила звука, частота и иные подобные переменные. Таким образом, является необходимым, что- бы микроконтроллер был способен считывать аналоговые значения и, если это необходимо, генерировать выходные аналоговые значения, хотя внутренне микроконтроллер и является чисто дискретным устройством. Процесс преобразования аналогового сигнала в цифровой, совместно с сопровождающим этот процесс манипулированием данными, обычно назы- вают “сбором данных”. Как только данные из внешнего мира были собраны, их необходимо обработать, а затем использовать. Может также потребоваться их усреднение, масштабирование или сохране- ние. Вполне возможно, что затем они будут использоваться для какой-либо формы управ- ления, также может потребоваться их отображение или передача в другие устройства. Сбор и использование собранных данных является темой данной главы. В ней вы уз- наете: • об основных характеристиках систем сбора данных; • о характеристиках аналого-цифрового преобразователя (АЦП); • о характеристиках АЦП в 16F873A; • о том, как может использоваться АЦП 16F873A; • о некоторых простых методах манипулирования данными; • об использовании компараторов и возможностях компаратора в 16F873A. Как только мы получим способность собирать данные и манипулировать ими просты- ми способами, мы окажемся в выгодной позиции, так как сможем создавать множество из- мерительных устройств. В силу этого в конце этой главы будет рассмотрен ряд иллюстра- тивных проектов. В них Derbot используется либо как АУСМ, либо как простая базовая конструкция, являющаяся основой других проектов, которые не требуют колес. 11.1. Основная идея — аналоговые и дискретные величины, их сбор и использование Большинство датчиков генерируют выходные сигналы, которые являются аналогом величин, которые они представляют. Таким образом, выходной сигнал напряжения от дат- чика температуры отражает температуру настолько точно, насколько позволяет использу- емый датчик, увеличиваясь или уменьшаясь, если то же самое происходит с температурой. Аналогичным образом, выходной сигнал микрофона отражает точные характеристики зву- ковой волны настолько хорошо, насколько это может сделать микрофон — по амплитуде, частоте и форме сигнала. Аналоговые сигналы — это великолепная вещь, однако они все
314 Глава 11. Сбор и манипулирование данными же, как показано табл. 11.1, страдают и значительным количеством больших недостатков. С другой стороны, как показывает та же таблица, дискретные сигналы ведут себя лучше при подсчете, а при использовании современных технологий с ними еще и легче работать. Табл. 11.1. Некоторые свойства аналоговых и дискретных величин Характеристика Аналоговая величина Дискретная величина Средства представления Переменные представляются непрерывно изменяющимся напряжением или током Переменные представляются двоичными числами Точность представления Может принимать неопределенный диапазон значений; абсолютная точность теоретически возможна при условии, что сигнал остается совершенно неискаженным. Только фиксированное количество цифровых комбинаций доступно для представления результата измерения, например 8-разрядное двоичное число может иметь только 256 различных комбинаций значений разрядов. Свойство “непрерывного изменения” аналогового сигнала не может быть воспроизведено. Сопротивляемость деградации сигнала Почти неизбежно страдает от дрейфа, затухания, искажений и помех. Полная коррекция не может быть достигнута. Цифровое представление значений по свое природе толерантно к большинству форм деградации сигналов. Контроль ошибок также может быть использован, а при применении соответствующих методов является возможным полное восста- новление поврежденного сигнала. Обработка Аналоговая обработка сигналов, использующая усилительные и другие цепи, достигла высокого уровня сложности, однако, в конечном счете, она ограничена по гибкости и всегда страдает от деградации сигналов. Могут быть использованы очень мощные компьютерные методы обработки данных. Хранение Чисто аналоговое хранение данных в течение любого срока времени почти невозможна. Все основные технологии полупроводниковых устройств хранения являются цифровыми. Является возможным достаточно легко преобразовать сигнал из аналоговой формы в цифровую, используя аналого-цифровой преобразователь (АЦП). Имеющиеся схемы, обес- печивающие такое преобразование, являются сравнительно сложными. Однако их разра- ботка — это уже сложившаяся форма искусства, они доступны в форме готовых к использо- ванию интегральных схем либо модулей, входящих в состав микроконтроллера. Поскольку мы собираемся разрабатывать внедренные системы, то нам необходимо понимать харак- теристики АЦП с тем, чтобы мы могли правильно выбрать микросхему и эффективно ее использовать. 11.2. Система сбора данных При преобразовании аналогового сигнала в цифровую форму обычно недостаточно выбрать просто подходящий АЦП. Часто требуется наличие более одного входного сигнала, кроме того сигналы могут потребовать обработки перед своим преобразованием. Таким
11.2. Система сбора данных 315 образом, в большинстве случаев будет необходимо создать законченную систему сбора данных. Элементы такой системы показаны на рис. 11.1. На ней в форме блок-схемы пока- зана система с множественными входами, обеспечивающая усиление, фильтрацию, выбор источника, выборку и хранение значений сигналов, а также само аналого-цифровое преоб- разование. Различные элементы этот системы рассматриваются в следующем подразделе. диапазон АЦП завершено Рис. 11.1. Элементы системы сбора данных (чегырехканальной) 11.2.1. Аналого-цифровой преобразователь Задачей АЦП является определение цифрового выходного сигнала, который был бы эквивалентен его входному напряжению. Разработка таких схем — это далеко не тривиаль- ная задача. Было разработано множество различных схем АЦП, ориентированных на раз- личные приложения. Некоторые из них, например, такой как двойной интегрирующий АЦП, работают медленно, но обеспечивают очень высокую точность преобразования — они очень полезны при проведении точных измерений, например в цифровых вольтметрах. Другие же, например, как преобразователи мгновенного действия, работают очень быстро, однако проигрывают в точности преобразования — они используются для преобразования высокоскоростных сигналов — например, видеосигналов или сигналов от радара. Другие же, как, например, АЦП с последовательной аппроксимацией, работают со средней скоро- стью и обеспечивают среднюю точность — они полезны в промышленных применениях общего назначения. Это именно тот тип АЦП, который обычно используется во встроенных системах. Описание того, как работают такие схемы АЦП можно найти в большинстве учебников по электронике. АЦП имеют описанные далее основные характеристики. Характеристики преобразования На АЦП поступает произвольно изменяющееся входное напряжение. АЦП преобразу- ет его в фиксированное количество выходных значений. Пример характеристики преобра- зования АЦП показан на рис. 11.2, где входное напряжение представлено по горизон- тальной оси, а соответствующий ему цифровой выход — на вертикальной оси. Если АЦП выполняет преобразование непрерывно, а его входное напряжение постепенно увеличива- ется от нуля, то выход первоначально будет нулевым. При каком-то значении входного сиг- нала, выход изменится и станет равным ...001. Он остается на том же уровне по мере то- го, как входной сигнал изменяется далее до тех пор, пока при каком-то значении входного
316 Глава 11. Сбор и манипулирование данными сигнала цифровой выход не изменится на ...010. Если входное напряжение будет непре- рывно расти, то в некоторый момент времени выход достигнет своего максимального зна- чения. Это значит, что входной сигнал прошел весь диапазон своего возможного измене- ния. Выходной сигнал изменяется ступенчато вплоть до своего максимального значения. Для n-разрядного АЦП, максимальное выходное значение будет равно (2П - 1). Например, для 8-разрядного АЦП, конечное значение будет равным (28 - 1), или 11111111в, либо 255d. Входной диапазон Рис. 11.2. Характеристики ввода-вывода для идеального АЦП Входной диапазон, показанный на рис. 11.2, начинается от нуля и достигает значения Vmax. Это значение немного смещено вправо от того места, где его можно было бы ожидать, т.е. в точке, в которой должен произойти переход на шаг 2П. Такое позиционирование позволяет разделить горизонтальную ось точно на 2П одинаковых сегментов, каждый из которых центрирован по переключению выходного сигнала. Многие АЦП имеют характеристики того же типа, что и характеристики, показанные на рис. 11.2, имея, например, входной диапазон 0-5 В. Другие же, однако, имеют биполярный диапазон, а их входное напряжение может принимать как положительные, так и отрицатель- ные значения, например от -5 до +5 В. В любом случае входной диапазон Vr является разни- цей между максимальным входным напряжением и минимальным входным напряжением. Диапазон обычно непосредственно связан со значением опорного напряжения, схема фор- мирования которого является частью АЦП. Из показанного графика интуитивно ясно, что чем больше количество выходных разря- дов, тем больше будет число выходных шагов и тем более точным будет преобразование. Мера точности преобразования называется разрешением. Это величина, на которую значе- ние выходного сигнала изменяется при его переходе от одного значения к соседнему. На приведенном графике разрешение — это ширина одного шага характеристики преобразо- вания. АЦП с п выходными разрядами может обеспечить 2П возможных значений выход- ного сигнала — от 0 до 2П - 1. Следовательно, разрешение равно V/2n, где Vr — это диа- пазон входного напряжения. Входной сигнал должен максимально использовать входной диапазон, не выходя из него. Если он будет использовать только часть диапазона, то реаль- ное разрешение упадет, и АЦП не будет использоваться наилучшим образом.
11.2. Система сбора данных 317 Скорость преобразования Преобразование, выполняемое АЦП, занимает определенное время. Это время назы- вается временем преобразования. Медленные АЦП, обладающие значительным временем преобразования, могут обеспечить преобразование только низкочастотных сигналов, по- скольку критерий Найквиста (смотрите подраздел 11.2.2) всегда должен соблюдаться. Вре- мя преобразования АЦП определяет, какой тип сигналов он может преобразовывать. Как уже отмечалось ранее, высокоточные АЦП, в общем, требуют большего времени для завер- шения преобразования. Цифровой интерфейс Цифровой интерфейс формируется сигналами управления и информационными выхо- дами АЦП. Типичные сигналы управления указаны на рис. 11.1. В общем случае, на АЦП подается сигнал, инициализирующий начало процесса преобразования. Когда преобразо- вание завершено, АЦП соответствующим сигналом сигнализирует о завершении преобра- зования. Другой сигнал инициализирует вывод информации из АЦП. В зависимости от типа требуемого интерфейса, АЦП могут иметь либо параллельный, либо последователь- ный информационный интерфейс. АЦП всегда работает в паре с блоком опорного напряжения. Это устройство или схема, которая поддерживает очень точное и стабильное напряжение — обычно в нем использу- ются полупроводниковые стабилитроны. Фактически, АЦП использует опорное напряже- ние как линейку, при помощи которой он измеряет входное напряжение. АЦП настолько хорош, насколько качественно его опорное напряжение. Чтобы получить качественное ана- лого-цифровое преобразование хороший АЦП должен использоваться совместно с качес- твенным блоком опорного напряжения. 11.2.2. Кондиционирование сигналов — усиление и фильтрация Для максимально эффективного использования АЦП, входное напряжение должно в максимально-возможной степени использовать его входной диапазон, не выходя за его пре- делы. В то же время большинство источников сигналов, например микрофоны или термо- пары, формируют очень низкие значения напряжения. Следовательно, во многих случаях понадобится усиление сигнала, для того чтобы использовать весь диапазон возможного изменения входного напряжения. Может также потребоваться сдвиг входного напряжения, например в случае, если входной сигнал является биполярным, а входное напряжение АЦП может быть только однополярным (только положительные значения напряжения). Если подлежащие преобразованию сигналы носят периодический характер, ю фунда- ментальным требованием преобразования будет требование о том, чтобы частота преоб- разования была, по крайней мере, в два раза выше самой высокой частоты сигнала. Это требование известно как критерий дискретизации Найквиста. Если не будет обеспечено соответствие этому критерию, то возникнет крайне неприятная форма нарушения сиг- нала, известная как наложение спектров. Тогда может понадобиться использование филь- тра защиты от наложения спектров, чтобы обеспечить соответствие критерию Найквиста. 11.2.3. Аналоговый мультиплексор В том случае, когда имеются множественные входы, используется аналоговый муль- типлексор. Альтернатива этому — использование нескольких АЦП — связана с дополни- тельным расходованием средств и пространства. Мультиплексор работает как селектор- ный переключатель, определяющий, какой вход из нескольких в данный момент времени будет подключен к АЦП. Мультиплексор формируется на базе использования набора полу- проводниковых ключей. Важно осознавать, что полупроводниковый ключ не является со- вершенным устройством. В особенности это сказывается при переводе ключа в состояние
318 Глава 11. Сбор и манипулирование данными “включения” — полупроводниковый ключ имеет внутреннее последовательное сопротив- ление, которое может иметь диапазон от десятков до тысяч Ом. Это, как мы увидим в даль- нейшем, может оказывать влияние на процесс сбора данных. 11.2.4. Выборка и удержание сигнала, а также время отбора сигнала Вследствие того, что большинство АЦП не могут обеспечить точное преобразование изменяющегося напряжения, часто используются схемы выборки и удержания сигнала (СВУС). Такая схема производит выборку напряжения сигнала — как бы выполняет его “снимок”, а затем удерживает сигнал в стабильном состоянии на время длительности пре- образования. Простая, однако, практичная СВУС показана на рис. 11.3. Ее основой явля- ется полупроводниковый ключ и конденсатор. Когда ключ замыкается, конденсатор заря- жается вплоть до значения входного напряжения Vs. В этот момент, в идеале, Vo Vc = Vs, поскольку буферный усилитель имеет единичный коэффициент усиления. Когда ключ раз- мыкается, заряд на конденсаторе остается и Vc (а, следовательно, и Vo) сохраняют фиксиро- ванные значения. На практике же, однако, наблюдаются некоторые утечки конденсатора, поэтому имеется дрейф выходного напряжения. Эту схему иногда называют схемой сле- жения и удержания, поскольку, когда ключ замкнут, выходное напряжение отслеживает входное напряжение. Рис. 11.3. Простой вариант схемы выборки и удержания сигнала Рис. 11.4. Иллюстрация времени отбора сигнала (не в масштабе) Одной из проблем, связанных с этой простой схемой, является то, что она неизбежно вносит последовательное сопротивление в путь прохождения сигнала. Оно отображено резистором, включенным в схему. Таким образом, когда ключ замыкается, напряжение конденсатора Vc не достигает уровня напряжения сигнала немедленно, а растет до него по экспоненциальному закону. Этот рост показан на рис. 11.4. Рост напряжения задается формулой:
11.2. Система сбора данных 319 Vc = Vs{l-exp(-t/RC)} (11.1) Наша цель, с точки зрения сбора данных, заключается в том, чтобы гарантировать, что напряжение возрастет достаточно близко к своему конечному значению еще до того, как ключ разомкнется (затем сигнал будет “удерживаться”) и будет запущен процесс преоб- разования. Время, которое уходит на то, чтобы Vc (а, следовательно, и Vo), достигло зна- чения, которое мы считаем приемлемым, называется временем отбора сигнала. Давайте предположим, что Vc должно расти до 90 процентов от своего конечного зна- чения Vs. Затем, подставляя это значение в уравнение (11.1), постепенно придем к такому результату: 0,9Vs = VS{1 -exp(-t/RC)} exp(-tZRC) =1-0,9 -t = RC ln(0,l) t = 2,3RC. Время отбора сигнала иллюстрируется рис. 11.4. Однако указанное значение погреш- ности является недостаточным. Для того чтобы гарантировать хорошую точность преоб- разования данных, погрешность, вносимая этим процессом, должна быть меньшей, чем эк- вивалент половины самого младшего разряда. Следовательно, для 8-ми разрядного преоб- разования это означает, что отобранное значение напряжения Vc должно достигнуть значения > (511/512)VS или 0,9980Vs. Для случая 10-разрядного преобразования оно дол- жно быть > (2047/2048)Vs или 0,9995Vs. Выполнив те же расчеты, что и раньше и подставив в них 10-разрядное значение, получим: -t = RC 1п( 1/2048) t = 7,6RC. Результирующие значения времени отбора сигнала также показаны на рис. 11.4. На нем отчетливо видно, что значения времени отбора сигнала возрастают с увеличением со- противления, емкости, а также с повышением требуемой точности. Позже в этой главе мы рассмотрим практическое применение приведенных расчетов. Стоит отметить, что цепи мультиплексора и СВУС могут быть объединены, при этом ключи мультиплексора могут использоваться как ключ СВУС. Это широко распространен- ная практика. 11.2.5. Синхронизация и управление от микропроцессора Обычно система сбора данных находится под управлением микропроцессора или мик- роконтроллера. Они могут управлять общей синхронизацией системы, включая управле- ние выбором входа, моментом выборки выбранного сигнала, а также моментом запуска преобразования. Процесс отдельно взятого преобразования может быть представлен в виде блок-схемы, показанной на рис. 11.5. При этом должны быть удовлетворены два главных требования временной привязки, касающиеся времени отбора сигнала (СВУС) и времени преобразо- вания (АЦП). Как только система будет инициализирована, должен быть настроен переключатель мультиплексора. После этого СВУС может начать процесс выборки данных. Затем должен истечь период времени, равный либо превосходящий значение периода времени отбора сиг- нала СВУС. После этого АЦП может начать преобразование. Это, опять-таки, также зай- мет конечное время. После завершения преобразования АЦП устанавливает соответству- ющий флаг, и только тогда микропроцессор может снять с него выходные данные.
320 Глава 11. Сбор и манипулирование данными Эти стадии объединяются, если мультиплексор формирует часть СВУС Рис. 11.5. Типичные требования по синхронизации аналого-цифрового преобразования 11.2.6. Сбор данных в микроконтроллерной среде Встроенные системы довольно часто нуждаются в АЦП, поэтому естественно ожидать, что АЦП, как одно из периферийных устройств, также интегрирован в микроконтроллер. Важно, однако, осознавать, что АЦП и микроконтроллер не составляют счастливую пару. Для того чтобы работать на хорошем уровне точности АЦП необходима тихая жизнь (в электронном смысле), с идеальным (чистым) электропитанием и заземлением при полном отсутствии помех. Микроконтроллер же, с другой стороны, будучи цифровым устройством, демонстрирует стабильную тенденцию засорять линию электропитания и землю всплес- ками напряжения при каждом переключении сигналов. Как следствие этого, в результате своей интенсивной внутренней цифровой деятельности микроконтроллер становится ло- кальным источником помех. Таким образом, интеграция АЦП с микроконтроллером будет, в лучшем случае, компромиссом, а высокая точность преобразования в данном случае яв- ляется обычно невозможной. Несмотря на вышесказанное, АЦП широко используются в микроконтроллерной среде, при этом многие микросхемы микроконтроллеров имеют встроенные АЦП. В своем боль- шинстве — это 8- или 10-разрядные АЦП. 11.3. Модуль АЦП в PIC® 16F87XA 11.3.1. Краткий обзор и блок-схема 16F87XA имеет универсальный и мощный 10-разрядный модуль АЦП, показанный на рис. 11.6. Он является поднабором компонент полной системы сбора данных, показанной на рис. 11.1, включающим АЦП и мультиплексор, а также обладающим способностью
11.3. Модуль АЦП в PIC® 16F87XA 321 использовать напряжения питания в качестве опорного напряжения. В данной конкретной конструкции АЦП интересным способом реализована функция выборки и удержания сиг- нала, которая будет рассматриваться далее в подразделе 11.3.3. Рис. 11.6. Аналого-цифровой преобразователь в 16F87XA (дополнительные надписи в затемненных прямоугольниках добавлены автором) Входной мультиплексор, который показан в правой части схемы, имеет пять каналов в исполнениях 16F873A и F875A, и восемь — в исполнениях 16F874A и F876A. Входы разделяются с пятью из шести разрядов порта А и тремя из восьми разрядами порта Е (для 16F874 и F876). Только разряд 4 порта А не используется, поскольку он уже разделя- ется входом таймера 0. Разряды порта могут распределяться гибким способом между аналоговыми и цифровыми входами, согласно установкам в специальном функциональ- ном регистре. Внешнее опорное напряжение может использоваться для приложений, требующих дос- таточно высокой точности, при этом имеются разъемы как для положительных, так и от- рицательных подключений. Предоставление вывода для подключения отрицательного нап- ряжения означает, что опорное напряжение не обязательно должно быть привязано к сис- темной земле. В тех случаях, когда требуется недорогое преобразование средней точно- сти, в качестве опорного напряжения может использоваться напряжение питания. Входной диапазон будет равен выбранному опорному напряжению. 11.3.2. Управление АЦП АЦП управляется двумя СФР: ADCONO (рис. 11.7) и ADCON1 (рис. 11.8). Результат преобразования помещается в два других СФР — ADRESH и ADRESL. Названные четы- ре регистра показаны на рис. 7.6. Другие СФР также оказывают существенное влияние на АЦП. В состав этих регистров входят регистры TRISA и (для интегральных схем с 40 выво- дами) TRISE. Любые разряды, используемые как аналоговые входы, должны быть объявлены
322 Глава 11. Сбор и манипулирование данными входами в этих регистрах. Регистры PIR1 и PIE1, которые содержат, соответственно, флаг прерывания и флаг разрешения прерывания АЦП — также используются. Сейчас мы рассмотрим возможности управления АЦП. Рассмотрение будет произво- диться в последовательности, которая приблизительно соответствует последовательности их использования. Включение АЦП включается и выключается битом ADON регистра ADCONO. Выключение АЦП на то время, когда он не используется, обеспечивает небольшую экономию в потреблении электроэнергии. Установка скорости преобразования Работа АЦП 16F87XA контролируется тактовым генератором АЦП, имеющим период Tad. Полный цикл 10-разрядного преобразования занимает приблизительно около 12 пери- одов Tad — эта величина до некоторой степени зависит от того, какой источник тактовой частоты выбран. Пользователь может выбирать тактовую частоту из ряда значений. Хотя, в общем случае, желательно, чтобы преобразование происходило настолько быстро, на- сколько это возможно, учитывая верхний предел тактовой частоты. В случае 16F87XA ми- нимальный период тактовой частоты для корректной работы АЦП равен 1,6 мкс (эта ве- личина указана в технических данных 16F87XA), что соответствует частоте в 625 кГц. Это означает, что минимально возможное время преобразования будет равно 19,2 мкс. В про- тивоположном экстремальном случае, если преобразование будет слишком медленным, то будет наблюдаться очевидная утечка заряда запоминающих конденсаторов и преобразо- вание станет неточным. Таким образом, наилучшая практика связана с установкой такой тактовой частоты АЦП, чтобы период тактового сигнала равнялся или был чуть меньше, чем 1,6 мкс. Выбор источника тактовой частоты АЦП управляется битом ADCS2 в ADCON1, а также битами ADCS1 и ADCS0 в ADCONO, как показано на рис. 11.7. Этот рисунок пока- зывает, что возможны различные варианты деления основной тактовой частоты. Допол- нительно имеется специализированный RC-генератор, который также может быть выбран. Его типичный период равен 4 мкс, однако его значение может быть выбрано из диапазона от 2 до 6 мкс. Если системная тактовая частота является высокой, то обычно она может быть исполь- зована и для получения тактовой частоты АЦП. Вместе с тем, когда системная тактовая час- тота является низкой, то лучше использовать RC-генератор. Барьер между понятиями “вы- сокая” и “низкая” в данном случае находится в районе около 500 кГц. При внутреннем ге- нераторе, работающем на этой частоте, самая быстрая тактовая частота АЦП, которая мо- жет быть получена из этой частоты, равна 250 кГц. Это дает период, равный 4 мкс, что со- ответствует типичному периоду сигналов от RC-генератора. Если основной тактовый гене- ратор работает на частоте, которая ниже, чем указанная частота, то в общем случае реко- мендуется использовать RC-генератор. Конфигурирование входных каналов и выбор опорного напряжения Способ, которым используются входные разряды порта, определяется установкой битов PGFC3 — PGFC0 регистра ADCON1. Стоит их внимательно изучить на рис. 11.8. Разнообразие возможностей достаточно внушительно — как в терминах выбора входных каналов, так и опорного напряжения. Из рисунка можем видеть, что диапазон выбора вход- ных каналов простирается от использования только одного канала порта A (PGFC3:PGFC0 = 1110) до использования всех восьми аналоговых входов (PGFC3:PGFC0 = 0000). Воз- можно также использование других комбинаций, которые предполагают использование внешнего опорного напряжения. Вновь обратите внимание на то, что любой штырек пор- та, который должен использоваться как аналоговый вход, должен быть объявлен входом
11.3. Модуль АЦП в PIC® 16F87XA 323 в регистре TRIS. В противном случае штырек будет работать как выход, т.е. будет выпол- няться нежелательное преобразование цифрового выходного значения! R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 U-0 R/W-0 ADCS1 ADCS0 CHS2 CHS1 CHSO GO/DONE — ADON разряд 7 разряд 0 разряды 7-6 ADCS1:ADCS0: биты выбора тактовой частоты аналото-цифрового преобразования (биты регистра ADCONO показаны жирным шрифтом) ADCON1 <ADCS2> ADCONO <ADCS1:ADCS0> Преобразование тактовой частоты 0 00 Fosc/2 0 01 Fosc/8 0 10 Fosc/32 0 11 Frc (тактовая частота поступает от внутреннего RC-генератора АЦП) 1 00 F osc/4 1 01 Fosc/1 1 10 Fosc/64 1 11 Frc (тактовая частота поступает от внутреннего RQ-генератора АЦП) разряды 5-3 CHS2;CHS0: биты выбора аналогового канала ООО = Канал О (AN0) 001 = Канал 1 (AN1) 010 = Канал 2 (AN2) 011 = Канал 3 (AN3) 100 = Канал 4 (AN4) 101 = Канал 5 (AN5) 110 = Канал 6 (AN6) 111 = Канал 7 (AN7) Примечание. Устройства PIC 16F873A/876A реализуют только каналы аналого-цифрового преобразования от 0 до 4; нереализованные варианты выбора зарезервированы. В случае использования названных устройств выбирать нереализованные каналы нельзя. разряд 2 GO/DONE: бит состояния аналого-цифрового преобразования Когда ADON = 1: 1 = выполняется аналого-цифровое преобразование (установка этого бита запускает аналого-цифровое преобразование. Этот бит автоматически очищается аппаратным способом, после завершения аналого-цифрового преобразования) 0 = аналого-цифровое преобразование не выполняется разряд 1 Не реализован: читается как “0” разряд 0 ADON: бит включения аналого-цифрового преобразователя 1 = питание на модуль аналого-цифрового преобразования подается 0 = питание на модуль аналого-цифрового преобразования не подается, рабочий ток не потребляется Рис. 11.7. Регистр ADCONO (адрес 1FH) Выбор входного канала Входной канал выбирается битами выбора канала от CHS2 до CHS0 в ADCONO. Эти биты определяют, какой ключ, из показанных на рис. 11.6, будет замкнут. Задание этого выбора является обычно первым шагом в процессе сбора данных, как мы увидим далее. Запуск преобразования и сигнализация о его завершении Преобразование инициализируется посредством установки бита GO/DONE в регистре ADCONO. Когда преобразование завершено, данный бит аппаратными средствами возвра- щается в нулевое состояние. О завершении преобразования сигнализируется установкой флага прерывания АЦП ADIF, как это показано на рис. 7.10. Следовательно, завершение
324 Глава 11. Сбор и манипулирование данными преобразования может быть обнаружено либо проверкой состояния бита GO/DONE, либо контролем флага ADIF, либо разрешением прерывания и реакцией на него в подпрограм- ме обслуживания прерываний. R/W-0 R/W-0 U-0 U-0 R/W-0 R/W-0 R/W-0 R/W-0 ADFM ADCS2 — — PCFG3 PCFG2 PCFG1 PCFG0 разряд 7 разряд О разряд 7 ADFM: бит выбора формата результата аналого-цифрового преобразования 1 = выравнивание по правому краю. Шесть (6) старших разрядов ADRESH читаются как “О”. О = выравнивание по левому краю. Шесть (6) младших разрядов ADRESH читаются как “О”. разряд 6 ADCS2: бит выбора тактовой частоты аналого-цифрового преобразования (биты ADCON1 указаны жирным шрифтом)) ADCON1 <ADCS2> ADCONO <ADCS1 :ADCS0> Преобразование тактовой частоты 0 00 F osc/2 0 01 Fosc/8 0 10 Fosc/32 0 11 Frc (тактовая частота поступает от внутреннего RC-генератора АЦП) 1 00 Fosc/4 1 01 Fosc/16 1 10 Fosc/64 1 11 Frc (тактовая частота поступает от внутреннего RC-генератора АЦП) разряды 5-4 Не реализованы: читается как “О” разряды 3-0 PCFG3:PCFG0: биты управления конфигурацией порта АЦП PCFG <3:0> AN7 AN6 AN5 AN4 AN3 AN 2 AN1 ANO Vref+ Vref- C/R 0000 А А А А А A A A Vdd Vss 8/0 0001 А А А А Vref» A A A AN3 Vss 7/1 0010 D D D А А A A A Vdd Vss 5/0 0011 D D D А Vref* A A A AN3 Vss 4/1 0100 D D D D А D A A Vdd Vss 3/0 0101 D D D D Vref* D A A AN3 Vss 2/1 011х D D D D D D D D — — 0/0 1000 А А А А Vref» Vref- A A AN3 AN2 6/2 1001 D D А А А A A A Vdd Vss 6/0 1010 D D А А Vref» A A A AN3 Vss 5/1 1011 D D А А Vref» Vref- A A AN3 AN2 4/2 1100 D D D А Vref» Vref- A A AN3 AN2 3/2 1101 D D D D Vref» Vref- A A AN3 AN2 2/2 1110 D D D D D D D A Vdd Vss 1/0 1111 D D D D Vref» Vref- D A AN3 AN2 1/2 А = аналоговый вход D = цифровой ввод-вывод C/R = число аналоговых входных каналов / номер аналого-цифрового опорного напряжения Рис. 11.8. Регистр ADCON1 (адрес 9FH) Форматирование результата Результат преобразования помещается в регистры ADRESH и ADRESL. Возможно ис- пользование двух форматов результата, показанных на рис. 11.9. Результат может вырав- ниваться по левому краю — в этом случае 8 старших разрядов результата размещаются в ADRESH. Этот формат полезен тогда, когда требуется получение результата, имеющего только 8 разрядов — тогда содержимое регистра ADRESL может игнорироваться. Во всех остальных случаях полезным будет результат, в котором выравнивание выполнено по пра- вому краю. Выбор формата задается битом ADFM в регистре ADCON1.
11.3. Модуль АЦП в PIC® 16F87XA 325 ADFM = 1 7 2107 О 0000 00 : ADRESH ADRESL 10-разрядный результат Выравнивание по правому краю ANx Cpin___ 5 pF 10-разрядный результат ADFM = О 10-разрядный результат Выравнивание по левому краю Рис. 11.9. Форматирование результата преобразования АЦП Vdd = 0.6V Ток утечки ± 500 nA Ключ отбора сигнала RiC<1K>SS Rss> -Wr CHOLD = Емкость ЦАП = 120 пФ Обозначения: Cpin = Входная емкость Vt = Пороговое напряжение Ток утечки = Ток утечки на штырьке ввиду различных контактов Ric = Межконтактное сопротивление SS = Ключ отбора сигнала Chold = Емкость отбора/удержания сигнала (от ЦАП) 2V-- VSS 6V-- 5V-- Vdd 4V- - 3V-- ...I I I I I I I 5 6 7 891011 Ключ отбора сигнала (кОм) Рис. 11.10. Модель входа АЦП в 16F87XA 11.3.3 . Аналоговая модель входа Ранее в этой главе было продемонстрировано, что для понимания и прогнозирования системных характеристик необходимо понимание реальных цепей прохождения сигналов. Рис. 11.10 представляет собой эквивалентную схему прохождения сигнала для рассматри- ваемого нами АЦП. Фактически эта схема представляет работающую в реальном времени модель части компонент, показанных на рис. 11.6, сформированную с точки зрения прохож- дения сигнала. Источник сигнала, совместно с его внутренним сопротивлением, представлены в левой части схемы — они моделируются источником напряжения, включенным последователь- но с резистором, отражающим внутреннее сопротивление источника сигнала. Напряжение сигнала попадает в микроконтроллер через штырек, помеченный как ANx. Имеется неболь- шая входная емкость (5 пФ). Кроме того, очевидно, что входные диоды защиты, а также другие входные цепи, имеют потенциал формирования утечек тока из цепи прохождения сигнала, что также показано на эквивалентной схеме. Далее сигнал проходит через сопро- тивление межсоединения Ric, после чего достигает ключа мультиплексора. Это один из ключей мультиплексора аналогового входа, показанного на рис. 11.6. На схеме показано
326 Глава 11. Сбор и манипулирование данными внутреннее сопротивление этого ключа — Rss- Приблизительное значение этого сопротив- ления зависит от напряжения питания — эта зависимость отражена небольшим графиком, приведенным в нижнем правом углу рис. 11.10. Из графика видно, что сопротивление клю- ча при напряжении питания 5 В приблизительно равно 7 кОм. Сам по себе АЦП относится к так называемому переключательно-конденсаторному типу (см. Главу 5). Прежде всего, это означает, что АЦП имеет внутреннюю емкость, ко- торая должна зарядиться до уровня входного напряжения к тому моменту, когда начнется процесс преобразования. Чтобы быть точными, следует отметить, что именно эта емкость осуществляет роль конденсатора отбора и удержания сигнала. Другими словами, все 120 пФ этого конденсатора должны быть заряжены до начала процесса преобразования. 11.3.4 . Расчет времени отбора сигнала Фирма Microchip в своей документации определяет три следующих источника времен- ной задержки в расчетах времени отбора сигнала tac: tac = длительность переходных процессов в усилителе + + время зарядки конденсатора удержания сигнала + + температурная поправка. (11.2) Там же рекомендуется рассматривать (как постоянную величину, равную 2 мкс) время длительности переходных процессов в усилителе^ Температурная поправка применяется только тогда, когда температура превосходит 25 С — она определяется следующим об- разом: Температурная поправка = (Температура - 25 С)(0,05 мкс/ С). Можно видеть, что эта поправка вносит время задержки, равное всего 0,5 мкс на каж- дые 10 С превышающих 25 С, поэтому ее влияние в большинстве случаев невелико. Доминирующей компонентой времени отбора сигнала является время заряда конден- сатора, которое мы сейчас и рассмотрим. Модель аналогового входа по рис. 11.10 может быть соотнесена со схемой выборки и удержания сигнала, приведенной на рис. 11.3, а так- же с уравнением (11.1). В процессе нашего анализа мы будем считать влияние входного тока утечки и небольшой входной емкости пренебрежимо малым. Фактические значения для R и С, показанных на рис. 11.3 для случая АЦП 16F87XA, могут быть определены по рис. 11.10. R формируется как (Rss+Ric+Rs) или (1 кОм + 7 кОм + Rs) для случая напряже- ния питания, равного 5 В. Емкость С, как показано на рис. 11.10, имеет значение, равное 120 пФ. Вычисления, иллюстрируемые рис. 11.4, показывают, что для получения точности, соответствующей 10-разрядному преобразованию, время отбора сигнала должно быть рав- ным 7,6RC. Подстановка названных величин, в предположении пренебрежимо малого внут- реннего сопротивления источника сигнала, даст: tac = 7,6RC = 7,6 х (1 кОм + 7 кОм) х 120 пФ = 7,3 мкс. Если к этой величине добавить значение длительности переходных процессов в усили- теле, то время отбора сигнала возрастет до 9,3 мкс. Полученная величина отражает минимальное возможное значение. Для определения общего времени, необходимого для завершения одного преобразования, эта значение вре- мени отбора сигнала необходимо добавить к времени преобразования, которое обсужда- лось в подразделе 3.2. Теперь можно определить, что минимально возможное время пре- образования будет равно 19,2 мкс. Складывая это значение с минимально возможным вре- менем отбора сигнала, получим, что общее время преобразования будет равно: (2 + 7,3 + 19,2) мкс, т.е. 28,5 мкс.
11.3. Модуль АЦП в PIC® 16F87XA 327 Во многих случаях внутреннее сопротивление источника сигнала не может считаться пренебрежимо малым, а любое внешнее сопротивление, включенное последовательно в цепь прохождения сигнала, будет увеличивать значение времени отбора сигнала, рассчитанное выше. Фирма Microchip рекомендует максимальное значение внутреннего сопротивления источника сигнала, равное 2,5 кОм. В этом случае: tac = 7,6 х (1 кОм + 7 кОм + 2,5 кОм) х 120 пФ = = 9,6 мкс. Обратите внимание, что это не максимальное значение времени отбора сигнала, которое может приниматься в расчет, поскольку в документации на PIC 16F87XA специфицируется максимально допустимое внутреннее сопротивление источника сигнала, равное 10 кОм. 11.3.5 . Повторные преобразования Когда преобразование завершено, преобразователь ожидает истечения периода време- ни, равного 2 х Тдо, перед тем как станет возможным запуск нового цикла преобразования. По истечении названного периода времени, может быть выполнено преобразование либо того же самого входного канала, либо другого (который к этому моменту может быть уже выбран). В подразделе 11.3.4 было определено, что минимально возможное время преобразо- вания равно 28,5 мкс. Если к этой величине добавить период времени, равный 2 х tADj т.е. минимум 3,2 мкс, то время цикла полного преобразования станет равным 31,7 мкс. В слу- чае последовательных повторных преобразований это означает максимальную частоту выборки сигнала, приблизительно равную 30 кГц. Обратите, однако, внимание на то, что эта цифра не принимает во внимание время выполнения программы, которое демонстри- рует тенденцию к снижению частоты преобразований. 11.3.6 . Компромисс между скоростью преобразования и разрешением Время преобразования, полученное выше, не столь уж мало по сегодняшним стандар- там и бывают случаи, когда требуется меньшее время преобразования. В то время как один из вариантов решения в этом случае связан с применением внешнего АЦП, другой вариант связан с анализом того, действительно ли требуется полное 10-разрядное преоб- разование. Если это не так, то время преобразования может быть снижено. Один из мето- дов такого снижения, из описанных в документации, заключается в том, что преобразо- вание запускается с использованием допустимой тактовой частоты АЦП, затем во время преобразования выполняется переключение на более высокую тактовую частоту, пре- восходящую специфицированную тактовую частоту АЦП. Старшие разряды результата, полученные до переключения частоты, будут корректными и могут быть использованы. Те же разряды, которые определились уже после переключения частоты, корректными не будут. Таким образом, в результате мы получим преобразование, выполняемое с большей скоростью, однако обеспечивающее более низкое разрешение. Указанное переключение частоты должно выполняться программно. Альтернативным подходом будет снижение времени отбора сигнала, как это показано на рис. 11.4, с тем, чтобы при выборке сигнала обеспечивалась точность, например, до 8-го разряда. После этого можно выполнять полное преобразование. Переключение тактовой частоты АЦП, описанное выше, также может использоваться.
328 Глава 11. Сбор и манипулирование данными 11.4. Использование АЦП в программе замера освещенности АУСМ Derbot АУСМ Derbot имеет три фоторезистора, которые используются как датчики освещен- ности, — они показаны на рис. А3.1. Два из них расположены спереди самодвижущегося механизма, а один — сзади. АУСМ Derbot использует АЦП в 16F873A при замере интен- сивности света — как в программе замера освещенности, так и в программе поиска источ- ника света. Пример программы 11.1 демонстрирует фрагменты программы Dbt_light_meter, которая полностью приведена на компакт-диске, прилагаемом к этой книге. Программа считывает выходные значения сигналов с датчиков освещенности и отображает их на ЖК- индикаторе ручного ПУ. Однако при этом возникает ряд вызовов, связанных с манипу- лированием данными. Результат, получаемый от АЦП, должен быть отмасштабирован с целью получения реальных отсчетов напряжения, а затем преобразован в формат, под- ходящий для выдачи на ЖК-индикатор. Таким образом, отсчеты сначала преобразуются в двоично-кодированный десятичный формат, а затем — в формат символов ASCII. Толь- ко затем результирующие символы передаются на ЖК-индикатор. Пример программы 11.1. Использование АЦП в программе замера освещенности АУСМ Derbot датчика освещенности масштабируется до уровня чего отображается в десятках милливольт. наличия ручного ПУ, загруженного соответствующей ;Dbt_light_meter /Программа считывает значения с датчиков освещенности с 10-разрядным /разрешением, затем масштабирует их и преобразует в 4-х разрядные /двоично-кодированные десятичные числа, после чего отображает их на /ЖК-индикаторе ручного ПУ. /Сигнал от заднего /милливольт, после /Программа требует /программой. ,-TJW 19.07.05, тестировано 20.07.05 (предшествующие программные секции опущены) bsf status,rpO movlw B'00001011' установка битов порта А в соответствии / с их функциями, movwf trisa / каналы АЦП объявляем входами movlw B'10000100' выбираем биты 0,1,3 порта А / для аналогового входа movwf adconl / результат выравниваем вправо bcf status,rpO movlw B'01000001' настраиваем АЦП: тактовая частота Fosc/8, ключ АЦП вкл., однако без преобразования movwf adconO / выбор входного канал не применяется /считываем и сохраняем сигналы с датчиков освещенности main_loop movlw B'01000001' /выбираем канал 0 как вход /(левый передний датчик освещенности) movwf ADConO call delay20u /время отбора сигнал bsf ADConO,go /запуск преобразования btfsc ADCon0,go done /ожидание завершения преобразования goto $-1
11.4. Использование АЦП в программе замера освещенности АУСМ Derbot 329 Пример программы 11.1. Окончание _______________________ movf adresh,0 /считываем и сохраняем выходные данные АЦП ;(старший байт) movwf ldr_left_hi bsf status,грО movf adresl,0 /считываем и сохраняем выходные данные АЦП /(младший байт) bcf status,грО movwf ldr_left_lo /выбираем канал 1 (правый датчик освещенности) movlw В'01001001' movwf ADConO /выбираем канал 1 в качестве входа /(правый передний датчик освещенности) call delay20u (выборка сигналов от других двух датчиков освещенности) (масштабирование, преобразование в форму десятичных двоично-кодированных чисел и выдача значений на отображение) goto main__loop 11.4.1. Конфигурирование АЦП Первичные настройки регистров управления АЦП — ADCONO и ADCON1 — приве- дены в примере программы. Рис. А3.1 показывает, что правый датчик освещенности под- соединен к разряду 0 порта А, левый — к разряду 1 порта А, а задний — к разряду 3 порта А. Внешнее опорное напряжение отсутствует, поэтому используется напряжение питания. Соответствующие межсоединения управляются битами PCFG регистра ADCON1 (см. рис. 11.8), которые устанавливаются в 0100. При периоде основной тактовой частоты, равном 250 нс (4 МГц), и минимальном спе- цифицированном времени Tad , равном 1,6 мкс, необходимо поделить значение тактовой частоты, по крайней мере, на 8. Эта величина выбирается при заданном TAD,? равном 2 мкс. Задается форматирование результата с выравниванием по правому краю. 11.4.2. Время отбора сигнала Процесс сбора данных может быть исследован путем изучения примера программы, приведенной выше. Время отбора сигнала должно быть рассчитано для наихудшего случая, когда окружа- ющее освещение находится на низком уровне и сопротивление датчика освещенности яв- ляется высоким. При этом можно свериться с техническими данными на датчик освещен- ности. В наихудшем случае сопротивление датчика освещенности будет очень высоким, а внутреннее сопротивление источника питания будет демонстрировать тенденцию прибли- жения к значению в 10 кОм — оно будет включено последовательно с датчиком освещен- ности. Обратите внимание, что это максимально-допустимое внутреннее сопротивление источника питания. Однако в нормальных условиях освещенности внутреннее сопротив- ление источника питания будет значительно более низким. По рис. 11.4 определяем: t = 7,6 х RC = 7,6 х (Ю кОм + 1 кОм + 7 кОм) х 120 пФ = 16,4 мкс.
330 Глава 11. Сбор и манипулирование данными Добавив время длительности переходных процессов в усилителе, получим величину, равную 18,4 мкс. 11.4.3. Преобразование данных Фактическую работу АЦП можно проследить, изучив пример программы, начиная от метки main_loop. Три датчика освещенности опрашиваются по очереди. В случае пер- вого датчика (передний левый) можно видеть, что выбирается соответствующий входной канал тем, что бит GO/DONE регистра ADCONO оставляется в состоянии логического нуля. Задержка в 20 мкс вводится для отбора сигнал — она перекрывает значение, рассчи- танное для наихудшего случая (18,4 мкс). Затем инициализируется фактическое преобра- зование установкой бита GO/DONE в состояние логической единицы. Затем ожидается за- вершение преобразования посредством проверки состояния этого же бита. После завер- шения преобразования его результат переносится из регистров ADRESH и ADRESL в две ячейки памяти, после чего программа переходит к отбору следующего входного сиг- нала. Последующее манипулирование данными в приведенном примере программы опу- щено, однако оно будет рассмотрено в этой главе несколько позже. 11.5. Некоторые простые методы манипулирования данными Почти сразу же, как только данные будут получены программой, возникает необходи- мость в их обработке. Это могли бы быть простые операции сложения и вычитания, кото- рые мы уже выполняли, или же другие арифметические операции, например умножение и деление. По мере роста требований к обработке информации, возрастает и сложность ее реализации с использованием языка Ассемблера, что создает сильную мотивацию для пе- рехода к использованию языка программирования высокого уровня. Вместе с тем, нет не- обходимости писать программу или подпрограмму для любой стандартной математиче- ской операции на Ассемблере. Многие стандартные подпрограммы уже созданы -— они описаны, например, в документации Microchip Technology. 11.5.1. Арифметика с фиксированной и плавающей точкой Мы уже неоднократно использовали тот факт, что n-разрядное двоичное число может представить любое целочисленное значение в диапазоне от 0 до 2П - 1. Например, 8-раз- рядное двоичное число может представить любое число из диапазона от 0 до 255D, 12-раз- рядное двоичное число — из диапазона от 0 до 4095D, а 16-разрядное двоичное — из диа- пазона от 0 до 6553 5d. Для представления больших чисел необходимо добавить большее количество разрядов. Мы могли бы представлять таким способом даже дробные числа, вставив в представление числа двоичную запятую. После этого цифры справа от двоичной запятой представляли бы отрицательные степени 2. Это показано в примере, приведенном на рис. 11.11, где двоичное число 1101.11 представляет десятичное число 13,75D. До тех пор, пока во всех числах десятичная запятая будет оставаться в одной и той же фиксиро- ванной позиции (фактически, нам просто достаточно воображать, что она там), то будет возможно выполнять целый набор арифметических операций с таким образом представ- ляемыми дробными числами. Этот тип представления двоичных чисел называется представлением с фиксированной запятой. При использовании этого представления предполагается, что двоичная запятая в представлении чисел всегда находится на определенном месте. Такое представление мо- жет удовлетворить потребности представления как целых, так и дробных чисел. Однако оно не решает проблему представления чисел, значения которых имеют диапазон от очень ма- леньких до очень больших. Так, например, наименьшее ненулевое число, которое может
11.5. Некоторые простые методы манипулирования данными 331 быть представлено 6-разрядным двоичным числом с фиксированной запятой, показанным на рис. 11.11, равно 0,25d, в то время как максимальное число равно 15,75d- При этом нет возможности, например, представить ни 0,0004D ни 2,3 х 10 . Решение этой проблемы заключается в использовании двоичного представления с пла- вающей запятой. При использовании этого представления число отображается с разрядом знака, мантиссой и показателем степени. При помощи такого представления можно пред- ставлять огромный диапазон чисел, однако значительно возрастает сложность обработки чисел в данном представлении. В то время как имеются подпрограммы для арифметики с плавающей запятой, написанные на Ассемблере, наиболее распространенной является ра- бота с этой арифметикой в программах, написанных на языках высокого уровня, в которых она используется для всех точных расчетов. В этой главе мы будем использовать только арифметику с фиксированной запятой. 1 10 1.1 1 ; ' 1 х г2 ! 1 х 21 1x2° 0х21 1 х22 1 *23 1101. 11в - 8+4Ю+ 1 +0. 5+0. 25 - 13. 75О Рис. 11.11. Дробное двоичное число 11.5.2. Преобразование из двоичного представления в двоично-кодированное десятичное представление В то время как все операции арифметики с фиксированной запятой выполняются над числами, заданными в двоичной форме, там, где имеется взаимодействие человека и ком- пьютера, более предпочтительным будет использование десятичной формы представле- ния чисел. Как же мы должны выполнять преобразования между двоичными и десятичны- ми числами? Простой промежуточной между двоичной и десятичной формами представления чисел является Двоично-Кодированная Десятичная форма представления чисел (ДКД). В ней для представления десятичного разряда используется 4-разрядное двоичное число, как это показано в табл. 11.2. Единственное, что отличает эту форму от шестнадцатеричного пред- ставления — это то, что в ДКД двоичные эквиваленты шестнадцатеричных значений Ан, Вн, Сн, Dh, Ен и Fh не разрешены. Таким образом, в табл. 11.2 показаны все допустимые ДКД-коды для одного десятичного разряда. Таблица также показывает ASCII-коды (Аме- риканский Стандартный Код для информационного обмена) для каждого из представлен- ных чисел. В случае цифровых символов ASCII можно видеть, что это просто однобайто- вый код, в котором само число занимает младший полубайт, а число 3 формирует старший полубайт. При использовании этого простого кодирования, многоразрядные десятичные числа могут представляться в ДКД-форме. В случае упакованной ДКД-формы, которая обычно
332 Глава 11. Сбор и манипулирование данными используется, байт используется для представления двух десятичных разрядов. Пример этого показан на рис. 11.12. Несмотря на простоту представления, в общем случае преобразование между ДКД формой и двоичной формой выполняются не так уж просто. Для этого, однако, разрабо- таны стандартные алгоритмы, описанные в документации Microchip Technology. В при- мере программы измерения освещенности для АУСМ Derbot, используется подпро- грамма, взятая из этого источника, которая преобразует 16-разрядное двоичное число в пятиразрядное число ДКД. Она используется при подготовке данных для выдачи на инди- катор. Описание соответствующего алгоритма может быть найдено во многих учебниках по компьютерной арифметике. Табл. 11.2. Двоичное представление, ДКД-представление и ASCII-представление Десятичное Двоичное (ДКД) ASCII (в шестнадц.) Десятичное Двоичное (ДКД) ASCII (в шестнадц.) 0 0000 30 5 0101 35 1 0001 31 6 оно 36 2 0010 32 7 0111 37 3 ООН 33 8 1000 38 4 0100 34 9 1001 39 Старший разряд Младший разряд 0 1 1 0 1 0 0 1 0 0 1 0 0 1 1 1 Рис. 11.12. Упакованное ДКД представление десятичного числа 6927 11.5.3. Умножение После операций сложения и вычитания, операция умножения является следующей по распространенности арифметической операцией, которая часто используется в компьютер- ной арифметике. Некоторые процессоры имеют встроенные аппаратные умножители и, сле- довательно, непосредственно выполняют команды умножения. В случае более простых процессоров, как, например, в устройствах семейства PIC 16, умножение реализуется под- программами. Стандартный алгоритм, реализованный в этих подпрограммах, обычно со- держит повторяющиеся команды сдвига и сложения. Имеется очень широкий диапазон стандартных подпрограмм — как для операций с фиксированной запятой, так и для опера- ций с плавающей запятой. Подпрограммы для арифметики с фиксированной запятой могут быть различными, в зависимости от используемой разрядности чисел. Неизбежно, что те подпрограммы, которые работают с более длинными машинными словами, требуют боль- шего времени для своего выполнения. Пример программы замера освещенности для АУСМ Derbot использует подпрограм- му умножения для формата 16x16 разрядов, взятую из документации Microchip Techno- logy, как это будет сейчас описано.
11.5. Некоторые простые методы манипулирования данными 333 11.5.4. Масштабирование и пример программы замера освещенности для АУСМ Derbot Обычное применение операции умножения связано с масштабированием входных дан- ных и, возможно, с преобразованием их к стандартным единицам измерения. В этом отно- шении пример программы для АУСМ Derbot является интересным. В АУСМ Derbot в качестве опорного напряжения используется напряжение питания, равное 5 В. При этом 10-разрядное разрешение равно (5/1024) = 4,883 мВ. Следовательно, самый младший разряд выхода АЦП при использовании этого опорного напряжения “ве- сит” 4,883 мВ. Если выходное значение АЦП умножается на 4,883, то результат даст истинное значе- ние выходного сигнала в милливольтах. Вместе с тем, прослеживание истинного место- положения двоичной запятой может оказаться достаточно трудоемким делом. Возможным решением могло бы быть масштабирование дробного числа на двоичный показатель сте- пени с последующим — после умножения — делением его на это же число. Это сделать легко, поскольку двоичное деление — это прямолинейный процесс сдвига числа вправо, что фактически сопряжено с аннулированием младших битов. Например, в программе измерения освещенности для АУСМ Derbot нам нужно вы- полнить следующие вычисления: выход АЦП х 4,883 = отсчет в милливольтах В то время как мы не можем выполнить умножение на 4,883, мы можем отметить, что 4,883 х 256 = 1250,048 и мы можем выполнить следующие вычисления, используя только целые числа: выход АЦП х 1250 = промежуточный результат При выходе АЦП, являющимся 10-разрядным числом, и множителе 1250d (т.е. 04Е2н), который представляет собой 11-разрядное число, результат будет иметь, по крайней мере, 21 разряд. Это определяет тип подпрограммы умножения, которую нужно использовать. Затем если промежуточный результат разделить на 256, что может быть выполнено просто посредством аннулирования его младшего байта, то на этом процесс масштабиро- вания завершится. Результатом будет значение входного сигнала АЦП, выраженное в милливольтах. Можно было бы ожидать, что возникнет вопрос: почему был выбран множитель 256, а не, скажем, 128 или 512? Это зависит от вносимой погрешности округления. Погрешность округления, возникающая от того, что мы берем 1250 вместо 1250,048 — незначительна, она ниже, чем 0,05 процентов, поэтому вполне приемлема при работе с 10-разрядными числами. Фактически было бы приемлемо использовать в качестве множителя и число 128, однако в этом случае удобство, связанное с отсечением младшего байта, было бы утеряно. Помните, что все это всего лишь вариант. Мы могли бы в качестве альтернативы пре- образовать 4,883 непосредственно в двоичную форму, что дало бы 100.11100010 или 4.Е2Н. Немного поразмыслив и сравнив это число с множителем, который мы использовали, мож- но было бы прийти к выводу, что по существу эти методы равноценны. Описанный выше процесс реализован в примере программы 11.2, в котором выполня- ется масштабирование сигнала от заднего датчика освещенности. При этом используются две подпрограммы: multi6x16, для умножения двух 16-разрядных чисел, и Bin2BCD16, для преобразования 16-разрядного числа в пятиразрядный ДКД-результат. Была дописана программная секция, которая начинает свою работу после аналого-цифрового преобразо- вания. Сохраненное значение выхода АЦП, сохраняемое в ячейках памяти ldr_rear_hi и ldr_rear_lo, переносится в переменные aargbO и aargbl, формирующие один из 16-разрядных входов подпрограммы умножения. Другим входом подпрограммы умноже- ния является слово, формируемое bargbO и bargbl. В это слово загружается значение 04Е2н, представляющее собой шестнадцатеричный эквивалент 1250d- Затем вызывается
334 Глава 11. Сбор и манипулирование данными подпрограмма multl6xl6, при этом результат помещается в aargbO : aargbl: aargb2 : аагдЬЗ. Поскольку результат может иметь только 21 разряд, старший байт aargbO бу- дет пустым, он будет игнорироваться. Младший байт также будет проигнорирован, по- скольку результат необходимо поделить на 256. Следующий по старшинству байт aargb2, становится младшим байтом нужного результата и, следовательно, переносится в млад- ший байт (tempi) 16-разрядного входа подпрограммы Bin2BCD16. Аналогичным обра- зом, aargbl переносится в старший байт — temph. После этого вызывается подпрограм- ма Bin2BCD16. Выходные байты этой подпрограммы непосредственно используются для выдачи на ЖК-индикатор подпрограммой four_dig_disp. Эта подпрограмма посылает ДКД-символы на линию 12С с целью их отображения на ЖК-индикаторе ручного ПУ. Все перечисленные подпрограммы полностью отображены в полном листинге про- граммы, приведенном на компакт-диске, прилагаемом к этой книге. Пример программы 11.2. Последовательность обработки данных для заднего датчика освещенности в программе замера освещенности для АУСМ Derbot (Преобразование в АЦП уже было выполнено для всех трех датчиков освещенности) масштабирование сигнала от ’ заднего датчика освещенности movf ldr__rear_hi, 0 /получаем старший байт результата ;аналого-цифрового преобразования movwf aargbO /это старший байт множимого movf ldr_rear_lo,0 movwf aargbl /это младший байт множимого movlw 04 /старший байт масштабирующего коэффициента movwf bargbO movlw 0e2 /младший байт масштабирующего коэффициента movwf bargbl call multi 6x16 /вызов подпрограммы умножения movf aargbl,0 /аннулирование самого старшего и самого /младшего байтов movwf temph /второй старший байт для ДКД-преобразования movf aargb2,0 /третий старший байт для ДКД-преобразования movwf tempi call Bin2BCD16 /вызов подпрограммы преобразования двоичного /числа в форму двоично-кодированного /десятичного числа call four_dig_disp /вызов подпрограммы, которая посылает /байты ДКД-числа на ЖК-индикатор 11.5.5. Использование для масштабирования опорного напряжения Факт того, что выход АЦП в примере для АУСМ Derbot немедленно должен подвер- гаться масштабированию с целью получения реальных значений отсчетов напряжения, само по себе, не приносит радости и, конечно же, использование подпрограммы умножения в процессе выполнения программы связано с дополнительным расходованием времени ЦП. В некоторых случаях разумный выбор величины опорного напряжения может значи- тельно упростить вычисления, которые должны быть выполнены. Например, если на АЦП АУСМ Derbot подать опорное напряжение, равное 4,096 В, то 1 младший байт выхода АЦП будет представлять точно 4 мВ и тогда сложное масштабирование не понадобиться. Ана- логичным образом, если опорное напряжение будет равно 1,024 В, то 1 младший байт вы- хода АЦП будет представлять точно 1 мВ. Опорное напряжение с подобными значениями может быть легко получено для данных конкретных целей.
11.6. Программа поиска источника света для АУСМ Derbot 335 11.6. Программа поиска источника света для АУСМ Derbot Эта программа дает нам другой пример использования АЦП 16F873A. Сравнивая за- меры между тремя датчиками освещенности, АУСМ находит источник самого яркого света и движется к нему. Он перемещается со скоростью, зависящей от различия освещенности между датчиками. Если же все три датчика будут сигнализировать о схожих уровнях осве- щенности, то АУСМ или замедлит движение или остановится. Как только сравнительные замеры сделаны, приложение не будет требовать высокой точности. В силу этого в про- грамме используется только 8-разрядный результат аналого-цифрового преобразования. Следовательно, более удобно в этом случае будет использование форматирования резуль- тата с левым выравниванием (рис. 11.9) с тем, чтобы результат мог извлекаться только из 8 разрядов регистра ADRESH. Это можно увидеть в примере по изменению установки раз- рядов в регистре ADCON1. При использовании только 8-разрядного результата, возникает возможность сократить время отбора сигнала, например до 6,2RC (рис. 11.4). Поскольку программа работает только при приемлемых уровнях окружающей освещенности, наивысшее оценочное значение со- противления датчика освещенности будет равным 10 кОм, что дает пересмотренное зна- чение максимального внутреннего сопротивления источника сигнала, равное 5 кОм. Вход- ная емкость АЦП остается на уровне 120 пФ, также как и внутреннее последовательное сопротивление АЦП. Следовательно, время отбора сигнала будет равно = 6,2 х 13 кОм х 120 пФ или = 9,7 мкс. Используется подпрограмма временной задержки на 11 мкс. Пример программы 11.3. Применение АЦП в программе поиска источника света для АУСМ Derbot ;Dbt_light_seek ;АУСМ Derbot осуществляет поиск источника света. Используется ШИМ. ;Скорость движения зависит от разности освещенности (спереди и сзади), ;при этом АУСМ Derbot замедляется, если разность освещенности ;оказывается меньшей. Микропереключатели используются для ;определения столкновений ;TJW 19.05.05 Тестировано 19.05.05 {начальные программные секции опущены) bsf status,rpO /выбор банка памяти 1 movlw B' 00001011' /установка разрядов порта А таким образом, /что разряды АЦП работают на вход movwf trisa movlw B' 00000100 ' /настройка АЦП, результат выравнивается влево movwf adconl /разряды 0,1,3 порта А устанавливаются на /аналоговый bcf status,rpO /выбор банка памяти 0 movlw B' 01000001 ' /настройка АЦП, тактовая частота Fosc/8, /АЦП включен, но не запущен, movwf adconO /выбор входного канала сейчас не используется /запуск преобразования movlw В'01001001 movwf adconO ;выбор канала 1 (загрузка Idr)
336 Глава 11. Сбор и манипулирование данными Пример программы 11.3. Окончание call delayllu bsf adconO,go ;запуск преобразования adc2 btfsc adconO,go /ожидание окончания преобразования goto adc2 movf adresh,0 movwf ldr_rt Фактический алгоритм управления представлен на рис. 11.13, он повторно запуска- ется приблизительно каждые 200 мс. Полный листинг программы приведен на компакт- диске, прилагаемом к этой книге. Считывая каждое значения сигнала с датчика освещенно- сти, этот алгоритм выполняет некоторые предварительные вычисления средних и разно- стных значений, используемых далее, когда должна быть вычислена скорость движения вперед. Затем определяется наиболее освещенный датчик и предпринимается соответст- вующее действие. Если наиболее освещенным является один из передних датчиков, то АУСМ движется вперед, поворачиваясь в направлении наибольшей освещенности. При этом его скорость и угол поворота зависят от относительных значений освещенности датчи- ков. Если же наиболее ярко освещенным есть задний датчик, то АУСМ разворачивается, а затем снова ориентируется по передним датчикам освещенности уже описанным выше способом. Когда АУСМ попадает в область, в которой разница световой интенсивности на всех датчиках уменьшается, то его скорость замедляется. Затем, если освещенность всех дат- чиков становится примерно одинаковой, то АУСМ останавливается. Рис. 11.13. Блок-схема программы поиска источника света для АУСМ Derbot
11.7. Модуль компаратора 337 11.7. Модуль компаратора Итак, изучив ряд сложностей, связанных с использованием АЦП, мы завершим главу рассмотрением простейшего интерфейса между аналоговым и цифровым мирами — ком- паратором. Этот важный элемент схем работает немного похоже на 1-разрядный АЦП. Обычно он используется для сравнения входного напряжения с опорным. Если входное напряжение выше опорного, то выход компаратора будет находиться в состоянии логи- ческой 1, а если ниже — то в состоянии логического нуля. Имеется много применений компараторов во встроенных системах. Среди них можно назвать очистку поврежденного цифрового сигнала (в этом случае физический смысл его использования приближается к назначению триггера Шмитта), тестирование напряжения электропитания, установка пре- дупредительного сигнала, если температура или иная переменная достигнет некоторого предельного значения и т.д. 11.7.1. Обзор работы компаратора Компаратор показан на рис. 11.14 (а). Компаратор просто сравнивает два входа, пока- занных на схеме как V+ и V_. Если V+ выше, чем V_, то на выходе компаратора будет присутствовать положительное напряжение, обычно максимально “насыщенный” уро- вень напряжения. Если же V+ будет меньшим, чем V_, то на выходе будет присутство- вать отрицательное или нулевое значение напряжения. При правильно сформированных выходных цепях уровни выходного напряжения могут быть легко сделаны распозна- ваемыми логическими уровнями. (а) V+ > V. Vo в состоянии положительного насыщения V+ < V. Vo в состоянии отрицательного насыщения Рис. 11.14. Компаратор: (а) — обозначение компаратора; (Ь) — пример сигналов Пример входных и выходных напряжений приведен на рис. 11.14 (b). V_ было уста- новлено на фиксированное напряжение, показанное штриховой линией, в то время как V+ изменяется. Когда V+ выше, чем V_, то выход переходит в состояние логической едини- цы, когда же оно меньше, то выход переходит в состояние логического нуля. 11.7.2. Компаратор в 16F87XA и опорное напряжение 16F87XA имеет два компаратора, которые разделяют свои входы с входами АЦП. Ком- паратор 1 имеет входы на AN0 и AN3, а компаратор 2 — на AN 1 и AN2. Они управляются регистром CMCON, показанным по адресу 9СН на рис. 7.6. Возможно формирование ряда
338 Глава 11. Сбор и манипулирование данными различных конфигураций. Например, выходы компаратора могут внешне маршрутизиро- ваться на штырьки RA4 и RA5, или же они могут просто отражаться как биты в регистре CMCON. Соответствующие установки могут быть легко найдены в технических данных, предоставляемых фирмой Microchip, здесь они не перечисляются. Важно отметить, что ком- параторы также формируют источник прерываний. Изменение состояния любого компа- ратора приведет к установке флага CMIF, показанного на рис. 7.10. 16F873A имеет также модуль опорного напряжения, работающий под управлением ре- гистра CVRCON (адрес 9DH). Это резистивная линейка, подключенная одним концом к напряжению питания (через транзисторный ключ), которая позволяет выбирать различные значения напряжения в качестве опорного сигнала. Опорное напряжение может использо- ваться как входное для одного или для обоих компараторов, оно также может выдаваться на штырек 4 микроконтроллера 16F873A. В этом случае оно может использоваться как очень грубое приближение к выходу ЦАП. 11.8. Применение схем Derbot для измерительных целей Мы сейчас достигли того этапа, когда уже можем выполнять ввод аналоговых напря- жений, обрабатывать собранные данные, а затем отображать их. Это очень многообещаю- щая позиция, поскольку она составляет базис очень многих измерительных систем. В дан- ном подразделе описывается, как печатная плата Derbot, совместно с ручным ПУ, может быть использована для создания различных измерительных средств (при использовании уже описанных программ). Ручной ПУ подключается к соединительному разъему АУСМ Derbot “bus” (Шина), который физически расположен под держателем микроконтроллера. ПУ должен быть загружен своей стандартной программой, т.е. согласно примеру програм- мы 10.3. Соответствующие проекты могут оформляться как автономные устройства или интег- рироваться в АУСМ Derbot. Если это будут автономные устройства, то, конечно же, конеч- ный продукт может оказаться несколько более неэкономным в отношении пространства, чем мы бы этого хотели, однако всегда остается вариант полного перепроэктирования ап- паратных средств и создания более компактных устройств. Цепи, требуемые для реализа- ции автономного проекта, иллюстрируются рис. 11.15. На приведенной схеме отражены компоненты и соединения, необходимые для реализации трех измерительных систем, ко- торые и будут рассмотрены далее. В нижеследующих подразделах указывается, какие компоненты необходимы для каждого отдельного проекта. В процессе программирования следует гарантировать, что все неиспользуемые разря- ды портов установлены как выходы. Таким образом, следует сверять аппаратную и прог- раммную реализацию проекта на этапе инициализации и, если необходимо, вносить кор- рекции в соответствующие программные секции. 11.8.1. Электронная измерительная рулетка Программа ультразвукового тестирования, частично показанная в примере програм- мы 9.7, формирует основу ультразвуковой “измерительной рулетки”, отображая в санти- метрах дистанцию от датчика до отражающей поверхности. При этом обработка данных очень похожа на обработку данных в примере программы 11.1 и, следовательно, реализу- ется много функций, схожих с функциями названной программы. Для сборки электронной измерительной рулетки как автономного устройства, схема по рис. 11.15 должна быть реализована на печатной плате Derbot, однако без датчиков осве- щенности и их резисторов. Необходимо использовать ультразвуковые датчики Devantech SRF04 или SRF05. Набор контактных точек для них имеется спереди от места установки электромотора на печатной плате Derbot. Выводы датчиков должны быть к ним припаяны. Руководствуясь спецификациями датчиков, подключите 0 В, 5 В, импульс и эхо-импульс,
11.8. Применение схем Derbot для измерительных целей 339 а затем приклейте либо установите каким либо другим способом датчики в выбранном вами месте печатной платы. LP2950 6‘АА Aik. (9V) Выключатель литания 1uF 100 u, 10 V tant. С2 24 k R1 2x 12k OV SCL ~ Bus Задний Левый электро- мотор C4,5 2x30p 4 MHz Соединительный разъем литания 10k R8 Правый Выводы вольтметра DERBOT AGV Assembly for Voltmeter, Light Meter, and Electronic Tape Measure TJW Rev.22.2.06 MCLR RAO RAI RA2 RA3 RA4 RA5 Vss Oscl Osc2 — RCO — RC1 “ RC2 — RC3 RB7 RB6 RB5 RB4 RB3 RB2 RB1 RBO Vdd Vss RC7 RC6 RC5 RC4 16F873A O2 Пьезо-зуммер (дополнительно) ICD2 conn. Переключатель режимов (дополнительно) -----R12 I/I Ультразвуковой -----О импульс Ультразвуковой -----О эхо-сигнал 820R «"Г n - K 1 Левый 2 6 inc) Диагностические 82OR сае™Дм°Ды -------1 [\J Правый Рис. 11.15. Сборка Derbot для вольтметра, измерителя освещенности и электронной измерительной рулетки Завершите описанный процесс сборки, затем создайте проект MPLAB® на основе про- граммы Dbt_US_Test, которая частично приведена в примере программы 9.7. Подкор- ректируйте секции инициализации с тем, чтобы они соответствовали вашей сборке, уста- новив все неиспользуемые биты портов как выходы. Скомпонуйте программу и выгрузите ее в микроконтроллер. Направьте датчик на отражающую поверхность — расстояние ме- жду датчиком и отражающей поверхностью должно непрерывно отображаться в сантимет- рах на ЖК-индикаторе ручного ПУ.
340 Глава 11. Сбор и манипулирование данными 11.8.2. Измеритель освещенности Для сборки измерителя освещенности соберите схему по рис. 11.15 без ультразвукового датчика. Выгрузите проект Dbt_light_meter с компакт-диска, прилагаемого к этой кни- ге, и на его основе создайте проект MPLAB. Подкорректируйте секцию инициализации программы так, чтобы она соответствовала вашей сборке, установив все неиспользуемые биты портов как выходы. Скомпонуйте программу и выгрузите ее в микроконтроллер. За- пустите программу и наблюдайте, как теперь будут индицироваться отсчеты со всех дат- чиков освещенности. Как ранее уже обсуждалось, все отсчеты выражены в милливольтах, однако они дают индикацию световой интенсивности. Обратите внимание на то, что отсче- ты уменьшаются при увеличении световой интенсивности. 11.8.3. Вольтметр Очень просто можно превратить программу измерения световой интенсивности в про- грамму вольтметра. В этом случае датчики световой освещенности на плате не устанав- ливаются. На схеме показано, что входами вольтметра являются точки, ранее использован- ные для подключения левого датчика освещенности, однако могут использоваться точки подключения любого другого датчика освещенности. Подсоедините и разместите удобным способом входные выводы вольтметра. Выгрузите программу Dbt_light_meter с компакт-диска, прилагаемого к этой кни- ге, и создайте на ее основе проект MPLAB, присвоив ему имя, соответствующее данному проекту. Подкорректируйте секцию инициализации программы так, чтобы она соответст- вовала вашей сборке, установив все неиспользуемые разряды портов как выходы (и обра- тите внимание на то, что входы АЦП более не используются). Во всех других отношениях программа может использоваться без изменений. Однако будет лучше удалить снятие двух неиспользуемых отсчетов АЦП, а также выдачу двух значений, которые более не будут иметь смысла, если только вы не хотите реализовать многовходовый вольтметр. Для про- верки работы прибора подайте постоянное напряжение на вольтметр, подсоединив парал- лельно с его входом цифровой вольтметр. Оба показания должны совпадать. Описанная адаптация ядра проекта Derbot приводит к созданию довольно неточного вольтметра, поскольку в качестве опорного напряжения используется напряжение питания. Однако точки подсоединения заднего датчика освещенности могут использоваться для под- ключения нужного опорного напряжения. Из рис. 11.6 и 11.8 можно видеть, что эти входы могут реконфигурироваться как входы опорного напряжения. Понадобиться использова- ние программного масштабирования с тем, чтобы отразить любые изменения значения опорного напряжения. Проведя соответствующие изменения, можно получить вольтметр приемлемой точности. 11.8.4. Другие измерительные системы Очень просто можно адаптировать уже реализованные нами идеи к другим измери- тельным системам. Они применимы к любым датчикам, имеющим выход в форме напря- жения. Имеется, например, широкий диапазон полупроводниковых датчиков температуры, которые имеют выходной сигнал в форме напряжения, прямо зависящего от температуры. Один из них может быть использован либо как навесной элемент, либо будучи впаянным в печатную плату. После соответствующей корректировки масштабирования, легко может быть получен цифровой термометр.
11.9. Конфигурирование АУСМ Derbot в качестве светопоискового робота 341 11.9. Конфигурирование АУСМ Derbot в качестве светопоискового робота Для конфигурирования АУСМ Derbot в качестве светопоискового робота на плате должны быть установлены датчики освещенности и соответствующие резисторы. Выгру- зите проект Dbt_light_seek с компакт-диска, прилагаемого к этой книге, и создайте на его основе проект MPLAB. Подкорректируйте секцию инициализации программы так, чтобы она соответствовала вашей сборке, установив все неиспользуемые разряды портов как выходы. Скомпонуйте программу и выгрузите ее в микроконтроллер. АУСМ Derbot теперь должен быть готов к работе в режиме поиска источника света. Этот режим хорошо работает в местах, где есть отчетливая разница в освещенности. Derbot будет “метаться” по территории с пятнистыми тенями или будет оставаться неподвижным в условиях рав- номерной освещенности. Резюме • Большинство сигналов, формируемых датчиками, имеют аналоговую природу, в то вре- мя как вся обработка, выполняемая микроконтроллерами, имеет цифровую природу. • Аналоговые сигналы могут быть преобразованы в цифровую форму с использованием аналого-цифрового преобразователя (АЦП). В общем случае АЦП формирует одну из компонент более крупной системы сбора данных. АЦП представляет собой великолеп- ный интерфейс между аналоговым и цифровым мирами. • При использовании АЦП и систем сбора данных, значительное внимание необходимо уделять использованию знаний, среди прочего, о требованиях синхронизации, требо- ваниях к кондиционированию (выделению) сигналов, требованиях к заземлению и ис- пользованию опорного напряжения. • 16F873A имеет 10-разрядный модуль АЦП, реализующий функции системы сбора ин- формации. Понимание работы таких систем является важным моментом для исполь- зования данного модуля. • Информационные значения, будучи введенными в систему, с большой вероятностью потребуют дальнейшей обработки, включая ввод смещения, масштабирование и пре- образование кодов. Для всех этих операций существуют стандартные алгоритмы, кроме того публикуются соответствующие библиотеки программ на Ассемблере. • Простой интерфейс между аналоговым и цифровым миром может быть сформирован за счет использования компаратора, который широко используется для преобразова- ния аналоговых сигналов в одно из двух состояний.
ЧАСТЬ 4. БОЛЕЕ СЛОЖНЫЕ СИСТЕМЫ И PIC® 18FXX2 В данной части книги мы перейдем к рассмотрению более сложных и мощных способов обработки информации и соответствующих им методов программирования. При этом мы начинаем рассмотрение семейства PIC 18 — именно эти устройства будут использоваться нами в этой части книги в качестве базовых устройств. Вместе с тем, эта часть книги посвящена, в основном, рассмотрению программных вопросов. Так, например, теперь описывается и используется язык программирования С. Рассматриваются вопросы реализации многозадачной обработки информации и работа в режиме реального времени, которые очень важны в мире встроенных систем. Используется операционная система реального времени SalvoTM.
ГЛАВА 12. БОЛЕЕ СЛОЖНЫЕ СИСТЕМЫ И PIC® 18FXX2 До сих пор в этой книге мы изучали применение двух микроконтроллеров из семей- ства PIC 16 — одного малого и одного большого. В то время как это, несомненно, — хорошие микроконтроллеры, в них имеются некоторые узкие места и для них характерны некоторые ограничения. Некоторые их аппаратные характеристики очень ограничивают круг возможностей этих микроконтроллеров, например небольшой размер стека или же то, что все источники прерываний должны разделять один и тот же вектор прерывания. Если говорить о наборе команд, то мы, конечно же, признаем ценность подхода RISC. Вместе с тем, отсутствие некоторых видов команд не добавляет удобства программиро- вания. Команды условного перехода, например, нужно формировать как комбинации команд пропуска и безусловного перехода. Более того, перспектива создания больших программ из маленьких команд-кирпичиков Ассемблера становится все более и более пугающей. Следует отметить, что многие из возникающих затруднений связаны с тем, что микро- контроллеры семейства PIC 16 сохраняют ядро, которое было спроектировано в расчете исключительно на самые скромные приложения. Теперь же количество периферийных устройств увеличилось самым драматическим образом, увеличились также объемы памя- ти. Сейчас пришло время для нового начала, призванного преодолеть ограничения, прису- щие семейству PIC 16, а также для переосмысления ядра микроконтроллера. Именно дос- тижение названных целей и стало основой создания семейства PIC 18. Если двигаться от 16F84A, то можно сказать, что 16F873A сохраняет ядро своего пред- шественника, однако для него характерно наличие большего числа периферийных уст- ройств. Сейчас же мы увидим, что для устройств семейства 18 характерны усовершенст- вования в области ядра при сохранении приблизительно постоянным возможного коли- чества используемых периферийных устройств. В результате упомянутых усилий был соз- дан совершенно новый тип микроконтроллера. Выдающиеся преимущества структуры PIC — архитектура RISC, высокая скорость и т.д. — конечно же, сохранены. Вместе с тем, появились новые функции, которые позволяют микроконтроллерам Р1С выйти на новую более широкую арену деятельности — это функции, позволяющие увеличить эффектив- ность работы в режиме реального времени, облегчающие использование языков програм- мирования высокого уровня и обеспечивающие возможность взаимодействия с памятью намного большего объема. Для детального изучения в этой книге среди членов семейства PIC 18 был выбран 18F242, совместно с его близкими родственниками из подсемейства 18FXX2. В этой главе предполагается, что читатели уже имеют опыт работы с устройствами семейства 16 и теперь намерены перейти к использованию устройств семейства 18. В ней проводится сравнение устройств семейства 18 с устройствами семейства 16, когда представляется интересным проследить эволюцию концепций разработки. В частности, описание набора команд выполняется через такое сравнение. Начиная с этой главы и на протяжении всей оставшейся части книги при программи- ровании мы будем теперь использовать язык программирования С, а не Ассемблер. Поэ- тому становится несколько менее важным до мельчайших деталей знать аппаратные особенности микроконтроллера. Компилятор С сам отслеживает эти детали. На самом
344 Глава 12. Более сложные системы и PIC® 18FXX2 деле это огромное облегчение, поскольку устройства семейства 18 далеко не просты. По этой причине вы можете прийти к выводу, что о многих темах в этой главе говорится весьма поверхностно, если сравнить их с эквивалентными подразделами, скажем, Главы 7. После изложения вводной информации о семействе 18 и 18F242, внимание в этой гла- ве будет сфокусировано на основных отличиях устройств данного семейства — а именно: ядре и памяти. Особое внимание будет уделено: • общей архитектуре группы микроконтроллеров PIC 18FXX2; • структуре и функционированию ядра микроконтроллеров семейства PIC 18; • набору команд семейства PIC 18; • структуре памяти, а также организации доступа к ней и адресации; • структуре прерываний в 18FXX2; • источнику электропитания 18FXX2, операции сброса и тактовому генератору. 12.1. Основная идея устройств семейства PIC 18 и 18FXX2 Микроконтроллеры семейства PIC 18 отличаются драматическим развитием ядра PIC, что делает их пригодными для использования в крупных проектах встроенных систем. Несмотря на то, что в них реализованы многие новые функции, они разрабатывались таким образом, чтобы всячески облегчить переход к ним от устройств семейства 16. Поэтому разработчики, которые будут их использовать, многие вещи найдут знакомыми. Итак, для устройств семейства 18 характерны следующие принципиальные характеристики: Похожие на характеристики семейства PIC 16: • набор команд RISC (компьютер с сокращенным набором команд), конвейерная орга- низация, 8-разрядный ЦП с одним рабочим регистром (W) и регистром состояния; • многие периферийные устройства являются идентичными или очень похожими на периферийные устройства семейства 16; • используется похожее пакетирование микросхем и похожая разводка их выводов; • назначение многих специальных функциональных регистров (СФР) и наименования битов остались без изменения; • все команды семейства 16, за исключением одной, являются поднабором набора ко- манд семейства 18; • командный цикл занимает четыре цикла тактовой частоты. Новое для семейства PIC 18: • количество команд возросло более чем вдвое, при этом используется 16-разрядное командное слово; • доработан регистр состояния; • выполняется аппаратное умножение по формату 8 х 8; • допускается больше внешних прерываний; • используется два вектора прерывания, которым присваиваются приоритеты; • используется радикально отличный подход к работе со структурами памяти при уве- личенном общем объеме памяти; • реализована генерация расширенных адресов — как для памяти программ, так и для памяти данных; • используется стек увеличенных размеров, допускающий определенный уровень дос- тупа и управления со стороны пользователя; • используется тактовый генератор с контуром фазовой автоподстройки частоты (ФАПЧ). Микроконтроллеры 18FXX2 формируют набор из четырех родственных устройств, основные характеристики которых показаны в табл. 12.1. Во многих отношениях эта таб- лица похожа на табл. 2.1, описывающую микроконтроллеры 16F87XA. Все устройства
12.2. Блок-схема 18F2X2 и регистр состояния 345 группы 18FXX2 имеют набор в 75 команд и используют тактовый генератор с диапазоном выходных частот от 0 до 40 МГц. Имеются также “низковольтные” версии каждого мик- роконтроллера, кодируемые как 18LFXX2. Полные технические данные по этому семей- ству приводятся в документации фирмы Microchip Technology. Разводка выводов для устройств семейства 18FXX2, для случая корпусов с двойным рядом выводов, показана на рис. 12.1. Этот рисунок очень похож на рис. 7.1, при этом порты, источник питания, тактовый генератор и линии сброса изображены на них в тех же местах. Это позволяет перейти к использованию новых устройств при минимальных изменениях в проекте. Табл. 12.1. Подсемейство 18FXX2 Индекс уст-ва Кол. вы- водов* Память Периферийные устройства/ специальные функции 18F242 28 16 Кбайт память программ (8 К — память команд**) 768 байт ОЗУ 256 байт ЭСППЗУ 3 параллельных порта, 4 счетчика/таймера 2 модуля сбора/сравнения данных/ШИМ 2 модуля последовательного информационного обмена 5 10-разрядных каналов АЦП 18F252 28 32 Кбайт память программ (16 К — память команд**) 1536 байт ОЗУ 256 байт ЭСППЗУ 3 параллельных порта, 4 счетчика/таймера 2 модуля сбора/сравнения данных/ШИМ 2 модуля последовательного информационного обмена 5 10-разрядных каналов АЦП 18F442 40 16 Кбайт память программ (8 К — память команд**) 768 байт ОЗУ 256 байт СППЗУ 5 параллельных портов, 4 счетчика/таймера 2 модуля сбора/сравнения данных/ШИМ 2 модуля последовательного информационного обмена 8 10-разрядных каналов АЦП 18F452 40 32 Кбайт память программ (16 К память команд**) 1536 байт ОЗУ 256 байт СППЗУ 5 параллельных портов, 4 счетчика/таймера 2 модуля сбора/сравнения данных/ШИМ 2 модуля последовательного информационного обмена 8 10-разрядных каналов АЦП * Только для корпусов с двойным рядом выводов (DIP). ** Однословные команды, обратите внимание, что некоторые команды занимают два слова. АЦП = аналого-цифровой преобразователь. ШИМ = широтно-импульсная модуляция. 12.2. Блок-схема 18F2X2 и регистр состояния Блок-схема микроконтроллера 18F2X2 показана на рис. 12.2. Исходя из рис. 12.1 (а) он, микроконтроллер, является устройством с 28 выводами. Стоит уделить некоторое вре- мя тому, чтобы идентифицировать основные отличительные черты этой важной схемы. Почти в центре блок-схемы находится ЦП (центральный процессор), содержащий 8- разрядное АЛУ (арифметико-логическое устройство), рабочий регистр “W-per.” (который иногда называют аккумулятором) и аппаратный блок умножения в формате 8><8 разрядов. Действия ЦП задаются командой, которую он получает из памяти программ и которая передается через регистр команд. Он виден выше и слева от блока ЦП. Важным элемен- том ЦП, который, однако, не показан на этой блок-схеме, является регистр состояния. Память программ показана в левой верхней части блок-схемы. Ее адресная шина вхо- дит в “триггеры адреса” памяти. При ее 21 разряде, является возможным адресовать 22 ячеек памяти, т.е. 2097152 (2 Мбайта) ячеек. Табл. 12.1 показывает, что в 18F242 имеется необходимость адресации только 16 К ячеек памяти, что требует использования всего 14 разрядов. Другие линии в этом случае будут избыточными. 16-разрядная шина, передаю- щая командное слово, показана как выходящая из “триггера данных памяти программ”. Можно видеть, как эта шина идет вниз по блок-схеме, выходя, наряду с другими устрой- ствами, на регистр команд, о котором мы уже упоминали. Справа от памяти программ
346 Глава 12. Более сложные системы и PIC® 18FXX2 находится область, помеченная как “генерирование адреса памяти программ”. Ее сердцем является, конечно же, счетчик команд. Под счетчиком команд показан стек, который со- стоит из 31 ячейки памяти. Указатель таблицы формирует средство доступа к таблицам или другим данным в памяти программ под управлением пользовательской программы. Память данных изображена вверху почти в центре блок схемы. Как и в случае памяти программ, ее схемы генерирования адреса с их банком регистров выбора файлов (напри- мер, FSR0) и регистром выбора банка (BSR) занимают значительную часть блок-схемы в целом. Адрес памяти данных содержит 12 разрядов, которые могут адресовать 4096 бай- тов. Опять-таки, табл. 12.1 показывает, что эта адресная шина используется не полностью. Данные передаются в/из памяти данных через основную шину данных. MCLR/VPP —► RA0/AN0 *-* RA1/AN1 *-* RA2/AN2/VREF- — RA3/AN3A/REF+ RA4/T0CKI * RA5/AN4/SS/LVDIN VSS----► OSC1/CLK1----► OSC2/CLKO/RA6 -*--- RCO/T10SOH"1CKI *-* RC1/T1OS1/CCP2* '*“*• RC2/CCP1 RC3/SCK/SCL Ej’1 2 3 4 5 6 7 8 9 см см LL СО Е Е Е Е Е Ею Ен Е 12 Пю 14 CL CM Ю CM U. СО Т“ о 28 □ 27 □ 26 □ 25 24 RB7/PGD RB6/PGC RB5/PGM □ —* RB4 □ -*-* RB3/CCP2* 23 □ RB2/INT2 22 □ -*-* RB1/INT1 □ RBO/INTO 20 □ ----VDD 19 □ -<--VSS 18 J -*-* RC7/RX/DT □ -*-* RC6/TX/CK 16 □ *-*- RC5/SDO 15 □ RC4/SDI/SDA 21 17 Е Е E RSS является альтернативным штырьком для мультиплексирования штырька ССР2 (а) MCLR/VPP — 1 40 3*- RB7/PGD RA0/AN0 -w- -*е 2 39 3 — -► RB6/PGC RA1/AN1 -*с 3 38 3 — -* RB5/PGM RA2/AN2/VREF- — —*-с 4 37 3 — RB4 RA3/AN3/VREF+ 5 36 3*- RB3/CCP2* RA4/T0CKI — — с 6 35 □ — -♦ RB2/INT2 RA5/AN4/SS/LVDIN — —с 7 34 3*- RB1/INT1 RE0/RD/AN5 •*- О СМ СМ 33 3 — RB0/INT0 RE1/WR/AN6 q XT У Н. Ц. 32 3*- VOD RE2/CS/AN7 — — с 10 00 СО 31 3 VSS Vdd — 11 О О 30 -* RD7/PSP7 Vss 12 П П 29 з — RD6/PSP6 OSC1/CLK1 — 13 28 3*- -► RD5/PSP5 OSC2/CLKO/RA6 —с 14 27 3*- RD4/PSP4 RC0/T1OS0H"1CKI 15 26 3*- RC7/RX/DT RC1/T1OS1/CCP2* *- —с 16 25 3 •*— -► RC6/TX/CK RC2/CCP1 -*Е 17 24 3 — RC5/SDO RC3/SCK/SCL •*- 18 23 3 — RC4/SDI/SDA RDO/PSPO ♦- — с 19 22 3 — RD3/PSP3 RD1/PSP1 20 21 3 RD2/PSP2 (Ь) Рис. 12.1. Схема разводки выводов PIC 18FXX2 и виды пакетирования корпусов DIL: (а) — 18F242 и 18F252; (b) — 18F442 и 18F452 При отдельной шине адреса и отдельном вводе-выводе данных для памяти программ и памяти данных, мы на данном этапе можем подтвердить использование Гарвардской структуры микроконтроллера.
12.2. Блок-схема 18F2X2 и регистр состояния 347 Адрес памяти программ Генерирование адреса памтгм программ Шина данных <8> Память программ 21 [Указатель таблицы | 8 |PCLAW|PCLATH) Триггер данных ПортА RAQ/ANO RA1/AN1 RA2/AN2/VREF- RA3/AN3A/HEF+ RA4/T0CKI. RASANVSS/LVDIN RA6 ОЗУ данных 21 Триггер адреса 21 Триггер адреса Адрес <12> Триггер данных |31-уровневыйстек| 16 I .—,—__________ [ Триггер таблицы | 8 Шина команд Регистр команд 3 Генерирование частоты 4XPLL MCLR Vou.Vss OSC2/CLKO OSC1/CLKI T1OSCI T1OSCO Встроенный отладчик Логические схемы инкрементирования/ декременги|Х)вания Таймер запуска тактового ген-ра Таймер вкл. питания Сторожевой таймер Прецизионное опорное напряжение Сброс по перегреву Сброс повадно питания Низковольтное программиро- вание [ PCU I РСН I PCL I Счетчик команд 'Память программ (до 2 Мбайт) Таймер 3 Таймер! Таймер 2 Периферия ЭСППЗУ данных Адресуемый USART Аналого-цифровой преобразователь Ведущий синхронный последовательный порт [Декодирование^ команд и управление 1Ш1 [pROOH [ PRODL [ | Умножение 8 * 8 | | БитОР] Адрес памяти данных Генерирование адреса памятиданных ПортВ RB0/INT0 RB1/INT1 RB2/INT2 RB3/CCP2(1> RB4 RB5/PGM RB6/PCG RB7/PGD Центральный процессор ПортС Подсоединения тактового генератора ТаймерО RCOT1OSO/T1CKI RCI/riOSl/CCPS*1» | RC2/CCP1 . RC3/SCK/SCL I RC4/SDI/SDA | RCS/SDO RC8/TX/CK RC7/RX/DT Примечания. 1. Дополнительное мультиплексирование ввода/вывода ССР2 с RB3 разрешается выбором бита конфигурирования. 2. Старшие биты прямого адреса ОЗУ берутся из регистра BSR (за исключением команды mdvff). 3. Многие из штырьков ввода-вывода общего назначения мультиплексируются только с одной либо большим числом функций периферийных модулей. Комбинация мультиплексирования является аппаратно-зависимой. USART — синхронно-асинхронный приемо-передатчик Рис. 12.2. Блок-схема PIC 18F2X2 (дополнительные надписи в затемненных прямоугольниках добавлены автором)
348 Глава 12. Более сложные системы и PIC® 18FXX2 Разъемы для подсоединения источника питания к микроконтроллеру — Vdd и Vss — показаны несколько выше левого нижнего угла схемы. Если опять вернуться к рис. 12.1. то можно видеть, что на любом из показанных корпусов выделены два штырька для по- дачи Vss- Этим гарантируется надежное подключение к О В. Меньший корпус имеет один вывод для VDd, в т0 время как больший — два. Связанными с подачей электропитания яв- ляются: • сигнал “сброс по включению питания”, который гарантирует приведение системы в исходное состояние после подачи электропитания; • таймер включения питания, который может использоваться для удержания микро- контроллера в исходном состоянии некоторое время после подачи электропитания; • и сигнал сброса по частичной потере электропитания, который принудительно при- водит микроконтроллер в исходное состояние при падении напряжения питания. Входы тактовой частоты — как для главного тактового генератора, так и для таймера 1 — можно видеть в левой части схемы. С главным тактовым генератором связана цепь ге- нерирования синхроимпульсов, которая вырабатывает различные внутренние сигналы синхронизации. Также связан с главным тактовым генератором таймер запуска генератора, который может использоваться для гарантии того, что генератор войдет в режим устойчи- вой работы до того, как будет запущен сам микроконтроллер. Новым элементом тактового генератора является контур фазовой автоподстройки частоты (ФАПЧ). Благодаря ФАПЧ появляется возможность увеличения частоты генератора с целью ускорения функциони- рования системы. Это оказывает воздействие на гибкость настройки функционирования системы и потребление электропитания. В нижней левой части схемы можно видеть сторожевой таймер и внутрисхемный от- ладчик. Первое устройство является компонентом временной привязки, который может использоваться для инициализации перезапуска микроконтроллера, если программа зависла или работает неправильно. Второе устройство обеспечивает диагностический потенциал, который фактически встроен в микроконтроллер. Его использование зависит от того, как микроконтроллер связан с хост-компьютером. Если используется внутрисхемный отлад- чик, то появляется возможность управления процессом выполнения программ микрокон- троллером с хост-компьютера. В этом случае является также возможным возврат диагно- стической информации, включая состояния регистров микроконтроллера, на хост-ком- пьютер для ее отображения. Эта функция уже описывалась в подразделе 7.11 Главы 7. И, наконец, параллельные порты, включая их функции ввода-вывода и все взаимосо- единения с периферийными устройствами, отображены в правой части схемы. Другие пе- риферийные устройства отображены в нижней части схемы. Среди них имеется еще один блок памяти, использующий технологию ЭСППЗУ. Наиболее важный компонент ЦП — регистр состояния — показан на рис. 12.3. Он со- держит 5 битов с информацией о состоянии для операции, которая выполнялась микро- контроллером последней. Ограниченное количество битов состояния (рис. 7.3) является, несомненно, одним из недостатков микроконтроллеров семейства 16. В устройствах се- мейства 18 добавлено 2 новых бита состояния. Это бит OV (разряд 3), который сигнали- зирует о переполнении 8-разрядного диапазона, и бит N, который указывает, что число, являющееся дополнением до 2, отрицательно. Поскольку знаковым разрядом в дополне- нии до 2 является самый старший разряд, то бит N — это просто самый старший разряд результата. Эти дополнительные биты позволяют осуществлять ветвление программы, а также увеличивают потенциал для решения математических задач. Вся остальная инфор- мация, приведенная на рисунке, объяснений не требует. 12.3. Набор команд семейства PIC 18 Полный набор команд устройств семейства 18 приведен в Приложении 5 — он вклю- чает 75 различных команд! Наборы команд семейств PIC 16 и 17 являются поднаборами
12.3. Набор команд семейства PIC 18 349 этого набора команд, поэтому любая программа, которая идет на любом из названных мик- роконтроллеров, будет идти на микроконтроллере семейства 18. При таком большом ко- личестве команд, набор команд начинает выглядеть как набор команд CISC (компьютер с полным набором команд — смотрите Главу 7), несколько теряя ту простоту, которая ожи- даема от набора команд RISC. Обратите внимание на то, что имеется также “расширенный” набор команд семейства 18, в котором к основному набору команд добавляется еще целый ряд команд. Этот набор команд описывается в Главе 13. U-0 U-0 U-0 R/W-x R/W-x R/W-x R/W-x R/W-x — — — N 0V Z DC С разряд 7 разряд О разряды 7-5 Не реализован: читается как 'О' разряд 4 N: бит отрицательного результата Данный бит используется в знаковой арифметике (использующей дополнение до 2). Он указывает, является ли результат отрицательным (старший разряд в АЛУ = 1) 1 = результат отрицателен О = результат положителен разряд 3 OV: бит переполнения Данный бит используется в знаковой арифметике (использующей дополнение до 2). Он указывает на переполнение 7-ми разрядного диапазона, приводящее к тому, что знаковый бит (разряд 7) изменяет свое состояние. 1 = при выполнении знаковой арифметической операции возникло переполнение О = переполнения не было разряд 2 Z: бит нулевого результата 1 = результат арифметической или логической операции является нулевым О = результат арифметической или логической операции не является нулевым разряд 1 DC: бит переноса/не-заимствования разряда Для команд ADDWF, ADDLW, SUBLW И SUBWF 1 = возник перенос из 4-го младшего разряда результата О = не было переноса из 4-го младшего разряда результата Примечание. Для не-заимствования полярность реверсируется. Вычитание выполняется посредством прибавления дополнения до 2-х второго операнда. Для инструкций циклического сдвига (rrf, rlf) данный бит загружается 4-м либо 3-м разрядом регистра-источника. разряд О С: бит переноса/не-заимсгвования Для команд ADDWF, ADDLW, sublw и subwf 1 = возник перенос из самого старшего разряда результата О = не было переноса из самого старшего разряда результата Примечание. Для не-заимствования полярность реверсируется. Вычитание выполняется посредством прибавления дополнения до 2-х второго операнда. Для инструкций циклического сдвига (RRF, rlf) данный бит загружается либо старшим, либо младшим битом регистра-источника. Рис. 12.3. Регистр состояния в PIC 18FXX2 При взгляде на табл. А5.1 возникает мысль о том, что знать все эти команды — устра- шающая перспектива. Однако есть и хорошая новость: это не нужно! После этой главы почти все программирование, которым мы будем заниматься, будет связано с языком С, по- этому пусть кто-либо другой беспокоится об Ассемблере. Однако обзор команд будет все же полезен — в конце концов, мы ведь иногда должны вставлять в программы на языке С фрагменты кода на Ассемблере. Для тех, кто переходит на семейства 18 от семейства 16, табл. 12.2 должна быть инте- ресной. В ней проводится краткое сравнение двух наборов команд. В первой колонке этой таблицы перечисляются все команды семейства 16, приблизительно в том порядке, в каком они рассматриваются в Приложении 1. Во второй колонке таблицы приводятся эк- виваленты из набора команд семейства 18, если они имеются, а также перечисляются все команды, которые являются полностью “новыми”. Для того чтобы начать исследование команд семейства 18, давайте посмотрим на пер- вые две колонки табл. А5.1. В них приводятся мнемонические обозначения команды на
350 Глава 12. Более сложные системы и PIC® 18FXX2 Ассемблере, соответственно, для семейств 16 и 18, а также перечисляются их операнды. Затем приводится описание того, что данная команда делает. Табл. 12.2. Сравнение наборов команд для семейств PIC 16 и PIC 18 Команды семейства 16 Эквиваленты семейства 18 Описание Байт-ориентированные операции с файловыми регистрами addwf f,d addwf f,d,a addwfc f,d,a Складывает W и f Складывает W и f с переносом andwf f,d andwf f,d,a Логически умножает W и f clrf f clrf f,a Очищает f clrw - Очищает W comf f,d comf f,d,a Дополнение f до 2 - cpfseq f,a cpfsgt f,a cpfslt f,a Сравнивает f с W, пропуск если равны Сравнивает f с W, пропуск если больше Сравнивает f с W, пропуск если меньше decf f,d decf f,d,a Декрементирование f decfsz f,d decfsz f,d,a decfsnz f,d, a Декрементирование f, пропуск если ноль Декрементирование f, пропуск если не ноль incf f,d incf f,d,a Инкрементирование f incfsz f,d incfsz f,d,a inefsnz f,d,a Инкрементирование f, пропуск если ноль Инкрементирование f, пропуск если не ноль iorwf f,d iorwf f,d,a Включающее ИЛИ f с W movf f,d movf f,d,a movff fs,fd Перемещение f Перемещение исходного файла fs в файл-приемник fd movwf f movwf f,a Перемещение W в f nop nop nop Отсутствие операции — пустая команда Второе слово двухсловной команды, которое кодируется для выполнения как пор, если она случайно будет интерпретирована как команда - mulwf f,a Умножение W и f - negf f,a Отрицание f rlf f,d rife f,d,a rlnfc f,d,a Циклический сдвиг влево с переносом Циклический сдвиг влево без переноса rrf f,d rref f,d,a rrnef f,d,a Циклический сдвиг вправо с переносом Циклический сдвиг вправо без переноса - setf Установка f subwf f,d subwf f,d,a subwfb f,d,a Вычитание W из f Вычитание W из f с заимствованием - subfwb f,d,a Вычитание f из W с заимствованием swapf f,d swapf f,d,a Обмен полубайтов f - tstfsz f,a Проверка f, пропуск если ноль xorwf f,d xorwf f,d,a Исключающее ИЛИ W с f
12.3. Набор команд семейст ва PIC 18 351 Табл. 12.2. Продолжение Команды семейства 16 Эквиваленты семейства 18 Описание Бит-ориентированные операции с файловыми регистрами bcf f,b bcf f,b,a Очистка бита b в регистре f bsf f,b bsf f,b,a Установка бита b в регистре f - btg f,d,a Переключение бита b в регистре f btfsc f,b btfsc f,b,a Проверка бита b в регистре f, пропуск если сброшен btfss f,b btfss f,b,a Проверка бита b в регистре f, пропуск если установлен Операции с литералами addlw k addlw k Прибавление литерала к W andlw k andlw k Логическое умножение литерала с W lorlw k iorlw k Включающее ИЛИ литерала с W movlw k movlw k Перемещение литерала в W - movlb перемещение литерала в BSR - Ifsr f,k Загрузка регистра выбора файла f 12-разрядным литералом к - mullw Умножение литерала на W sublw k sublw k Вычитание W из литерала xorlw k xorlw k Исключающее ИЛИ литерала с W Операции управления call k call n,s rcall n Вызов подпрограммы с (s = 1) либо без (s = 0) сохранения контекста в стеке Относительный вызов подпрограммы clrwdt clrwdt Сброс сторожевого таймера - daw Десятичная настройка W goto k goto n Переход по абсолютному адресу, где k/n представляет собой какой-либо адрес из пространства памяти программ - Pop Выталкивание вершины стека возврата (TOS) - push Вталкивание вершины стека возврата (TOS) - reset Программный сброс retfie retfie s Возврат из прерывания с (s = 1) либо без (s = 0) извлечения контекста из стека retlw k retlw k Возврат с литералом в W return return s Возврат из подпрограммы с (s = 1) либо без (s = 0) извлечения контекста из стека sleep sleep Переход в резервный режим be, bn, bnc, bnn, bnov, bnz, bov, bz Восемь команд условного перехода, по одной для каждого состояния битов N, OV, Z, С регистра состояния, во всех используется 8-разрядный относительный адрес п в форме дополнения до 2 - bra n Безусловный переход по 8-разрядному относительному адресу п в форме дополнения до 2
352 Глава 12. Более сложные системы и PIC® 18FXX2 Табл. 12.2. Окончание Команды семейства 16 Эквиваленты семейства 18 Описание Операции чтения/записи таблицы в памяти программ tblrd*, rblrd*+, tblrd*-, tblrd+* Четыре команды чтения таблицы со следующим порядком изменения указателя, соответственно: не изменяется, пост-инкрементирование, пост-декрементирование, пред-инкрементирование tblwt*, tblwt*+, tblwt*-, tblwt+* Четыре команды записи таблицы со следующим порядком изменения указателя, соответственно: не изменяется, пост-инкрементирование, пост-декрементирование, пред-инкрементирование Символы, используемые для обозначения операндов, например a, d или f, поясня- ются в табл. А5.2. В то время как некоторые из них вам уже знакомы по семейству 16. бит а операнда является новым, его наличие ведет к возможности использования команд с тремя операндами. Он определяет область памяти, называемую “оперативной памятью доступа”, которая будет описана позже в этой главе. Благодаря наличию этого бита, про- граммист теперь имеет выбор того, нужно ли использовать оперативную память доступа или нет. Третий столбец табл. А5.1 указывает, сколько командных циклов занимает выполне- ние команды. Как и можно ожидать от RISC-архитектуры и конвейерной структуры, все обычные команды выполняются за один цикл. Те же, которые вызывают ветвление прог- раммы, занимают два цикла. Команда пропуска занимает • один цикл, если пропуск отсутствует; • два цикла, если за ней следует однословная команда; • три цикла, если за ней следует двухсловная команда. Небольшое количество сложных команд также занимает более одного цикла. Следующий столбец (столбец 4) показывает фактическое кодирование команды. К счастью, этот код генерируется ассемблером или компилятором. Большинство команд занимает одно 16-разрядное слово — только четыре из них занимают два 16-разрядных слова. Это команды call, goto, movf f и If sr. Посмотрите на машинные коды этих команд. Обратите внимание, что в то время как второе слово любой из этих команд содер- жит полезную информацию, будучи взято само по себе, это слово является кодом ко- манды пор. Это достигается за счет того, что старшие 4 разряда слова формируют ма- шинный код команды пор, для которой младшие разряды являются “несущественными”. Такой подход позволяет организовать самовосстановление программы, если когда-либо микроконтроллер попытается интерпретировать это второе слово как отдельную команду. Последний столбец табл. А5.1 — Воздействие на регистр состояния — указывает, на какие биты регистра состояния (рис. 12.3) воздействует выполнение команды. С этой точки зрения интересно сравнить “идентичные” команды, которые присутствуют как в наборе команд семейства 16 {Приложение 7), так и в наборе команд семейства 18. На- пример, команда addwf в семействе 16 воздействует только на биты С, DC и Z. В семей- стве 18 эта команда воздействует на те же самые биты, а также на биты OV и N. В то время как команда осталась неизменной по своей функции, она стала более мощной, воздейст- вуя на большее количество битов регистра состояния. Приняв во внимание связь с командами семейства 16, а также просмотрев табл. 12.2. можно отметить, что команды семейства 18 можно разделить на категории, перечислен- ные ниже.
12.3. Набор команд семейства PIC 18 353 12.3.1 . Команды, которые не изменились Это команды, чьи функции и форма идентичны командам семейства 16. Много при- меров этого можно найти среди литеральных команд, например addlw к и andlw к. Единственное отличие команд семейства 18 в этом случае — это воздействие на большее число битов регистра состояния. 12.3.2 . Команды, которые были доработаны Эти команды являются почти идентичными своим предшественникам из семейства 16, но в них добавлены функциональные возможности и гибкость, частично благодаря изме- нениям в архитектуре. Наиболее впечатляющий пример — это возможность выбирать оперативную память доступа в качестве целевой области памяти, о чем уже говорилось выше. Можно заметить, что это изменение реализовано в большом количестве побайтовых арифметических и логических операций, например addwf f, d, а или andwf f, d, а. Другим интересным направлением развития команд является гибкость, добавленная в команды call, return и retf ie. Новый операнд s позволяет делать выбор — нужно ли сохранять контекст в стеке, с последующим его восстановлением, или нет. Чтобы гарантировать совместимость сверху вниз, все эти команды ассемблируются в корректный формат кодов семейства 18, даже если они заданы в формате семейства 16. 12.3.3 . Новые варианты команд В отношении некоторых команд семейства 16 чувствовалась их ограниченность, по- этому для эффективного их использования в некоторых ситуациях необходимо было при- менять их в непосредственной связи с другими командами. Набор команд семейства 18 до- бавляет варианты использования многих из этих команд с тем, чтобы ослабить имеющие- ся ограничения. Например, команда простого сложения addwf теперь доступна в вари- анте сложения с переносом — addwf с. Это упрощает выполнение огромного количества 16-разрядных операций сложения или операций сложения с большей разрядностью. Точ- но так же теперь доступна операция вычитания с заемом, операция циклического сдвига с переносом или без него, а также команда incf snz (инкрементирование f, пропуск, если результат не равен нулю). 12.3.4 . Новые команды И, наконец, имеется много команд, которые являются совершенно новыми. Во многих случаях они стали результатом либо использования более совершенных аппаратных средств, либо методов адресации памяти. Команда умножения, занимающая видное место среди арифметических команд, теперь доступна в виде mulwf (умножение W на f) и mullw (умножение W на литерал). Эти команды активируют аппаратный блок умноже- ния, который мы уже видели на рис. 12.2. Множитель и множимое трактуются как числа без знака, а результат помещается в регистры PRODH и PRODL. Стоит отметить, что ко- манды умножения не вызывают никаких изменений флагов состояний даже при том, что возможен нулевой результат. Другим важным добавлением к набору команд является целый блок команд чтения/ записи таблиц, команд передачи данных в/из стека, а также удачная подборка команд ус- ловных переходов, работа которых основана на увеличившемся числе флагов условий в регистре состояния. Имеются также команды, которые имеют отношение к командам ус- ловного перехода. В их составе имеется группа команд сравнения, например команда cpf seq, а также команды проверки состояния, например команда tstf sz. Еще одной новой и полезной командой перемещения данных является команда movf f — она обеспечивает возможность прямой передачи данных из одной ячейки памяти в
354 Глава 12. Более сложные системы и PIC® 18FXX2 другую. Следует отметить, что эта команда занимает два машинных слова и, следова- тельно, для ее выполнения требуются два командных цикла. В силу этого ее преимуще- ство, по сравнению с соответствующей командой из набора команд семейства 16, кото- рую она заменила, может оказаться незначительным. Однако она предохраняет значение регистра W от перезаписи. Некоторые из новых команд будут рассмотрены в примере программы и упражнениях, приведенных в подразделе 12.10. 12.4. Память данных и специальные функциональные регистры Табл. 12.1 показывает различные размеры памяти в устройствах семейства 18FXX2. В следующих подразделах, в которых мы будем рассматривать память, мы будем использо- вать микроконтроллер 18F242 как основной пример. Другие устройства семейства похожи на него, однако имеют большие возможности с точки зрения объема используемой памяти, реализованной тем либо иным способом. Те, кто переходит от использования устройств семейства PIC 16 к использованию устройств семейства PIC 18, должны быть готовы к освоению ряда новых подходов к структуре памяти. 12.4.1. Карта памяти данных Общая карта памяти данных для 18F242 показана на рис. 12.4. Каждая ячейка памяти занимает 1 байт, в то время как адрес является 12-разрядным, при потенциале адресации вплоть до 4096 ячеек памяти. Вся структура памяти формируется фактически из 16 банков, каждый из которых состоит из 256 байт. Специальный регистр — регистр выбора банка (РВБ), содержит биты, которые выбирают банк памяти. Они также показаны на рис. 12.4. Эти биты формируют самые старшие 4 разряда 12-разрядного адреса памяти. Еще рис. 12.4 показывает, что в 18F242 только три банка памяти, с минимальными номерами, реализо- ваны как набор “регистров общего назначения” (т.е. ОЗУ общего назначения). Это дает 768 (3 х 256) байт памяти данных, как указано в табл. 12.1. В то время как нижние три банка памяти данных используются как ОЗУ общего назна- чения, СФР содержатся в блоке, расположенном в самой верхней части памяти, в верхней половине старшего банка. Они показаны на рис. 12.5. Обратите внимание на то, что четыре столбца, показанные на этом рисунке, сами по себе не являются банками памяти. Факти- чески, взятые вместе, они только формируют часть самого старшего банка памяти, как это видно из рис. 12.4. 12.4.2. ОЗУ доступа Мы уже упоминали о термине “ОЗУ доступа”, когда рассматривали набор команд. Рис. 12.4 показывает две области памяти, которые так называются. Это самые нижние и самые верхние 128 байтов памяти. Нижние адреса памяти содержат ОЗУ общего назначе- ния, в то время как верхние содержат все СФР. Концепция “ОЗУ доступа” предоставляет способ быстрой адресации части ОЗУ. В то время как две половины ОЗУ доступа распо- ложены на противоположных концах карты памяти, при его использовании они трактуют- ся как непрерывный блок памяти. При этом биты регистра выбора банка игнорируются, а используется только 8-разрядный адрес с адресом СФР, которые расположены сразу же после области нижних адресов ОЗУ доступа. ОЗУ доступа доступно для всех команд, которые имеют операнд а, как это описано в Приложении 5 либо табл. 12.2. Если а установлен в 0, то доступно только ОЗУ доступа, работа с которым выполняется, как описывалось выше.
12.4. Память данных и специальные функциональные регистры 355 Когда а = 1, регистр выбора банка используется для специфицирования ячейки ОЗУ, используемой командой Когда а = 0, регистр выбора банка игнорируется и используется банк доступа. Первые 128 байт— зто ОЗУ общего назначения (из банка 0). Вторые 128 байт—это специальные функциональные регистры (из банка 15) Рис. 12.4. Карта памяти данных в PIC 18F242 12.4.3. Косвенная адресация и доступ к таблицам, расположенным в памяти данных Концепция косвенной адресации для устройств семейства 16 рассматривалась в Главе 5, подразделе 5.4.1. Там описывалось, как регистр выбора файла (РВФ) может использовать- ся для запоминания адреса. Если программа обращается к (несуществующему) регистру INDF, то тогда содержащийся в РВФ адрес используется как адрес для данной команды. Эта концепция продолжает применяться и в семействе PIC 18, однако она расширена с тем, чтобы соответствовать большему объему используемой памяти, а также наличию ряда РВФ и регистров INDF. Следует отметить, что теперь имеется три РВФ (FSR0:FSR2), которые также показаны на рис. 12.2. По причине намного большего объема памяти, каж- дый из них имеет по 12 битов. Следовательно, каждый из них формируется из двух ячеек памяти — они показаны на карте СФР, приведенной на рис. 12.5, как FSR2H:FSR2L, FSR1H-.FSR1L и FSROH-.FSROL.
356 Глава 12. Более сложные системы и PIC® 18FXX2 Адрес Имя Адрес Имя Адрес Имя Адрес Имя FFFh TOSU FDFh INDF2*3* FBFh CCPR1H F9Fh IPR1 FFEh TOSH FDEh POSTINC2*3* FBEh CCPR1L F9Eh PIR1 FFDh TOSL FDDh POSTDEC2*3* FBDh CCP1CON F9Dh PIE1 FFCh STKPTR FDCh PREINC2*3* FBCh CCPR2H F9Ch — FFBh PCLATU FDBh PLUSW2*3* FBBh CCPR2L F9Bh —— FFAh PCLATH FDAh FSR2H FBAh CCP2CON F9Ah — FF9h PCL FD9h FSR2L FB9h — F99h — FF8h TBLPTRU FD8h STATUS FB8h — F98h — FF7h TBLPTRH FD7h TMROH FB7h — F97h — FF6h TBLPTRL FD6h TMROL FB6h — F96h TRISE<2> FF5h TABLAT FD5h TOCON FB5h — F95h trisd<2> FF4h PRODH FD4h — FB4h —— F94h TRISC FF3h PRODL FD3h OSCCON FB3h TMR3H F93h TRISB FF2h INTCON FD2h LVDCON FB2h TMR3L F92h TRISA FF1h INTCON2 FD1h WDTCON FB1h T3CON F91h — FFOh INTCON3 FDOh RCON FBOh — F90h — FEFh INDFO*3* FCFh TMR1H FAFh SPBRG F8Fh — FEEh POSTINCO*3* FCEh TMR1L FAEh RCREG F8Eh — FEDh POSTDECO*3* FCDh T1CON FADh TXREG F8Dh LATE{2) FECh PREINCO*3* FCCh TMR2 FACh TXSTA F8Ch LATD<2i FEBh PLUSWO*3* FCBh PR2 FABh RCSTA F8Bh LATC FEAh FSROH FCAh T2CON FAAh — F8Ah LATB FE9h FSROL FC9h SSPBUF FA9h EEADR F89h LATA FE8h WREG FC8h SSPADD FA8h EEDATA F88h — FE7h INDF1*3* FC7h SSPSTAT FA7h EECON2 F87h — FE6h POSTINC1*3* FC6h SSPCON1 FA6h EECON1 F86h — FE5h POSTDEC 1*3* FC5h (SSPCON2 FA5h — F85h — FE4h PREINC1*3* FC4h ADRESH FA4h — F84h PORTE*2* FE3h PLUSW1*3* FC3h ADRESL FA3h — F83h PORTD*2* FE2h FSR1H FC2h ADCONO FA2h IPR2 F82h PORTC FE1h FSR1L FC1h ADCON1 FA1h PIR2 F81h PORTB FEOh BSR FCOh — FAOh PIE2 F80h PORTA Примечания. 1. Нереализованные регистры читаются как “О”. 2. Этот регистр недоступен в устройствах PIC18F2X2. 3. Это не физический регистр. Рис. 12.5. Специальные функциональные регистры (СФР) в PIC 18F242 Реальное положение еще больше усложняется в результате наличия пяти эквивален- тов регистра INDF. Они показаны в табл. 12.3. Их также можно найти на карте СФР, при- веденной на рис. 12.5. Теперь, если команда обращается по одному из адресов, указанных в табл. 12.3, то 12- разрядное число, содержащееся в соответствующем РВФ, используется в качестве косвен- ного адреса, организуя доступ к ячейке памяти данных, с которой данная команда будет работать. Во время выполнения команды значение РВФ модифицируется, как отмечено в таблице. 12.5. Память программ Как и в случае памяти данных, при рассмотрении памяти программ в качестве приме- ра мы будем использовать самое младшее устройство семейства 18FXX2 — PIC 18F242.
12.5. Память программ 357 Табл. 12.3. “Виртуальные” регистры, используемые при косвенной адресации Адресуемые “виртуальные” регистры, п = 0,1 или 2 Действия, происходящие после того, как команда обратится к РВФ INDFn Никаких изменений в РВФ POSTINCh После обращения РВФ автоматически инкрементируется POSTDECh После обращения РВФ автоматически декрементируется PREINCh До обращения РВФ автоматически инкрементируется PLUSWh Значение WREG добавляется к РВФи, формируя косвенный адрес. Ни РВФ, ни WREG не изменяются 12.5.1. Карта памяти программ Карта памяти программ показана на рис. 12.6. Можно видеть, что эта память занимает только небольшую часть общего объема памяти, которая может адресоваться 21-разряд- ной шиной. Каждая ячейка памяти имеет размер, равный 1 байту. Поскольку обычное ко- мандное слово содержит 16 разрядов, то каждая команда занимает 2 или 4 байта. Младший байт при этом сохраняется в ячейке памяти с четным адресом. Вектор сброса, по которому программа запускается, показан как ячейка памяти с адресом 0000, а два вектора преры- вания размещены по адресам 0008н и 0018Н- Подпрограммы обслуживания прерываний (ISRs) должны так писаться, чтобы они запускались по этим адресам. 12.5.2. Счетчик команд Счетчик команд, показанный наверху рис. 12.6, имеет размерность, равную 21 раз- ряду. С каждой командой, сохраненной как 2 или 4 байта, сч,етчик команд инкременти- руется, соответственно, два или четыре раза на каждую команду. Доступ к счетчику команд выполняется через специальные функциональные регист- ры карты памяти. Самый младший его байт называется PCL. Он может читаться и записы- ваться. Этот байт отображается как ячейка памяти FF9h на рис. 12.5. Средний байт счетчи- ка команд и старшие 5 разрядов не могут непосредственно считываться либо записываться. Модификация их содержимого может, однако, быть выполнена через регистры PCLATH и PCLATU, которые показаны как на рис. 12.2, так и на рис. 12.5. Содержимое этих регис- тров переносится в счетчик команд любой операцией, которая осуществляет запись в PCL. Аналогичным образом, любая операция, которая считывает PCL, инициализирует перенос соответствующих старших разрядов счетчика команд в регистры PCLATH и PCLATU. 12.5.3. Переход от устройств семейства 16 к устройствам семейства 18 и команда вычисляемого безусловного перехода goto В семействе 16 мы использовали вычисляемый безусловный переход goto как сред- ство извлечения данных из поисковой таблицы (смотрите, например, рис. 5.5 или пример программы 5.4). При этом к счетчику команд добавлялось смещение, чтобы инициализи- ровать переход на одну из списка команд retlw. Эта команда затем вызывала возврат в основную программу при выбранном байте данных, сохраненном в регистре W. Такой порядок действий все еще возможен в семействе 18, но при этом важно не забыть, что каждая команда теперь занимает 2 байта памяти программ. Следовательно, любое смеще- ние, добавляемое к счетчику команд в программе для семейства PIC 16, должно быть удво- ено — с тем, чтобы обеспечить тот же эффект в программе для семейства PIC 18.
358 Глава 12. Более сложные системы и PIC® 18FXX2 | РС<20:0> CALL,RCALL,RETO RETFIE,RETLW Уровень стека 1 Уровень стека 31 Вектор сброса Вектор прерывания с высоким приоритетом Вектор прорывания с низким приоритетом OOOOh 0008h 0018h Встроенная память программ 3FFFh 4000h Читается как "О" IFFFFFh 200000h' Рис. 12.6. Карта памяти программ в PIC 18F242 и стек адресов возврата 12.5.4. Регистры конфигурации В то время как микроконтроллеры семейства 16 имеют одно 14-разрядное слово кон- фигурации, микроконтроллеры семейства 18 имеют целый набор регистров конфигурации, отражая большую сложность и гибкость устройств. Эти регистры показаны в табл. 12.4, а сводка функций каждого разряда регистра — в табл. 12.5. Легко видеть, что обычные функ- ции — настройка генератора и сторожевого таймера, синхронизация подачи напряжения питания, сброс по частичной потере напряжения питания и кодовая защита — все выпол- няется этими битами. Большинство этих функций имеют расширенный диапазон предла- гаемых ими опций. Так, например, сейчас имеется восемь вариантов настройки тактового генератора, альтернативный режим работы сторожевого таймера и большее число настроек сброса по частичной потере напряжения питания. В результате этого и необходимо исполь- зовать большее число битов. Регистры конфигурации отображаются на память программ, начиная от ячейки памяти с адресом ЗОООООн- Как и ячейки памяти программ, они имеют 8 разрядов. Два регистра идентификации устройств — DEVID1 и DEVID2 — предназначены только для чтения. Они содержать предварительно запрограммированную информацию, идентифицирующую устройство и номер его исполнения.
12.5. Память программ 359 Табл. 12.4. Слово конфигурации семейства PIC 18: регистры конфигурации 18FXX2 и идентификация устройств (таблица предоставлена фирмой Microchip) Имя файла Разряд 7 Разряд 6 Разряд 5 Разряд 4 Разряд 3 Разряд ' 2 Разряд 1 Разряд о Используемое по умол- чанию / ««запрограм- мированное значение ЗОООО1Н CONFIG 1H - - OSCSEN - - FOSC2 FOSC1 FOSCO — 1- -111 300002И CONFIG2L - - - - BORV1 BORVO BOREN PWRTEN 1111 300003b CONFIG2H - - - - WDTPS2 WDTPS1 WDTPS0 WDTEN '1111 300005b CONFIG3H - - - - - - - CCP2MX 1 3000061т CONFIG4L DEBUG - - - - LVP - STVREN 1 -1-1 30000811 CONFIG5L - - - - CP3 CP2 CPI CP0 1111 300009h CONFIG5H CPD СРВ - - - - - - 1 i — 30000Ah CONFIG6L - - - - WRT3 WRT2 WRT1 WRT0 1111 ЗООООВЬ CONFIG6H WRTD WRTB WRTC - - - - - 1 1 1 - ЗООООСЪ CONFIG7L - - - - EBTR3 EBTR2 EBTR1 EBTR0 1111 30000Dh CONF1G7H - - - - - - - - -1-- 3FFFFEh DE VID 1 DEV2 DEVI DEV0 REV4 REV3 REV2 REV1 REVO (1) 3FFFFFh DEVID2 DEV 10 DEV9 DEV8 DEV7 DEV6 DEV5 DEV4 DEV3 0000 0100 Табл. 12.5. Слово конфигурации семейства PIC 18: сводка данных о битах конфигурации и идентификации устройств для 18FXX2 Биты конфигурации Описание функции (^запрограммированное значение соответствует 1, активное (разрешающее) значение обычно соответствует 0) OSCSEN Бит разрешения переключения источника синхроимпульсов FOSC2:FOSCO Выбор одного из восьми режимов тактового генератора (см. табл. 12.6) BORV1, BORVO Выбор напряжения сброса по частичной потере питания — по напряжению 2,5 В, 2,7 В, 4,2 В или 4,5 В BOREN Бит разрешения сброса по частичной потере питания PWRTEN Бит активирования таймера подачи питания WDTPS2:WDTPS0 Биты пост-деления частоты сторожевого таймера, выбор одного из восьми значений — от 1: 1 до 1: 128 WDTEN Бит активирования сторожевого таймера CCP2MX Мультиплексор ССР2, выбор RC1 (1) или RB3 (0) DEBUG Бит разрешения фоновой отладки LVP Бит разрешения низковольтного программирования STVREN Бит разрешения сброса по заполнению стека/потере значимости CP3:CP0 Биты кодовой защиты CPD Бит кодовой защиты данных ЭСППЗУ СРВ Бит кодовой защиты загрузочного блока WRT3:WRT0 Бит защиты от записи в память программ WRTD Бит защиты от перезаписи данных в ЭСППЗУ WRTB Бит защиты от перезаписи загрузочного блока WRTC Бит защиты от записи в регистр конфигурации EBTR3:EBTR0 Бит защиты от чтения таблицы EBTRB Бит защиты от чтения таблицы загрузочного блока DEV2:DEV0 Биты идентификации устройств: 000 = 18F252, 001 = 18F452, 100 = 18F242, 101 = 18F442 REV4:REV0 Биты идентификации версии DEV10:DEV3 Дополнительные биты идентификации устройств
360 Глава 12. Более сложные системы и PIC® 18FXX2 12.6. Стеки Стек в современных микропроцессорах — это разносторонний блок памяти, который может использоваться как автоматически — например, для сохранения адреса возврата при вызове подпрограммы, так и программистом — для кратковременного хранения данных. Конечно же, во многих случаях имеется несколько стеков. Стек семейства 16, который мы рассматривали раньше, был небольшой прямолинейно работающей структурой. При нали- чии только восьми уровней, он был непосредственно связан со счетчиком команд и просто сохранял, а затем возвращал свое значение (или при вызове некоторых подпрограмм, или в условиях прерываний). Стек семейства 18 — это результат определенного продвижения вперед с целью дос- тижения соответствия функциям, реализованным в больших микропроцессорах. Автома- тические функции стека остаются — например, для вызова подпрограмм, однако теперь обеспечен определенный уровень пользовательского доступа. Имеется также ограничен- ная возможность организации стеков в других областях памяти, например в области основ- ных информационных регистров. 12.6.1. Автоматическая работа стека Основной стек в устройствах семейства 18 называется “стеком адреса возврата”. Это отличает его от меньших областей памяти, работающих как стеки, которые также сущест- вуют. Этот стек виден на рис. 12.6. Он состоит из 31 ячейки памяти, которые допускают как считывание, так и запись. Каждая из этих ячеек памяти состоит из 21 разряда. На этом ри- сунке приведены также мнемонические обозначения на Ассемблере для тех команд, кото- рые автоматически выполняют доступ к стеку. Все эти команды имеют отношение либо к вызову подпрограмм, либо к их возврату, за исключением команды retf ie, которая вы- полняет возврат из прерывания. 12.6.2. Программный доступ к стеку Текущий адрес в стеке запоминается в указателе стека, который не показан на рис. 12.6. Он устанавливается в ноль при всех операциях сброса, а его значение изменяется при каж- дой операции автоматического доступа. Таким образом, он инкрементируется, когда какое- либо значение заносится в стек и декрементируется, когда значение выталкивается из стека. Он также конфигурируется как часть СФР, называемая STKPTR. Как и в случае всех СФР, STKPTR допускает считывание и запись пользователем. STKPTR на рис. 12.5 показана как ячейка памяти с адресом FFCH. 5 младших разрядов STKPTR формируют указатель стека. Этот регистр также содержит биты флагов, отражающих либо факт переполнения, либо потери значимости стека — соответственно, бит STKOVF (который также называется STKFUL, разряд 7) и бит STKUNF (разряд 6). Программист имеет доступ к значению, содержащемуся на вершине стека, — он может считывать его и выполнять запись. Будучи 21-разрядным, стек занимает три регистровые ячейки памяти — TOSU, TOSH и TOSL. Они также видны над STKPTR на карте регист- ров, приведенной на рис. 12.5. Команды push и pop позволяют программисту заносить те- кущее значение счетчика команд в стек или считывать вершину стека и заносить соответ- ствующее значение в счетчик команд. 12.6.3. Быстрый регистровый стек Архитектура семейства 18 предоставляет не только стек для счетчика команд, она также обеспечивает (в примитивной форме) отдельные “стеки” для регистров STATUS, WREG и BSR. Это отдельные ячейки памяти, к которым программист не имеет прямого доступа — все вместе они называются быстрым регистровым стеком. Когда происходит прерывание,
12.7. Прерывания 361 — как высокого, так и низкого приоритета — значения перечисленных трех регистров со- храняются. Эти занесенные в стек значения возвращаются, если отрабатывается “быстрый” возврат из прерывания. Другими словами, команда ret fie должна использоваться с опе- рандом s, установленным в 1. В подразделе 12.7.7 мы вернемся к этой теме. Быстрый стековый регистр также может быть использован с вызовом подпрограммы и возвратом из нее. Как видно из Приложения 5, как команда call, так и команда return могут использоваться с битом s, установленным в 1, что инициализирует использование быстрого регистрового стека. Конечно же, это можно безопасно делать только тогда, когда прерывания не используются. В противном случае прерывание, возникшее во время выпол- нения подпрограммы, приведет к тому, что быстрый регистровый стек будет перезаписан. 12.7. Прерывания Микроконтроллеры 18FXX2 реализуют усложненную структуру прерываний, которая имеет ярко выраженные преимущества, по сравнению с семейства 16. Улучшения вклю- чают введение второго вектора прерывания, при этом различается вектор прерывания вы- сокого приоритета и вектор прерывания низкого приоритета. Эти вектора также показаны на карте памяти программ, приведенной на рис. 12.6. Все прерывания, кроме одного, мо- гут быть поставлены в соответствие вектору высокого либо низкого приоритета. Имеется большее количество внешних прерываний, а также обеспечивается автоматическое сохра- нение контекста при использовании стека “быстрого возврата” (см. подраздел 12.5). 12.7.1. Обзор структуры прерываний Структура прерываний показана на рис. 12.7. Она достаточно сложна, однако ее хоро- шее понимание приведет к более эффективному использованию прерываний микрокон- троллера. Источники прерываний показаны в левой части рисунка. Три основных выхода показаны справа. Два из них идут на вектора прерываний. Активирование любого из этих выходов инициализирует прерывание ЦП, при этом подпрограмма обслуживания преры- ваний запускается по одному из векторов прерываний, которые показаны на рис. 12.6. Тре- тий выход — “Активирование” — используется тогда, когда микроконтроллер находится в режиме бездействия. При анализе упомянутой схемы мы сможем отметить наличие на ней следующих ком- понент: • источники прерываний (примите, однако, к сведению, что показаны не все); • логические схемы стробирования источников прерываний; • логические схемы приоритета источников прерываний; • логические схемы общего разрешения приоритета; • логические схемы общего (глобального) активирования. 12.7.2. Источники прерываний, их разрешение и установка приоритетов Давайте начнем наше рассмотрение с идентификации некоторых из источников пре- рываний. Сначала полезно проанализировать блок, помеченный как “Внешние источники прерываний и таймер 0”. Этот блок содержит пять схем И. При этом все они, кроме одной, имеют три входа. Посмотрите на верхний элемент И — его входы помечены как TMR0IF, TMR0IE и TMR0IP. Это входы таймера 0, они отображают структуру, которая много- жратно повторяется. Вход .. .IF — это бит флага прерывания, он устанавливается, если про- изошло прерывание от таймера 0; вход ...IE — это бит разрешения, входящий в СФР, — он может быть установлен программно либо сброшен. Вход ...IP — это бит приоритета,
362 Глава 12. Более сложные системы и PIC® 18FXX2 он также входит в СФР и может быть установлен либо сброшен программно. Если все эти входы находятся в состоянии логической единицы, т.е. если прерывание разрешено, вы- брано как имеющее высокий приоритет и установлен флаг прерывания, то выход схемы И переходит в состоянии логической единицы — при этом прерывание передается на сле- дующий уровень логических схем. Обратите внимание, что выходы всех схем И этого бло- ка подаются на схему ИЛИ. Внеййа»источнио1 прврывангёитаймерО TMR1IF TMR1IE TMR1IP INT1IF INT1IE INT1IP INT2IF INT2IE INT2IP TMR0IF TMROIE TMROIP RBIF RBIE RBIP INTOIF INTOIE Сигнал активирования в режиме бездействия GIEH/GIE Активирование высокоприоритетного вектора Прерывания ЦП, вектор прерывания по адресу OOSh I Генерирование низкоприоритетного + прерывания Нулевой бит внешнего прерывания. Приоритеты не используются | Генерирование высокоприоритетного I прерывания XXXXIF XXXXIE XXXXIP О Обобщенная схема проходам низмзприоритетньгх прерываний IPEN GIEL/PEIE Внешние источники прерывания Sw флага пясыиикя и ирифеаийногаустеЛгаа Емр(1реаи1Ш1ферыи1ШИ1>Фф^ Багг фкхиша прерышна и периферийного усгройспа TMR1IF TMR1IE TMR1IP XXXXIF XXXXIE XXXXIP Оа Внешние источники прерывания О TMROIF TMROIE TMROIP INT2IF INT2IE INT2IP RBIF RBIE RBIP INT1IF INT1IE INT1IP Внешние источники прерываний, младшие биты НТО и таймер О Логические схемы управления прерываниями GIEUPEIE GIE/GIEH Прерывания ЦП, вектор прерывания по адресу 01Ш1 Активирование нюколриорювппго вектора Обозначения GIEH - глобальное разрешение прерывания высокого приоритета IREN - бит разрешения использования приоритетов прерываний GIEL - глобальное разрешение прерывания низкого приоритета Рис. 12.7. Логические схемы обработки прерываний PIC 18F242 (дополнительные надписи в затемненных прямоугольниках добавлены автором) Только что описанная схема повторяется и в других блоках, идущих до самого низа рис. 12.7. Стоит обратить внимание на третий вход схемы И таймера 0 в нижней половине схемы. Теперь используется отрицание сигнала TMROIP (т.е. TMROIP). Можно видеть, что каждый источник прерываний (за исключением одного, который мы рассмотрим далее) появляется один раз в верхней половине схемы и один раз — в нижней. В верхней полови- не он разрешается, если его бит приоритета находится в состоянии логической 1; в нижней же половине он разрешается, если его бит приоритета находится в состоянии логического 0. Опять-таки, выходы всех схем И в этом блоке подаются на схему ИЛИ. Единственным источником прерывания, которому не присваивается приоритет, являет- ся внешнее прерывание 0. Оно всегда имеет высокий приоритет, что отмечено на рассмат- риваемой схеме. Прерывания от периферийных источников, показанные в левой части схемы, подчи- няются схеме, подобной схеме прохождения внешних прерываний. Опять-таки, для них может устанавливаться высокий либо низкий приоритет. Показаны они не все, поскольку их много. Обобщенная схема для высоко-приоритетных источников прерываний показана
12.7. Прерывания 363 в направлении верхнего левого края схемы — она повторяется для низкоприоритетных ис- точников поблизости от левого нижнего края схемы. Как и ранее, логические схемы обеспе- чивают возможность установки высокого либо низкого приоритета для любого источника прерываний. В качестве примера использован вход таймера 1. Опять-таки, выходы всех схем И в каждом блоке подаются на схему ИЛИ. 12.7.3. Общее разрешение установки приоритетов прерываний В то время как мы уже видели, что является возможной установка приоритета инди- видуальных источников прерываний, мы, однако, можем не всегда хотеть использовать эту возможность. При этом является возможным в целом разрешить или запретить весь процесс использования приоритетов. Это выполняется битом IPEN — битом разрешения приори- тетов прерываний. IPEN — это самый старший бит регистра RCON, который показан на рис. 12.14. Посмотрите теперь на блок, расположенный поблизости от центра схемы, показанной на рис 12.7, — он помечен как “логические схемы управления приоритетом”. В этом бло- ке линия IPEN появляется три раза (один раз она помечена некорректно как IPE). Если эта линия находится в состоянии логического нуля, то тогда прерывания из нижней части схемы, идущие либо от периферийных источников, либо от внешних источников, переда- ются в верхнюю часть схемы через две схемы И, присутствующие в данном блоке. В этом случае все прерывания идут через высокоприоритетный вектор и, фактически, приори- теты не используются. В этом состоянии имеется еще один момент, к рассмотрению кото- рого мы скоро перейдем. Когда IPEN находится в состоянии логического 0, как уже было описано, система прерываний становится сравнимой с системой прерываний семейства 16. Если IPEN находится в состоянии логической 1, то высокоприоритетные и низкопри- оритетные прерывания разделяются и идут на свои собственные вектора прерываний. При этом разрешено использование прерываний — т.е. отдельные источники прерываний мо- гут настраиваться либо на низкий, либо на высокий приоритеты, с использованием их ин- дивидуальных битов управления приоритетом. 12.7.4. Глобальное разрешение Имеется два уровня глобального разрешения прерываний — они управляются битами GIE/GIEH и PEIE/GIEL. До некоторой степени эти биты имеют двойственную функцию, характер которой определяется состоянием бита IPEN — отсюда и двойственная природа их названий. Можно видеть, что GIE/GIEH управляет обеими логическими элементами И, идущи- ми на вектора прерываний. Таким образом, этот бит выполняет свою функцию “глобаль- ного разрешения прерываний”. Если GIE/GIEH находится в состоянии логического 0, то никаких прерываний не будег, вне зависимости от состояния IPEN. Когда IPEN находится в состоянии логического нуля, все прерывания направляются на высокоприоритетный вектор прерывания, поэтому в этом случае он работает как “глобальное разрешение”. Ко- гда IPEN находится в состоянии логической единицы, он имеет возможность отключить как высокоприоритетные, так и низкоприоритетные прерывания. Однако он не может са- мостоятельно разрешить низкоприоритетные прерывания, поскольку в этом также должен участвовать бит PEIE/GIEL. Следовательно, он работает как разрешение только для высо- коприоритетных прерываний. Когда IPEN находится в состоянии логического нуля, PEIE/GIEL работает как линия разрешения всех немаскированных прерываний от периферийных устройств. Он выполняет эту функцию через логический элемент ИЛИ, который изображен на схеме в центре блока “Логические схемы управления приоритетом”. Когда IPEN находится в состоянии логи- ческой единицы, он работает как “глобальное разрешение” низкоприоритетных входных
364 Глава 12. Более сложные системы и PIC® 18FXX2 сигналов благодаря его соединению с выходным логическим элементом И низкоприори- тетного вектора. 12.7.5. Другие аспекты логики прерываний Два последних элемента этой схемы составляют линию, идущую от выхода высоко- приоритетного прерывания вниз по схеме — на логические схемы управления низкопри- оритетными прерываниями. Мы можем видеть, что ее действие заключается в том, что при возникновении высокоприоритетного прерывания низкоприоритетное прерывание блоки- руется. Обратное не является истиной — высокоприоритетное прерывание может преры- вать обработку низкоприоритетного прерывания. Имеются также линии, идущие от любой магистрали прерываний вверх по схеме на логический элемент ИЛИ, выход которого вы- водит микроконтроллер из режима бездействия. Действие этих линий не зависит от состо- яния двух линий “глобального разрешения”. 12.7.6. Регистры прерываний При огромном количестве битов, показанных на рис. 12.7, совершенно очевидно, что потребуется большое количество регистров, которые могли бы содержать их все. Каждый источник прерывания требует теперь бит флага, бит разрешения и бит приоритета, все биты управления также необходимы. Помимо этого также имеется дополнительный контроль над некоторыми входами — например для установки активного фронта внешнего прерывания. При создании регистров прерываний использовался проектный подход, целью которого было сохранить максимально возможное количество регистров, которые использовались в семейства PIC 16. Это позволяет разработчикам систем сравнительно просто перейти от семейства 16 к семейству 18. Таким образом, регистр INTCON в 16F87XA, показанный на рис. 7.11, почти точно воспроизводиться регистром INTCON семейства 18, показанным на рис. 12.8. Вместе с тем имеются некоторые незначительные переименования битов, а функ- циональные возможности GIE и PEIE, как только что обсуждалось, был расширены. К регистру INTCON добавлены два регистра управления прерываниями — INTCON2 и INTCON3. Они показаны, соответственно, на рис. 12.9 и 12.10. Эти регистры содержат биты уп- равления прерываниями, отраженными в регистре INTCON. Назначение битов может быть легко понято по их названиям. Исключением является только бит RBPU, который вообще не является битом прерывания, — он управляет нагрузкой порта В. В семействе 16 он на- ходился в регистре опций, который в семействе 18 отсутствует. Биты разрешений, биты флагов (или “запросов”) и биты приоритетов для источников прерываний ввода-вывода помещены в регистры PIE1, PIE2, PIR1, PIR2, IPR1 и IPR2. Эти регистры изображены на рис. 12.11 и 12.12. Опять-таки, чтобы обеспечить совмести- мость по принципу “снизу-вверх”, они сделаны очень похожими на регистры семейства 16 с тем же наименованием, исключая, конечно, регистры приоритетов. Интересно сравнить их с регистрами семейства 16, вернувшись к рис. 7.12 и 7.13. Сделав это, вы сможете уви- деть, какие прерывания были добавлены (таймер 3 и обнаружение падения напряжения) и какие были удалены (от компаратора). Дальнейшие подробности в отношении функцио- нирования некоторых отдельных прерываний от периферийных устройств приведены в подразделах, посвященным этим устройствам — главным образом в Главе 13. 12.7.7. Сохранение контекста при использовании прерываний При использовании быстрого стекового регистра, описанного в подразделе 12.6.3 этой главы, сохранение контекста в некоторых обстоятельствах может быть восхитительно простым делом. При этом программист должен сначала решить, будут ли три регистра, со- храняемые в этом стеке, — WREG, STATUS и BSR, адекватными для этих целей. Если
12.8. Электропитание и приведение в исходное состояние 365 это не так, или если быстрый возврат из прерывания не используется, то программисту по- надобиться написать программный код, чтобы сохранить все необходимые регистры в на- чале выполнения подпрограммы обслуживания прерывания и восстановить их в конце вы- полнения этой подпрограммы. Важно также не забыть о том, что высокоприоритетное пре- рывание может прерывать обработку прерывания более низкого приоритета. В этом случае прерывание высокого приоритета перезаписывает содержимое быстрого стекового регист- ра, и низкоприоритетное прерывание теряет свой контекст! В таких случаях использование быстрого стекового регистра при обработке низкоприоритетных прерываний не является безопасным. Контекст для этих прерываний должен сохраняться программно. R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-x GIE/GIEH PEIE/GIEL TMROIE INTOIE RBIE TMROIF INTOIF RBIF разряд 7 разряд О разряд 7 GIE/GIEH: 6ni разрешения глобального прерывания Когда IPEN = 0: 1 = разрешает все немаскированные прерывания 0 = запрещает все прерывания Когда IPEN = 1: 1 = разрешает все высокоприоритетные прерывания 0 = запрещает все прерывания разряд 6 PEIE/GIEL: бит разрешения прерываний от периферийных устройств Когда IPEN = 0: 1 - разрешает все немаскированные прерывания от периферийных устройств 0 = запрещает все прерывания от периферийных устройств Когда IPEN = 1: 1 = разрешает все низкоприоритетные прерывания от периферийных устройств 0 = запрещает все низкоприоритетные прерывания от периферийных устройств разряд 5 TMR0IE: бит разрешения прерывания по переполнению TMR0 1 = разрешает прерывание по переполнению TMR0 0 = запрещает прерывание по переполнению TMR0 разряд 4 INT0IE: бит разрешения внешнего прерывания INTO 1 = разрешает внешнее прерывание INTO 0 = запрещает внешнее прерывание INTO разряд 3 RBIE: бит разрешения прерывания по изменению состояния порта RB 1 = разрешает прерывание по изменению состояния порта RB 0 = запрещает прерывание по изменению состояния порта RB разряд 2 TMR0IF: бит флага прерывания по переполнению TMR0 1 = регистр TMR0 переполнился (должен сбрасываться программно) 0 = TMR0 не переполнялся разряд 1 INT0IF: бит флага внешнего прерывания INTO 1 = произошло внешнее прерывание INTO (должен сбрасываться программно) 0 = внешнее прерывание INTO не происходило разряд 0 RBIF: бит флага прерывания по изменению состояния порта RB 1 = изменилось состояние, по крайней мере, одного из штырьков RB7:RB4 (должен сбрасываться программно) 0 = состояние ни одного из штырьков RB7:RB4 не изменилось Примечание. Состояние несоответствия приводит к установке этого бита. Считывание PORTB приводит к устранению состояния несоответствия и позволяет выполнить сброс данного бита Рис. 12.8. Регистр INTCON в PIC 18FXX2 12.8. Электропитание и приведение в исходное состояние 12.8.1. Электропитание Требования по электропитанию устройств 18LFXX2 и 18FXX2 приведены на рис. 12.13. На этом рисунке показано, что устройства 18LFXX2 могут работать при напряжениях пи- тания, лежащих в диапазоне от 2,0 до 5,5 В, a 18FXX2 — от 4,2 до 5,5 В. Низковольтные устройства, однако, не могут при пониженном напряжении работать на полной скорости.
366 Глава 12. Более сложные системы и PIC® 18FXX2 Технические данные, приведенные в документации, показывают, что максимальная такто- вая частота, с которой могут работать эти устройства при минимальном напряжении пита- ния, равна 4 МГц. При напряжении питания, равном 4,2 В, эта частота возрастает до 40 МГц. R/W-1 R/W-1 R/W-1 R/W-1 U-0 R/W-1 U-0 R/W-1 RBPU INTEDG0 INTEDG1 INTEDG2 — TMR0IP — RBIP разряд 7 разряд 0 разряд 7 RBPU: бит актирования нагрузки PORTB 1 = все нагрузочные сопротивления PORTB заблокированы О = все нагрузочные сопротивления PORTB активированы индивидуальными схемами разрешения разряд 6 INTEDG0: бит выбора фронта сигнала внешнего прерывания 0 1 = прерывание по нарастающему фронту О = прерывание по срезу разряд 5 INTEDG1: бит выбора фронта сигнала внешнего прерывания 1 1 = прерывание по нарастающему фронту О = прерывание по срезу разряд 4 INTEDG2: бит выбора фронта сигнала внешнего прерывания 2 1 = прерывание по нарастающему фронту О = прерывание по срезу разряд 3 Не реализован: читается как "0” разряд 2 TMR0IP: бит приоритета прерывания по переполнению TMRO 1 = высокий приоритет 0 - низкий приоритет разряд 1 Не реализован: читается как "О” разряд О RBIP: бит приоритета прерывания по изменению состояния порта RB 1 = высокий приоритет О = низкий приоритет Рис. 12.9. Регистр INTCON2 в PIC 18FXX2 R/W-1 R/W-1 U-0 R/W-0 R/W-0 U-0 R/W-0 R/W-0 INT2IP INT1IP — INT2IE INT1IE — INT2IF INT1IF разряд 7 разряд 0 разряд 7 INT2IP: бит приоритета внешнего прерывания INT2 1 = высокий приоритет 0 = низкий приоритет разряд 6 INT1IP: бит приоритета внешнего прерывания INT1 1 = высокий приоритет 0 = низкий приоритет разряд 5 Не реализован: читается как 'О' разряд 4 INT2IE: бит разрешения внешнего прерывания INT2 1 = разрешение внешнего прерывания INT2 0 = запрет внешнего прерывания INT2 разряд 3 INT1IE: бит разрешения внешнего прерывания INT1 1 = разрешение внешнего прерывания INT1 О = запрет внешнего прерывания INT1 разряд 2 Не реализован: читается как 'О' разряд 1 INT2IF: бит флага внешнего прерывания INT2 1 = возникло внешнее прерывание INT2 (должен сбрасываться программно) 0 = внешнее прерывание INT2 не возникало разряд 0 INT1IF: бит флага внешнего прерывания INT1 1 = возникло внешнее прерывание INT1 (должен сбрасываться программно) О = внешнее прерывание INT1 не возникало Рис. 12.10. Регистр INTCON3 в PIC 18FXX2
12.8. Электропитание и приведение в исходное состояние 367 12.8.2. Подача электропитания и сброс В подразделе 2.8 Главы 2 мы анализировали цепь прохождения сигнала сброса для про- стого микроконтроллера PIC 16F84A. Микроконтроллеры 18FXX2 имеют структуру про- хождения сигнала сброса, которая непосредственно сформирована на базе модели, пока- занной на рис. 2.11, при нескольких дополнительных источниках сигнала сброса. В их со- став входят: сигнал сброса по переполнению либо потере значимости стека, сигнал сброса по частичной потере питания (уже присутствующий в 16F873A) и программный сброс. разряд? разряд О PIE1 PIR1 IPR1 (биты разрешения) (биты флагов) (биты приоритета) Переполнение таймера 1 TMR1IE TMR1IF* TMR1IP Соответствие между таймером 2 и PR2 TMR2IE TMR2IF* TMR2IP Сравнение собранных данных 1 CCP1IE CCP1IF* CCP1IP Синхронный последовательный порт SSPIE SSPIF* SSPIP Передача USART TXIE TXIF TXIP Прием USART RCIE RCIF RCIP Аналого-цифровой преобразователь ADIE ADIF* ADIP Считывание/запись параллельного порта, PSPIE PSPIF* PSPIP работающего в режиме подчиненного устройства * Должен сбрасываться программно ** Только для 18F4X2. В18F2X2 все разряды зарезервированы Рис. 12.11. Регистры PIE1/PIR1/IPR1 в 18FXX2 (Разрешение прерывания от периферийных устройств / Запрос прерывания от периферийных устройств / Приоритет прерывания от периферийных устройств) разряд? разряд О PIE2 (биты разрешения) PIR2 (биты флагов) IPR2 (биты приоритета) Сравнение собранных данных 2 CCP2IE Переполнение таймера 3 TMR3IE Обнаружение падения LVDIE напряжения питания u u Коллизия шины BCLIE Запись ЭСППЗУ/флеш-память EEIE Не реализован читается как 0 Не реализован читается как 0 CCP2IF CCP2IP TMR3IF TMR3IP LVDIF LVDIP BCLIF BCLIP EEIF EEIP читается как 0 читается как 0 читается как 0 читается как 0 читается как 0 читается как 0 (должны сбрасываться программно гш pvcuirwutJdM MHiduiun как и Все биты флагов Рис. 12.12. Регистры PIE2/PIR2/IPR2 в 18FXX2 (Разрешение прерывания от периферийных устройств / Запрос прерывания от периферийных устройств / Приоритет прерывания от периферийных устройств) Помимо добавления дополнительных источников сброса, семейство 18 некоторым ин- тересным способом идет дальше, обеспечивая регистрацию истории того, какой конкретно источник вызвал сброс. Следовательно, выход из условий сброса — это не полностью но- вое начало, как в случае простых микроконтроллеров. Теперь мы можем выяснить, почему имел место принудительный сброс. В некоторых обстоятельствах это знание может оказать- ся очень ценным, например, в случае срабатывания сторожевого таймера. Эта информация предоставляется через регистр RCON, биты которого указывают, какой тип сброса прои- зошел последним. Мы уже говорили о регистре RCON, поскольку его самый старший бит — это бит прерывания IPEN.
368 Глава 12. Более сложные системы и PIC® 18FXX2 PIC18LFXX2 (промышленное исполнение) Стандартные рабочие условия (если не указано иное) Рабочая температура -40 С < ТА £ +85 С для промышленных исполнений PIC18FXX2 (промышленное исполнение и исполнение повышенной стойкости) Стандартные рабочие условия (если не указано иное) Рабочая температура -40 С < ТА < +85 С для промышленных исполнений -40 С < Та£ +125 С для исполнений повышенной стойкости пара- метр № обозна- чение характеристика МИН. типич. макс. ед. измер. условия D001 Vdd Напряжение питания PIC18LFXX 2,0 — 5,5 в режимы тактового генератора HS, XT, RC и LP D001 P1C18FXX 4,2 5,5 в D002 Vdr Напряжение сохранения данных в ОЗУ<1> 1,5 — — в D003 Vror Стартовое напря- жение VDD, гаранти- рующее сигнал сброса по включе- нию питания 0,7 в см. детали в разделе 3.1 (сброс по включению питания) D004 SvDD Скорость роста VDo, гарантирующая внут- ренний сигнал сброса по включению питания 0,05 — — В/мс см. детали в разделе 3.1 (сброс по включению питания) D005 Vror Напряжение сброса по частичной потере питания PIC18LFXX2 BORV1 :BORVO = 11 1,98 — 2,14 В 85°С> Т > 25°С BORV1 :BORVO = 10 2,67 — 2,89 В BORV1 :BORV0 = 01 4,16 — 4,5 В BORV1 :BORVO = 00 4,45 — 4,83 В 0005 PIC18FXX2 BORV1 :BORV0 = 1x имя В Не действующие уровни напряжений BORV1 :BORV0 = 01 4,16 — 4,5 в BORV1 :BORVO = 00 4,45 4,83 в Примечание 0. Затемнение строк имеет целью повысить читабельность таблицы Примечание 1. Это предел, до которого может снижаться VDD в режиме бездействия или во время сброса устройства без потери данных в ОЗУ Рис. 12.13. Параметры электропитания PIC 18FXX2 Перечень всех видов сброса в 18ХХ2 приведен на рис. 12.14. На нем также показаны значения счетчика команд, битов регистра RCON и двух битов стека переполнения (описан в подразделе 12.5 этой главы), имеющие место после того, как сброс произошел. Теперь при перезапуске программы можно проверить состояние регистра RCON, имеется также возможность выполнения целевых действий в случае, если произошел конкретный тип сброса. Программный сброс, показанный на рис. 12.14, вызывается выполнением команды reset (табл. А5.1). Он воспроизводит внешний сброс от логического блока 0 на входе MCLR. Условия, обеспечивающие сброс по включению питания, приведены на рис. 12.13 вместе с различными возможными настройками сброса по частичной потере питания. 12.9. Источники тактовой частоты До сих пор в этой главе мы рассматривали ситуации, когда возможности аппаратных средств семейства 18 были сравнимы с возможностями устройств семейства 16. При этом основным стержнем была тема: эволюционируем от семейства 16, получая более высокую эффективность и большую гибкость. Аналогичные моменты мы обнаружим и при рассмот- рении источников тактовой частоты в 18FXX2.
12.9. Источники таю оной частоты 369 Как и в случае с группой устройств 16F87XA, устройства 18FXX2 имеют внутренние цепи управления тактовым генератором, совместно с двумя внешними штырьками — OSC1 и OSC2 — предназначенными для подключения любых необходимых внешних компонен- тов. Эти штырьки можно видеть на рис. 12.1. Интересно, что они разделяются другими функциями. Периферийное устройство таймер 1 также имеет источник тактовой частоты с внешними подключениями, помеченными как T1OS0 и T1OS1 (они также разделяются другими функциями). 18FXX2 обеспечивает все четыре режима работы тактового генератора 16F87XA, к ко- торым добавлены еще четыре режима. Все они перечислены в табл. 12.6. Соответствую- щие биты конфигурации расположены в слове конфигурации 1 (табл. 12.4). Режимы работы тактового генератора имеют характеристики, описанные ниже. Соответственно, разряды 4, 3, Соотв., разряды 7 и 6 2,1,0 регистра RCON регистра STKPTR Л Условие Счетчик команд Регистр RCON Rl TO PD POR BOR STKFUL STKUNF Сброс по включению питания OOOOh 0--1 1100 1 1 1 0 0 u u Сброс MCLR во время нормальной работы OOOOh 0 — u uuuu u u u u u u u Программный сброс во вре- мя нормальной работы OOOOh 0 — 0 uuuu 0 u u u u u u Сброс по заполнению стека во время нормальной работы OOOOh 0 — u u u 1 1 u u u u u u 1 Сброс по потере значимости стека во время нормальной работы OOOOh 0 — u u u 1 1 u u u u u 1 u Сброс MCLR в режиме бездействия OOOOh 0--u 1 0 u u u 1 0 u u u u Сброс WDT OOOOh 0--u 01u u 1 0 1 u u u u Активирование WDT PC + 2 u — u OOuu u 0 0 u u u u Сброс по частичной потере питания OOOOh 0--1 1 1u 0 1 1 1 1 0 u u Прерывание по выходу из режима бездействия PC + 2<1) u — u OOuu u 1 0 u u u u Обозначения. и = без изменений, - = нереализованный бит, читается как 'О' Рис. 12.14. Источники сброса в PIC 18FXX2, а также значения счетчика команд и состояния флагов после сброса (дополнительные надписи в затемненных прямоугольниках добавлены автором) Табл. 12.6. Режимы тактового генератора Режим Описание Биты конфигурации FOSC2.FOSCO LP Потеря питания ООО XT Кварцевый резонатор 001 HS Высокочастотный кварцевый резонатор 010 RC Внешний резистор/конденсатор 011 EC Внешняя тактовая частота 100 ECIO Внешняя тактовая частота; штырек OSC2 сконфигурирован как RA6 101 HS + PLL Высокочастотный кварцевый резонатор с контуром ФАПЧ но RCIO Внешний резистор/конденсатор; штырек OSC2 сконфигурирован как RA6 111
370 Глава 12. Более сложные системы и PIC® 18FXX2 12.9.1. Режимы работы тактового генератора: LP, XT, HS и RC Эти режимы работы являются такими же, как и одноименные режимы в семействе PIC 16, они описаны в подразделе 3.5.3 Главы 3. Читателям рекомендуется перечитать этот подраздел. 12.9.2. Режимы работы тактового генератора: ЕС, ЕСЮ и RCIO В режиме работы тактового генератора ЕС внешний источник тактовой частоты под- ключается к штырьку OSC1. Для микроконтроллеров PIC эта концепция не нова — это один из возможных режимов работы устройств семейства 16. Отличие этого режима состо- ит лишь в том, что отключается контур обратной связи внутренней схемы управления, за счет чего экономится немного тока. В режиме работы ЕС в качестве входа используется только один штырек — штырек OSC2 остается неиспользованным. В режиме ЕСЮ этот штырек задействуется, форми- руя дополнительный бит порта А — бит RA6. Аналогичный подход используется в ре- жиме RCIO — тактовый RC-генератор использует только один штырек, также оставляя возможность для использования штырька OSC2 в качестве штырька 6 порта А. 12.9.3. Режим HS + PLL работы тактового генератора Контур ФАПЧ (PLL) состоит из достаточно сложных аналоговых и дискретных цепей, которые, среди прочего, могут использоваться для умножения частоты сигнала на целое число. PLL находит все более широкое применение в микроконтроллерах, связанных с манипулированием тактовой частоты. Это или позволяет некоторым компонентам микро- контроллера работать быстрее других, или обеспечивает возможность микроконтроллеру работать с тактовой частотой, которая выше частоты основного тактового генератора. PLL в 18FXX2 может активироваться, если микроконтроллер будет настроен на режим HS + PLL, а затем будет выполнено умножение тактовой частоты на коэффициент, равный 4. Так, на- пример, тактовый генератор может работать на частоте 10 МГц, однако, при работающем контуре ФАПЧ, внутренняя тактовая частота будет равна 40 МГц. Это может иметь эффект снижения уровня внешних электромагнитных помех. Вследствие того, что PLL требует, как и кварцевый генератор, конечного времени для входа в устойчивый режим, введен таймер, который задерживает запуск ЦП до момента достижения устойчивого режима работы PLL. Фактически он формирует часть таймера включения питания (PWRT), показанного на рис. 2.11 в версии для семейства 16. Вводи- мая задержка обозначается как TPLL — она устанавливается равной 2 мс. 12.9.4. Переключение источника тактовой частоты Если микроконтроллер рассчитан на экономное энергопотребление и, в особенности, если приложение работает длительный период времени, может оказаться полезным распо- лагать возможностью переключения тактовой частоты. Благодаря этому микроконтроллер сможет работать быстрее в периоды востребованной интенсивной активности и более медленно — при снижении уровня активности. В каком-то смысле — это менее экстре- мальный вариант использования режима бездействия. Способность переключать источники тактовой частоты контролируется битом конфи- гурирования OSCSEN (см. табл. 12.4 и 12.5). Если этот режим разрешен, то источник тактовой частоты может выбираться из двух вариантов: основной генератор тактовой час- тоты (в том режиме, в котором он был сконфигурирован) и генератор таймера 1. Выбор управляется битом SCS, который является самым младшим в регистре OSCCON. Когда этот бит находится в состоянии логического 0, то выбирается основной тактовый генера- тор, а когда в состоянии логической 1, то выбирается генератор таймера 1.
12.10. Введение в программирование 18F242 371 При переключении между двумя несинхронизованными генераторами с различными частотами, конечно же, является важным гарантировать, что нежелательные искажения не возникнут в сигнале тактовой частоты. В силу этого 18FXX2 содержит схемы, гарантирую- щие гладкое переключение. Когда бит SCS изменяет свое состояние, программа в начале следующего командного цикла входит в состояние паузы. Восемь циклов сигнала такто- вого генератора отсчитываются до того момента, как завершится процесс переключения. Затем ЦП может продолжать свою работу. Точные детали переключения, которые зависят также и от типа используемого генератора, можно найти в полных технических данных на конкретный микроконтроллер. 12.10. Введение в программирование 18F242 В то время как большая часть программ, рассматриваемых в этой части книги, напи- сана на языке программирования С, сейчас представляется пока еще целесообразным вы- полнить имитацию выполнения пробных программ, написанных на Ассемблере, с тем, что- бы получить первоначальный опыт в использовании набора команд. Если вы изучали эту книгу с самого начала, то уже ознакомились со средой разработки MPLAB® и имитатором MPSIMTM. Давайте снова применим MPLAB для создания некоторых простых программ. В случае необходимости читателям рекомендуется просмотреть подраздел 4.6 Главы 4, чтобы освежить свои знания по данному вопросу. 12.10.1. Использование MPLAB IDE для семейства 18 Попытайтесь открыть MPLAB, а затем, выполнив команду Configure (Конфигуриро- вать) > Select Device (Выбор устройства), выберите 18F242. Обратите внимание на то, что все уже знакомые вам инструментальные средства остаются доступными. Затем, выбрав Configure (Конфигурировать) > Configuration Bits (Биты конфигурирования), вы сможе- те увидеть, что теперь доступно гораздо большее количество битов конфигурирования. Их можно видеть в табл. 12.4 и 12.5. В форме экрана MPLAB они показаны на рис. 12.15. 12.10.2. Программа расчета ряда Фибоначчи В программном примере 5.6 мы рассматривали программу, которая рассчитывает ряд Фибоначчи, используя ЦП семейства PIC 16. УПРАЖНЕНИЕ ПО ПРОГРАММИРОВАНИЮ 12.1 Создайте проект в MPLAB, назвав его Fibonacci-18, Скопируйте с компакт-диска, при- лагаемого к данной книге, в этот проект файл примера программы 5.6. Используя Con- figure (Конфигурировать) > Select Device (Выбор устройства), установите выбор мик- роконтроллера на 18F242. Внесите любые изменения, существенные для правильного выполнения программы. Сделав это, вы должны быть способны проиллюстрировать факт того, что набор команд семейства 18 — это метанабор команд семейства 16. При этом вы увидите, что необходимые изменения будут минимальными. Обратите внима- ние на то, что в данном примере мы используем значения, используемые ассемблером по умолчанию. Так, например, прямая замена кодов типа той, которая нами использу- ется, не специфицирует в команде значение операнда ‘а’ (Приложение 5), Следова- тельно, используется значение 1, принимаемое по умолчанию; Упражнение по программированию 12.1 показывает, что устройства семейства PIC 18 могут работать при использовании только тех команд, которые присущи семейству PIC 16. Однако это приведет к игнорированию новых мощных функций ЦП для семейства 18. При- мер программы 12.1 обеспечивает средний уровень адаптации программы расчета ряда
372 Глава 12. Более сложные системы и PIC® 18FXX2 Фибоначчи к семейству 18, при этом изменения выделены жирным шрифтом. Этот при- мер иллюстрирует использование некоторых новых команд. В Configuration Bits Address 1 Value |Category • Setting | Ц300001 27 Oscillator RC-OSC2 as RA6 1 Osc. Switch Enable Disabled 300002 OF Power Up Timer Disabled Brown Out Detect Enabled Brown Out Voltage 2.5V 300П03 OF Watchdog Timer Enabled Watchdog Postscaler 1:128 3000U5 01 CCP2 Mux RC1 300006 85 stack Overflow Reset Enabled Low Voltage Program Enabled 300008 OF Code Protect 00200-01FFF Disabled Code Protect 02000-03FFF Disabled 300009 CO Data EE Read Protect Disabled Code Protect Boot Disabled 30000А OF Table Write Protect 00200-01FFF Disabled Table Write Protect 02000-03FFF Disabled 30000В E0 Data EE Write Protect Disabled Table Write Protect Boot Disabled Config. Write Protect Disabled 30000C OF Table Read Protect 00200-01FFF Disabled Table Read Protect 0200D-03FFF Disabled 30000D 40 Table Read Protect Boot Disabled - >' '• "» •. < - - - • » | Рис. 12.15. Установка слова конфигурации для 18F242 в MPLAB — все показанные значения используются по умолчанию Пример программы 12.1. Программа генерирования чисел ряда Фибоначчи, адаптированная для микроконтроллера 18F242. ;Fibo 18 ;В ряде Фибоначчи каждое число представляет собой сумму двух предыдущих, ;например: 0,1,1,2,3,5,8,13,21.... ;Эта программа вычисляет числа Фибоначчи в пределах 8-разрядного /диапазона — сначала от меньших к большим, а затем наоборот. ;Эта программа предназначена только для имитации, поэтому она не выполняет /никаких операций ввода-вывода. /Эта программа демонстрирует только сложение, вычитание, сравнение и /условные переходы. /TJW 10.10.05 тестировано 10.10.05 /нет необходимости в установке битов конфигурации list p=18F242 ♦include P18F242.inc /порты ввода-вывода не используются /эти ячейки памяти содержат ряд Фибоначчи fibO equ 10 /самое меньшее число (самое старое при движении /от меньших к большим и самое новое /при движении в обратном направлении) fibl equ 11 /среднее число fib2 equ 12 /самое новое число fibtemp equ 13 /временная ячейка памяти для самого нового числа
12.10. Введение в программирование 18F242 373 Пример программы 12.1. Окончание___________________________________ counter equ 14 /указывает, какого значения мы достигли, /начальное значение равно 3 org 0 0 /Инициализируем BSR movlb 00 /очищаем BSR /предварительно загружаем начальные значения movlw 0 movwf fibO movlw 1 movwf fibl movwf fib2 movlw 3 movwf counter /мы предварительно загрузили первые три числа, /поэтому начинаем с 3 forward movf fibl,0 addwf fib2,0 be reverse /реверсируем счет ряда, если возникло переполнение movwf fibtemp /последнее число теперь помещается в fibtemp incf counter,1 /теперь смещаем хранимые числа, аннулируя самое старое movff fibl,fibO movf f fib2,fibl movff fibtemp,fib2 goto forward /при реверсировании мы вычитаем fibO из fibl /для формирования нового fibO reverse movf fib0,0 subwf fibl,0 movwf fibtemp /последнее число теперь помещено в fibtemp decf counter, 1 /теперь смещаем хранимые числа, аннулируя самое старое movff fibl,fib2 movff fibO,fibl movff fibtemp,fibO /проверяем, если счетчик достиг 3, то возвращаемся к прямому счету movlw 3 epfseq counter goto reverse goto forward end УПРАЖНЕНИЕ ПО ПРОГРАММИРОВАНИЮ 12.2 С компакт-диска, прилагаемого к данной книге, возьмите исходный файл примера про- граммы 12.1. Создайте вокруг него проект и скомпонуйте его. Выполните имитацию вы- полнения программы и, выбрав View (Вид) > Special Function Registers (Специаль- ные функциональные регистры) и View (Вид) > File Registers (Файловые регистры), просмотрите соответствующие области памяти. Обратите внимание на то, как теперь их структура отличается от структуры семейства 16. Перемещайте экран в режиме скрол- линга в окне Special Function Registers (Специальные функциональные регистры), чтобы увидеть значение PCL. Пошагово выполняйте программу и наблюдайте, как PCL будет дважды инкрементироваться при выполнении каждой команды, как было описано в подразделе 12.5.2. Также наблюдайте числа Фибоначчи, появляющиеся в регистрах данных.
374 Глава 12. Более сложные системы и PIC® 18FXX2 Резюме • Микроконтроллеры семейства 18 представляют собой значительный шаг вперед в проектной стратегии PIC. ЦП и структура памяти были радикально перепроектирова- ны, в то время как многие периферийные устройства сохранились. • Набор команд расширился (увеличив свое количество до 75), обеспечивая больше но- вых возможностей в области арифметических операций, операций перехода, доступа к таблицам и использования памяти. • Память данных структурирована таким образом, чтобы обеспечить намного большую емкость ОЗУ и отдельное группирование специальных функциональных регистров. • Емкость памяти программ была значительно увеличена при увеличении разрядности шины адреса, при этом 16-разрядные команды теперь разбиты, с целью их хранения, на два байта. Стек имеет больше уровней и более гибок.
ГЛАВА 13. ПЕРИФЕРИЙНЫЕ УСТРОЙСТВА В PIC® 18FXX2 Цель этой главы состоит в том, чтобы представить читателям периферийные устрой- ства в PIC 18FXX2. Для семейства микроконтроллеров со многими периферийными уст- ройствами, эта глава удивительно коротка. Для этого имеются две причины. Во-первых, как уже было отмечено в Главе 12, многие из периферийных устройств семейства 18 подобны или идентичны устройствам, использованным в семействе 16. Мы воспользуемся этим зна- нием, и не будем повторять материал, ранее приведенный в этой книге. Во-вторых, по- скольку мы движемся к программированию на языке С, мы извлечем пользу из той под- держки, которую обеспечивает компилятор С. Мы увидим, что библиотечные функции С берут на себя все взаимодействие с периферийными устройствами, и при обычном их ис- пользовании мы не будем нуждаться в близком знакомстве с периферийными устройства- ми. Энергия, которую мы раньше затрачивали (программируя на Ассемблере) на изучение каждой тонкой подробности периферийного устройства, теперь может быть направлена на созидательную задачу написания рабочих программ. Это весьма освобождающий шаг. Описания, которые следуют далее, часто ссылаются на периферийные устройства се- мейства 16, уже рассмотренные в более ранних главах. Так что, если вы продуктивно изу- чали периферийные устройства семейства 16, то эти ссылки будут работать как полезное повторение и, в тоже время, демонстрировать небольшие изменения, которые были вве- дены в семейство 18. Если вы не знаете периферийных устройств семейства 16, то вы их таким образом изучите (а, следовательно, и периферийные устройства семейства 18). Таким образом, мы не будем рассматривать все, что имеется в 18FXX2 как предста- вителе всех устройств семейства 18. Более того, эта глава завершается рассмотрением другого члена семейства — 18F2420. Этот микроконтроллер имеет некоторые интересные характеристики, о которых следует знать. Особенно это касается расширенного набора команд и нановатт ной технологии. Эта глава имеет целью: • сделать обзор всех периферийных устройств PIC 18FXX2, в большинстве случаев ба- зируясь на знании их эквивалентов из семейства 16; • бросить взгляд на некоторые дальнейшие доработки, которые доступны в мире се- мейства 18. Эту главу можно пролистать. В качестве альтернативы, ее можно пропустить и про- сто использовать в качестве справочного материала при изучении последующих глав, когда это будет необходимо. 13.1. Основная идея периферийных устройств 18FXX2 Список периферийных устройств микроконтроллеров 18FXX2 приведен в таблице 12.1, также они видны на блок-схеме 18F2X2, показанной на рис. 12.2. При сравнении их с периферийными устройствами 16F87XA, приведенными на рис. 7.2, можно заметить, что почти в каждом случае отображены те же самые периферийные устройства, с тем же самым именем и с той же структурой. Различие, которое необходимо отметить, заключается лишь
376 Глава 13. Периферийные уоройспза в PIC® 18FXX2 в том, что 18FXX2 имеет дополнительный таймер (таймер 3), но не имеет модуля компа- ратора 16F87XA. 13.2. Параллельные порты Параллельные порты 18FXX2 очень похожи на соответствующие порты семейства 16 — как по структуре, так и по интерфейсу. Каждый из них имеет регистр PORTX, для пе- редачи данных, и регистр TRISX, предназначенный для установки направления переме- щения данных. Имеется только одно значительное различие, которое мы должны принять во внимание — оно вкратце описано чуть ниже. При работе с портом нам может потребоваться реализовать четыре основные функции: установить направление перемещения данных, считать входное значение, установить зна- чение выхода и вновь считать предварительно записанное значение выхода. Проект семей- ства 16 имел во всем этом одну слабость — он не был достаточно хорош при выполнении четвертой функции из приведенного перечня. Предположим, что разряд порта, наподобие показанного в рис. 7.15 (а), был установлен как выход, и в него заносится значение бита. Если затем порт считывается ЦП, то было невозможно достоверно убедиться в том, что считанное значение действительно совпадает с предварительно записанным значением. Это имело место потому, что считывалось фактическое состояние штырька разряда порта. А это могло быть как выходное значение, установленное схемами управления разрядом порта, так и иное значение, принудительно установленное внешним устройством, соеди- ненным с данным штырьком. Чтобы обойти эту маленькую проблему, в портах семейства 18 выполнена интересная доработка. Каждый порт имеет третий регистр: LATA — для порта A, LATB — для пор- та В и так далее, который удерживает значение фиксируемого выходного разряда порта. Это значение может читаться программой, и программист может иметь полную уверен- ность в том, что он читает именно то значение, которое было предварительно сохранено в порте и ничего иного. Теперь мы рассмотрим порты 18ХХ2, анализируя их и другие изменения. 13.2.1. Порт А в 18FXX2 Позиции штырьков порта А можно видеть на схеме разводки штырьков, приведенной на рис. 12.1. Неудивительно, что общая схема их разводки почти совпадает с таковой для 16F873A, при этом функции цифрового ввода-вывода порта разделяются с входами АЦП (аналого-цифрового преобразователя). Вход таймера 0 разделяется разрядом 4 порта, ко- торый имеет выход с открытым стоком. Имеется также возможность использования допол- нительного разряда порта — RA6, если используются режимы тактового генератора ECIO или RCIO, как было описано в подразделе 12.9.2 Главы 12. Три регистра, связанные с портом А -— PORTA, TRISA и LATA можно видеть в чет- вертом столбце карты регистров (см. рис. 12.5). Работа дополнительного триггера фикса- ции данных LATA иллюстрируется на рис. 13.1. Эта схема очень похожа на ее эквивалент для семейства 16 (рис. 7.15 (а)). При введенном новом регистре LATA, можно ожидать уви- деть где-нибудь на схеме дополнительный триггер. Интересно, что дело обстоит совсем не так. Быстрый взгляд на схему показывает, что LATA и PORTA совместно используют тот же самый триггер данных; запись в один эквивалентна записи в другой. Единственное ре- альное различие в схеме — это буфер LATA, который виден в верхней части схемы. Счи- тывание LATA активизирует этот буфер, и значение, удерживаемое на фиксаторе данных PORTA/LATA, переносится на шину данных. Следовательно, LATA в действительности — это вообще не отдельный регистр, однако обращение к нему позволяет осуществить прямое считывание выхода фиксатора данных PORTA.
13.2. Параллельные порты 377 Примечание. Штырек ввода/вывода имеет диодную защиту от Vdd и Vss Рис. 13.1. Штырьки RA0-RA3 и RA5 в 18FXX2 (дополнительные надписи в затемненных прямоугольниках добавлены автором) 13.2.2. Порт В в 18FXX2 Позиции штырьков порта В можно видеть на схеме разводки штырьков, приведенной на рис. 12.1, а три его основных регистра — PORTB, TRISB и LATB — на рис. 12.5. LATB играет функцию, идентичную LATA, которая уже обсуждалась. Порт сохраняет большинство характеристик аналогичного порта из семейства PIC 16, являясь сравнительно несложным по конструкции. Имеется некоторое увеличение числа разделяемых функций, особенно в связи с введением большего числа внешних источников прерываний. Можно также видеть, что разряды 5-7 разделяются с функциями внутрисхем- ной отладки — PGD, PGC и PGM, при этом последняя функция перекочевала непосред- ственно из семейства 16. Три входа внешних прерываний разделяются тремя младшими битами порта. Интересным дополнением является введение альтернативного подключения ССР2 на разряде 3. Это снижает нагрузку на самый “загруженный” штырек порта С — разряд 1, и позволяет использовать внешний генератор таймера 1 одновременно с ССР2. Внутренние нагрузки также доступны на всех штырьках, с управляющим битом RBPU, теперь размещенном в регистре INTCON2 (рис. 12.9). Имеется прерывание от функции из- менения состояния, при этом изменение состояния любого из штырьков 4—7 также вызы- вает установку флага прерывания. Бит разрешения и бит флага — RBIE и RBIF — нахо- дятся в регистре INTCON (см. рис. 12.8).
378 Глава 13. Периферийные устройства в PIC® 18FXX2 13.2.3. Порт С в 18FXX2 Как и в случае других портов, позиции штырьков порта С можно видеть на схеме раз- водки штырьков, приведенной на рис. 12.1, а три его основные регистра — PORTC, TRISC и LATC — на рис. 12.5. Как и в случае с 16F87XA, этот порт разделяет штырьки с после- довательными портами и функциями ССР, в то время как разряд 0 разделяется с входом таймера 1. Этот разряд совместно с разрядом 1 могут также использоваться как входы внешнего тактового генератора таймера 1. Из-за этих разделяемых функций, схемы уп- равления штырьками порта сравнительно сложны. Более того, функции штырьков могут быть подавлены функциями периферийных устройств — следовательно, необходимо про- являть внимание. Это подавление, однако, не включает чтение регистра LATC. Он может читаться в любом режиме работы штырька порта. 13.2.4. Параллельный подчиненный порт Он реализован в устройствах с 40-штырьковыми корпусами и является тем же, что и порт, описанный в подразделе 7.12 Главы 7. Параллельный порт — это порт D, при этом разряд 3 порта Е используется для подтверждения связи. Режим работы порта управляет- ся, прежде всего, регистром TRISE, который является тем же, что и регистр, показанный на рис. 7.26. Единственным добавлением к порту является включение регистра LATD, функционирующего так, как это было описано ранее для порта А. 13.3. Таймеры Все версии 18FXX2 имеют не менее четырех программируемых таймеров, а также сто- рожевой таймер. Мы рассмотрим таймеры по очереди, интенсивно используя информацию, которая уже была изложена для их эквивалентов из семейства 16. 13.3.1. Таймер О Таймер 0 в 18FXX2 отчетливо демонстрирует, что его корни исходят из таймера 0 се- мейства 16. Однако он может функционировать как в 8-разряд ном, так и в 16-разрядпом режимах. Его регистр управления TOCON показан на рис. 13.2. Младшие 6 разрядов этого регистра имеют функцию, подобную регистру OPTION семейства 16, показанному на рис. 6.9, который он заменил. Режим работы задается разрядом 6, который определяет, какой режим будет использоваться — 8-разрядный или 16-разрядный. В 8-разрядном режиме работа таймера 0 происходит, фактически, точно так же, как и работа таймера 0 из семейства 16, показанного на рис. 6.8. В отличие от таймера 0 семей- ства 16, который разделяет предварительный делитель со сторожевым таймером, сейчас предварительный делитель полностью предоставлен таймеру. Следовательно, бит PSA ре- гистра TOCON просто определяет, находится предварительный делитель в цепи или нет; он непосредственно не подключает его к сторожевому таймеру. Работа таймера в 16-разрядном режиме иллюстрируется рис. 13.3. Младший байт са- мого счетчика называется TMR0L, в то время как старший байт называется просто TMRO, поскольку он представляет собой ту же ячейку памяти, что и в 8-разрядной версии. Интересная проблема возникает тогда, когда 16-разрядные таймеры работают в 8-раз- рядной среде. Предположим, что программа должна считать значение, содержащееся в таймере. 2 байта считываются по очереди. Является возможным, однако, что произойдет инкрементирование таймера уже после того, как первый байт считан, возможно, вызвав пе- реполнение, идущее от младшего байта до старшего байта. Таким образом, считанное 2- байтовое значение окажется неверным. Решение этой проблемы показано на рис. 13.3. Буфер TMR0H используется для про- межуточного храпения старшего байта TMRO. Теперь невозможно обратиться к старшему
13.3. Таймеры________________________________________________________________________379 байту непосредственно. Всякий раз, когда младший байт считывается, значение TMR0 одновременно перемещено в TMR0H. Оно может быть считано следующей командой. Его значение гарантировано соответствует значению младшего байта на момент его считыва- ния. Точно так же, если программист захочет записать какое-либо значение в таймер, то программа должна сначала записать требуемый старший байт в TMR0H. Когда младший байт будет записываться в TMR0L, то тогда сохраненное в TMR0H значение будет одно- временно перемещено в TMR0. Опять-таки, 16-разрядное значение, загружаемое в таймер, будет гарантировано правильным и не будет искажено операцией инкрементирования, воз- можно произошедшей во время перемещения 2-байтового значения. R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 TMROON T08BIT TOCS T0SE PSA T0PS2 T0PS1 T0PS0 разряд 7 разряд О разряд 7 TMROON: бит управления включением/выключением таймера О 1 = активирует таймер О О = останавливает таймер О разряд 6 T08BIT: бит управления 8-/16-битными режимами таймера О 1 = таймер О сконфигурирован как 8-битный таймер/счетчик О = таймер 0 сконфигурирован как 16-битный таймер/счетчик разряд 5 TOCS: бит выбора источника синхронизации таймера О 1 = переключение на штырьке T0CKI О = синхронизация по внутреннему командному циклу (CLKO) разряд 4 T0SE: бит выбора фронта сигнала от источника для таймера О 1 = инкрементирование по переключению с 1 в 0 на штырьке T0CKI О = инкрементирование по переключению с 0 в 1 на штырьке T0CKI разряд 3 PSA: бит использования предвари тельного делителя таймера О 1 = предварительный делитель таймера О НЕ используется. Вход синхронизации таймера 0 обходит предварительный делитель. О = предварительный делитель таймера 0 используется. Вход синхронизации таймера 0 снимается с выхода предварительното делителя. разряды 2-0 T0PS2:T0PS0: бит выбора коэффициента предварительного делителя таймера 0 111 = значение коэффициента равно 1: 256 110 = значение коэффициента равно 1:128 101 = значение коэффициента равно 1:64 100 = значение коэффициента равно 1:32 011 = значение коэффициента равно 1:16 010 = значение коэффициента равно 1:8 001 = значение коэффициента равно 1:4 000 = значение коэффициента равно 1:2 Рис. 13.2. Регистр управления таймером 0 T0CON TOCS PSA Примечание. После СБРОСА таймер 0 активируется в 8-битном режиме с тактированием от штырька TOCKI при максимальном коэффициенте предварительного делителя. Рис. 13.3. Таймер 0, работающий в 16-разрядном режиме
380 Глава 13. Периферийные устройства в PIC® 18FXX2 В любом режиме работы таймера 0 прерывание генерируется, когда счетчик переполня- ется из максимального значения (FFH ДЛЯ 8-разрядного и FFFFh для 16-разрядного таймера). Тот же самый бит TMR0IF, показанный на рис. 12.7, используется для обоих прерываний. Таймер 0 в 16-разрядном режиме с прерываниями используется в ряде примеров про- грамм на языке С в последующих главах. 13.3.2 . Таймер 1 Таймер 1 в 18FXX2 в своей базисной форме почти идентичен таймеру из семейства 16, который можно видеть на рис. 9.1. Он имеет регистр управления T1CON. Этот регистр точно такой же, как показанный на рис. 9.2, за исключением того, что разряд 7 (не исполь- зуемый в семействе 16) называется RD16. Будучи установленным в 1, этот бит разрешает режим “16-разрядного чтения-записи”. Все происходит точно так, как это было описано для таймера 0. Когда этот режим разрешен, то таймер работает так, как показано на рис. 13.4. В нем имеется буферный регистр TMR1H для старшего байта, позволяющий синхронизо- вать передачу данных в/из таймера. Еще одно небольшое отличие от таймера 1 семейства 16 заключается в возможности сброса таймера по “специальному событию” от модуля ССР. Этот отличие также отображено на рис. 13.4 и описано в подразделе 13.4. T1CKPS1:T1CKPS0 Примечание. Когда бит разрешения T10SCEN сбрасывается, резистор обратной связи и инвертора отключается. Это устраняет утечку тока. Рис. 13.4. Таймер 1, работающий в 16-битном режиме считывания/записи 13.3.3 . Таймер 2 Таймер 2 в 18F242 является точно таким же, как и таймер 2 из семейства 16, показан- ный на рис. 9.4. Точно так же он имеет регистр управления T2CON — такой же, как по- казано на рис. 9.5. 13.3.4 . Таймер 3 Таймер 3 структурно является таким же, как таймер 1, поэтому он не создает никаких новых проблем в области понимания его работы. В своей базисной форме он показан на рис. 13.5, с регистром управления T3CON, показанном на рис. 13.6. Как и в случае с
13.3. Таймеры 381 таймером 1, таймер 3 может работать в режиме таймера с синхронизацией как от внутрен- него источника тактовой частоты, так и от внешнего тактового генератора, а в режиме счет- чика — с синхронизацией от внешнего источника тактовой частоты. В случае использова- ния внешнего тактового генератора входы тактовой частоты разделяются с таймером 1. Таким образом, если используется внешний тактовый генератор, то он будет тем же, что и для таймера 1 — он должен быть разрешен битом T1OSCEN, расположенным в регистре T1CON. Если используется внешний вход, то он будет одинаковым для таймера 1 и для таймера 3, в случае 18F2X2 — это будет штырек 11. T3CKPS1:T3CKPS0 Примечание. Когда бит разрешения T1OSCEN сбрасывается, резистор обратной связи и инвертора отключается. Это устраняет утечку тока. Рис. 13.5. Блок-схема таймера 3 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 RD16 ТЗССР2 ТЗССР1 T3CKPS1 T3CKPS0 T3SYNC TMR3CS TMR3ON разряд 7 разряд 0 разряд 7 RD16: бит разрешения режима 16-битного чгения/записи 1 = разрешает регистровое чтение/запись таймера 3 в одном 16-битном режиме 0 = разрешает регистровое чтение/запись таймера 3 в двух 8-битных режимах разряды 6-5 ТЗССР2:ТЗССР1: биты активирования таймера 3 и таймера 1 на ССРх 1х = таймер 3 является источником синхронизации для модулей сравнения/сбора данных ССР 01 = таймер 3 является источником синхронизации для модуля сравнения/сбора данных ССР2, таймер 1 является источником синхронизации для модуля сравнения/сбора данных ССР1 00 = таймер 1 является источником синхронизации для модулей сравнения/сбора данных ССР разряды 4-3 T3CKPS1:T3CKPS0: входная тактовая частота таймера 3 Бит выбора коэффициента предварительного деления для тактового входа 11 = значение коэффициента равно 1:8 10 = значение коэффициента равно 1:4 01 = значение коэффициента равно 1:2 00 = значение коэффициента равно 1:1 разряд 2 T3SYNC: бит управления внешним входом синхронизации таймера 3 (не применим, если системная тактовая частота снимается от таймера 1 или таймера 3) Когда TMR3CS= 1: 1 = не синхронизовать вход внешней синхронизации 0 = синхронизовать вход внешней синхронизации Когда TMR3CS = 0: Этот биг игнорируется. Таймер 3 использует внутреннюю синхронизацию, когда TMR3CS = 0. разряд 1 TMR3CS: бит выбора источника синхронизации таймера 3 1 = внешний вход синхронизации от генератора таймера 1 или T1CKI (по нарастающему фронту после первого среза) 0 = внутренняя синхронизация (Fosc/4) разряд 0 TMR3ON: бит включения таймера 3 1 = включает таймер 3 0 = останавливает таймер 3 Рис. 13.6. Регистр управления таймера 3, T3CON
382 Глава 13. Периферийные уоройства в PIC® 18FXX2 Анализ рис. 13.6 показывает, что разряды 0, 1, 2, 4 и 5 имеют ту же самую функцию, что и соответствующие разряды из регистра T1CON (см. рис. 9.2). Разряд 7 показывает, что режим “16-разрядного чтения-записи” для таймера 3 так же доступен, как это было описа- но для таймеров 0 и 1. Если он не установлен, то таймер функционирует, как это показано на рис. 13.5. Если же он установлен, то интерфейс таймера с шиной данных приобретает форму “16-разрядного чтения-записи”, показанную на рис. 13.4. Чтение или запись стар- шего байта буферизуется, при буфере, отображаемом на пространство памяти как TMR3II. Из описания назначения битов 6 и 3 регистра T3CON очевидно, что таймер 3 может быть связан с модулем ССР (сбор данных/сравнение/ШИМ) и использоваться для сбора данных и их сравнения, или же работать автономно, как таймер 1. На рис. 13.5 можно ви- деть “триггер специального события модуля ССР”, который стробируется одним из битов управления. Если разряд 3 или разряд 6 будет находиться в состоянии логической едини- цы, то эта цепь будет разрешена. Соответствующие функции будут описаны далее в под- разделе 13.4. 13.3.5 . Сторожевой таймер Сторожевой таймер (WDT) идентичен по своей концепции WDT из семейства 16, как это описано в подразделе 6.5 Главы 6. Это постоянно работающий счетчик, который, если он активирован и разрешен его тайм-аут, вызывает сброс микроконтроллера. Он активи- руется битом WDTEN регистра конфигурации CONFIG2H (табл. 12.4). Он имеет свой соб- ственный специализированный постделитель (в отличие от семейства 16, где он разделяет постделитель с таймером 0), установки которого задаются битами WDTPS2:WDTPS0 в том же самом регистре конфигурации. В документации указывается, что типичный период тайм-аута обычно равен 18 мс, при минимальном значении в 7 мс и максимальном значе- нии в 33 мс, для коэффициента постделителя, равном 1. Если постделитель установлен на 128, то типичный период тайм-аута возрастает до 2,3 с. Как WDT, так и постделитель сбрасываются выполнением команды clrwdt. Важной доработкой проектной стратегии WDT является ввод программного бита раз- решения WDT — SWDTEN. Это самый младший и единственный активный бит регистра WDTCON, который отражен как ячейка памяти с адресом FD1H на рис. 12.5. Если WDT был заблокирован в регистре конфигурации, то он может быть разрешен установкой бита SWDTEN. Если WDT разрешен в регистре конфигурации, то состояние бита SWDTEN не имеет никакого значения. Способность включения и выключения WDT до некоторой сте- пени идет в разрез со всей концепцией WDT — остается вопрос: насколько разумно иметь функцию безопасности, которая может быть выключена? Однако это позволяет разрешать WDT в некоторых режимах работы и блокировать его для других режимов. Как и все функции безопасности или обеспечения надежности, эта функция должна использоваться с осторожностью. 13.4. Модуль сбора данных/сравнения/ШИМ (ССР) 18FXX2 имеет два модуля ССР, которые показаны на рис. 12.2. Они очень похожи на одноименные модули семейства 16, в них применяются точно те же принципы, которые были описаны в подразделе 9.4.1 Главы 9. Модули ССР работают с таймерами 1, 2 и 3 с тем, чтобы обеспечить сбор данных, сравнение и функционирование ШИМ. Важным отличи- ем от семейства 16 и большим шагом вперед в терминах гибкости работы является введе- ние таймера 3 и его взаимосвязь с модулями ССР. 13.4.1. Регистры управления Модули ССР управляются прежде всего регистрами CCPxCON, показанными на рис. 13.7. Они очень похожи на регистры CCPxCON из семейства 16, приведенные на рис. 9.7.
13.4. Модуль сбора данных/сравнения/ШИМ (ССР) 383 Имеется, однако, небольшое различие в деталях доступных режимов, как покажет ниже- изложенный анализ младших 4 разрядов. Так, например, новый режим доступен в 18FXX2, — он соответствует установке разрядов 3-0 в состояние 0010. Можно видеть, что имеется изменение имен разрядов 4 и 5 этих регистров, но не их функций. U-0 U-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 — — DCxB1 DCxBO ССРхМЗ CCPxM2 CCPxMl CCPxMO разряд 7 разряды 7-6 Не реализованы: читается как 'О' разряд 0 разряды 5-4 DCxB1 :DCxB0: биты 1 и 2 рабочего периода ШИМ Режим сбора данных: Не используется Режим сравнения: Не используется Режим ШИМ: Эти биты являются двумя младшими разрядами (разряд 1 и разряд 0) 10-разрядного рабочего цикла ШИМ. Старшие восемь разрядов (DCx9:DCx2) рабочего цикла находятся в CCPRxL разряды 3-0 ССРхМЗ:ССРхМ0: биты выбора режима ССРх 0000 - сбор данных/сравнение/ШИМ запрещены (сброс модуля ССРх) 0001 = зарезервирован 0010 = режим сравнения, переключение выхода по соответствию (бит CCPxlF установлен) 0011 = зарезервирован 0100 = режим сбора данных, по каждому срезу 0101 = режим сбора данных, по каждому нарастающему фронту 0110 = режим сбора данных, по каждому 4-му нарастающему фронту 0111 = режим сбора данных, по каждому 16-му нарастающему фронту 1000 = режим сравнения; инициализация штырька ССР в 0, по соответствию сравнения установка штырька ССР в 1 (бит CCPIF установлен) 1001 = режим сравнения, инициализация штырька ССР в 1, по соответствию сравнения установка штырька ССР в 0 (бит CCPIF установлен) 1010 = режим сравнения, генерирование программного прерывания по соответствию сравнения (бит CCPIF установлен, штырек ССР не изменяется) 1011 = режим сравнения, переключение специального события (бит CCPIF усгановлен) 11хх = режим ШИМ Рис. 13. 7. Регистры CCP1CON и CCP2CON (адреса FBDH и FBAH) 13.4.2. Режим сбора данных Модуль ССР, сконфигурированный для режима сбора данных, показан на рис. 13.8. Это прямой эквивалент рис. 9.8, он применим к принципам, описанным в подразделе 9.4.2 Главы 9. Оба входа, однако, показаны и на рис. 13.8. Главное структурное различие заключается в том, что теперь доступны для использо- вания оба таймера — 1 и 3. Это позволяет тестировать два входных сигнала с довольно разными временными характеристиками, поскольку таймеры 1 и 3 могут теперь оба исполь- зоваться и оба являются оптимизированными в терминах установки частоты и настройки предварительного делителя для сигнала, который они “регистрируют”. Выбор таймера, ко- торый нужно использовать, определяется значениями битов ТЗССРх, которые мы уже видели в регистре T3CON, показанном на рис. 13.6. Если только выбор сделан, операция сбора данных протекает так же, как и в семействе 16. 13.4.3. Режим сравнения Модуль ССР, сконфигурированный для режима сравнения, показан на рис. 13.9. Это прямой эквивалент рис. 9.9, он применим к принципам, описанным в подразделе 9.4.3 Главы 9. Как и в случае режима сбора данных, описанного выше, оба входа показаны и на рис. 13.9. Главное структурное различие заключается в том, что теперь доступны для
384 Глава 13. Периферийные устройства в PIC® 18FXX2 использования оба таймера — 1 и 3. Выбор таймера, который нужно использовать, опять- таки, определяется значениями битов ТЗССРх, как указано на рис. 13.6. Q’s Рис. 13.8. Отработка режима сбора данных (дополнительные надписи в затененных прямоугольниках добавлены автором) Триггер специального события сбрасывает таймер 1 или таймер 3, однако не устанавливает бит флага прерывания Таймера 1 или Таймера 3. Он также устанавливает бит GO/DONE (ADCONO<2>), который запускает аналого-цифровое преобразование (только ССР2). Триггер специального события Выбор режима Рис. 13.9. Работа в режиме сравнения
13.5. Последовательные порты 385 Действие “специального события” иллюстрируется в верхней левой части схемы. Оно настраивается через установку соответствующей комбинации младших 4 разрядов в реги- стре CCP1CON или CCP2CON (см. рис. 13.7). 13.4.4. Широтно-импульсная модуляция (ШИМ) ССР модули, сконфигурированные для ШИМ, работают в соответствии с принципа- ми, описанными в подразделе 9.5.1 Главы 9. Они ведут себя точно как модули семейства 16, работая, следовательно, точно так же, как описано в подразделе 9.5.2 Главы 9 и как по- казано на рис. 9.11. 13.5. Последовательные порты 18FXX2 имеет два основных модуля последовательного информационного обмена — модуль ведущего синхронного последовательного порта (MSSP) и модуль адресуемого универсального синхронно-асинхронного приемо-передатчика (USART), как это можно было видеть на рис. 12.2. MSSP идентичен периферийному устройству семейства 16 с тем же наименованием. Таким образом, он может быть сконфигурирован либо на режим SPI (последовательный периферийный интерфейс), либо на режим 12С. Работа обоих портов кратко рассматривается в подразделах, которые следуют далее. 13.5.1. MSSP в режиме SPI В этом режиме MSSP конфигурируется так, как показано на рис. 10.7. Данные переме- щаются в или из последовательного порта через регистр SSPBUF, показанный на рис. 12.6 по адресу FC9h. Порт управляется двумя регистрами — SSPCON1 и SSPSTAT. Они пока- заны, соответственно, на рис. 10.8 и 10.9, в то время как их адреса на карте памяти семейст- ва 18 показаны на рис. 12.5 (соответственно, адреса FC6h и FC7h). Работа периферийного устройства в этом режиме точно соответствует описанию, приведенному в подразделе 10.3 Главы 10. Поскольку в семействе 18 введены приоритеты прерываний (см. подраздел 12.7 Главы 12), прерыванию MSSP (SSPIF в PIR1, рис. 12.11) может также быть присвоен при- оритет. Значение этого приоритета управляется битом SSPIP регистра IPR1 (см. также рис. 12.11). 13.5.2. MSSP в режиме 12С MSSP в режиме 12С ведет себя точно так же, как MSSP семейства 16. Таким образом, применяются все принципы ГС, как было описано в подразделе 10.6 Главы 10. Использу- ются те же самые регистры управления — SSPCON1, SSPCON2, SSPSTAT и SSPADD. В режиме подчиненного устройства модуль конфигурируется так, как показано на рис. 10.17, а в режиме ведущего устройства — как показано на рис. 10.19. В целом, модуль ведет се- бя точно так же, как описано в подразделе 10.7 Главы 10. 13.5.3. USART Этот модуль является тем же, что и одноименное с ним периферийное устройство се- мейства 16 и, следовательно, его поведение полностью соответствует описанию, приве- денному в подразделе 10.10 Главы 10. При более высокой максимальной частоте тактово- го генератора он имеет потенциал работы при более высоких скоростях информационного обмена. Его прерываниям (биты RCIF и TXIF в регистре PIR1, рис. 12.11) могут быть присвоены приоритеты, они также являются “объектами воздействия” механизма разре- шения прерываний семейства 18.
386 Глава 13. Периферийные усгройова в PIC® 18FXX2 13.6. Аналого-цифровой преобразователь (АЦП) Модуль АЦП в 18FXX2 фактически является тем же, что и соответствующий модуль в 16F873A, описанный в подразделе 11.3 Главы 11. Ему соответствует блок-схема, приве- денная на рис. 11.6, при восьми входах, доступных в 18F442 и 18F452, и пяти — в 18F242 и 18F252. Эти входы показаны на рис. 12.1. АЦП контролируется регистрами ADCONO и ADCON1, которые отображаются теперь в ячейки памяти FC2H и FCIh (рис. 12.5). Ре- зультат преобразования помещается в ADRESL и ADRESH (FC3H и FC4H, рис. 12.5). Мо- дель аналогового входа показана на рис. 11.10. Рис. 13.9 показывает, что модуль ССР в режиме сравнения может быть настроен таким образом, чтобы запустить АЦП-преобразование. Для того чтобы это произошло, модуль АЦП должен быть активирован битом ADON в регистре ADCONO (Рис. 11.7). Входной мультиплексор также должен быть предвари- тельно установлен, с достаточным временем, отводимым на сбор данных, как это описыва- лось в подразделе 11.3.4 Главы 11. Если таймер, вызывающий специальное событие (таймер 1 или 3), оставлен в режиме непрерывной работы, то этим обеспечивается полезное сред- ство выполнения периодического аналого-цифрового преобразования. 13.7. Обнаружение падения напряжения Способность обнаружения падения электропитания очень ценна для встроенной сис- темы. В системах с аккумуляторным питанием эта функция может использоваться для то- го, чтобы обнаружить факт разряда аккумуляторов. Она может использоваться также для того, чтобы обнаружить факт отключения электропитания. В любом случае микрокон- троллер может пожелать активизировать предупредительный сигнал или осуществить ор- ганизованное отключение системы, возможно, с сохранением значений ключевых рабочих переменных в ЭСППЗУ. В случае полной потери электропитания остаточный заряд на системном буферном конденсаторе все еще обеспечит некоторое время для того, чтобы это сделать. Функция обнаружения падения электропитания доступна во многих интегральных мик- росхемах стабилизаторов напряжения, особенно предназначенных для батарейных источ- ников электропитания. Если обнаружено пониженное напряжение питания, они генериру- ют выходной сигнал, который может использоваться как прерывание микроконтроллера. 18FXX2, однако, имеет свою собственную встроенную функцию обнаружения падения на- пряжения электропитания со своим собственным источником прерывания. Общая концеп- ция иллюстрируется на рис. 13.10. Напряжение электропитания VDD прикладывается к верхнему концу цепочки резисторов. Другой конец этой цепочки может быть соединен с землей через ключевой транзистор, напряжение затвора которого обозначено как LVDEN. Им может быть значение разряда 4 регистра LVDCON (рис. 13.11). Если LVDEN установлен в состояние логической 1, то цепочка резисторов действует как делитель напряжения, отводы от которого заведены на входы мультиплексора. Один из этих входов задается, установкой младших 4-х разрядов регистра LVDCON, как выход мультиплексора. Выходное значение мультиплексора сравнивается с внутренне генериру- емым опорным напряжением, равным 1,2 В. Если выходное напряжение мультиплексора падает ниже опорного напряжения, то выход компаратора LVDIF устанавливается в состо- яние логической единицы. Он и является флагом прерывания по обнаружению падения на- пряжения электропитания, который можно видеть на рис. 12.12. Если прерывания раз- решены, то генерируется прерывание, и микроконтроллер может выполнить соответству- ющие действия, предусмотренные в случае падения напряжения электропитания. Интересно рассмотреть пороговые значения напряжения, которые могут быть выбра- ны, как показано на рис. 13.11, и сравнить их как с диапазоном допустимых напряжений электропитания устройства, так и с возможными настройками функции сброса по обнару- жению частичной потери электропитания, как это отражено на рис. 12.13. Очевидно, что
13.8. Применение устройств семейства 18 в АУСМ Derbot-18 387 не будет разумным устанавливать порог обнаружения падения напряжения электропита- ния ниже порога сброса по частичной потере электропитания, поскольку в этом случае сис- тема всегда бы сбрасывалась еще до того, как обнаруживался бы факт падения электропи- тания! Таким образом, разработчик может' предпочесть не использовать функцию сброса по частичной потере электропитания, однако обеспечить при этом мониторинг цепей электро- питания функцией обнаружения падения электропитания. Рис. 13.10. Цепь определения факта падения напряжения электропитания Альтернативой использованию напряжения, полученного от внутреннего резисторного делителя напряжения, может быть использование внешнего входа. Это напряжение может быть подано через входной штырек обнаружения падения напряжения LVDIN (штырек 7 для любого варианта корпуса, см. рис. 12.1). Цепь прохождения сигнала показана на рис. 13.10, а необходимые настройки — на рис. 13.11. Если выбрано внешнее напряжение, то оно будет непосредственно сравниваться с внутренним опорным напряжением, равным 1,2 В. Поскольку после своего активирования цепи обнаружения падения напряжения по- требляют некоторый ток (порядка 30 мкА), то для экономии электроэнергии может ока- заться целесообразным только периодически активировать эти цепи. В таком случае опор- ное напряжения потребует некоторого времени достижения устойчивого уровня. Состоя- ние опорного напряжения индицируется битом IRVST регистра LVDCON. Прерывание должно разрешаться только тогда, когда этот бит установлен в состояние логической 1. Необходимо отметить, что эффект от любого сброса связан с очисткой бита LVDEN и, следовательно, с отключением функции обнаружения падения напряжения. 13.8. Применение устройств семейства 18 в АУСМ Derbot-18 Ввиду совместимости на уровне штырьков между 16F873А и 18F242, собранный Derbot непосредственно совместим с устройствами семейства 18 — никакие изменения в нем не нужны! Эта совместимость включает весь параллельный ввод-вывод, АЦП, ШИМ, счет- чики и таймеры, а также интерфейс 12С. АУСМ Derbot, в котором установлен микрокон- троллер 18F242, используется в последующих главах во всех программных примерах. Чтобы подчеркнуть замену микроконтроллера (однако, без каких-либо иных изменений), наш АУСМ теперь будет называться “Derbot-18”.
388 Глава 13. Периферийные устройства в PIC® 18FXX2 U-0 и-о R-0 R/W-0 R/W-0 R/W-1 R/W-0 R/W-1 — — IRVST LVDEN LVDL3 LVDL2 LVDL1 LVDL0 разряд 7 разряд О разряды 7-6 Не реализованы: Читается как 'О' разряд 5 IRVST: бит флага стабильности внутреннего опорного напряжения 1 = указывает на то, что логические схемы обнаружения падения напряжения будут генерировать флаг прерывания в специфицированном диапазоне напряжений 0 = указывает на то, что логические схемы обнаружения падения напряжения не будут генерировать флаг прерывания в специфицированном диапазоне напряжений и прерывание по падению напряжения не будет разрешено разряд 4 LVDEN: бит активирования питания цепей для обнаружения падения напряжения 1 = разрешает определение падения напряжения, цепи обнаружения запитываю гея; 0 = запрещает определение падения напряжения, цепи обнаружения отключаются; разряды 3-0 LVDL3:LVDL0: биты пределов обнаружения падения напряжения 1111 = используется внешний аналоговый вход (входной сигнал поступает от шгырька LVDIN) 1110 = 4,5 В - 4,77 В 1101 =4,2 В-4,45 В 1100 = 4,0 В-4,24 В 1011 = 3,8 В-4,03 В 1010 = 3,6 В-3,82 В 1001 =3,5 В-3,71 В 1000 = 3,3 В-3,50 В 0111 =3,0В-3,18В 0110 = 2,8 В-2,97 В 0101 =2,7 В-2,86 В 0100 = 2,5 В-2,65 В 0011 =2,4 В-2,54 В 0010 = 2,2 В-2,33 В 0001 = 2,0 В - 2,12 В 0000 = зарезервировано Примечание. Режимы LVDL3:LVDL0, которые задают порог, ниже допустимого рабочего напряжения устройства, не отрабатываются Рис. 13.11. Регистр LVDCON С аппаратной точки зрения имеется немного такого, что можно делать с 18F242, но нельзя выполнить с 16F873A. Большой шаг вперед связан с использованием языка прог- раммирования С, который работает намного лучше с семейством 18. Это, в свою очередь, ведет к использованию операционной системы реального времени, которую мы рассмот- рим в конце этой книги. 13.9. 18F2420 и расширенный набор команд Микроконтроллеры 18FXX2 — это успешная и мощная группа устройств, однако они представляют собой только один этап достижений для микроконтроллеров семейства 18. Имеется интересное семейство устройств PIC 18, которое очень близко связано с семейст- вом 18FXX2. Оно состоит из набора устройств, которые обозначаются дополнительным О в конце идентификатора устройства. Таким образом, 18F242 имеет эквивалент 18F2420, 18F442 — эквивалент 18F4420, и так далее. Каждое устройство имеет те же самые возмож- ности с точки зрения памяти, подобный набор периферийных устройств и ту же самую ба- зисную разводку штырьков, что и его эквивалент. Мы только подведем итоги важных достижений, воплощенных в этом подсемействе, поскольку оно демонстрирует и другие характеристики, которые характерны для некото- рых устройств семейства 18. Дальнейшие подробности могут быть найдены в соответст- вующей документации.
13.9.18F2420 и расширенный набор команд 389 13.9.1. Нановаттная технология Много встроенных систем имеют батарейное питания, поэтому для них очень важно потреблять настолько мало электроэнергии, насколько это возможно. В этой книге мы не приводим детальное описание того, как потребляемая мощность может быть уменьшена. Такое описание может быть найдено в документации. Как там объясняется, существует три простых способа уменьшения потребляемой мощности для заданной схемы и технологии: • снижение напряжения питания; • снижение тактовой частоты; • выключение неиспользуемых частей схемы. Режим бездействия был доступен во всех микроконтроллерах, которые мы до сих пор рассматривали, как средство снижения потребляемой мощности, когда устройство не было задействовано. Однако имеется много ситуаций, когда микроконтроллер должен продол- жать работать, но потребляемая мощность при этом должна быть минимизирована. Под- ход фирмы Microchip, связанный с использованием нановаттной технологии, делает это возможным. Он включает возможности, кратко перечисленные далее. Альтернативные режимы работы Вместо того чтобы синхронизоваться от основного тактового генератора, микрокон- троллер может быть переключен на работу от генератора таймера 1. Следовательно, когда ЦП должен работать на полной скорости, он может делать это, синхронизуясь от основного тактового генератора. Для тех же периодов времени, когда активность микроконтроллера невелика, он просто может работать более медленно. Тогда в этих случаях он должен пе- реключаться на генератор таймера 1, работающий на меньшей частоте. Эта концепция уже обсуждалась в подразделе 12.9.4 Главы 12. Этот подход может давать значительную эко- номию потребляемой мощности. В этой группе микроконтроллеров имеется также внут- ренний генераторный блок, который обеспечивает набор дополнительных источников син- хроимпульсов. Их выбор находится под управлением программных кодов, поэтому все переключения могут инициализироваться по ходу выполнения программы. Множественные режимы неактивности Не трудно вообразить ситуации, когда необходимо сохранить активность периферий- ных устройств при прекращении работы ЦП. Этого можно добиться только весьма огра- ниченным образом в режиме бездействия, однако упомянутое состояние является основой режимов неактивности. Вход в режим неактивности выполняется посредством предвари- тельной установки бита режима неактивности IDLEN, входящего в специальный функ- циональный регистр, с последующим выполнением команды sleep. В этом случае акти- вируется режим неактивности, при этом сохраняется тот источник синхроимпульсов, ко- торый использовался перед выполнением команды sleep. Имеются различные режимы неактивности, которые соответствуют различным доступным источникам синхроимпуль- сов. Работа ЦП в режиме неактивности от медленного источника синхроимпульсов при- водит к очень значительному снижению потребляемой мощности. 13.9.2. Расширенный набор команд 18F2420 имеет обычный набор команд семейства 18, с 75 командами, которые мы рас- сматривали в Главе 12. Он также имеет дополнительный набор из восьми команд. Они должны быть разрешены посредством установки бита XINST при настройке конфигура- ции. При использовании этих команд говорят, что микроконтроллер работает в расширен- ном режиме.
390 Глава 13. Периферийные устройства в PIC® 18FXX2 Дополнительные команды предназначены для того, чтобы повысить эффективность компилятора С. Следовательно, маловероятно, что программист использовал бы их в программе, написанной на Ассемблере, и мы не будем даже перечислять их здесь. Они все связаны со способностями микроконтроллера использовать косвенную и индексную адресацию, и, следовательно, расширять таким образом возможности компилятора при работе с программным стеком и другими функциями. Важно осознавать существование расширенного набора команд, поскольку компи- лятор С С18, который мы будем применять, использует его. 13.9.3. Расширенные периферийные устройства Ряд периферийных устройств в этом подсемействе доступны в своей “расширенной” версии. Они кратко перечисляются ниже. Расширенные модули ССР Эти модули доступны только на больших устройствах — 18F4420 и 18F4520. Они со- храняют базисные возможности ССР, описанные в подразделе 13.4, но также обеспечивают четыре ШИМ-выхода и способность “инвертировать” полярность выходного сигнала, де- лая активным низкий уровень сигнала, вместо высокого. Расширенный адресуемый USART В этом модуле последовательной связи введен ряд важных доработок, которые вклю- чают автоматическое распознавание скорости информационного обмена, автоматический выход из режима бездействия, а также иные возможности, которые делают его подходя- щим для использования шины Локальной Сети Взаимосвязи (LIN). Модуль АЦП Модуль АЦП теперь имеет 10 возможных входов для корпусов с 28 штырьками и 13 входов для корпусов с 40 или с 44 штырьками. Учитывая доработки модулей ССР, теперь стало возможным устанавливать повторяющуюся последовательность сбора данных при минимальном взаимодействии с программой. Резюме • Микроконтроллеры семейства PIC 18 работают с периферийными устройствами семей- ства PIC 16 при некоторых доработках последних. • Работа с периферийными устройствами всегда протекает в контексте архитектуры се- мейства 18. Наиболее яркими отличиями этого семейства являются: обновленная кар- та регистров и пересмотренная структура прерываний. • Помимо этого, использование некоторых периферийных устройств не претерпело из- менений — они могут применяться точно так же, как их аналоги в семействе 16. • Возможности ряда периферийных устройств были расширены при переходе к семей- ству 18. Разработчики, переходящие от использования устройств семейства 16 к исполь- зованию устройств семейства 18, должны знать эти возможности и давать себе отчет в их потенциальном воздействии на проект. • В общем случае периферийные устройства спроектированы на использование режимов электропитания, которые в максимально возможной степени приближены к их анало- гам в семействе 16. • Набор новшеств, реализованных в семействе 18, отражен в 18F2420 и его близких род- ственниках. Самыми значительными среди них являются использование “нановаттной” технологии и расширенного набора команд.
ГЛАВА 14. ВВЕДЕНИЕ В ЯЗЫК С В предыдущих главах мы создавали все более и более сложные программы, поэтому стало тяжелее программировать на Ассемблере. Стало трудно управлять сложностью про- грамм, находить ошибки, сложно контролировать поток данных программ и даже достаточ- но простые математические задачи (например, такие как измерение света) стало реализо- вывать довольно утомительно. Альтернатива этому — изменить стратегию программирова- ния. На рис. 4.1 показана дилемма программиста и описаны три альтернативных подхода. Вначале вы приняли язык Ассемблер, третий из предложенных пугей, так как он представ- ляет способ написания программ, который напрямую контролирует аппаратное обеспече- ние. Однако теперь, учитывая описанную проблему, целесообразнее рассмотреть другой подход. Языки программирования высокого уровня были созданы для поддержки програм- мной сложности и облегчения отладки. Так можем ли мы использовать какой-либо из этих языков программирования во встроенной среде? Да, можно, например, выбрать С — язык программирования, отлично подходящий для наших целей. Цель этой и трех последующих глав — знакомство с языком С, от начальных принци- пов до практического овладения основными характеристиками, и знание того, как он при- меняются во встроенной среде. Но не все аспекты С охвачены — например, подробно не рассмотрены наиболее передовые возможности. Для обучения будет использоваться компилятор Microchip С18, предназначенный для работы в среде MPLAB®. Его можно или купить, или загрузить бесплатную учебную вер- сию с вебсайта Microchip. Одну из версий этого компилятора можно найти также и на ком- пакт-диске этой книги. Т.о. далее предполагается, что читатели уже имеют к нему доступ. Обучение будет осуществляться на нескольких уровнях. Вначале рассмотрим собствен- но язык программирования С — эти знания полностью независимы от встроенной среды и их можно применять на персональном компьютере или где-нибудь в другом месте. Парал- лельно будем рассматривать как С применяется во встроенной среде и конкретно в среде PIC®. Для того чтобы все это происходило параллельно, знакомство с компилятором С18 проведем в начале главы. Затем практика написания программ на С, развиваемая с помо- щью ступенчатых примеров, будет частично применена в Derbot-18 AGV. Изучая эту и по- следующие главы через некоторое время вы начнете признавать преимущества языка С над языком Ассемблер. А к концу этой главы вы будете знать следующее: • основные возможности языка программирования С; • основные возможности компилятора MPLAB С18, включая его библиотеки. Читатели, имеющие опыт работы с языком С, могут пропустить первые три раздела этой главы, да и некоторые последующие разделы будут, скорее всего, для них также про- стыми. 14.1. Основная идея — почему С? В разделе 4.1 Главы 4 было дано общее представление о языках программирования высокого уровня (HLL). HLL — это язык программирования, который делает возможным использование языка и его конструкций, удобными для человека. В тоже время HLL имеет
392 Глава 14. Введение в язык С однозначно определенные правила, для того чтобы написанная программа могла быть точ- но преобразована в машинный код. Какой бы HLL ни использовался, необходима компьютерная программа-посредник для преобразования написанной программы в машинный код компьютера. Если программа пре- образуется перед ее запуском, то конвертирующая программа называется компилятором. С — пример языка программирования, использующего компилятор. Если протрамма пре- образуется во время ее работы, то конвертирующая программа называется интерпрета- тором. Basic — пример языка программирования, использующего интерпретатор. Огромное преимущество HLL — это портативность. Написанная человеком npoipaM- ма не зависит от компьютера, на котором она будет запущена. А компилятор или интерпре- татор, создающий действующий машинный код, зависит от компьютера. Таким образом, один код может запускаться (опять же, нужно обратить внимание, теоретически) на совер- шенно разных компьютерах. Это, конечно, совершенно отличается от подхода языка Ас- семблер, который полностью зависит от модели компьютера. Выбирая HLL для встроенных программ, мы хотим получить преимущества в более простом и надежном кодировании. В тоже время мы хотим максимально сохранить пре- имущества тесной работы с аппаратным обеспечением, которые доступны при использо- вании Ассемблера. Язык С создавался для намного более простых компьютеров 1970-х го- дов. Несмотря на то, что во многих случаях С обогнали другие языки программирования для ПК и рабочих станций, он остается очень мощным языком программирования именно для тесной работы с аппаратным обеспечением компьютера, что нам и нужно во встроен- ных системах. С обладает необходимыми нам возможностями HLL, в тоже время, позво- ляя иметь доступ к элементам аппаратного обеспечения. 14.2. Введение в С Несмотря на относительную простоту языка в современном понимании, С позволяет создавать сложные замысловатые программы. Цель этого раздела — рассмотреть основы С, используя простые примеры программ. Это делается с той целью, чтобы читатель смог двигаться как можно быстрее, используя компилятор MPLAB С18, и начать писать прос- тые программы для микроконтроллеров семейства PIC 18. 14.2.1. Немного истории С был создан в конце 1970-х годов в Bell Labs, Нью-Джерси, США. В 1978 году Брайен Керниган и Денис Ритчи опубликовали его первую общедоступную документацию. Эта документация стала настолько известна, что ее часто называют версией ‘K&R’. В 1989 эта версия С была признана Американским национальным институтом стандартов (ANSI) как стандарт ХЗ.159-1989. Признание этого стандарта было важным событием, так как имен- но на нем основан компилятор Microchip С18. Этот стандарт стал широко признанным, можно много найти его упоминаний под именем ‘ANSI С’. В 1990, Международная ассо- циация стандартов (ISO) приняла эту же версию как Международный Стандарт с исправ- лениями 1995 и 1999 годов. Версия 1999-го года включает расширения, которые не выпол- няются компиляторами встроенных систем. 14.2.2. Первая программа Традиционно принято, что книги по С должны начинаться с примера программы, ко- торая выдает на экран слова ‘Hello world’. Во многих встроенных системах не будет такого экрана для вывода. В качестве альтернативы почти во всех встроенных системах выступа- ет первейшая необходимость вывода данных в порт. Следовательно, наш первый пример программы будет просто увеличивать число и выводить его в порт В микроконтроллера семейства PIC 18. Эту программу можно увидеть в примере 14.1.
14.2. Введение в С 393 Пример программы 14.1. Увеличение значения для вывода в порт В______________ /************->t************************************************************ Пример 1. Вводный пример программирования на С для микроконтроллера семейства PIC 18. 8-битовое значение для вывода в порт В постоянно увеличивается. Файлы c018i.o и p!8f242.1ib добавлены Скриптом Компоновщика. TJW 21.10.05 Протестировано 23.10.05 //Присоединить файл заголовка 18F242 со специфичными для процессора //объявлениями #include <pl8f242.h> unsigned , char counter; //определяем counter как беззнаковый символ void main (void) //здесь начинается главная программа { TRISB = 0; //инициализируем все биты PORTB для вывода counter = 1; //значение counter инициализируем как 1 while (1) r t PORTB = counter; //поместим значение 'counter' в порт В counter } } = counter + 1; //увеличим counter 14.2.3. Трассировка программы — объявления, инструкции, комментарии и пространство С — язык программирования в так называемой свободной форме. Это означает, что не существует строго определенного формата, которого нужно придерживаться при на- писании программ, в отличие от Assembler, когда местоположение слова в строке может быть решающим. Грубо говоря, программа на С состоит из: объявлений, выделяющих память и инициа- лизирующих что-либо; инструкций, выполняющих программные действия; комментариев, объясняющих читателю, что делает программа; пространства, обеспечивающего необхо- димые интервалы между используемыми символами и словами, а также улучшающего понятность расположения кода. Давайте рассмотрим все эти составляющие по очереди. Комментарии Комментарии начинаются с комбинации /♦ и заканчиваются */. В такой форме они мо- гут выходить за пределы одной строки, могут предшествовать или следовать за инструк- циями и объявлениями. Так, например, можно увидеть, что первые семь строк примера про- граммы — это комментарии, несмотря на то, что открывающие и закрывающие символы комментария слились со строками звездочек. После блока заголовка находится пустая строка. Для С это не проблема — такие строки можно использовать для повышения каче- ства зрительного восприятия и, как результат, понятности программы. Альтернативный формат комментариев — двойной слэш (//) перед комментарием. То- гда такой комментарий продолжается только до конца данной строки и не требует ника- кого завершающего символа. Удобно использовать оба формата комментариев: первый для
394 Глава 14. Введение в язык С крупных комментариев, второй — для отдельных строк. Такая практика принята и в дан- ной книге, как можно увидеть в примерах программ. Как и в программировании на Assembler, можно свободно использовать комментарии для краткого и понятного описания того, что предполагается делать в программе. Объявления Объявления используются во многих местах для создания программных элементов (на- пример, таких как переменные и функции) и указания их свойств. Важно, что все пере- менные и функции в С должны быть объявлены до того, как они будут использоваться. За- даваемые характеристики включают тип элемента данных (например, с фиксированной или плавающей точкой), размещение в памяти или характеристики функций. Объявления за- вершаются точкой с запятой. В примере программы имеется строка unsigned char counter; //определяем counter как беззнаковый символ Это объявление, смысл которого будет скоро раскрыт. В простых программах объявления обычно находятся вначале программе, что выглядит логично. Однако, по мере знакомства с более сложными программами, мы увидим, что объ- явления могут встречаться в пределах всей программы, и будет иметь значение, где они располагаются. Инструкции Инструкция — это то, что выполняет программные действия. Инструкции выполняют математические или логические операции, определяя процесс выполнения программы. Каждая инструкция, которая не является блоком (смотри ниже), заканчивается точкой с запятой. Существует много видов инструкций. Наиболее общий из них — это команда-выраже- ние, включающая математические манипуляции. Примерами команд-выражений из при- мера программы 14.1 являются: TRISB =0; // инициализируем все биты PORTB для вывода counter =1; // значение counter инициализируем как 1 Инструкции выполняются в порядке их появления в программе, исключениями явля- ются ветви программы. Блоки кода Объявления и инструкции могут группироваться в блоки. Блоки заключаются в фигур- ные скобки. Пример блока из примера программы 14.1: while (1) ( PORTB = counter; //поместим значение 'counter' в порт В counter = counter + 1; //увеличим counter } Блоки могут находиться внутри других блоков, каждый из которых заключается в фи- гурные скобки. Отслеживание этих пар фигурных скобок — важное времяпрепровожде- ние в программировании на С, так как в сложных частях программного обеспечения могут находится многочисленные пары вложенных фигурных скобок. Общая, и очень хорошая практика — делать отступы для пар фигурных скобок так, чтобы совместимые пары нахо- дились на странице строго одна под другой, а каждая последующая вложенная пара была сдвинута несколько глубже. В таком случае легче отслеживать пары фигурных скобок.
14.2. Введение в С 395 Пространство Разумное использование пространства в программах на С может быть очень важным моментом для ясности понимания программы. Пространство необходимо для разделения слов, которые в противном случае сольются в одно, например в объявлениях в упоминав- шемся выше примере. Добавочные промежутки, включая пустые строки, компилятором игнорируются и используются программистом лишь для оптимизации макета программы. Это одновременно относится и к пустым строкам, и к отступам внутри строк. Например, в приведенном выше примере блока фигурные скобки вынесены в отдельные строки и рас- положены строго одна над другой. Однако программа компилировалась бы точно также, если бы выглядела следующим образом: while (1)(PORTB = counter; //поместим значение 'counter' в порт В counter = counter + 1;} //увеличим counter Очевидно, что программа была бы менее удобочитаемой, в частности при поиске окон- чания блока. Необходимость в хорошем макете программы заметно увеличивается вместе с ростом сложности программы. 14.2.4. Зарезервированные слова языка С В языке С определено только 32 зарезервированных слова. Они перечислены в табли- цах А6.1-А6.3 вместе с кратким описанием. Можно увидеть, что основное количество зарезервированных слов относится к типам данных. В нашем примере объявление unsigned char counter; //определяем counter как беззнаковый символ описывает переменную с именем counter и использует зарезервированные слова unsig- ned char для определения типа переменной как “беззнаковый символ”. Другие зарезервированные слова (см. табл. А6.2) касаются процесса выполнения про- граммы. В нашем примере зарезервированное слово while определяет бесконечный цикл, описанный в разделе 14.2.8. Зарезервированные слова распознаются компилятором, который ожидает, что они при- меняются в строго определенном смысле. Их нельзя использовать для других целей, напри- мер, как имена переменных. 14.2.5. Функции С Программы на С оформляются как функции. Каждая программа должна содержать, по крайней мере, одну функцию, называемую главной (main). Выполнение программы все- гда начинается с главной функции, и программа находится внутри нее. Не считая главной функции, в некотором смысле функции С похожи на подпрограммы Ассемблера. Они используются похожим образом, в основном для содержания опознавае- мого программного действия. Для того чтобы иметь хорошую структуру программы, стре- мятся поместить как можно больше кода внутри функций, имея главную функцию, вызы- вающую вложенные функции. Любая функция может вызывать любую другую. Функции С и подпрограммы Ассемблера различаются процессом передачи данных из вызывающей программы в функцию. В функцию могут передаваться элементы данных, называемые аргументами. Они, однако, должны быть такого типа, как было объявлено за- ранее. Разрешается только одна возвращаемая переменная, тип которой также должен быть описан. Данные только копируются в переменную, следовательно, функция не меняет зна- чение этой переменной. Соответственно, результат функции должен быть предсказуемым и контролируемым. Вместо термина ‘’'аргумент'" часто используется термин “параметр". Различие между этими двумя терминами описывается в спецификациях языка С. В данных главах мы будем, тем не менее, использовать их по очереди.
396 Глава 14. Введение в язык С Функция определяется в программе блоком кода, имеющим особые характеристики. Его первая строка является заголовком функции. Заголовок функции из приведенного здесь примера программы иллюстрирует ее общий формат: Сначала указывается тип возвращаемого результата. В данном примере зарезервиро- ванное слово void используется для того, чтобы указать, что не ожидается никакого воз- вращаемого результата. Это общая практика для главной функции. После имени функ- ции в квадратных скобках можно перечислить один или больше типов данных, опреде- ляющих аргументы, которые должны передаваться в функцию. В данном случае (снова, как и ожидается для главной функции) передаваемых аргументов нет, и опять-таки заре- зервированное слово void используется для того, чтобы это указать. После заголовка функции в фигурных скобках содержится собственно код функции. Он может быть любым, начиная от одной строки до многих страниц. Последней инструкцией функции может быть зарезервированное слово return, которое определяет значение, воз- вращаемое в вызывающую функцию. Это необязательно, если возвращаемое значение не требуется. Можно увидеть, что для ясности программа располагается так, что фигурные скобки, в которых находится главная функция, выровнены по левому краю, а которые содержат инструкцию while — с отступом. В примере программы 14.1 главная функция только одна. Количество последующих вызовов функций увеличивается, когда используется много функций. Такие ситуации опи- сываются в последующих главах. 14.2.6. Типы и хранение данных Переменные в программе на С имеют четыре атрибута: имя, тип, значение и место хра- нения в памяти. Было уже сказано, что тип переменной (например, со знаком или беззна- ковое, с фиксированной или плавающей точкой) нужно описать до ее использования. После того, как тип объявлен, компилятор может определить объем памяти, необходимый для хра- нения этой переменной. Ее значение может быть потом, если нужно, инициализировано. Слова, которые используются для задания типа переменной, перечислены в табл. А6.1. Фактический объем памяти, выделенный для каждого типа данных, может отличаться для разных компьютеров. Типы данных, доступные в компиляторе MPLAB Cl8, вместе с объе- мом выделяемой для их хранения памяти показаны в табл. А6.4. Например, в примере про- граммы 14.1 переменная counter определена как беззнаковый символ. В табл. А6.4 по- казано, что компилятор С18 определит для ее хранения объем памяти в 8 бит. Это полез- ный тип данных для многих однобайтовых переменных, которые используются в среде Р1С. Позже мы увидим, что PORTB и TRISB также определены как беззнаковые символы. Имя элемента данных должно начинаться с буквы. При написании сложных программ имя переменной обычно начинают с буквы или букв, определяющих тип переменной, например, имя counter в примере программы могло бы быть заменено на uicounter — для напоминания программисту о том, что это беззнаковое целое. Это помогает програм- мисту помнить тип переменной и, тем самым, уменьшить количество ошибок. Тем не ме- нее, в данной книге не принята такая практика в примерах программ. Числа, объявляемые
14.2. Введение в С 397 в программах, по умолчанию считаются десятичными, с первой ненулевой цифрой (не zero). Восьмеричные числа задаются со старшим 0, шестнадцатеричные начинаются с Ох. 14.2.7. Операции С Множество разнообразных операций, признаваемых в С, можно увидеть в табл. А6.5. Символы, которые используются, привычны, но их применение не всегда такое, как в обычной алгебре. Например, одиночный символ равенства (‘=’) используется для присвое- ния значения переменной. Двойной символ равенства (‘==’) используется в качестве обыч- ного ‘равно’. Так, в примере программы 14.1 строка TRISB = 0; //инициализируем все биты PORTB для вывода означает, что переменной TRISB присвоено значение 0. Это можно прочитать как “пере- менная TRISB принимает значение 0”. В заголовочном файле 18F242 переменная TRISB была определена как беззнаковый символ, следовательно, как 8-разрядное число. Благода- ря макрокоманде порта строка программы, упомянутая ранее, устанавливает биты порта В для вывода. Операторы имеют определенный порядок приоритетов, показанный в таблице. Компи- лятор использует этот порядок, когда выполняет инструкции. Если более чем один опера- тор имеют одинаковый приоритет в инструкции, тогда эти операторы выполняются по очереди, слева направо или справа налево, как показано в табл. А6.5. В качестве очень простого примера можно привести строку из примера программы counter = counter + 1; содержащую два оператора. В табл. А6.5 можно увидеть, что оператор сложения имеет приоритет 4, в то время как оператор присваивания — 14. Следовательно, сначала будет выполнен оператор сложения, а затем присваивание. В результате переменная counter будет увеличена на 1. 14.2.8. Контроль за ходом выполнения программна зарезервированное слово while Все зарезервированные слова из табл. А6.2 связаны с ходом выполнения программ, например циклами и ветвлением. Первый пример, зарезервированное слово while, позво- ляет выполнять оператор или группу операторов до тех пор, пока выполняется заданное ус- ловие. Это первая, встретившаяся нам, структура из ряда циклических и разветвляющих конструкций. Общая конструкция while выглядит так: while (условное выражение) statement; В результате оператор будет выполняться до тех пор, пока “условное выражение” будет “истина” (т.е. ненулевое). Когда условное выражение перестанет быть “истина”, выйол- нение программы продолжится после этого цикла. Если нужно сопоставить while более одного оператора, тогда группу операторов мож- но заключить в фигурные скобки, как показано ниже: while (условное выражение) ( оператор 1; оператор 2; оператор 3;
398 Глава 14. Введение в язык С Заметим, что условие в цикле while вычисляется вначале выполнения цикла. Если оно истинно, тогда цикл будет выполнен полностью даже в том случае, если условие меняется в середине цикла. В этом примере задается бесконечный цикл, поставив 1 в качестве условного выра- жения. while (1) { PORTB = counter; //поместить значение 'counter' в порт В counter = counter + 1; } Следовательно, два оператора, находящиеся внутри фигурных скобок while, будут бесконечно повторяться. 14.2.9. Препроцессор С и его директивы Процесс компиляции состоит из определенных этапов. Первый из них берет на себя препроцессор. Он реагирует на любые директивы препроцессора, которые найдет. Это похоже на директивы Ассемблера, когда инструкции даются непосредственно компилято- ру. Примеры директив препроцессору можно просмотреть в табл. А6.6. Формат директив препроцессора требует, чтобы каждая директива размещалась в отдельной строке. Дирек- тивы не заканчиваются точкой с запятой. Строка в примере программы ♦include <pl8f242.h> //для всех объявлений 18F242 использует директиву #include для присоединения особого для компилятора заголовоч- ного файла. Этот особый для компилятора С18 файл содержит объявления, необходимые для этого процессора из семейства 18, и сохраняет уже имеющиеся объявления для того, чтобы узнать их в исходной программе. Он содержит объявления для всех СФР (Специ- альных Функциональных Регистров), включая и те, что используются в программе для порта В. 14.2.10. Использование библиотек, Стандартная библиотека Так как С — простой язык, большая часть его функциональности порождается из стан- дартных функций и макросов, которые доступны из сопровождающих любой компилятор библиотек. Библиотека С — это набор предварительно скомпилированных функций в виде объектных файлов, которые можно присоединить к приложению. Состав Стандартной библиотеки определен в стандарте ANSI. Он включает в себя функции для ввода и вывода данных, семейство математических функций (например, все тригонометрические функции) и другие функции для обработки данных. В дополнение к Стандартной библиотеке, как мы увидим дальше, компилятор может иметь и свою собственную библиотеку функций, специально предназначенную для его ко- мандной среды. 14.3. Компиляция программ на С Когда исходная программа на С закончена, она компилируется. В итоге этот процесс приводит к получению файла, содержащего машинный код, равноценный оригинальному, который может выполняться на компьютере. Мы уже обсуждали концепцию заголовочных и библиотечных файлов. Они широко ис- пользуются, поскольку очень немногие исходные программы на С автономны. Как только дополнительные файлы присоединены, конечная исполняемая программа компонуется
14.4. Компилятор MPLAB С18 399 из сопутствующих файлов, часто достаточно сложным способом. В процессе компиляции программы на С последовательно создается семейство выходных файлов. Процесс компиляции, вместе с используемыми и создаваемыми файлами, в общих чер- тах показан на рис. 14.1. Главная программа (исходная программа на С) написана на язы- ке С в файле с расширением . с. Она, очень вероятно, содержит (используя директиву пре- процессора #include) другие стандартные файлы, например особый для компилятора заголовочный файл, который мы уже видели. Исходный файл, вместе со всеми присоеди- ненными заголовочными файлами, называют единицей трансляции. Рис. 14.1. Структура файла С с файловыми расширениями С18 Когда исходная программа закончена, она компилируется, используя компилятор С, с созданием объектного файла. Он состоит из перемещаемого кода с еще не полностью сос- тавленной картой распределения памяти процессора. Могут также создаваться и другие файлы, включая скомпилированные и смонтированные таким же образом файлы на Ассем- блере, которые управляются объектными файлами содержащими (в основном) перемеща- емый код. На этой стадии все простейшие программы можно объединить с другими файлами, на- ходящимися уже в стадии объектного файла. Это могут быть файлы из библиотек, сопро- вождающих компилятор, или файлы, предварительно созданные программистом или ком- панией. Задача Компоновщика — объединить все эти файлы вместе, в результате получив один исполняемый файл. Этот процесс происходит под руководством Сценария компонов- щика — файла, который определяет карту распределения памяти процессора и предостав- ляет другую информацию, включая возможность получения информации из других файлов, также предварительно скомпилированных. Начальный заглавный блок в примере програм- мы 14.1 устанавливает связь с двумя объектными файлами, c018i . О и pl8f242 . lib, которые присоединяются к программе Компоновщиком. Как это происходит и какую роль они играют, объясняется в главе 17. После завершения процесса связывания, предполагая, что ошибок получено не было, создается семейство выходных файлов. Файлы, создаваемые компилятором Microchip С18. подробно обсуждаются в разделе 14.5.4. 14.4. Компилятор MPLAB С18 Компилятор MPLAB Cl8 — это собственный компилятор С компании Microchip, напи- санный специально для микроконтроллеров семейства PIC 18. Он соответствует стандарту
400 Глава 14. Введение в язык С ANSI ХЗ.159-1989, за исключением того, что содержит также ряд компонентов, созданных для оптимального использования этого компилятора именно микроконтроллерами PIC. Компилятор С18 функционирует в главной среде MPLAB IDE, рядом работая с Ассем- блером, Компоновщиком и Программой управления библиотеками. Установив компилятор один раз, его можно присоединять к этому рабочему набору. В отличие от MPLAB, компи- лятор нужно покупать, он стоит в пределах $150. На момент написания книги учебную версию можно скачать бесплатно на сайте Microchip. Ее копия находится также на ком- пакт-диске, прилагаемом к книге. Компилятор достаточно хорошо описан (естественно, на английском языке) в докумен- тации. Она доступна на сайте Microchip. В следующих разделах этой главы компилятор описан на достаточном уровне для запуска всех примеров программ. 14.4.1. Основы MPLAB С18 соответствует основным функциональным требованиям С, упомянутым в разделе 14.2.6. Он также вводит для двоичных чисел очень полезную приставку ‘Ob’. Например: TRISA = 0b'10000110'; //инициализируем PORTA TRISB = 0x86; //инициализируем PORTB TRISC = 134; //инициализируем PORTC помещает одинаковые значения в каждый из регистров TRIS. 14.4.2. Арифметические операции Стандарт ISO/ANSIС требует выполнения всех арифметических операций с целой сте- пенью точности (т.е. 16 разрядов) или выше. Компилятор С18, используя 8-разрядную точность, выходит за пределы этого требования и берет на себя арифметику символьных типов данных. В последующих разделах подразумевается, что читатель установил MPLAB IDE и ком- пилятор MPLAB С18, следуя простой процедуре описанной в документации. Использует- ся версия 3.00 компилятора С18. 14.5. Учебник по С18 Описав, насколько это возможно, простейшую программу на С, давайте попробуем ее откомпилировать и смоделировать. Создадим в MPLAB новый проект с подходящим име- нем, на следующих далее рисунках используется совершенно неоригинальное имя exam- ple!. Откройте новый файл и введите туда код из примера программы 14.1. Сохраните этот файл, например, с именем example! . с и добавьте его в проект, используя команду Project > Add Files to Project. 14.5.1. Компоновщик и его сценарии Поскольку процесс компиляции автоматически использует Компоновщика, важно включить Сценарий компоновщика. Форма Сценария будет обсуждаться в Главе 17, пока же мы просто включим его. В окне проекта, как видно на рис. 14.2, щелкнем правой кноп- кой мыши на строке Linker Scripts. В результате появится приглашение Add File. Щелк- нув на этом приглашении, найдем в окне Add Files to Project папку mccl 8/lkr/. Внутри этой папки щелкнем на файле 18f242 . Ikr. Теперь окно проекта будет выглядеть точно так, как показано на рис. 14.2.
14.5. Учебник поС18 401 В examplel.m... IStaxamolel .mcp Н Source Files example! с Header Files - Object Files ' Library Files H Linker Scripts : 18f242.lkr : Other Files Рис. 14.2. Включенный в проект Сценарий компоновщика Отметим, что мы использовали здесь Сценарий компоновщика в его исходной форме и местонахождении. В более сдожных проектах лучше создавать копию Сценария в том же каталоге, где находится проект. Это дает возможность менять этот файл и избегать, при этом, повреждения исходного файла. 14.5.2. Заголовок для компоновки и библиотечные файлы В нашем примере программы включен заголовочный файл в строке #include <p!8f242.h> Следовательно, важно позаботиться о том, чтобы путь для поиска файла был правильным. Сценарий компоновщика вызывает и другие библиотечные файлы, которые также должны быть найдены. Можно проверить, что эти пути заданы правильно, используя для этого меню Project > Build Options > Project > General. Тогда появится окно, показанное на рис. 14.3. Если компилятор установлен в заданном по умолчанию месте, можно просто щел- кнуть на Suite Defaults — это установит указанные пути. Потом нажмите кнопку ОК. Build Options For Project "example 1 mcp" Oi General | MPASM/C17/C18 Suite ] MPASM АэветЫаг| MPUNK Linker | MPIABC18| Output Directory J(BINDIR) J | Intermediates Directory JjTMPDIR) j . Browse.,. I AssemWei Include Pain. I(AINDIR) Include Path. iiINCDIH) iC.\mcc18\h Blows».. Library Pu8i. $(L.BDIR) |c \mcc18Vib * ' Browse,, bnkerScnptPalh. IfLKRDIR) jc \mcc18\lib—— Browse. Help | Sute Defaults j I OK | Cancel Рис. 14.3. Установка путей для заголовочных файлов
402 Глава 14. Введение в язык С 14.5.3. Компоновка проекта Теперь можно скомпоновать проект. Как и в Ассемблере, выберите меню Project > Build АП. Если все введено и связано правильно, в окне Output, в конечном счете, появит- ся сообщение Build Succeeded, как показано на рис. 14.4. Отметим, что процесс компонов- ки состоит из множества определенных этапов и занимает значительно больше времени, чем в Ассемблере, даже для таких маленьких программ как эта. Этапы компоновки пока- заны на рис. 14.4. На стадии компиляции в окне показывается, что выполняется множество установок компиляции, обозначаемых как -Ou- -Ot- -Ob и т.д. Это значения компилятора по умолчанию, и они не представляют особого интереса на этом (раннем) этане использо- вания компилятора. В Output Build J Version Control | Fittci itt fifes j MPLAB SIM | Clean: Deleting intermediary and output files. Clean: Deleted file “C:\My Documents\MPLAB Projects\C Projects\exatnple1.o". !Clean: Deleted file "examplel.cof”. Clean: Deleted file “examplel.cod". iClean: Deleted file "examplei.hex". Clean: Deleted file "exampleUst". Clean: Done. Executing: "c:\mcc18\bin\mcc18.exe" -p=18F242 "examplel.c”-fo="example1.o,,/i,,C:\mcc18\h" -Ou- -Ot- -Ob- ; Executing: "c:\Program Files\Microchip\MPASM Suite\MPLink.exe"/r'c:\mcc18\lib'7k',c:\mcc18\lib" "C:\nicc18 MPLINK 3.93. Linker ^Copyright (c) 2004 Microchip Technology Inc. : Errors : 0 IMP2COD 3.90, COFF to COD File Converter jCopyright (c) 20U4 Microchip Technology Inc. Errors : 0 1MP2HEX 3.90, COFF to HEX File Converter iCopyright (c) 2004 Microchip Technology Inc. Errors : LI Loaded C:\My Documents\MPLAB Projects\C Projects\example1.cof BUILD SUCCEEDED: Sat Oct 22 14:53:48 2005 ............................................................................... .. .............. Jd Рис. 14.4. Окно Output, с сообщением об успешной компоновке Если проект не был успешно откомпилирован, необходимо внимательно исследовать сообщения с суммарными ошибками. Вначале компилятор проверяет правильный синтак- сис программы, т.е. то, что программа удовлетворяет правилам форматирования для языка С. Даже если вы не сделали никаких ошибок, попробуйте все же удалить, например, точку с запятой или вставить несколько мелких ошибок — для того, чтобы посмотреть на реакцию компилятора. Если присутствует синтаксическая ошибка, компилятор сообщит об этом в окне Output вместе с номером строки, в которой присутствует ошибка. Если номера строк не отображаются, то они могут быть включены. Выполните команду меню Edit > Properties > Editor и в окне MPLAB и установите флажок Line Numbers. Возможно, стоит заметить, что номер строки, в которой компилятор нашел ошибку, не обя- зательно может соответствовать той строке, на которой ошибка действительно находится. В качестве примера попробуйте закомментировать открывающую скобку главной функ- ции. Вы увидите, что синтаксическая ошибка будет указана на следующей строке — той, которая написана правильно. Когда все синтаксические ошибки будут исправлены, компилятор продолжит поиск других типов ошибок и также выдаст их номера. Номера ошибок, с кратким описанием их сути и возможных путях исправления, описаны в документации.
14.6. Моделирование программы на С 403 14.5.4. Файлы проекта Успешно скомпонованный проект с результирующими файлами показан на рис. 14.5. Многие файлы можно также увидеть на схеме — см. рис. 14.1. Исходные и результирующие файлы, которые находятся в окне проекта, следующие: • Исходный файл (. с). Это первоначальный исходный файл, написанный на языке С. • Файл отладки и обозначений (. cod). Это файл для отладки, используемый MPLAB IDE версии 5.хх и более ранних версий. • COFF-файл с конечным модулем (. cof). Этот файл предоставляет отладочную инфор- мацию для MPLAB IDE версии б.хх или более поздних версий. • Исполнимый файл (. hex). Это фактический программный код, который можно загру- зить в микроконтроллер и использовать для моделирования или эмуляции. • Файл листинга (. 1st). Файл показывает первоначальный исходный код вместе с объ- ектным кодом. Также там находятся символьные значения, информация об использо- вании памяти, ошибках и уведомлениях. • Объектный файл (. о). Этот файл содержит перемещаемый код. Он является результи- рующим для компилятора или Ассемблера, и исходным — для Компоновщика. Объ- ектные файлы также можно найти в библиотеке. Рис. 14.5. Файлы простого проекта на С 14.6. Моделирование программы на С Теперь исследуем моделирование примера 1. Несмотря на то, что программа очень простая, моделирование откроет много интересного о том, как программа на С компону- ется в общем, и вернет нас снова к рис. 14.1. Как и в разделе 4.7 Главы 4 выберем симулятор MPLAB, открыв меню Debugger > Select Tool > MPLAB SIM. С помощью меню View > Watch откроем окно Watch и по- кажем значения counter, PortB и PCL. Используя панель инструментов отладки (см. рис. 4.9), установим counter в нуль, отметив для себя, что, как и ожидалось, Program Counter (PCL) очищает в нуль. Другое окно программы, которое открывается на экране, абсолютно непрошенное. Это — c018i . с, программа, запускаемая Компоновщиком. Она включает определенную инициализацию процессора, необходимую для правильной рабо- ты С. Мы вернемся к ней в Главе 17.
404 Глава 14. Введение в язык С Выполняя программу пошагово (или используя Animate), вы обнаружите, что выпол- нение, в конце концов, перейдет к исходной программе. В окне Watch затем можно уви- дегь, что значения counter и PORTB были увеличены. Начиная с этого места, выполне- ние программы остается бесконечным в цикле while. Интересный способ увидеть, как программа на С была создана — это просмотреть Лис- тинг дизассемблирования, выбрав меню View > Disassembly Listing. В этом окне (как показано на рис. 14.6) можно увидеть исходный код на С и заменивший его код на Ассемб- лере. Можно заметить, что некоторые строки кода на С были транслированы в одну строку Ассемблера. Однако в большинстве случаев одна строка кода на С заменяется несколькими строками Ассемблера. Это первый признак того, что при программировании на С созда- ются более простые исходные файлы. По мере того, как увеличивается сложность кода на С, коэффициент масштабирования между кодом на С и Листингом дизассемблирования становится все большим. Disassembly Listing OOEA OOEC OOEE 00F0 00E4 00E6 00E8 14: 15: 00E2 12 : .13: 18: 00F2 19: 6А93 0100 0E01 SFOA D7FB C08A FF81 298A 6F8A OOF4 0012 unsigned char counter; void main (Void) /‘Min function starts here’/ TRISB 0; CLRF Cx±93, counter " M0VLB MOVLW MOVWF 0 0x1 0x0a, while f1i BRA Oxea PORTB = MOVFF 0x8a, HOP counter IWCF C>:8az ' MOVWF 0x8a, RETURN 0 о£ PORTB аз output ACCESS 1; /’counter value 13 initialised BANKED counter; 0xf81 - counte; I, BANKED BANKED Рис. 14.6. Листинг дизассемблирования для части примера программы 14.1 На рис. 14.6 можно также увидеть, что адрес TRISB, 0F93H, применяется правильно, как было показано на рис. 12.5. Адрес ячейки памяти 8АН в банке 0 предназначен для пе- ременной counter. Перенести значение counter в PORTB можно следующим опера- тором: MOVFF 0x8a,0xf81 где Oxf 81 — адрес порта В. Подобным образом можно увидеть и увеличение переменной counter. Заметим, что операторы Ассемблера, как видно из их адресов в памяти, распо- лагаются не по порядку. Оператор перехода по адресу в памяти 00F2H задает, фактически, непрерывный цикл и должен находиться в конце листинга. 14.7. Второй пример программы на языке С — программа Фибоначчи Давайте сделаем следующий шаг в программировании на С, слегка увеличив сложность программы. Пример программы 14.2 предоставляет версию на С уже знакомой нам про- граммы — генератора последовательности чисел Фибоначчи. Эта программа считает
14.7. Второй пример программы на языке С — программа Фибоначчи 405 последовательность Фибоначчи, сначала двигаясь до определенного уровня, а потом ра- ботая в обратном направлении. Эти действия повторяются бесконечно. Пример программы 14.2. Генератор последовательности Фибоначчи_____________ /************************************************************************* Фибоначчи В последовательности Фибоначчи каждое число является суммой двух предыдущих чисел. Данная программа рассчитывает числа Фибоначчи с 8-битовой точностью. Файлы c018i.o и pl8f242.1ib включены Сценарием компоновщика. Программа предназначается только для моделирования и, следовательно, написана без команд ввода/вывода. TJW 21.10.05 Протестирована 23.10.05 ;*************о******о**************о*********о**********************/ #include <pl8f242.h> //эти адреса памяти выделены для последовательности Фибоначчи unsigned char fibO; //наименьшее число //вверх, последнее (первоначальное при движении при возвращении назад) unsigned char fibl; //среднее число unsigned char fib2; //последнее число unsigned char fibtemp; //временное место хранения последнего числа unsigned char counter; //показывает, какое значение //последовательности посчитали void main (void) ( fibO = 0; fibl = 1; fib2 = 1; counter = 3; //при инициализации загрузили первые три числа, //поэтому начинаем с 3 loop: do ( fibtemp = fibl + fib2; counter = counter + 1; //теперь перетасовываем номера, не учитывая первоначальное fibO = fibl; //сначала переместим среднее число, //затерев первоначальное fibl = fib2; fib2 = fibtemp; } while (counter<12); //двигаясь в обратном направлении, отнимем fibO от fibl //для получения нового fibO do { fibtemp = fibl -fibO;//последнее число сейчас помещено в fibtemp counter = counter -1; //теперь перетасовываем номера, не учитывая первоначальное fib2 = fibl; //сначала переместим среднее число, //затерев первоначальное
406 Глава 14. Введение в язык С Пример программы 14.2. Окончание fibl = fibO; fibO = fibtemp; } while (fib0>0); goto loop; } 14.7.1. Предварительные сведения о программе — больше об объявлении переменных В соответствии со вступительными комментариями первые строки программы объяв- ляют пять беззнаковых символьных переменных, в то время как первые три строки глав- ной функции присваивают трем из них определенные начальные значения. Существует нес- колько способов сократить этот процесс. Во-первых, объявление одного типа данных не обязательно делать только для одной переменной. Следовательно, пять переменных мож- но объявить в одной строке вместе вот так: unsigned char fibO, fibl, fib2, fibtemp, counter; Программист может решать самостоятельно, предпочтителен ли ему этот формат записи или другой. Недостатком этого формата является то, что в нем сложнее добавить коммен- тарии для каждой переменной, как этого бы, возможно, хотелось. Также во время объявления переменной можно одновременно устанавливать и ее на- чальное значение. Тогда возможный формат объявления выглядит следующим образом: unsigned char fibO = 0; //первоначальное число unsigned char fibl = 1; //среднее число unsigned char fib2 = 1; //последнее число Опять же, программист сам решает, дает ли ему какие-либо преимущества данный фор- мат записи. 14.7.2. Конструкция do-while В программе Фибоначчи присутствуют два цикла. Они записываются здесь, используя зарезервированные слова do и while. Блок кода, следующий за словом do, выполняется до тех пор, пока условие while (для первого цикла counter < 12) истинно, т.е. не ну- левое. В таком цикле код после слова do выполняется хотя бы один раз до того, пока бу- дет проверено условие while. Это отличает цикл do от цикла while, в котором код цикла не выполнится ни разу, если условие на входе в цикл не выполняется. Во время обратного возвращения в последовательности Фибоначчи цикл выполняется до тех пор, пока f ibO не станет нулем, используя другое условие в операторе while. 14.7.3. Метки и зарезервированное слово goto Непосредственно перед первым циклом do появляется выражение loop :. Это метка, определяемая завершающим двоеточием. Последняя строка программы возвращает выпол- нение на метку loop:, используя зарезервированное слово goto. Оператор goto исполь- зуется только для применения таких меток, больше ни с какой другой целью. Этот опе- ратор осуществляет безусловный переход внутри функции, он не может переходить в другую функцию. Программисты не очень любят оператор перехода goto в С, поскольку его неконтролируемое использование ведет к неструктурированным программам.
14.8. Библиотеки MPLAB С18 407 14.7.4. Моделирование программы Фибоначчи Как обычно имеет смысл смоделировать данную программу. Скопируем программу с компакт-диска книги в соответствующий проект и смоделируем, используя MPLAB SIM. Откроем окно Watch с отображенными там PCL и всеми переменными. Запустим програм- му в пошаговом режиме и один раз в главной функции понаблюдаем за выполнением цик- ла. Заметим, что когда counter станет равным 12, блок кода после слова do выполнится, и после этого начнет выполняться следующий цикл. Альтернативная конструкция этого цикла рассматривается в главе 15 и видна в примере программы 15.2. 14.8. Библиотеки MPLAB С18 В завершение этой главы мы сделаем обзор библиотечных функций, доступных в ком- пиляторе С18. Компилятор имеет обширное множество библиотек, которые включают как Стандартную библиотеку С, так и множество других функций, специфических для среды PIC. Большинство программ, написанных для использования компилятором, почти неиз- бежно будут использовать по крайнее мере одну из этих функций, если не больше. Безус- ловно, все последующие примеры программ будут использовать библиотечные функции. Каждая библиотечная функция имеет собственную запись в справочнике по библиоте- кам. Эта запись описывает назначение функции, передаваемые аргументы, тип результата и заголовочные файлы, которые нужно включить. Функции относятся к различным кате- гориям, которые описаны в следующих разделах. 14.8.1. Функции, предоставляющие технические средства для внешних устройств Существует набор функций, которые относятся к внешним устройствам микроконтрол- лера: для включения и настраивания внешних устройств, изменения режима их работы, счи- тывания данных и выключения. Например, функции, перечисленные в табл. 14.1, доступны для АЦП. Можно увидеть (пользуясь, если необходимо, ссылкой к разделу 11.3 главы 11), что эти функции полностью обеспечивают функциональность, необходимую для нормаль- ного использования АЦП. Фактические настройки передаются через аргументы функции, которые описаны в справочнике по библиотекам. Многие из этих функций используются в примере программы в Главе 16. Внешние устройства могут, конечно, управляться напрямую через их СФР (специаль- ный функциональный регистр), но обычно библиотечные функции делают программиро- вание более простым, наглядным и надежным. Знание деталей СФР остается важным и в некоторых случаях все еще необходимым. Это помогает осмыслить, какие параметры дол- жны передаваться в функцию. Рассматриваемые функции являются специфическими для компилятора С18 и не су- ществуют в Стандартной библиотеке С. 14.8.2. Функции, предоставляющие программные средства для внешних устройств Данная библиотека содержит функции с драйверами для многих внешних устройств, которые могут быть подключены к системе. Они включают, например, как драйвера для Hitachi HD44780 LCD (смотри Главу 8), МСР2510 CAN (Локальная управляющая сеть, опи- санная в Главе 20), так и функции для генерирования последовательного обмена данными между программным обеспечением.
408 Глава 14. Введение в язык С Как и функции, предоставляющие технические средства для внешних устройств, рас- сматриваемые функции являются специфическими для компилятора С18 и не существуют в Стандартной библиотеке С. Табл. 14.1. Функции компилятора С18 для АЦП Функция Действие OpenADC( ) Настраивает АЦП SetChanADC( ) Выбирает канал, который будет использоваться ConvertADC( ) Начинает перекодировку АЦП BusyADC( ) Проверяет, занят ли сейчас АЦП ReadADC( ) Считывает результат перекодировки АЦП CloseADC( ) Отключает АЦП 14.8.3. Библиотека общих функций для программного обеспечения Функции из этой библиотеки являются смесью функций из Стандартной библиотеки С и специфическими для Microchip. Их можно разделить на несколько категорий. Классификация символов Данные функции удовлетворяют требованиям Стандартной библиотеки С ctype и осу- ществляют проверки символов для определения их сущности. Примеры таких функций приведены в табл. 14.2. Табл. 14.2. Примеры функций для классификации символов Функция Действие isalnum( ) Определяет, является ли символ алфавитно-цифровым isalpha( ) Определяет, является ли символ символьным iscntrl( ) Определяет, является ли символ управляющим isdigit( ) Определяет, является ли символ десятичным знаком Преобразование данных Эти функции обеспечивают преобразование из одной формы представления данных в другую. Это может быть очень полезно во встроенной среде, так как мы преобразовываем данные из двоичной формы в строку для вывода, или наоборот — читаем строки с клавиа- туры и преобразовываем их в двоичную форму. Примеры таких функций представлены в табл. 14.3. Эти функции являются смесью стандартных функций С и функций, специфич- ных для компилятора С18. Табл. 14.3. Примеры функций для преобразования строк/символов Функция Действие atop( ) Преобразует строку в байт со знаком atof( ) Преобразует строку в значение с плавающей точкой atoi( ) Преобразует строку в 16-битовое целое со знаком atol( ) Преобразует строку в длинное целое itoa( ) Преобразует 16-битовое целое со знаком в строку
14.8. Библиотеки MPLAB С18 409 Управление памятью и строками Этот набор функций позволяет управлять памятью. Большинство взято из Стандарт- ной библиотеки С, хотя есть и отличия. Примеры функций представлены в табл. 14.4. Табл. 14.4. Примеры функций управления памятью Функция Действие memchr( ) Ищет значение в заданной области памяти memcmp( ) Сравнивает содержимое двух массивов memcpy( ) Копирует буфер из данных или программной памяти в данные memset( ) Инициализирует массив повторяющимся значением памяти Функций задержки Все доступные функции задержки перечислены в табл. 14.5. Первая из них — фикси- рованная однотактная задержка, которая компилируется как оператор пор (без действия). Все остальные позволяют осуществлять программируемую задержку, основанную на вре- мени выполнения команды микроконтроллером. Это обеспечивает очень полезный меха- низм задержки во встроенной среде. Табл. 14.5. Г)римеры общих программных функций задержки Функция Действие DelaylTCY ( ) Задержка в один цикл выполнения команды DelaylOTCYx( ) Задержка в десять циклов выполнения команды DelaylOOTCYx ( ) Задержка в сто циклов выполнения команды DelaylKTCYx ( ) Задержка в тысячу циклов выполнения команды DelaylOKTCYx ( ) Задержка в десять тысяч циклов выполнения команды Функции сброса Данные функции позволяют программисту выяснять причину сброса, основываясь на информации о регистре RCON из семейства PIC 18 (рис. 12.14). Примеры функций пред- ставлены в табл. 14.6. Табл. 14.6. Примеры общих программных функций сброса Функция Действие ‘ isBOR( ) Определяет, было ли уменьшение освещения причиной сброса isLVD( ) Определяет, было ли низкое напряжение причиной сброса isMCLR( ) Определяет, было ли очищение ведущего устройства причиной сброса isPOR( ) Определяет, было ли включение питания причиной сброса 14.8.4. Математическая библиотека Эта библиотека содержит математические функции, необходимые Стандартной биб- лиотеке С. Обычно используются переменные с плавающей точкой. Примеры функций приведены в табл. 14.7.
410 Глава 14. Введение в язык С Табл. 14.7. Примеры функций из математической библиотеки С16 Функция Действие sin ( ) Вычисляет синус cos ( ) Вычисляет косинус tan ( ) Вычисляет тангенс sqrt( ) Вычисляет квадратный корень ioglO ( ) Вычисляет десятичный логарифм pow ( ) Возводит х в степень у — (ху) 14.9. Дальнейшее чтение В процессе изучения С стоит обратить внимание на различные виды доступных ссы- лок, которые могут использоваться для расширения знаний по языку. Некоторые из них дают общее представление о С. Часто таких книг вполне достаточно для программирования на настольных ПК, с акцен- том на ввод данных с клавиатуры и вывод на экран компьютера. Также существует много полезных справочников. Они предоставляют полную справочную информацию по языку, не пытаясь структурировать материал в обучающем виде. Быть может очень полезно иметь доступ к одной из них для проверки синтаксиса и т.д. Также есть много книг о встроенной среде. Такие книги нас интересуют больше. Однако они стремятся подробно описать мик- роконтроллер или компилятор, а в таких подробностях много сведений, не очень полезных для конкретных процессоров. Резюме • Несмотря на то что С является языком программирования высокого уровня, у него есть некоторые особенности, благодаря которым С очень эффективно используется на уров- не встроенной системы. Именно его продолжают активно использовать как язык про- граммирования высокого уровня для многих встроенных приложений. • Основные конструкции С относительно просты и логичны, и его изучение не вызывает больших трудностей. • Компилятор MPLAB Cl8 можно использовать как инструмент в MPLAB IDE. Следо- вательно, все специальные знания программиста об этой среде можно сразу же приме- нить в программировании на С. • Для написания программ на С необходимы знания как собственно о языке программи- рования, так и о библиотечных функциях, доступных для используемого компилятора или процессора. В компиляторе С18 доступна богатая коллекция библиотечных функ- ций, обеспечивающих общие служебные потребности, управление внешним оборудо- ванием, данными и выполнение математических задач.
ГЛАВА 15. ЯЗЫК С И ВСТРОЕННАЯ СРЕДА В Главе 14 было дано краткое описание языка программирования С. Теперь мы начнем применять приобретенные знания для написания настоящих встроенных программ на С, начиная с основных встроенных потребностей и заканчивая взаимодействием с внешними устройствами. В процессе будет дано много дополнительных сведений о С — по мере то- го, как они будут появляться в примерах программ. Большинство примеров программ из данной главы применяются в Derbot-18 AGV. Их также можно смоделировать, поэтому не имеет большого значения, есть ли у вас аппарат- ное обеспечение или нет. Много примеров просто переписаны с программ на ассемблере, которые были приведены ранее. При адаптации программ на ассемблере можно сравнить два эти языка программирования; и тот, кто читает книгу сначала, будет встречать уже знакомые сведения, когда будет описываться аппаратное обеспечение. К концу этой главы вам нужно будет хорошо понять следующее: • как получить доступ и управлять отдельными разрядами; • как писать простые функции и вызывать их; • как использовать библиотечные функции, включая те, которые предназначены для контроля над внешними устройствами микроконтроллера; • как структурировать программы на С, должным образом используя функции, циклы и конструкции перехода. 15.1. Главная идея — перенос С во встроенную среду Сейчас мы выбрали язык программирования высокого уровня (HLL), это то же самое, как если бы мы выбрали лучшее в обеих сферах. Мы хотим использовать преимущества HLL, но также сохранить стремление работать напрямую с аппаратным обеспечением — настройка внешних устройств, установка или очищение отдельных разрядов порта и, ко- нечно, установка и реагирование на всевозможные прерывания. Это противоречие разре- шается несколькими способами, которые мы сейчас и рассмотрим. 15.2. Настройка и управление значениями разрядов Пример программы 14.1 демонстрирует очень простой способ использования портов микроконтроллера. Он основывается на СФР регистрах порта, которые объявляются в за- головочном файле; направление передачи данных устанавливается записью в регистр TRIS, и потом данные передаются в порт целыми байтами. Фундаментальным в написании программ для встроенных сред является, конечно же, возможность считывать и устанавливать отдельные разряды. Пример программы 15.1, пере- носящий состояние передних микропереключателей Derbot на светодиоды, показывает, как это делается на С. Этот пример, по большому счету, переписывает пример программы 7.1. Как и требуется, программа состоит из главной функции main, а также двух заданных пользователем функций: для инициализации initialise () и диагностики diagnos- tic (), которые находятся в листинге программы. Для получения сигнала от диагности-
412 Глава 15. Язык С и встроенная среда ческого светодиода программа использует библиотечную функцию С18. Способ исполь- зования функций будет обсуждаться в разделе 15.3. Пример программы 15.1. Derbot — передача состояния передних микропереключателей на светодиоды______________________________________________________________ /************************************************************************* Sw_to_led_l8С Использует PIC 18F242 Работает на Derbot-18. Перевод состояния передних микропереключателей на светодиоды. Файлы c018i.o и pl8f242.1ib добавлены сценарием компоновщика. TJW 22.10.05 Протестировано 24.10.05 Один такт — 4 МГц Слово конфигурации по умолчанию, исключение: кварцевый генератор (HS), таймер питания вкл., контроль понижения напряжения выкл-., WDT выкл., LV программа выкл. */ ♦include <pl8F242.h> ♦include <delays.h> //заголовочный файл для временных задержек //Прототипы функций (Прототипы библиотечных функций в заголовочном файле) void initialise (void); void diagnostic (void); void main (void) initialise (); //вызов функции инициализации diagnostic (); //вызов функции диагностики //перевод состояния микропереключателей на диагностические светодиоды loop: if (PORTBbits.RB4 == 0) PORTCbits.RC6 = 0; else PORTCbits.RC6 = 1; if (PORTBbits.RB5 == 0) PORTCbits.RC5 = 0; else PORTCbits.RC5 = 1; goto loop; } //Инициализировать СФР и установить начальные состояния выходов. //Подразумевается, что аппаратное обеспечение находится в состоянии "Build Stage 1". Все не использующиеся разряды портов установить для вывода. void initialise (void) { TRISA = ObOOOOOOOO; //все разряды порта А устанавливаем на выход // (в этой программе не используются) TRISB = ОЬООИОООО; //Разряды 6 и 5 (микропереключатели) //только для ввода TRISC = 0Ы0000000; //Все разряды для вывода, за исключением //разряда 7 (переключатель режима) //Выключаем все выходы PORTA = 0; PORTB = 0; PORTC = 0; J
15.2. Настройка и управление значениями разрядов 413 Пример программы 15.1. Окончание______________________ //Диагностика: включить светодиоды для Is (Тсу = lus) void diagnostic (void) { PORTCbits.RC6 = 1; PORTCbits.RC5 = 1; DelaylOKTCYx (100); PORTCbits.RC6 = 0; PORTCbits.RC5 = 0; DelaylOKTCYx (100); } 15.2.1. Управление отдельными разрядами Разряды каждого порта определены в заголовочном файле микроконтроллера, ис- пользуя конструкцию С, описанную в разделе 17.9 Главы 17. Для данной программы достаточно знать, что разряд порта можно задать, используя формат PORTxbits . Rxy, где х обозначает порт, а у — разряд этого порта. Примером может служить программа диагностики, находящаяся в конце листинга. В ней разряды 5 и 6 порта С устанавлива- ются в состояние логической 1 в следующих строках: PORTCbits.RC6 =1; PORTCbits.RC5 = 1; Таким образом, теперь у нас есть возможность устанавливать и очищать отдельные разряды в регистре, так как они были объявлены ранее. Поскольку все СФР регистры микроконтроллера и их разряды объявляются в заголовочном файле, данная возможность является большим шагом вперед. 15.2.2. Конструкции условного перехода if и if-else Работа данной программы построена на использовании конструкции условного пе- рехода if-else, которая предоставляет нам возможность выбирать между двумя вари- антами действий. Пример такой структуры находится в главной программе, как показа- но ниже: if (PORTBbits.RB4 == 0) PORTCbits.RC6 = 0; else PORTCbits.RC6 = 1; Это может быть интерпретировано следующим образом: если разряд 4 порта В ра- вен логическому 0, тогда установить разряд 6 порта С в 0; в противном случае (иначе) установить его в 1. Если операторы if и/или else сопровождают блок кода (который предпочтительнее, чем одна строка), то блок должен быть помещен в фигурные скобки. Например: if (PORTBbits. RB4 == 0) { PORTCbits.RC6 = 0; PORTCbits.RC0 = 1; } else PORTCbits.RC6 = 1; В данном примере изменяются два разряда порта С в том случае, если разряд 4 порта В равен нулю. Можно также использовать конструкцию if. В таком случае, если условие не вы- полняется, то никакого альтернативного действия не будет. Например:
414 Глава 15. Язык С и встроенная среда if (PORTBbits. RB4 == 0) PORTCbits.RC6 = 0; if (PORTBbits.RB5 == 0) PORTCbits.RC5 = 0; В данном случае, разряд 6 порта С устанавливается в 0, если разряд 4 порта В равен нулю, и ничего не предпринимается в том случае, если разряд 4 порта В равен логиче- ской 1. В следующих двух строках примера происходит то же самое с разрядом 5 этих же портов. Обратим внимание на использование оператора присваивания и оператора равен- ства ’ в данных примерах. Как можно видеть, первый из них используется для при- сваивания значения переменной. Второй внутри конструкции if проверяет, равна ли пе- ременная определенному значению. 15.2.3. Установка разрядов конфигурации Установки для разрядов конфигурации приведены в листинге программы. В настоя- щее время они могут быть сделаны в окне Configuration Bits MPLAB, как можно увидеть на рис. 12.15. Это, конечно, не очень приятная процедура, поэтому в Главе 17 мы приве- дем способ такой установки внутри программы. Отметим, что установки в данном окне можно вернуть в их исходное состояние, щелкнув правой кнопкой мыши в этом окне и в появившемся диалоговом окне выбрав команду Reset to Defaults. 15.2.4. Моделирование и запуск примера программы Интересно смоделировать данную программу в симуляторе MPLAB®. Создав и ском- поновав проект, настроим моделирование, используя такие шаги: • Выберем симулятор в MPLAB, используя пункты меню Debugger > Select Tool > MPLAB SIM • Откроем окно Watch и выберем порты В и С в качестве переменных для показа. • Установим входной контроллер и смоделируем входные данные для входов RB5 и RB4 микропереключателей, выбрав Toggle в Action. • Поставим точки останова в функции diagnostic ( ), как показано на рис. 15.1 (а). • Используя пункт меню Debugger > Settings > Osc/Trace, установим частоту процес- сора равную 4 МГц. • С помощью меню Debugger > Stopwatch откроем окно Stopwatch, как показано на рис. 15.1 (Ь). Теперь вернемся в исходное положение и запустим программу до первой точки оста- нова, показанной на рис. 15.1 (а). В этой точке будет начало отсчета контрольного таймера, потом продолжим выполнение программы до следующей точки останова — следующей строки. Чтобы дойти до этой строки программа, однако, должна выполнить функцию DelaylOKTCYx () . Сейчас контрольный таймер должен быть точно таким, как показано на рис. 15.1 (Ь). Выполнение функции длилось ровно одну секунду — это достаточное под- тверждение точности данной функции. Теперь поставим еще одну точку останова в строке, следующей за меткой loop :. Продолжим выполнение программы до этой точки и один раз выполним цикл. Исполь- зуя входной контроллер, изменим значения входов микропереключателя (разряды 4 и 5 порта В) и проследим, что произойдет в цикле программы. Если у вас есть аппаратное обеспечение Derbot-18, загрузите программу обычным спо- собом. Функция программы довольно простая, но при этом вы насладитесь работой вашей первой программы на С, используя аппаратное обеспечение.
15.3. Больше о функциях 415 (а) В C:\...\sw tnjed 18.t: //Diagnostic: switches ieds on for Is (Tcy = lus) void diagnostic (void1 { PORTCbits.RC6 - 1; PORTCbits.RC5 1; DelaylOKTCYx 1100); PORTCbits.RC6 - 0; PORTCbits.RC5 = 0; DelaylOKTCYx ilOCh; i Stopwatch Total Simulated Г j | Instruction Cycles | 1000000 1000050 г ! 2ero Time (Secs5 I 1.000000 I 1X00050 j Processor Frequency- (MHz) | I.OOOOOfl” j Рис. 15.1. Установки моделирования для примера программы 15.1: (а) — предполагаемые гонки осганова в функции диагностики; (Ь) — контрольный таймер после выполнения функции задержки. 15.3. Больше о функциях Сейчас, когда у нас есть пример программы с несколькими функциями, полезно сде- лать некоторое отступление для дальнейшего рассмотрения того, как используются функ- ции. В частности, нам необходимо знать, как функция пишется, называется, как в нее передаются данные, как возвращается результат. 15.3.1. Прототип функции Если в программе есть не только главная функция, нужно включить прототип для каждой функции — объявление, которое сообщает компилятору тип аргумента(ов) функ- ции, если они есть, и тип возвращаемого результата. Это объявление подобно заголовку функции, который мы видели раньше, и имеет такой же общий формат. Например, библи- отечная функция DelaylOKTCYx (), описанная ранее, имеет следующий прототип: Имя функции | Тип аргумента?! результата [ void DelaylOKTCYx (unsigned char);
416 Глава 15. Язык С и встроенная среда Можно увидеть, что у данной функции один аргумент, беззнаковый символ, и не ожи- дается никакого возвращаемого значения. Прототипы библиотечных функций находятся в библиотечном заголовочном файле, и их не нужно повторять в коде. В данном случае, описанный выше прототип можно найти в заголовочном файле delays . h. Прототипы для двух задаваемых пользователем функ- ций в примере можно увидеть в начале программы. В них видно, что не ожидается ника- ких аргументов и никакого возвращаемого значения. 15.3.2. Определение функции Фактический код функции называется определением функции. Он соответствует фор- мату, описанному в разделе 14.2.5 Главы 14. Определение функции DelaylOKTCYx () на- ходится в общей программной библиотеке (см. табл. 14.5) и объединяется с главной про- граммой на этапе компоновки. Определения для двух задаваемых пользователем функций можно увидеть в конце листинга программы. Они расположены там для ясности, но могут, тем не менее, распола- гаться где угодно в листинге программы, только не внутри другого определения функции. Эти определения легко отслеживать. Функция инициализации устанавливает СФР и инициализирует порты в 0. Строго говоря, инициализация переменных в 0 не является необходимой, поскольку стандарт ANSI подразумевает ее в любом случае. В С18 инициализация делается только в том слу- чае, если используется запускаемая утилита c018iz . о (описанная позже в разделе 17.7.1 Главы 17). Мы не используем ее в примере программы этой книги, и, следовательно, пе- ременные не инициализируются нулем. Функция диагностики устанавливает разряды 5 и 6 порта С в 1 (два разряда для вывода сигнала светодиодам) и вызывает функцию задер- жки; потом очищает эти разряды перед повторным вызовом такой же функции задержки. 15.3.3. Вызовы функции и передача данных Функция вызывается указанием ее имени и помещением необходимых аргументов в скобки, которые должны следовать за именем функции. Если аргументы в функцию не передаются, скобки все равно должны быть, но пустые. Вызовы функций в примере про- граммы 15.1 простые и понятны без объяснений. Отметим, что в функцию задержки пе- редается параметр 100р. Важно знать, что существует много особенностей вызова функций, которые не оче- видны в данном конкретном примере. В частности, важно, что вызов функции содержит тип и значение возвращаемого типа. Это условие очень значимо! Оно означает, что вызов можно вставить в выражение; функция вычисляется и ее возвращаемое значение играет свою роль в выражении. Так сделано несколько раз в примере программы 16.1 и после- дующих программах. Примером оттуда может служить следующая строка: ldr_rt = ReadADC()&0x03FF; // прочитать и отключить ненужные разряды Здесь вызов функции ReadADC () используется в выражении. Сначала функция вычисля- ется, а потом возвращаемое ей значение используется в операции логического сложения. Напомним также, что в функцию передаются только копии параметров, а их исходные значения (если переменные объявлены) сохраняются. Эти значения используются внутри функции для вычисления возвращаемого значения, а исходные значения переменных не могут быть изменены. 15.3.4. Библиотечные функции задержки и DelaylOKTCYx () Все функции задержки, доступные в общей программной библиотеке С18, приведены в табл. 14.5. Они все имеют прототип функции в такой же форме, как у DelaylOKTCYx (),
15.4. Больше о переходах и циклах 417 используя беззнаковый символ (т.е. 8-разрядное слово) в качестве множителя для уста- новки текущей задержки. Используемая здесь функция DelaylOKTCYx () дает наибольшую задержку — про- граммную задержку в десять тысяч циклов выполнения команды, максимум 255 х Ю4 циклов. Таким образом, с генератором в 4 МГц и переменной, представленной как 100 (как в данном примере), общая задержка составит 10000 х 100 х 1 мкс, т.е. 1 секунду. За- головочный файл delays . h, необходимый для этой функции, может быть присоединен на ранних этапах данной программы. 15.4. Больше о переходах и циклах 15.4.1. Использование зарезервированного слова break Теперь, когда у нас есть такой механизм в С, который дает доступ к отдельным раз- рядам регистра, мы можем использовать его в дальнейшей поразрядной проверке и на- стройке. Возвращаясь к программе Фибоначчи из примера программы 14.2, исследуем другой способ построения первого цикла. Цель этого цикла — генерация последовательности Фибоначчи с 8-разрядным ограничением на числа, которые рассчитываются (с объявлен- ным типом беззнаковый символ). В примере программы 14.2 мы пошли несколько ис- кусственным путем, ограничив количество рассчитываемых значений известным “безо- пасным” максимумом. Теперь давайте попробуем заменить этот первый цикл частью программы из примера программы 15.2 — получим бесконечный цикл, используя конструкцию while (1). Внут- ри цикла, однако, существует стратегия выхода из цикла, основанная на использовании зарезервированного слова break. Данный оператор является частью проверки значения разряда переноса и осуществляет выход, если это значение 1. Если вы произведете мо- делирование в данной проверенной версии, вы увидите, что выход из цикла происходит сразу же после этого оператора, как только значение разряда переноса станет 1. Пример программы 15.2. Альтернативный первый цикл для программы Фибоначчи while (1) {fibtemp = fibl + fib2; if (STATUSbits.C == 1) break; //выход из цикла, если установлен //разряд переноса counter = counter + 1; //теперь перетасовываем номера, не учитывая первоначальное fibO = fibl; //сначала переместим среднее число, затерев первоначальное fibl = fib2; fib2 = fibtemp; } Глядя на этот способ проверки разряда переноса, может возникнуть вопрос — почему не сделать эту проверку в условии оператора while? Тогда цикл выглядел бы следующим образом: while (STATUSbits.С != 1) //цикл продолжается до тех пор, //пока значение разряда переноса не станет 1 {fibtemp - fibl + fib2; Проблема данного варианта в том, что условие проверяется только в конце цикла. К этому времени сложение вызовет переполнение, и неправильные числа будут помещены, по крайней мере, в одно место в последовательности Фибоначчи. Цикл, конечно, можно
418 Глава 15. Язык С и вс [роенная среда переделать так, что сложение будет производиться в конце цикла, и проверка разряда переноса тогда будет срабатывать незамедлительно. 15.4.2. Использование зарезервированного слова for Зарезервированное слово for дает другое понимание расположения условий цикла и имеет следующий общий формат: for (начальное значение; условие; изменение) оператор или группа операторов в фигурных скобках Все три выражения внутри скобок, называемые начальное значение, условие и из- менение, определяются программистом. Теперь покажем, что первый цикл из примера программы 14.2 может быть переписан следующим образом: for (counter = 0; counter<12; counter = counter + 1) {fibtemp = fibl + fib2; //теперь перетасовываем номера, не учитывая первоначальное fibO = fibl; //сначала переместим среднее число, //затерев первоначальное fibl = fib2; fib2 = fibtemp; } В первом выражении переменной counter присвоено значение 0. Это происходит только раз, при входе в цикл. Проверяется условие, меньше ли значение counter чем 12 и если ДА, то осуществляется увеличение значения counter и выполняется первый шаг цикла. Однако обратим внимание — это увеличение уже не влияет на выполнение текущего шага цикла. В процессе работы программы цикл постоянно выполняется и переменная counter каждый раз увеличивается. Когда ее значение увеличится до 12, при очередной проверке условия это мгновенно обнаружится и цикл больше выполняться не будет. Интересно изменить программу Фибоначчи, заменив первый цикл приведенным бло- ком кода, и смоделировать ее работу. Любые из трех выражений, связанных с циклом for, могут быть опущены. Если опущено условие, тогда нет никакой проверки, и цикл станет бесконечным. Начальное значение и условие могут, тем не менее, применяться. Простой способ создания беско- нечного цикла — не задавать никаких выражений вообще: for (; ; ) { • • • Это точная альтернатива условию: while(1) { • • • 15.5. Использование таймера и периферийных устройств ШИМ Сейчас мы перейдем к управлению периферийными устройствами микроконтроллера, используя библиотечные функции. Будем использовать Derbot программу “навигации вслепую”, ранее представленную как пример программы 8.4. На С эта программа представ- лена в примере программы 15.3. Программа использует библиотечные функции для тай- мера 2 и ШИМ, а затем создает собственные функции, которые дублируют подпрограммы исходной программы.
15.5. Использование таймера и периферийных устройств ШИМ 419 Программа просто заставляет Derbot двигаться вперед до тех пор, пока не встретится препятствие, выявленное микропереключателем. Затем он возвращается и поворачивает направо, если левый микропереключатель обнаружил препятствие, и наоборот — если правый. После этого он продолжает двигаться вперед. Эти простые движения требуют использования возможности ШИМ микроконтроллера, который в свою очередь нужда- ется в установке таймера 2. Пример программы 15.3. Derbot программа “навигации вслепую”________________ /★★★★tiiittttiiiiitititirittiiitiitiitiiittitii*************************** Dbt blind Nav PWM С Derbot управляется вслепую. Двигается вперед, при столкновении поворачивает и возвращается. Файлы c018i.o и pl8f242.1ib включены Сценарием компоновщика. Фиксированное значение ШИМ применяется для установления приемлемых скоростей. TJW 3.11.05 Протестировано 07.11.05 Один такт — 4 МГц Слово конфигурации по умолчанию, исключение: кварцевый генератор (HS), таймер по питанию вкл., контроль падения напряжения выкл., WDT выкл., LV программа заблокирована*/ #include <pl8F242.h> #include <delays.h> //заголовочный файл для временных задержек #include <timers.h> //заголовочный файл для Таймеров #include <pwm.h> //заголовочный файл для ШИМ /*прототипы функций, воспроизведенные для информации из заголовочных файлов void OpenPWMl (char); void OpenPWM2 (char); void OpenTimer2 (unsigned char); void DelaylOKTCYx (unsigned char); */ //определенные пользователем прототипы функций void diagnostic (void); void leftmot_fwd (void); void rtmot_fwd (void); void rev_left (void); void rev_rt (void); void main (void) { /*Проинициализировать СФР и установить начальные устройства вывода. Подразумевается, что аппаратное обеспечение находится в состоянии "Build Stage 2". Все не использующиеся разряды портов установить для вывода. Задать разряды, которые используются.*/ TRISA = ОЬОООООООО; //Все разряды для вывода, 2 & 5 используются //для разблокирования двигателя. TRISB = ОЬООИОООО; //Только разряды 5 и 4 (микропереключатели) //для ввода, TRISC = 0Ы0000000; //Все разряды для вывода, исключая разряд 7 //(переключатель режима), //1 & 2 используются для ШИМ ADCON1 = ОЬОООООНО;//Установить порт А для цифрового ввода/вывода
420 Глава 15. Язык С и встроенная среда Пример программы 15.3. Продолжение____________________________ //Выключить все выходы PORTA = 0; PORTB = 0; PORTC = 0; //Вызвать функцию диагностики diagnostic (); //Открыть ШИМ OpenTimer2 (TIMER_INT_OFF & T2_PS_1_1 & T2_POST_1_1); OpenPWMl (OxFF) ; //Открыть 1ПИМ1 и установить период OpenPWM2 (OxFF) ; //Открыть 1ПИМ2 и установить период while (1) { //запустить мотор leftmot_fwd (); rtmot_fwd (); //контроль столкновения — возвращение и поворот, //если какой-либо микропереключатель включается if (PORTBbits.RB4 == 0) //Проверить правый микропереключатель rev_left (); if (PORTBbits.RB5 == 0) //Проверить левый микропереключатель rev_rt (); DelaylOKTCYx (10); /************************************************************** Функции электропривода void leftmot_fwd (void) //запустить левый двигатель для движения вперед { CCPR2L = 196; PORTAbits.RA5 = 1; //включить двигатель } void rtmot_fwd (void) //запустить правый двигатель для движения вперед { CCPR1L = 196; PORTAbits.RA2 = 1; //включить двигатель } void leftmot_rev (void) //запустить левый двигатель для разворота { CCPR2L = 60; PORTAbits.RA5 = 1; //включить двигатель } void rtmot_rev (void) //запустить правый двигатель для разворота { CCPR1L = 60; PORTAbits.RA2 = 1; //включить двигатель } void rev rt (void) //возвратиться и затем повернуть направо { PORTCbits.RC6 = 1; //установить правый светодиод PORTAbits.RA5 - 0; //выключить двигатели PORTAbits.RA2 = 0;
15.5. Использование таймера и периферийных устройств ШИМ 421 Пример программы 15.3. Окончание____________ • '________________ PORTBbits.RBI = 1; //короткий писк из аудиоустройства DelaylOKTCYx (50); PORTBbits.RBI = 0; //выключить аудиоустройство leftmot_rev (); //развернуть оба двигателя rtmot_rev (); DelaylOKTCYx (200); leftmot_fwd (); //левый двигатель направить к повороту DelaylOKTCYx (100); PORTCbits.RC6 = 0; //выключить светодиод } void rev_left (void) //возвратиться и затем повернуть налево PORTCbits.RC5 = 1; //установить левый светодиод PORTAbits.RA5 = 0; //выключить двигатели PORTAbits.RA2 = 0; PORTBbits.RBI = 1; //короткий писк из аудиоустройства DelaylOKTCYx (50) ; PORTBbits.RBI = 0; lef tmot__rev (); //развернуть оба двигателя rtmot_rev (); DelaylOKTCYx (200) ; rtmot_fwd (); //правый двигатель направить коловороту DelaylOKTCYx (100); PORTCbits.RC5 = 0; //выключить светодиод Функция диагностики такая же, как и в примере программы 15.1. 15.5.1. Использование периферийных таймеров В 18FXX2 в наличие имеется четыре таймера и по четыре библиотечные функции для каждого из них. Эти функции представлены в табл. 15.1, где х может быть 0, 1, 2 или 3. Подробные сведения о сопряженных аргументах для этих функций находятся в докумен- тации. Рассмотренная программа использует только одну функцию 0penTimer2 (), относя- щуюся к таймерам. Она представляет собой библиотечную функцию для запуска перифе- рийных устройств, мы еще встретим другие такие функции. В данной функции аргумент задается разрядной маской, представленной логическим “И” различных установочных параметров. Они подробно описаны в документации, а для данной функции продублиро- ваны в табл. 15.2. В нашем случае должны быть заданы следующие три установочных па- раметра: разрешение прерываний, предварительный и последующий масштабы. Они мо- гут быть перечислены при вызове функции, как приведено в примере: OpenTimer2 (TIMER_INT_OFF & T2_PS_1_1 & T2_POST_1_1); Табл. 15.1. Библиотечные функции для работы с таймерами Функция Действие OpenTimerx () Настраивает таймер х ReadTimerx () Считывает таймер х WriteTimerx() Записывает в таймер х CloseTimerx() Прекращает работу таймера х
422 Глава 15. Язык С и встроенная среда Табл. 15.2. Установочные парамещы для функции 0penTimer2 ( ) Значение Результат Разрешение прерываний TIMER_INT_ON Прерывание разрешено TIMER_INT_OFF Прерывание запрещено Предварительный масштаб T2_PS_1_1 Предварительный масштаб 1:1 T2_PS_1_4 Предварительный масштаб 1:4 T2_PS_1_16 Предварительный масштаб 1:16 Последующий масштаб T2_POST_1_1 Последующий масштаб 1:1 T2_POST_1_2 Последующий масштаб 1:2 T2_POST_1_16 Последующий масштаб 1:16 Приведенные установочные параметры включают таймер, запрещают его прерывания, устанавливают предварительный и последующий масштабы в формате деления единицы. Они эффективно заменяют две строки на ассемблере, приведенные ниже из примера про- граммы 9.2: movlw В'00000100' /включить таймер 2 без предварительного ;и последующего масштабирования movwf t2con В терминах экономии строк кода версия на С дает небольшое преимущество. Основ- ная выгода, однако, проявляется не в этом — используя библиотечные функции подобно этой программисту больше не нужно углубляться в детали строения периферийных уст- ройств или их СФР. Как только технические требования функции становятся понятны, можно использовать периферийные устройства даже при ограниченных знаниях об их внутренней работе. 15.5.2. Использование ШИМ Концепция ШИМ (PWM) и использование периферийных устройств были описаны в разделе 9.5 Главы 9. Аппаратное обеспечение построено вокруг таймера 2 и вначале мо- жет быть несколько сложным для понимания, однако оказаться легким в использовании. Табл. 15.3 содержит библиотечные функции ШИМ, которые доступны для микрокон- троллера 18FXX2, где вместо х может быть подставлено значение 1 или 2. Функция OpenPWMx () используется в примере программы 15.3 в двух строках кода, здесь продублированных: OpenPWMl (OxFF); //Открыть PWM1 и установить период OpenPWM2 (OxFF); //Открыть PWM2 и установить период Функция открывает доступ к модулю ССР в режиме ШИМ и подгружает регистр PR2, который можно увидеть на рис. 9.11. Безусловно, регистр PR2 используется модулями ССР совместно и может быть установлен только в одно значение, поэтому ожидается, что ар- гумент в обоих вызовах функции одинаковый. Для установки частоты повторений при- меняется уравнение (9.2). В данном случае, когда предварительный масштаб таймера 2 не задан, и аргумент функции равен OxFFh, частота ШИМ составляет 3.906 кГц.
15.5. Использование таймера и периферийных устройств ШИМ 423 В данном примере программы функция SetDCPWMx () не используется для задания и изменения скорости. Учитывая 8-разрядное разрешение, регистры CCPR1L и CCPR2L заполняются напрямую. 15.5.3. Цикл главной программы Цикл главной программы снова образован конструкцией while (1). Микропереклю- чатели проверяются по очереди оператором if, как показано ниже: if (PORTBbits.RB4 == 0) //проверка правого переключателя rev_left (); if (PORTBbits.RB5 == 0) //проверка левого переключателя rev_rt (); Табл. 15.3. Библиотечные функции для работы с ШИМ Функция Действие OpenPWMx() Настраивает период и временную развертку ШИМ х SetDCPWMx() Записывает 10-разрядное значение дежурного цикла в ШИМ х ClosePWMx() Выключает ШИМ х Если какой-то микропереключатель активизирован, то соответствующее ему входящее значение станет равно 0, и будет вызвана или функция rev_left, или функцця rev_rt. Не очень трудно проследить, какая из этих функций была вызвана. Приостанавливается AGV, и потом оба двигателя двигаются в обратном направлении на протяжении фиксиро- ванного периода. Затем первый или второй двигатель движется вперед (пока другой про- должает двигаться в обратном направлении) для осуществления разворота. Потом выполне- ние программы возвращается в главный цикл, и AGV снова двигается вперед. Этот цикл использует как функцию электропривода, так и функцию задержки DelaylOKTCYx (). Резюме В этой главе было начато рассмотрение того, как язык С может применятся на прак- тике во встроенной среде на примере микроконтроллера семейства PIC 18. • К отдельным разрядам регистров памяти можно легко обращаться и управлять ними. • Существует большое количество циклических конструкций и конструкций перехода, которые позволяют точно определить алгоритм программы. • Можно легко определять и использовать библиотечные функции, которые существен- но облегчают работу с периферийными устройствами микроконтроллера. • Писать и использовать функции несложно; в хорошо структурированной программе отдельные задания помещаются в функции, которые вызываются из главной прог- раммы.
ГЛАВА 16. ПОЛУЧЕНИЕ И ИСПОЛЬЗОВАНИЕ ДАННЫХ С ПОМОЩЬЮ С Рассмотрев основы использования встроенного языка С, сейчас уместно выяснить, как можно применять С для получения и последующего использования данных. Первым делом нас интересует взаимодействие, используя С, с внешними устройствами АЦП. Мы найдем много полезных библиотечных функций, которые облегчают згу задачу. Получив данные, затем нужно будет продумать, как их можно хранить и обрабатывать — это приведет нас к массивам и строкам. Целесообразно также рассмотреть использование внешних устройств ГС, поскольку необходимо перемещать данные. В целом эта тема мо- жет стать сложной областью для изучения, поэтому мы будем рассматривать ее на на- чальном уровне — только управление целочисленными данными. Как и в предыдущей главе, большинство примеров будут использоваться в Derbot-18 AGV, но все они могут быть успешно смоделированы и без него. К концу этой главы вам нужно будет хорошо понять следующее: • как использовать в 18FXX2 библиотечные функции для АЦП и внешних устройств 12С; • как работать с массивами, строками и указателями; • как использовать библиотечные функции, облегчающие обработку строк. 16.1. Главная идея — использование С для манипуляции данными Одной из сильных сторон С является его способность работать с данными. Он легко оп- ределяет типы данных, управляет перемещением данных и защищает их от нежелатель- ных изменений. При использовании С на настольном компьютере существует много биб- лиотечных функций, созданных для того чтобы облегчить перемещение блоков данных. В этой главе мы познакомимся с некоторыми такими возможностями для встроенной среды. Как уже упоминалось, для простоты будем использовать только целочисленные данные. Стоит также заметить, что программы для работы с плавающей точкой на 8-разрядном мик- роконтроллере семейства 18 требуют для выполнения достаточно больших затрат времени — это является причиной для того чтобы, по возможности, избегать их, за исключением разве что тех ситуаций, где это действительно необходимо. 16.2. Использование АЦП в 18FXX2 Пример программы 16.1 предоставляет собой важный пример программирования на С для Derbot-18 AGV. Это программа поиска света, первоначально представленная на ассемб- лере примером программы 11.3. С помощью трех фоторезисторов (LDRs) Derbot ищет свет, останавливаясь, если все сенсоры будут иметь равный уровень освещенности. Программа предоставляет полезные нам в будущем примеры условного перехода и использования АЦП. Обратим ваше внимание на то, что некоторые номера строк встроены как ком- ментарии.
16.2. Использование АЦП в 18FXX2 425 Пример программы 16.1. Программа поиска источника света для АУСМ Derbot __ /******,****************************************** **************** ******** Dbt_light_seek_c Derbot ищет свет. Используется широтно-импульсная модуляция. Скорость зависит от разницы света (спереди и сзади), так что Derbot замед- ляется и останавливается, если разница света будет минимальна. Микропереключатели используются для определения столкновения. Файлы c018i.o и p!8f242.1ib добавлены сценарием компоновщика. TJW 12.11.05 Протестировано 27.11.05 Один такт - 4 МГц Слово конфигурации по умолчанию, за исключением: кварцевый генератор (HS), таймер по включению питания вкл., контроль понижения напряжения выкл., WDT выкл., LV программа выкл. */ ^include <pl8F242.h> #include <adc.h> #include <timers.h> #include <pwm.h> #include <delays.h> /*прототипы функций, воспроизведенные из заголовочных файлов только для информации void OpenPWMl (char); void OpenPWM2 (char); void OpenTimer2 (unsigned char); void DelaylOKTCYx (unsigned char); void DelaylOTCYx (unsigned char); void OpenADC (unsigned char, unsigned char); void SetChanADC (unsigned char); void ConvertADC(void); char BusyADC(void); int ReadADC(void); */ //Определенные пользователем прототипы функций void leftmot_fwd (void); void rtmot_fwd (void); void leftmot_rev (void); void rtmot_rev (void); void rev_left (void); void rev_rt (void); void fwd_left (void); void fwd_rt (void); void rotate_rt (void); void rotate_left (void); void diagnostic (void); //Объявление переменных int ldr_rt; //значение правого светочувствительного резистора int ldr_left; //значение левого светочувствительного резистора int ldr_rear; //значение заднего светочувствительного резистора int ldr_ave; //вычисленное среднее значений передних //светочувствительных резисторов int ldr_diff; //разница между передними светочувствйтрльными //резисторами, левый — правый int ldr_fwd; //необходимая средняя передняя скорость int fwd_dr_left; //к левому ШИМ добавлено смещение, //для движения вперед
426 Глава 16. Получение и использование данных с помощью С Пример программы 16,1. Продолжение_________________________________________ int fwd_dr_rt; //к правому ШИМ добавлено смещение, //для движения вперед //Главная программа void main (void) ( //Строка 57 Инициализировать. Установлены активные разряды. Неиспользуемые //разряды установлены как выходы. TRISA = ObOOOOlOll; //каналы АЦП установлены для ввода, //разряды 2 и 5 включают двигатель TRISB = ObOOllOOOO; //разряды 4 и 5 — входы микропереключателей TRISC = 0Ы0000000; //разряд 7 — переключатель режима, 1 и 2 — ШИМ //Включить таймер 2 с предварительным и последующим масштабами //в формате деления на единицу OpenTimer2 (TIMER_INT_OFF & T2_PS_1_1 & T2_POST_1_1); OpenPWMl (OxFF); //Открыть ШИМ1 и установить период OpenPWM2 (OxFF); //Открыть ШИМ2 и установить период //Включить АЦП. Разряды 0,1,3 порта А для аналогового входа, //внутреннее опорное напряжение, результат выравнивается вправо OpenADC(ADC_FOSC_8 & ADC_RIGHT_JUST & ADC_3ANA_OREF,ADC_CH0 & ADC_INT_OFF) ; //выключить все выходы PORTA = PORTB = PORTC = 0; //вызвать функцию диагностики diagnostic(); //включить двигатели в холостом режиме CCPR1L = CCPR2L = 0x80; PORTAbits.RA5 = 1; PORTAbits.RA2 = 1; //****************** ******* ****** *************************************** //главный цикл. //********************************************************************** while (1) { //Строка 83 Сначала проверить на конфликты if (PORTBbits.RB4 == 0) //Проверить правый микровыключатель rev_left (); if (PORTBbits.RB5 == 0) //Проверить левый микровыключатель rev_rt (); //Считать и сохранить все значения светочувствительных резисторов //левый канал SetChanADC (ADC_CH0); DelaylOTCYx (2); //задержка приблизительно на 20 мкс, //время захвата ConvertADC(); while (BusyADCO); //подождать до конца переноса данных АЦП ldr_left = ReadADC()&0x03FF; //считать АЦП, //и выключить ненужные разряды ldr_left = 1024 -ldr_left; //обратная полярность //Строка 96 правый канал SetChanADC (ADC CHI);
16.2. Использование АЦП в 18FXX2 427 Пример программы 16.1. Продолжение __________________________________________ DelaylOKTCYx (2); //задержка приблизительно на 20 мкс, //время захвата ConvertADC () ; while (BusyADC()); ldr_rt = ReadADC()&0x03FF; //считать АЦП, //и выключить ненужные разряды Idrrt = 1024 -ldr_rt; //обратная полярность //задний канал SetChanADC (ADC_CH3); DelaylOKTCYx (2); //задержка приблизительно на 20 мкс, //время захвата ConvertADC (); while (BusyADC ()); ldr_rear = ReadADC()&0x03FF; //считать АЦП, //и выключить ненужные разряды ldr_rear = 1024 -ldr_rear; //обратная полярность //Строка 110 Вычислить некоторые промежуточные переменные ldr_diff = (ldr_left -ldr_rt);//разница между показателями //светочувствительных резисторов ldr_ave = (ldr_left + ldr_rt);//среднее от показателей двух передних //светочувствительных резисторов ldr_ave = (ldr_ave>>l); //разделить предыдущее среднее //значение на 2 ldr_fwd = Idr ave -ldr_rear; //разница между показателями передних //и задних фоторезисторов, //для передней скорости if (Idr fwd < 0) Idr fwd = 0; //установить минимальное значение //Строка 116 определить действие, сравнив показатели светочувствительных //резисторов if (ldr_left > ldr_rt) (if (ldr_left > ldr_rear) fwd left(); //ldr_left самый яркий, двигаться налево else rotate left (); //задний светочувствительный резистор самый //яркий, повернуть по направлению к свету } else {if (ldr_rt > ldr_rear) fwd_rt(); //ldr_rt самый яркий, двигаться направо else rotate_rt (); } DelaylOKTCYx (10); } //конец while } //конец main у************************************** Функции движения На каждой итерации цикла выбирается одна из этих четырех функций ***************************************************************/ /*свет находится слева спереди, следовательно, нужно двигаться налево. Алгоритм следующий: fwd drive left = Idr fwd - ldr_diff, fwd drive right = ldr_diff + ldr_fwd */
428 Глава 16. Получение и использование данных с помощью С Пример программы 16.1. Продолжение__________________________________________ void fwd_left (void) { fwd_dr_left = ldr_fwd -ldr_diff; if (fwd_dr_left < 0) fwd_dr_left = 0; //если значение fwd_dr left //отрицательно, то установить его в нуль fwd_dr_left = fwd_dr_lef t>>l; //повернуть направо, //чтобы уменьшить значение if (fwd_dr_left > 127) fwd_dr_left = 127; //граничное максимальное //значение fwd_dr_rt = ldr_fwd + ldr_diff; if (fwd_dr_rt < 0) fwd_dr_rt = 0;//если fwd_dr_rt отрицательно, //установить его в нуль fwd_dr_rt = fwd_dr_rt>>l; //повернуть направо, чтобы //уменьшить значение if (fwd_dr_rt >127) fwd_dr_rt = 127; //граничное максимальное //значение CCPR1L = 0x80 + fwd_dr_rt; //установить правый двигатель, //значение которого больше CCPR2L = 0x80 + fwd_dr_left; //установить левый двигатель, //значение которого меньше } /*свет находится справа спереди, следовательно, двигаться направо. Алгоритм следующий: fwd drive right = ldr_fwd + ldr_diff, fwd drive left = ldr_fwd - ldr_diff (имея в виду противоположность ldr_diff) */ void fwd_rt (void) ( fwd_dr_rt = ldr_fwd + ldr_diff; if (fwd_dr_rt < 0) fwd_dr_rt = 0; //если fwd_dr_rt отрицательно, //установить его в нуль fwd_dr_rt = fwd_dr_rt>>l; //повернуть направо, чтобы //уменьшить значение if (fwd_dr_rt > 127) fwd_dr_rt = 127; //граничное максимальное //значение fwd_dr_left = ldr_fwd -ldr_diff; if (fwd_dr_left < 0) fwd_dr_left = 0; //если fwd_dr_left //отрицательно, установить его в нуль fwd_dr_left = fwd_dr_left»l; //повернуть направо, чтобы //уменьшить значение if (fwd_dr_left >127) fwd_dr_left = 127;//граничное максимальное //значение CCPR1L = 0x80 + fwd_dr_rt; //установить правый двигатель, //значение которого меньше CCPR2L = 0x80 + fwd_dr_left; //установить левый двигатель, //значение которого больше } //поворот налево с фиксированной скоростью (свет находится сзади слева) void rotate_left (void) { rtmot—fwd (); leftmot—rev (); }
16.2. Использование АЦП в 18FXX2 429 Пример программы 16.1. Окончание__________________________________________ //поворот направо с фиксированной скоростью (свет находится сзади справа) void rotatert (void) { leftmot_fwd (); rtmot_rev (); } у************************************************************** Функции электропривода „it***********************************************************/ (такие же функции, как в примере программы 15.3 - программа "навигации вслепую") При таком увеличении сложности программы полезно остановиться для того, чтобы изучить ее структуру. Для этого существуют различные способы, целью каждого из них является ясность программы. Здесь, учитывая наличие вложенных блоков кода, принята следующая практика — каждую открывающую скобку вложенного блока кода распола- гать с отступом вправо. Сначала обратим внимание на открывающую скобку функции main, которая находится у левого края. Потом посмотрим на открывающую скобку главного цикла while, начинающегося на строке 83, — эта скобка расположена с от- ступом вправо на одну позицию табуляции. Следующие вложенные блоки кода нахо- дятся с дальнейшим отступом вправо, а соответствующие закрывающие скобки всегда находятся точно под открывающими скобками. Конец цикла while и конец цикла main снабжены комментариями, и их легко найти в этой структуре программы. Расположение пары фигурных скобок, которые 'полностью слева’, в этой книге зарезервировано, в ос- новном, для главной функции main, поэтому скобки для меньших функций располагаются с отступом, но тоже одна под другой. Большие комментарии располагаются на о тдельной строке или строках, а небольшие — находятся просто справа от кода. 16.2.1. Структура программы поиска света Данная программа, содержащая около 20 функций, демонстрирует, как по мере услож- нения программ быстро увеличивается количество функций. Половина функций взяты из библиотек, остальные задаются пользователем. Прототипы функций для библиотечных функций находятся в соответствующих заголовочных файлах, и поэтому в исходном файле не нужны. Они, однако, скопированы здесь как комментарии, просто для инфор- мации. Прототипы остальных функций включены в исходный файл в действительности. Главная функция начинается с функции initialization, за которой следует, как обычно, функция диагностики. Потом программа переходит в бесконечный цикл, опреде- ленный зарезервированным словом while. Внутри него сначала тестируются передние микропереключатели, реагируя, если необходимо, также как и в примере программы 15.3. Дальнейшая структура программы приблизительно соответствует структурной диаграмме на рис. 11.13. 16.2.2. Использование АЦП В разделе 11.3 Главы 11 описывается структура АЦП для 16F873A и 18F242. Табл. 14.1 содержит шесть функций для работы с АЦП. Рассмо тренная программа использует все эти функции, кроме одной. Самая сложная из них OpenADC, прототип которой процитиро- ван в начале программы и здесь повторен: void OpenADC (unsigned char, unsigned char);
430 Глава 16. Получение и использование данных с помощью С Два беззнаковых символа, передающиеся в качестве аргументов, задаются разрядной маской так, как уже было описано для функции OpenTimer2 () в разделе 15.1 Главы 15. Параметры для АЦП более сложные, чем для таймера 2. Здесь они не представлены, но их можно легко найти в документации. Функция OpenADC здесь используется следую- щим образом: //Включить АЦП. Разряды 0,1,3 порта А для аналогового входа, //внутреннее опорное напряжение, результат выравнивается вправо OpenADC(ADC_FOSC_8 & ADC_RIGHT_JUST & ADC_3ANA_OREF,ADC_CH0 & ADC_INT_OFF); Как показывают комментарии, данная функция выполняет следующие установки: • Устанавливает скорость переноса данных в АЦП, которая определяется управляющим генератором. С минимальным тактом переноса данных (TAd) в 1,6 мкс, внутренний генератор в 4 МГц при делении па 8 дает нам TAd в 2,0 мкс. • Результат выровнен по правому краю, как видно из рис. 11.9. • Три канала используются для ввода, опорное напряжение — внутреннее. Это позволяет установить младшие 4 разряда в регисзре ADCON1 в 0100, как видно из рис. 11.8. • В данный момент выбран канал 0. Это никак не влияет на последующую программу. • Прерывание выключено. Использование этой функции эффективно заменяет следующие строки на ассемблере: bsf status,rpO movlw В' 10000100' /разряды 0,1,3 порта А устанавливаются ;на аналоговый movwf adconl /результат выравнивается вправо bcf status,rpO movlw B'01000001 ' /установить АЦП: таймер Fosc/8, /АЦП включен, но не запущен movwf adconO /выбор входного канала сейчас не используется Приведенный ниже процесс преобразования отражает структурную схему сбора дан- ных, представленную на рис. 11.5. Процесс повторяется для каждого светочувствительно- го резистора и здесь воспроизведен для канала 0: SetChanADC (ADC_CH0); Delay1OTCYx (2); //задержка приблизительно на 20 мкс, //время захвата ConvertADC(); while (BusyADCO); //подождать до конца переноса данных в АЦП ldr_left = ReadADC()&0x03FF; //считать АЦП, //и выключить ненужные разряды ldr_left = 1024 -ldr_left; //обратная полярность Используемые здесь функции достаточно понятны: функция SetchanADC () выбирает входной канал, задержка на 20 мкс обеспечивает достаточное время для работы функции. Функция ConvertADC () начинает перенос данных, а функция BusyADC () проверяет, продолжается ли еще перенос данных, и возвращает 1, если да. Вспомним из раздела 15.3.3 Главы 15, что вызов функции действует как ее возвращаемое значение. Здесь вызов функции находится внутри конструкции while, и это заставляет программу зацикли- ваться в этом месте, пока перенос данных не закончится. После этого функция ReadADC () считывает результат переноса данных. Эта функ- ция находится внутри выражения, действуя как ее возвращаемое значение, которое яв- ляется результатом АЦП, — это 10-разрядное значение, следовательно, его максимально возможное значение 1023d- Результат объединяется логическим И с 03FFh для того, чтобы убедиться, что старшие разряды были считаны. Это перемещение, возможно ненужное, помогает проиллюстрировать, как можно поместить функцию в выражение. Благодаря
16.2. Использование АЦП в 18FXX2 431 аппаратной конфигурации светочувствительных резисторов результирующее значение уменьшается вместе с увеличением интенсивности света. В качестве последующего арифметического примера, далее результат вычитают из его 10-разрядного максимума, 1024D— таким образом, значение ldr_left увеличивается вместе с увеличением света. 16.2.3. Дальнейшее использование if-else После переноса данных и некоторых промежуточных вычислений программа, начи- ная со строки 116, выбирает один из четырех возможных вариантов действий. Здесь программа действует так, как показано на диаграмме рис. 11.13. Если один из передних светочувствительных резисторов самый яркий — программа повернет устройство в этом направлении. Если же самым ярким окажется задний светочувствительный резистор, то программа повернет устройство в обратном направлении, по или против часовой стрелки. Эти решения принимаются с помощью трех проверок if-else, воспроизведенных ниже. Можно увидеть, что первый оператор if содержит внутри еще одну проверку if-else, как и соответствующий ему оператор else. //определить действие, сравнив показатели //светочувствительных резисторов if (ldr_left > ldr_rt) {if (ldr_left > ldr_rear) fwd_left(); //ldr_left самый яркий, двигаться влево else rotate_left (); //самый яркий задний светочувствительный //резистор, повернуть по направлению к свету } else {if (ldr_rt > ldr_rear) fwd_rt(); //ldr_rt самый яркий, двигаться вправо else rotate_rt (); } 16.2.4. Моделирование программы поиска света Интересно смоделировать эту программу в симуляторе MPLAB®, независимо от того, имеете вы Derbot или нет. Это позволит проверить используемые переходы и операции. Настройте параметры моделирования, используя следующие шаги: • Выберем симулятор в MPLAB, используя пункты меню Debugger > Select Tool > MPLAB SIM. • Откроем окно Watch и выберем переменные для показа, как на рис. 16.1. • Установим входной контроллер и смоделируем входные данные для входов RB5 и RB4 микропереключателя. • Используя пункт меню Debugger > Settings > Osc/Trace, установим частоту процес- сора как 4 МГц. Это важно только потому, что симулятор достаточно “умен”. Ведь если мы установим частоту очень большой, то симулятор это определит и просигнали- зирует, что такт переноса данных TAD (раздел 11.3.2 Главы 77) слишком короткий. • Добавим точки останова на строки 84 и 111. Запустим программу до первой точки останова. С помощью входного контроллера ус- тановите разряды 4 и 5 порта В в 1 для того, чтобы смоделировать неактивные микропе- реключатели. Теперь снова запустим программу до точки останова на строке 111. Окно Output выдаст предупреждение, что “Никакой входной файл не присоединен к ADRESL для АЦП”. Не волнуйтесь по этому поводу. Теперь в окне Watch введем первый набор значений для ldr_left, ldr_right и ldr_rear из табл. 16.1. (Вводим десятичные значения для каждой переменной, другие
432 Глава 16. Получение и использование данных с помощью С столбцы являются результатами) Теперь сделаем один шаг в программе, используя кнопку Отладчика “Step Into”. Посмотрим, как в этом случае выбирается правильная функция fwd_left, а в окне Watch мы увидим результаты вычислений. Результаты для каждого набора входных данных показаны в таблице. Как только вы получили первый набор ре- зультатов, снова запустим программу до первой точки останова, затем перейдем ко вто- рой точке и введем другой набор результатов. Продолжаем действовать таким же обра- зом, вводя различные пробные значения и наблюдая в программе за ответными циклами и вычислениями. Watch Add SFR | ADCONO jr] Add Symbol 11_ _tmp_0 Address | Symbol Name I i Decimal] Binary ] * I 0082 Idr left 0028 40| 00000000 ooi6ibo6] 0080 l.dr rt 0050 80 00000000 01010000 • 0084 Idr rear 0064 100 00000000 01100100 008A Idr fwd 0000 0 00000000 00000000 0088 Idr diff FFD8 65496 11111111 11011000 . 0086 Idr ave 003C 60 00000000 00111100 008C fwd dr left 0000 0 00000000 00000000 008E fwd dr rt 007F 127 00000000 01111111 0FBE CCPR1L 50 80 01010000 0FBB CC.PR2T, B0 176 10110000 ““ 0F81 PORTB 30 48 00110000 ж Рис. 16.1. Окно Watch для моделирования “поиска света” Табл. 16.1. Пробные значения для моделирования “поиска света” Условие Пробные значения из АЦП (десятичные) Результирующие действия и значения (десятичные) ldr„left ldr„rt ldr„rear Выбранная функция fwcLdr—left fwcLdr„rt left>right>rear 0100 0080 0040 fwcLleft 015 035 right>left>rear 0080 0100 0040 fwd_rt 035 015 lef t»right>rear 0200 0040 0020 fwcLleft 00 127 rear>left>right 0080 0040 0100 rotate_left - - rear>right>left 0040 0080 0100 rotate—right - - Если у вас есть Derbot AGV, то это интересная программа для запуска. Она будет несколько улучшена еще в этой главе, путем добавления возможностей вывода. 16.3. Указатели, массивы и строки В Главе 14 мы видели, как объявлялись и использовались элементы данных. Однако многие данные существуют как набор переменных, например строка данных, приготов- ленная для вывода на экран. В связи с этим в этом разделе мы посмотрим на то, как мож- но определять и использовать наборы данных, знакомясь с массивами и строками, а также как можно работать с указателями для доступа к этим данным. 16.3.1. Указатели Вместо того чтобы определять переменную по имени, мы можем указать ее адрес. В терминологии С такой адрес называется указателем. Адрес переменной может быть за- гружен в указатель, используя унарную операцию ‘&’, как это показано ниже:
16.3. Указатели, массивы и строки 433 my_pointer = &fred; В переменную my_pointer загружается адрес переменной f red; потому говорят, что my_pointer указывает на f red. Или наоборот, значение переменной, на которую указывает указатель, может быть определено присоединением к указателю приставки * (звездочка), например *my_pointer можно прочитать, как “значение, на которое указывает my_pointer”. Оператор “*” (звез- дочка), используемый таким образом, иногда называют оператором разыменования или косвенной адресации. Косвенное значение указателя, например *my_pointer, можно ис- пользовать в выражении как любую другую переменную. Указатель объявляется типом данных, на который он указывает. Так int *my_pointer; означает, что my_pointer указывает на переменную типа int. Отражая Гарвардскую структуру памяти микроконтроллера PIC®, компилятор С18 разрешает создавать указатели на программную память и память для хранения данных. Итоговый размер указателя показан в табл. 16.2. Понятие “близкий” и “дальний” в дан- ном контексте объясняется в разделе 17.6.5 Главы 17. Табл. 16.2. Размеры указателей С18 Тип указателя Размер указателя Память для хранения данных 16 бит Близкая программная память 16 бит Дальняя программная память 24 бит 16.3.2. Массивы Массив в С определяется как набор элементов данных одного типа. Можно исполь- зовать любой тип данных. Элементы массива сохраняются в следующих подряд ячейках памяти. Массив объявляется именем, типом данных и (необязательно) количеством эле- ментов. Например, объявление unsigned char messagel[8]; определяет массив с именем message!, состоящий из восьми символов. Массив легко узнать по использованию после имени квадратных скобок. К элементам массива можно получить доступ по индексу, начинающемуся с нуля. Следовательно, для приведенного выше массива message [ 0 ] выберет первый элемент, a message [ 7 ] — последний. Индекс можно заменить любой переменной, которая имеет необходимое значение. Важно, что имя массива устанавливается равным адресу первого элемента, поэтому при передаче имени массива в функцию фактически передается этот адрес. 16.3.3. Использование указателей вместе с массивами Можно устанавливать указатели на массивы, используя описанные выше операторы, например, оператор ADC_val_ptr = &ADC_val_BCD[0] ; присваивает адрес первого элемента массива ADC_val_BCD указателю ADC_val_ptr. Это присваивание, если хотите, можно объединять с объявлением самого указателя, как приведено ниже: int *ADC_val_ptr = &ADC_val_BCD[0] ;
434 Глава 16. Получение и использование данных с помощью С Исходя из такого присваивания, значение ADC_val_BCD [ 0 ] (первый элемент мас- сива) равно *ADC_val_ptr (значение, на которое указывает ADC_val_ptr). Получа- ется, что, например, значения ADC_val_BCD [ 1 ] и * (ADC_val_ptr + 1) также рав- ны, как ADC_val_BCD [2 ] и * (ADC_val_ptr + 2),ит.д. Поскольку имя массива — это также и адрес первого элемента, то приведенное выше присваивание можно записать как ADC_val_ptr = ADC_val_BCD; Позже мы увидим, что ADC_val_BCD [ i ] равен * (ADC_val_BCD + i), а имя массива эффективно используется как указатель. Дальнейшим усовершенствованием будет возможность использования указателя с индексом. Так, ADC_val_ptr [i] — это то же самое, что и * (ADC_val_ptr + i). Выглядит так, что указатель и имя массива почти взаимозаменяемы, и что указатель не очень нужен. Нужно все же помнить, что имя массива — это константа (массив нахо- дится в памяти постоянно), в то время как указатель — настоящая переменная со всеми ее свойствами. 16.3.4. Строки Строка — это особый вид массива, состоящий из символов, которые заканчиваются пустым символом “\0”. Поэтому размер массива строки должен быть, по крайней мере, на один байт больше, чем сама строка для того, чтобы содержать этот конечный символ. 16.3.5. Пример программы: использование указателей, массивов и строк Немного неправдоподобный пример программы 16.2 демонстрирует несколько спосо- бов использования массивов, строк и указателей. Этому примеру нечего не нужно делать во встроенной среде, он предназначен только для моделирования. Объявляется массив символов, называемый списком, каждое значение которого установлено в нуль. После этого объявляется строка с именем it eml, содержащая слово Apple, аналогичная строка item2, содержащая слово Pear, и отдельный символ с именем plural. Обратим внимание на то, что строки заключены в двойные кавычки, а символы — в одинарные. Также объяв- ляется два указателя: первый, pntrl, содержит адрес первого элементы строки iteml, а второй, pntr2, — адрес переменной number. Пример программы 16.2. Работа с указателями, массивами и строками Л*********************************************************** ************* Strings&chars_c Данная программа только для моделирования, изучает символы, строки и ука- затели Файлы с0181.о и pl8f242.1ib добавлены сценарием компоновщика. TJW 29.11.05 Протестировано 30.11.05 *************************************************************************/ //Разряды конфигурации устанавливать не нужно ♦include <pl8F242.h> //определения типов данных char counter; //индекс для списка char list[8] = (0,0,0,0,0,0,0,01; char number = 0; char iteml[] = "Apple"; char item2[] = "Pear"; char plural = 's';
16.3. Указатели, массивы и строки 435 Пример программы 16.2, Окончание__________• _________________________________ char *pntrl = &iteml[0]; //Указатель на строку "Apple" char *pntr2 = &number; //Главная функция void main (void) ( loop: //Работа с яблоками ('Apple') counter = 0; //установить индекс для списка list [counter] = number; //показать количество элементов while (iteml[counter] != 0) //показать тип элемента { list[counter+1] = * (pntrl + counter) ; counter = counter + 1; } if (number >1)list[counter+1] = plural; //постановить элемент во //множественное число (добавить переменную plural) else list[counter+1] = 0x20; //вернуть элемент в //единственное число, с ASCII промежутком //Работа с грушами ('Pear') counter = 0; //установить индекс для списка list[counter] = number; //показать количество элементов while (item2[counter] != 0) //показать тип элемента { list[counter+1] - * (item2 + counter); counter = counter + 1; } if (number >1)list[counter+1] = plural; //постановить элемент во //множественное число (добавить переменную plural) else list[counter+1] = 0x20; //вернуть элемент в единственное число, //с ASCII промежутком counter = counter + 1; list[counter+1] = 0x20; //добавить ASCII промежуток number = *pntr2 + 1; if (number > 9)number = 0; goto loop; } 16.3.6. Несколько слов об использовании условия while Зарезервированное слово while было представлено в разделе 14.2.8 Главы 14. До этого времени мы использовали его много раз для создания бесконечного цикла, а в этот раз — с условием в строке: while (iteml[counter] != 0) //показать тип элемента Подобным образом while используется и несколькими строками ниже. В данном случае условие цикла — элемент массива, идентифицированный значением counter, не должен быть равен нулю. В действительности, мы может упростить это условие, как объяснялось в Главе 14. Цикл будет выполняться до тех пор, пока условное выражение будет истинно (т.е. ненулевое), а при нулевом значении произойдет выход их цикла. Сле- довательно, самый простой способ записи оператора while следующий: while (iteml[counter]) //показать тип элемента Он будет работать так же, как и исходный вариант строки.
436 Глава 16. Получение и использование данных с помощью С 16.3.7. Моделирование примера программы Если у вас есть компилятор С18, создайте проект для примера программы 16.2 (исход- ный код находится на компакт-диске этой книги), скомпонуйте его и смоделируйте, ис- пользуя симулятор MPLAB. Откройте окно Watch, показывающее такие же переменные, как на рис. 16.2. Это даст нам возможность увидеть, как симулятор выводит на экран массивы. Рисунок показывает, что массивы можно вывести только по имени, как для item2, или отобразить полностью все элементы, как для list и iteml. Заметим, что массив iteml был создан с шестью элементами, последний из которых — нулевой символ. |И Watch ИВНЦ Add SEfi [ |ADCON( y| Add Symbol |item2 Address | symbol Name value | Hex |Decimal| Binary ' | .. . ,.± Il 0080 e list 0080 — [01 02 2 00000010 0081 — [1] A 41 65 01000001 0082 [2] p 70 112 01110000 0083 [3] p 70 112 01110000 0084 — [4] 1 6C 108 01101100 : 0085 [5] e 65 101 01100101 0086 — [6] s 73 115 01110011 0087 [7] 00 0 UDUOUUOO 00 АЗ counter 0x00 00 0 00000000 0088 number 0x02 02 2 00000010 0089 R iteml "Apple" 0089 — [0] A 41 65 01000001 008A — [1] p 70 112 01110000 008B [2] p 70 112 01110000 008C — [3] 1 6C 108 01101100 008D — [4] e 65 101 01100101 008E [5] 00 0 00000000 008F w item2 "Pear" .-.mi 1 | Watch 1 Watch 2 Watch 3| Watch A | Рис. 16.2. Окно Watch для моделирования примера программы 16.2 Поставьте точки останова, так как показано на рис. 16.3, и запустите программу сначала до первой точки останова. Дальше аккуратно двигаемся по программе, отмечая, что про- исходит на каждой строке. В программе есть две части, определяемые по комментариям “Работа с яблоками (Apple)” и “Работа с грушами (Pear)”. Главная работа каждой части заполнить массив list значением переменной number и типом продукта, т.е. яблоко или груша. После инициализации counter переменная number переносится в первый элемент массива в строке list[counter] = number; //показать количество элементов Здесь используется самая простая форма доступа к массиву, когда число, находящееся в квадратных скобках, определяет элемент массива. В данном случае первому элементу массива присвоено значение number. Теперь определяется цикл while. Как мы уже знаем, строка завершается пустым символом, поэтому на этот символ и делается проверка, используя оператор “! =” (не ра- вен) следующим образом: while (iteml[counter] != 0) //показать тип элемента
16.4. Использование внешних устройств I2C 437 //Do apples counter ~ en- list [counter ] number; while iitemlfcounter1 •- 0) {list[counter+1[ ’(pntrl+counter; counter - counter + 1; //set index to 1ist /’/indicate number of items /'/indicate type of item if .number '-1) list [counter+1 [ ~ plural; //set the .item to plural else list[counter+1j " 0; //return item to single © //Do pears counter - 0; list counter) ~ number; while iitem2.counter) s~ Ch list [ counter +1' - * ( item2-^counter counter “ counter + 1; //set index to list //'indicate number of items //indicate type of item Рис. 16.3. Рекомендуемое расположение точек останова для примера программы 16.2 До тех пор, пока символ ненулевой, он переносится из строки it eml в массив list в следующей строке: {list[counter+1] = *(pntrl + counter); Элемент массива list опять определяется индексом в квадратных скобках. Теперь значение counter смещается на 1, поскольку его первый элемент уже заполнен. Присво- енное ему значение — это косвенное значение pntг 1, смещенное на значение counter. Проверка сравнивает количество яблок с 1 — если это количество больше 1, то к типу продукта нужно добавить окончание ‘s’, в противном случае вставляется промежуток. if (number >1)list[counter+1] = plural; //постановить элемент во //множественное число (добавить переменную plural) else list[counter+1] = 0x20; //вернуть элемент в единственное число, //с промежутком ASCII Заметим, что в части программы, работающей с грушами, строка перемещается по- другому. Теперь элемент массива в строке item2 определяется, используя имя массива как базовый адрес, смещаясь по очереди на значение counter. Косвенное значение этого вычисленного адреса переносится в list. {list[counter+1] = *(item2+counter); По мере движения к концу цикла значение number увеличивается. С правой стороны присваивания доступ к переменной number осуществляется, используя косвенное значе- ние этого указателя, т.е. собственно number. number = *pntr2 + 1; Выполняйте пошагово программу до тех пор, пока вы не поймете, что делает каждая строка кода. Потом запустите ее от одной точки останова до другой и посмотрите, как на каждой итерации цикла обновляется содержимое массива list. Одна деталь может оказаться для вас немного непонятной — это то, что объявленные строки (как видно в окне Watch) находятся совсем не в программной памяти, как мы ожи- дали увидеть. Мы вернемся к этому вопросу в следующей главе, когда будем рассмат- ривать, как можно поместить строки и другие константы в определенный тип памяти. 16.4. Использование внешних устройств 12С В Главе 8 мы видели, что 12С — это полезный стандарт для последовательной связи, немного сложный в использовании. Библиотека компилятора С18 включает несколько
438 Глава 16. Получение и использование данных с помощью С очень полезных функций, которые позволяют легко и надежно использовать функцио- нальность 12С. В документации перечислено не менее 15 функций для ГС, хотя среди них есть и похожие. Несколько примеров таких функций приведено в табл. 16.3 в том поряд- ке, в каком они могут использоваться. Табл. 16.3. Примеры библио генных функций 12С Функция Действие OpenI2C ( ) Настраивает модуль SSP для I2C StartI2C( ) Создает условие старта для 12С WriteT2C( ) Записывает отдельный байт в 12С Readl2C( ) Считывает отдельный байт из 12С StopI2C( ) Создает условие остановки для 12С 16.4.1. Пример программы 12С В примере 16.3 приведена простая программа, которая использует возможности 12С микроконтроллера и функции из табл. 16.3. Программа предназначена для Derbot AGV. Она посылает отдельный символ, а затем строку на ручное управляющее устройство. Пример программы 16.3. Использование lzC для отправления символа и строки на ручное управляющее устройство Derbot______________________ 7****************************************************************** ******* Dbt_I2C_test_c Периодически посылает отдельный символ, потом строку, на I С. Установлено как ведущее устройство. Файлы c018i.o и pl8f242.1ib добавлены сценарием компоновщика. TJW 12.11.05 Протестировано 04.12.05 Один такт — 4 МГц Код конфигурации по умолчанию, за исключением: кварцевый генератор (HS), таймер по включению питания вкл., контроль пониженного напряжения выкл., WDT выкл., LV программа выкл. */ ♦include <pl8F242.h> ♦include <i2c.h> ♦include <delays.h> ♦define slave_addrl 0xA4 //заголовочный файл для IZC //заголовочный файл для задержек //адрес узла ручного управляющего //устройства Derbot //Прототипы функций. Прототипы библиотечных функций находятся //в заголовочном файле. void diagnostic (void); //константы и переменные unsigned char message!] = " Derbot"; unsigned char *i = &message[0]; //указатель на message]] char loop_cntr = 0; у************************************************************* ********** Главная функция. ***********************************************************************/ void main (void) { //Проинициализировать порты
16.4. Использование внешних устройств I2C 439 Пример программы 16.3. Окончание_______________________.____________________ TRISA = ObOOOOlOll; //каналы ADC установлены для ввода TRISB = 0Ы1001000; TRISC = 0Ы0011000; //оба разряда 12С установлены как ip //Выключить все выходы PORTA = PORTB = PORTC = 0; //вызвать функцию диагностики (флэш-светодиоды) diagnostic(); //Проинициализировать 12С Openl2C (MASTER, SLEW_OFF); SSPADD = 0x07; //установить скорость в бодах в 125kHz loop: //Отправить отдельный символ i = &message[0]; StartI2C(); //отправить условие старта Writel2C (slave_addrl); //отправить адресное слово, //функция пока ожидает //запись окончена loop_cntr = loop_cntr| 0x30; //преобразовать счетчик в ASCII Writel2C (loop_cntr); loop_cntr = loop_cntr&OxOF; //восстановить счетчик из ASCII StopI2C(); //отправить условие остановки DelaylOKTCYx (100); //Отправить строку Startl2C(); //отправить условие старта Writel2C (slave_addrl); //отправить адресное слово, //функция пока ожидает //запись окончена while (*i) //проверить на нулевой символ ( Writel2C (*i); i++; DelaylKTCYx (5); //необходима задержка для ручного //управляющего устройства } Stopl2C(); //отправить условие остановки DelaylOKTCYx (100); loop_cntr++; if (loop_cntr == 10) loop_cntr = 0; goto loop; } //конец main // Диагностика: включить светодиоды для Is '(Тсу = lus) void diagnostic (void) (функция диагностики такая же, как и в примере программы 15.1) Первые строки программы указывают, какие заголовочные файлы должны быть до- бавлены, и определяют А4Н как адрес подчиненного узла ручного управляющего уст- ройства, как описано в разделе 10.8 Главы 10. Здесь также объявляется символьная строка, формирующая сообщение, которое должно быть послано, а также описывается для нее указатель. Функция Ореп12С () частично инициализирует порт 12С. Эта функция имеет два ар- гумента, описанные в документации, которые определяют режим работы (ведущий или подчиненный) и выбирают скорость нарастания напряжения. Отметим, что все еще нужно
440 Глава 16. Получение и использование данных с помощью С устанавливать скорость в бодах для регистра SSPADD. Сообщение 12С запускается функ- цией StartI2C(), которая помещает условие старта 12С в последовательный канал. По- сле условия старта посылается байт адреса, который передается как аргумент в функцию WriteI2C (). Эта функция устанавливает разряд R/W в небольшое передаваемое сооб- щение, как можно увидеть на рис. 10.13. Формируется ASCII версия значения счетчика цикла, который потом отсылается функцией WriteI2C (). Функция StopI2C () преры- вает сообщение. Строка отсылается, используя, главным образом, уже известные технологии, хотя есть и некоторое усовершенствование. Новое 12С сообщение инициализируется функцией Start I2C () с последующей отсылкой подчиненного адреса. Потом создается цикл while со следующим условием while (*i) где i — это указатель на строку, * i указывает на элемент строки. Помня, что последний элемент строки всегда нулевой символ, цикл будет повторяться до конца строки, после чего произойдет выход из цикла. 16.4.2. Использование операторов ++и — В конце примера программы мы видим оператор ++, который применяется как к ин- дексу i, так и к loop_cntr. Оператор, увеличивающий переменную, к которой он применяется, можно увидеть в табл. А6.5, следовательно i++; очевидно, то же самое, что и i = i + 1; Хотя есть несколько важных отличий. Этот оператор можно поставить перед пере- менной, в таком случае он означает предварительное увеличение, а если он находится по- сле переменной, то означает последующее увеличение. В этой программе разница незна- чительна, однако разницу можно понять, если посмотреть на следующие два примера: index = 4; index = 4; new_val = index++; new_val = ++index; В примере слева переменной new_val присваивается значение 4 и только потом увеличивается переменная index. В примере справа (предварительно) увеличивается пе- ременная index, а затем переменной new_val присваивается значение, теперь уже 5. Оператор уменьшения на единицу, применяется таким же образом. 16.5. Форматирование данных для вывода на дисплей Только что мы увидели, как можно отправлять символы и символьные строки через ка- нал 12С на жидкокристаллический дисплей. Что мы еще не сделали — не создали пока- зательные данные для вывода на дисплей. Эта часть улучшает Derbot-программу поиска света (пример программы 16.1) таким образом, что значения, которые считываются зави- симыми от света резисторами, выводятся на дисплей ручного управляющего устройства. 16.5.1. Обзор примера программы В примере программы 16.1 значения считываются с ADC как 10-разрядные числа. Для того чтобы преобразовать их в символьную строку, нам нужно конвертировать зна- чения в двоично-десятичный код, а потом в ASCII. Ранее мы делали это на ассемблере в примере программы 11.2, и это оказалось довольно тяжело. Можно ли такое преобразова- ние на С сделать лучше?
16.5. Форматирование данных для вывода на дисплей 441 Ответ на этот вопрос положительный — в С есть много функций, которые созданы для преобразования данных из одного формата в другой. Несколько примеров представлены в табл. 14.3. Для нашего приложения нужна функция, которая берет 10-разрядный резуль- тат из АЦП и преобразовывает его в символьную строку. Такое преобразование удобно предоставляется функцией itoa, которая присутствует в таблице. Пример программы 16.4 демонстрирует части программы light_seek_&_disp, которая полностью есть на компакт-диске книги. Приведенные части — это расширение примера программы 16.1. Здесь были добавлены две новые функции: одна, disp_int (), форматирует выходное значение АЦП и отправляет результирующую символьную строку в канал 12С. Другая, send_sрасе (), для оптимизации вывода информации, просто по- сылает последовательность интервалов на дисплей. Данные выводятся на дисплей только один раз в каждые 10 итераций главного цикла. Если этот вывод сделать хотя бы немного быстрее, то получим неприятное мерцание дан- ных. В главный цикл был добавлен счетчик цикла, loop_.cntг, который увеличивается на каждой итерации цикла. Можно увидеть, что функция disp_int () вызывается три раза для вывода данных, по разу для каждого светочувствительного резистора. Первые два результата работы этой функции будут помещены в первую строку двух-строчного дисплея. До и после вывода на дисплей показателя заднего светочувствительного рези- стора посылаются интервалы для того, чтобы поместить результат по центру второй стро- ки дисплея. Пример программы 16.4. Форматирование данных для вывода на жидкокристаллический дисплей (П.пdude <stdlib.h> //для функции itoa ♦include <string.h> //для функции strlen (эта часть программы находится внутри главного цикла программы после того, как значения АЦП были считаны) //Вывести на дисплей значения светочувствительных резисторов //каждые 10 циклов if (loop_cntr == 10) { disp_int (ldr_left);//вывести на жидкокристаллический дисплей //значение левого светочувствительного резистора disp_int (ldr_rt); //вывести на дисплей значение правого //светочувствительного резистора send_space (2); //вывести интервалы для центрирования значения //заднего светочувствительного резистора disp_int (ldr_rear) ; //вывести на дисплей значение заднего //светочувствительного резистора send_space (2); //заполнить вторую строку, //вынуждая перевод строки loop_cntr = 0; } у******************************************** Функции вывода на дисплей ********************************************/ //Преобразовывает целое в строку и посылает его на жидкокристаллический //дисплей через 12С с интервалами для того, чтобы гарантировать, что //всегда будут посланы 4 разряда void disp int (int op int)
442 Глава 16. Получение и использование данных с помощью С Пример программы 16.4. Окончание___________________________________________ { char disp_val[5]; //будет содержать строковое представление //любого значения светочувствительного резистора char *disp_val_ptr; //указатель на disp_val[] char space_no; //количество интервалов, //которые должны быть вставлены disp_val_ptr = &disp_val[0] ; itoa (op_int, disp_val_ptr) ; //сначала преобразовать в //двоично-десятичную строку space_no=4-strlen(disp_val_ptr); //определить, сколько нужно //интервалов //Теперь отправить сообщение StartI2C(); //отправить условие старта WriteI2C (slave_addrl); //отправить адресное слово while (space_no) //дополнить начальными интервалами { WriteI2C (' '); DelaylKTCYx (5); //ручному управляющему устройству //необходима небольшая задержка space_no--; } //отправить строку while (*disp_val_ptr) { Writel2C (*disp_val_ptr) ; disp_val_ptr++; DelaylKTCYx(5) ; //необходима задержка для ручного //управляющего устройства } Stopl2C(); //отправить условие остановки } //Отправить интервалы на жидкокристаллический дисплей через 12С void send_space (char space_no) { StartI2C(); //отправить условие старта WriteI2C (slave_addrl); //отправить адресное слово, //отправить интервал while (space_no) { WriteI2C (' '); DelaylKTCYx (5); //необходима задержка для ручного //управляющего устройства space_no-~; //отправить условие остановки } StopI2C (); } 16.5.2. Использование библиотечных функций для форматирования данных Давайте посмотрим ближе на функцию disp_int () в примере программы 16.4, по- скольку у нее есть несколько важных особенностей. Сначала обратим внимание на то, что массив, указатель и символьная переменная объявляются вначале функции. Они будут
16.5. Форматирование данных для вывода на дисплей 443 существовать только во время работы функции. Объявляется массив из пяти элементов, так как максимальное количество разрядов 10-разрядного числа будет 4 (1023d), а пятый байт необходим для завершающего нулевого символа. Аргумент, который передается в функцию, обозначен как op_int. Указатель устанавливается на начало массива. Затем вызывается функция itoa (), которая имеет следующий прототип: char * itoa (int value, char * string); где value — это целое, которое нужно преобразовать, string — строка, в которую бу- дет помещен результат, а результирующее значение — указатель на строку. Эта функ- ция используется в следующей строке: itoa (op_int, disp_val_ptr); //сначала преобразовать в //двоично-десятичную строку Можно увидеть, что op_int — это переменная, которую нужно преобразовать, а ре- зультирующая строка — та, в которую будет помещен результат путем использования предварительно объявленного указателя disp_val_ptr для массива disp_val. Можно также увидеть, что эту символьную строку возможно сразу же отправить на дисплей, одна- ко она может быть любой длины — от одного до четырех разрядов. Для того чтобы гаран- тировать, что она будет всегда располагаться на дисплее в одном и том же месте, нужно сначала определить ее длину. Это делается с помощью функции strlen () из общей про- граммной библиотеки. Эта функция определяет длину строки и возвращает это значение. Ее прототип выглядит так: size_t strlen(const char *string); Здесь string — это строка, длину которой нужно определить, а возвращаемое зна- чение, size_t, содержит длину строки. Эта функция используется для расчета значе- ния space_no — количество интервалов, которое нужно отправить, чтобы дополнить исходное значение до четырех разрядов. Эти интервалы отправляются непосредственно перед данными, потом отправляется строка, и функция завершает работу. 16.5.3. Характеристика программы Эта программа объединяет предыдущую функцию измерителя света (пример програм- мы 11.2) и программу поиска света. Ее можно смоделировать так же, как было описано в разделе 16.2.4, задав пробные значения для ldr_lef t, ldr_rt и ldr_rear, и наблюдая за их преобразованием в строки и определением длины строки. Это также довольно интересная программа для запуска на Derbot, поскольку и ее ра- бота, и вывод данных на дисплей, обеспечивают очень точную демонстрацию того, что делает программа. Резюме Целью этой главы было показать, как можно использовать С для получения и исполь- зования целых данных во встроенных системах. Были рассмотрены следующие пункты. • В 18FXX2 с помощью библиотечных функций можно прямо управлять АЦП и 12С пор- том последовательного ввода-вывода. • Массивы и строки, а также связанные с ними указатели, предоставляют нам эффек- тивные способы управления наборами данных. Нужно быть внимательным в пони- мании того, как С с ними работает. • Существует несколько полезных библиотечных функций для обработки строковых данных. Они особенно полезны для форматирования данных с целью вывода их на дисплей.
ГЛАВА 17. БОЛЕЕ ГЛУБОКИЕ ЗНАНИЯ ЯЗЫКА С И ЕГО СРЕДЫ ОКРУЖЕНИЯ Мы уже достигли уровня, когда можем с некоторой уверенностью создавать простые программы на С для микроконтроллера PIC®. Однако в наших знаниях все равно еще есть пробелы. Один из них — использование прерываний. Исследование этого вопроса ведет нас к границам использования С и, фактически, выходит за рамки языка. Более того, когда программы становятся сложнее, полезно знать о более широкой среде окружения, в кото- рой мы программируем, например, что представляют собой файлы, которые мы присоеди- няем или включаем. Ранее мы делали это, не имея представления о том, как же все это ра- ботает. Цель данной главы двойственная. С одной стороны — осветить аспекты языка, которые позволяют работать с аппаратным обеспечением на более низком уровне. Они включают в себя использование ассемблерных вставок и прерываний. С другой стороны — расши- рить знания о контексте, в котором работает С. Для того чтобы это сделать, нам придется узнать об определенных аспектах языка как такового. К концу этой главы вам нужно будет хорошо понять следующее: • использование ассемблерных вставок; • использование прерываний; • более глубокое понимание процессов определения и хранения данных, а также как можно контролировать использование памяти; • файлы, которые наиболее часто присоединяются к программе, включая заголовок и файлы начальной загрузки; • работа компоновщика, сценарии компоновщика. Как и в других главах, мы постараемся приводить примеры как можно чаще. 17.1. Основная идея — более глубокие знания С и его среды Несмотря на то, что эта глава предполагает более глубокое понимание С, мы не будем здесь развивать непосредственно навыки кодирования на С. Вместо этого мы рассмотрим С и его ограничения при работе с оборудованием на низком уровне через прерывания, а также необычные методы работы с памятью. Кроме того, рассмотрим файлы, которые не являются исходным кодом, и работу компоновщика по их сборке в единое целое. Для того чтобы помочь связать эти разные элементы, приведем несколько примеров из файла, который запускает все примеры программ на С в этой книге, — это файл начальной загрузки c018i. с. Он содержит много интересных особенностей программирования. Изу- чая примеры, мы в то же время поймем значение этого важного программного компонента. Его код не простой, и необязательно понимать его весь. Предполагается, что при работе над главой под рукой всегда будет печатная копия этого файла. Это сравнительно корот- кий фрагмент кода — распечатка займет приблизительно две с половиной страницы. Для того чтобы его найти, запустите в MPLAB® любой файл С из этой книги, и среда автома- тически выведет его на экран при запуске программы. Другой способ — найти этот файл в папке mccl8\src\traditional\startup инсталляции С18.
17.2. Ассемблерные вставки 445 17.2. Ассемблерные вставки Несмотря на полезность С во встроенной среде, всегда бывают ситуации, когда лучше использовать ассемблер. Это случаи, когда: • определенные команды выполняют очень специфические для процессора действия, для которых в С просто нет эквивалента — в среде PIC это команды SLEEP или CLRWDT; • есть особенные требования ко времени выполнения программы, и программисту нужно иметь прямой контроль над тем, как написаны определенные части программы; • часть программного кода должна выполняться очень быстро, и программист желает написать код наиболее оптимальным способом. Поэтому полезно, когда это необходимо, иметь возможность внутри программ на С переключаться на ассемблер. Это называется встроенный ассемблер. Он позволяет избе- жать необходимости писать отдельную часть программы на ассемблере и присоединять ее к главной программе на этапе компоновки, как показано на рис. 14.1. Компилятор MPLAB Cl8 позволяет вставлять ассемблерный код в программы на С. Это может быть как отдельная команда, так и большой программный блок. Логично пред- положить, что компилятор С передаст встроенный ассемблерный код в MPASM™, а стан- дартный ассемблер в MPLAB. Однако это не так. У компилятора С18 свой собственный внутренний ассемблер, который обрабатывает все ассемблерные вставки. Встроенный ассемблер С18 отличается от стандартного ассемблера среды MPLAB ря- дом характерных особенностей. Главные отличия: • ассемблерный код должен располагаться между специальными идентификаторами _asm и _endasm; • не должны использоваться директивы ассемблера; • комментарии должны быть в стиле C/C++; • не используются значения аргументов по умолчанию, все аргументы должны быть полностью определены; • должны использоваться полные версии имен команд из таблицы чтение/запись (как описано в конце табл. А5.1); • система счисления по умолчанию — десятичная; • литералы определяются, используя позиционную систему счисления С; • метки должны заканчиваться двоеточием. Пример программы 17.1. Фрагмент стартового файла c018i. с asm --------------Начало ассемблерной вставки | // определяем, есть ли байты для копирования-ч- movlb curr_byte movf cur г byte, 1,1 .................... copy loop - ______—__________-___~т Метка оканчивается двоеточием | bnz 2 // копировать 1 байт movf curr_byte+l, 1, 1 bz 7 // выполнение копирования copy_one_byte: tblrdpostinc **------------ movf TABLAT, 0, 0 •[ Комментарии в стиле С | Полное имя функции TBLRD*+ | movwf POSTINCO, 0 // уменьшение счетчика байтов ________________________________ decf curr byte 1 M______________| Указаны значения аргументов по умолчанию | еndasm-ч—————--------1 Конец ассемблерной вставки | Пример встроенного ассемблерного кода приведен в Примере программы 17.1. Хотя на первый взгляд он выглядит как обычный фрагмент кода, в нем показаны шесть характе-
446 Глава 17. Более глубокие знания языка С и его среды окружения ристик встроенного ассемблера. Все они подписаны и относятся непосредственно к выше- указанному списку. Пример взят из стартового файла c018i . с. Встроенный ассемблер нужно использовать с некоторой осторожностью, особенно если блок ассемблерного кода длинный. Как мы знаем, ассемблер требует меньшей дис- циплины, чем С, поэтому можно очень легко случайно нарушить эту дисциплину при на- писания кода на ассемблере и, таким образом, разрушить работу основной программы. Начинающим не стоит писать вставки, которые влияют на переменные или функции, объявленные в коде на С. При необходимости написать большой блок кода на ассемблере лучше оформить его отдельным файлом, обработать ассемблером MPASM и собрать вме- сте с основной программой. Это позволит быть уверенным, что при работе с памятью, ис- пользовании переменных и вызове функций не возникнет никаких проблем. 17.3. Контроль за выделением памяти Одним из преимуществ работы с языком программирования высокого уровня должно быть то, что программисту не нужно волноваться о схеме распределения памяти или соб- ственно о том, как выделить память. Компилятор С будет сам следить почти за всем этим, если мы захотим. Кое-где, конечно, компилятору необходимо дать информацию о памяти компьютера, для которого производится компиляция. Эта информация спрятана в сцена- рии компоновщика, который описан в разделе 17.10 Однако во встроенной среде бывают ситуации, когда мы хотим взять на себя управ- ление распределением памяти. Эти ситуации включают действия, специфические для аппаратного обеспечения -— как работа с разрядами конфигурации или прерываниями, так и оптимизация использования схемы распределения памяти. В компиляторе С18 доступны разнообразные методы управления распределением па- мяти. Некоторые из них достаточно сложные, и их следует использовать только опытным программистам, а некоторые нужно знать всем. Сейчас мы их и рассмотрим. 17.3.1. Директивы распределения памяти Мы уже встречали концепцию директив препроцессора в разделе 14.2 Главы 14. Дирек- тивы #pragma являются особым типом директив. Они дают С возможность ориентиро- ваться на конкретный компилятор — каждый раз, когда используется директива #pragma, следующий за ней оператор будет специфичным для данного компилятора. Компилятор С18 имеет в своем расположении четыре директивы управления рас- пределением памяти. Они изменяют часть кода (т.е. специально определенный блок кода) в такой, в котором компилятор помещает данные в память. Эти директивы приведены в табл. 17.1. Формат каждой из них разрешает использовать большое количество различных параметров, которые полностью представлены в документации. Эти параметры могут быть довольно сложными, поэтому здесь мы ограничимся рассмотрением деталей. Табл. 17.1. Директивы распределения памяти Директива Результат # pragma code ... Размещает код программы в программной памяти # pragma romdata ... Размещает данные в программной памяти # pragma udata ... Размещает неинициализированные пользователем переменные в программной памяти # pragma idata ... Размещает инициализированные пользователем переменные в программной памяти Директива #pragma, которая чаще всего употребляется, находится в таблице первой. Общий формат этой директивы следующий:
17.3. Контроль за выделением памяти 447 #pragma code (имя секции) (=адрес) Эта директива действует как директива ассемблера org, указав, если нужно, где по- местить код программы в памяти. Оба выражения в скобках необязательны. Эта дирек- тива — одна из тех директив, с которых начинается каждая написанная нами программа С18, и она располагается в начале файла начальной загрузки c018i . с. Первые его стро- ки приведены ниже: ♦pragma code _entry__scn=0x00 void _entry (void) ( _asm goto _startup _endasm } ♦pragma code _startup_scn void ^startup (void) { В данном случае формат #pragma code применяется к секции с именем _entry_scn и адресом 0x00. Несколькими строками ниже директива pragma используется снова с именем секции _startup_scn, хотя теперь адрес не задается. Это разрешает компонов- щику установить адрес. Оба имени _entry_scn и _startup_scn — это имена, зарезер- вированные для С18, вначале для расположения нулевого вектора, а позже для содержа- ния кода начальной загрузки. 17.3.2. Установка машинных слов конфигурации Учитывая большое количество разрядов конфигурации в микроконтроллерах семей- ства PIC 18, привлекательно уметь устанавливать их в программе. Версия 3.0 компиля- тора С18 позволяет легко устанавливать их с помощью директивы #pragma config. Фактически используемые установочные параметры специфичны для процессора, но да- же для одного микроконтроллера элементы выбора, как ни удивительно, обширны. По- этому они здесь не представлены, но для всех микроконтроллеров семейства PIC 18 эти параметры можно найти в документации. Пример программы 17.2 демонстрирует установочные параметры, которые свойст- венны Derbot-18. Полезно вернуться к табл. 12.4 для того, чтобы проверить установки конфигурации. На каждое машинное слово конфигурации используется одна строка #pragma config с форматом директивы из документации. Все незаданные разряды конфигурации остаются с их значениями по умолчанию. Пример программы 17.2. Установка разрядов конфигурации для Derbot___________ ♦pragma config OSC = HS, OSCS = OFF//тип генератора — HS, генератор выкл. ♦pragma config PWRT = ON, BOR = OFF//таймер по включению питания вкл., //контроль понижения напряжения выкл. ♦pragma config WDT = OFF //сторожевой таймер выкл. ♦pragma config STVR = ON, LVP = OFF//сброс по переполнению стека вкл., //низковольтное программирование выкл. Установив директивой pragma разряд конфигурации, мы тем самым переопределим любые установки в окне Configuration Bits MPLAB IDE. Во время компоновки проекта компилятор устанавливает разряды в те установочные значения, которые заданы в про- грамме. Интересно проверить это на практике, задав неправильные установки для разря- дов конфигурации в окне Configuration Bits и потом скомпоновав проект. Заметим, одна- ко, что если разряд не определен в исходном коде, но отдельно установлен в окне Configuration Bits, то процесс компоновки принудительно не возвращает этот разряд к его значению по умолчанию. Как и в разделе 7.11.3 Главы 7, выберите в MPLAB пункты
448 Глава 17. Более глубокие знания языка С и его среды окружения меню Configure > Settings > Program Loading и установите флажок Clear configuration bits upon loading the program. Это гарантирует, что при загрузке программы настройки окна очистятся, и будут загружены только разряды конфигурации, заданные в программе. 17.4. Прерывания Прерывания представляют ряд многообещающих возможностей в.среде С. Работая с прерываниями, мы, тем самым, работаем с аппаратным обеспечением на низком уровне, в то время как языки программирования высокого уровня склонны от него отдаляться. Нуж- но рассмотреть по порядку ряд различных важных действий для того, чтобы обеспечить успешную работу прерываний семейства 18. Прерывания нужно разрешить и расположить в желаемой очередности. Программу обслуживания прерываний необходимо разместить в программной памяти, начиная с правильного адреса (заметим, что в структуре семейства 18 два вектора прерываний), также нужно организовать сохранение контекста. Посмотри- те на рис. 12.7 и сопровождающее его описание — для того чтобы, если нужно, вспомнить эти вопросы. 17.4.1. Программа обслуживания прерываний Программы обслуживания прерываний похожи на функции С, за исключением разве что того, что они вызываются при наступлении прерывания и заканчивают свою работу с выдачей результата из команды прерывания. В таких программах могут быть локальные переменные (т.е. переменные, объявленные внутри программы обслуживания прерываний), кроме того эти программы имеют доступ к глобальным переменным. Глобальные пере- менные, к которым могут иметь доступ программы обслуживания прерываний, должны, однако, быть определены как volatile. Это указывает на то, что значение переменной можно изменять снаружи нормальной программной операции. Поскольку программы обслуживания прерываний могут вызываться откуда угодно, не разрешается передавать никаких параметров или возвращать значения. 17.4.2. Расположение и обозначение программ обслуживания прерываний Компилятор С18 использует несколько директив для того, чтобы расположить начало программы обслуживания прерываний в нулевой вектор, а затем отличить такую програм- му от обычной функции. Как и нулевой вектор, компилятор С18 автоматически не размещает программу обслу- живания прерываний в младший или старший вектор прерываний в программной памяти. Для этого нужно использовать уже описанную директиву #pragma code. Она исполь- зуется для того, чтобы правильно организовать запуск программы обслуживания преры- ваний. Программу обслуживания прерываний можно узнать по использованию слова pragma. Возможны два определения такой программы: • #pragma interrupt имя_функции (save = список_сохранений). Эта дирек- тива определяет программу обслуживания прерываний с именем имя_ функции и вы- соким приоритетом. Для сохранения минимального контекста — регистров STATUS, WREG и BSR — используется стек быстрого регистра (см. раздел 12.6.3 Главы 12). Прерывание завершается с быстрой выдачей результата из прерывания. • #pragma interruptlow имя__функции (save = список_сохранений). Эта ди- ректива определяет программу обслуживания прерываний с именем имя_ функции и низким приоритетом. Для сохранения минимального контекста используется програм-
17.5. Пример прерывания на переполнение — мигание светодиодов на Derbot 449 мный стек, что замедляет ответный сигнал прерывания. Прерывание завершается с нормальной выдачей результата из прерывания. Дальнейшее сохранение контекста, сверх минимума, также можно осуществить в типе прерывания, указав регистр(ы), которые нужно сохранить, в необязательной части save директивы pragma. 17.5. Пример прерывания на переполнение — мигание светодиодов на Derbot Пример программы 17.3 использует прерывания по переполнению таймера 0 в 18F242 для мигания светодиодов на Derbot. Из этого, вроде бы простого, приложения можно получить несколько новых полезных сведений. Пример программы 17.3. Программа “Мигание светодиодов”, использует прерывания от Таймера 0 ______________________________________________________________ y********************i**i**ii*i****ii*i**i*i**i+***ii**ii**i***i*i*******^ Мигание светодиодов Заставляет мигать Derbot светодиоды, управляемые прерыванием по переполне- нию таймера О Демонстрирует: использование внешнего Таймера 0, прерываний и встроенного ассемблерного кода TJW 30.10.05 *************************************************************************! ♦include <pl8F242.h> ♦include <timers.h> ♦pragma config OSC = HS, OSCS = OFF//тип генератора — HS, генератор выкл. ♦pragma config PWRT = ON, BOR = OFF//таймер по включению питания вкл., //контроль понижения напряжения выкл. ♦pragma config WDT = OFF //сторожевой таймер выкл. ♦pragma config STVR = ON, LVP = OFF//сброс по переполнению стека вкл., //низковольтное программирование выкл. //прототипы функций, приведенные для информации void timerO_isr (void); unsigned char counter = 0; //Определить старший вектор прерываний по адресу 0008h ♦pragma code high_vector=0x08 void interrupt (void) ( _asm GOTO timerO_isr _endasm //перейти к программе обслуживания //прерываний } ♦pragma code //вернуться к обычному (по умолчанию) разделу кода //Функция timerO_isr определяется как программа обслуживания прерываний с высоким приоритетом ♦pragma interrupt timerO_isr //функция timerO_isr. Не передается никаких параметров, как и требуется для программ обслуживания прерываний
450 Глава 17. Более глубокие знания языка С и его среды окружения Пример программы 17.3. Окончание____________________________' _________ void timerO_isr (void) { counter = counter + 1; PORTC = counter«5; //сместить переменную counter влево, //и переместить ее в порт С INTCONbits.TMROIF = 0; //очистить флаг прерывания TMR0 } void main (void) { //Инициализировать TRISC = 0Ы0000000; PORTC = 0; //Выключить все выходы ^Инициализировать TMRO: разрешить прерывания, 16-разрядная команда, внутренний генератор, предварительный делитель частоты 4, следовательно, (с генератором в 4 МГц) период 1 мкс х 64k х 4 = 262 мс */ OpenTimerO (TIMER_INT_ON & T0_SOURCE_INT & T0_16BIT & T0_PS_l_4); INTCONbits.GIE = 1; //Включить глобальное прерывание while (1) //Ожидать прерывания { } j Можно увидеть, что главная функция этой программы очень короткая — она осуще- ствляет только инициализацию, а все важные действия содержатся в программе обслужи- вания прерываний. Все, что делает главная функция — это инициализирует порт С и уста- навливает его значение в нуль, инициализирует таймер 0 (см. ниже), разрешает глобальное прерывание и, наконец, заходит в бесконечный цикл while, ожидая наступления преры- ваний. 17.5.1. Использование таймера 0 Мы уже встречали библиотечные функции для работы с таймером семейства 18 в раз- деле 15.5.1 Главы 15. Собственно таймер 0, вместе с его разнообразными режимами рабо- ты (показанными на рис. 13.2), был описан в разделе 13.3.1 Главы 13. Заголовочный файл таймера timers . h нужно включать в любую программу, которая будет использовать этот таймер, как видно в примере программы. Можно увидеть, что эта программа использует функцию OpenTimerO в части ини- циализации главной функции, как приведено ниже: OpenTimerO (TIMER_INT_ON & TO_SOURCE_INT & T0_16BIT & T0_PS_l_4); Данные для настройки таймера задаются в аргументе этой функции. Информацию о полном наборе параметров для данной функции можно найти в документации. Эта реа- лизация включает прерывания на переполнения таймера, устанавливает внутренний гене- ратор в качестве источника генератора тактовых импульсов, выбирает 16-разрядную ко- манду (противоположно к 8-разрядной) и устанавливает предварительный делитель час- тоты в 4. Как только все это установлено, таймер начинает свободно работать и генериро- вать серию прерываний, на которые микроконтроллер может отреагировать. Учитывая все сделанные установки, переменной counter, для того чтобы пройти всю область значе- ний, нужно 65 536 циклов, и каждый входной цикл продолжается 4 мкс. Интервал между прерываниями, следовательно, будет 65 536 х 4 мкс, или 262,144 мс.
17.5. Пример прерывания на переполнение — мигание светодиодов на Derbot 451 17.5.2. Использование прерываний и работа программы обслуживания прерываний Этот пример программы использует разовое прерывание от таймера 0. Не было вклю- чено назначение приоритетов, поэтому по умолчанию используется старший вектор пре- рывания. Как уже упоминалось, векторы прерываний нужно указывать в программном листинге, используя код после директивы #pragma. Для того чтобы установить стар- ший вектор прерывания (рис. 12.6), используется следующая команда: #pragma code high_vector = 0x08 Это директива указывает, что часть последующего кода нужно поместить в память, начиная с адреса 08н. Эта часть кода была названа программистом high_vector, это не зарезервированное слово, поэтому можно было выбрать любое другое. И, наоборот, для младшего вектора прерывания: #pragma code low_vector = 0x18 означает, что последующий код нужно поместить в память по адресу 18н. Этот код был назван программистом low_vector. После правильного размещения векторов идет одна строка подставляемого ассемб- лерного кода, осуществляющая переход в основную часть программы обслуживания пре- рываний _asm GOTO timerO_isr _endasm //перейти в программу обслуживания //прерываний Для отмены действия предыдущих директив pragma и разрешения компилятору снова управлять расположением кода, используется следующая директива: #pragma code Она возвращает правило расположение кода к принятому по умолчанию. Программа обслуживания прерываний, timerO_ISR, появляется как прототип функ- ции в начале программы. Работа этой программы проста: сначала увеличивается значение переменной counter, затем это значение пять раз сдвигается влево, а затем присваива- ется порту С. В результате этого как минимум 2 разряда переменной counter перено- сятся в светодиоды, которые находятся в разрядах 5 и 6 порта С, и затем очищается флаг прерывания от таймера 0. Этот простой пример прерывания использует только одно прерывание и не применяет возможность назначения приоритетов прерываниям семейства 18. Использование двух прерываний, расположенных в соответствии с приоритетом, демонстрируется в примере программы 19.6. 17.5.3. Моделирование программы мигания светодиодов Интересно смоделировать пример программы 17.3 независимо от того, загружается ли она в аппаратное обеспечение. Создайте проект для программы, используя исходный код на компакт-диске этой книги. Выполните его сборку и смоделируйте с помощью симуля- тора MPLAB. Откройте окно Watch и отобразите значения PCL, counter, PORTC и INTCON, как показано на рис. 17.1 (а). Пошагово пройдите начало программы, заметив, когда появится функция OpenTimerO. Войдя в главную функцию и завершив заданную пользователем инициализацию, программа зайдет в бесконечный цикл, ожидая преры- вания. Теперь принудительно инициируем прерывание, установив флаг прерывания от тай- мера 0 (разряд 2 регистра INTCON) в окне Watch. Далее пошаговое выполнение програм- мы перейдет к программе обслуживания прерываний посредством ассемблерной вставки
452 Глава 17. Более глубокие знания языка С и его среды окружения в старший вектор прерывания. Можно наблюдать за работой программы обслуживания прерываний, продолжая пошаговое выполнение. (а) в Watch Add SER | ADCONO y|' .Add Symbol| |ADCONO Address | Symbol Name | Hex | Decimal | Binary | ,ж. 008A counter 02 2 00000010 43 0FF9 PCL 0 8 8 0000 ICO0 — 0FF2 INTCON 2 4 3 6 00100100 0F82 PORTC 40 64 01000000 0FD6 TMRO 0001. 1 ООЗООНО OOCOOOOl V | Watch 1 Watch 2 | Watch 3 | Watch А | (Ь) ^pragma code high_vector“0x08 void interrupt (void; as=m GOTO timer0_isr _endassm //gump to ISR Рис. 17.1. Ожидаемые установки для моделирования программы “Мигание светодиодов”: (а) — окно Watch; (Ь) — расположение точки прерывания Теперь исследуем работу прерывания от таймера. Сначала поместим точку прерыва- ния в самом начале подпрограммы обслуживания прерывания, как показано на рис. 17.1 (Ь). Если теперь запустить программу, то она будет останавливаться всякий раз, когда дойдет до этой точки, т.е. каждый раз, как только произойдет прерывание. Выберите из панели ин- струментов команду Debugger > Settings > Osc/Trace и установите частоту генератора в 4 МГц. Откройте окно Stopwatch из ниспадающего меню Debugger, как показано на рис. 17.2. Рис. 17.2. Окно Stopwatch для моделирования программы “Мигание светодиодов” Запустите программу до точки останова из любого места программы, где бы вы ни находились. Обнулите контрольный таймер и запустите программу снова. Через мгно- вение выполнение программы снова остановится на точке останова. Показанное время контрольного таймера должно быть 262,144 мс, точь-в-точь, как на рис. 17.2. Это под- тверждает время между переполнениями. В тоже время, значения в окне Watch должны быть такими же, как и на рис. 17.1 (а). Таймер 0 был только что переполнен и снова начал постепенно увеличиваться с нуля; младший байт счетчика команд (PCL) был установлен
17.6. Классы памяти и их применение 453 как нулевой вектор с высоким приоритетом, 08н; также был установлен флаг прерывания от таймера — разряд 2 регистра INTCON. Если у вас имеется аппаратное обеспечение — Derbot-18, тогда эту программу мож- но использовать для привлекательной демонстрации мигания светодиодов. 17.6. Классы памяти и их применение Цель оставшейся части данной главы — посмотреть на более широкое окружение, внутри которого находятся исходные файлы С. Среди них известны три файла, которые используются практически каждой программой: заголовочный файл микроконтроллера, файл начальной загрузки и сценарий компоновщика. Для того чтобы разобраться с этими' файлами, необходимо рассмотреть еще несколько аспектов С — мы начнем это рассмот- рение с классов памяти. 17.6.1. Классы памяти Как мы уже увидели, язык программирования С осторожно управляет использова- нием данных, с точки зрения объявления данных и того, как их можно использовать. Это необходимо отчасти потому, что программы на С могут быть сложными объектами, состо- ящими из различных файлов и функций, которые написаны в разное время разными людь- ми и сохранены на различных стадиях компиляции. Функции и данные могут быть объяв- лены, к примеру, в одном файле, но к ним может потребоваться доступ из других файлов. Характеристикой данных, которые используются в С, следовательно, являются их классы памяти. Класс памяти определяет статус данных внутри и снаружи блоков кода, функций и файлов. Табл. А6.3 содержит четыре зарезервированных слова С, которые для этого используются. Компилятор С18 использует только три класса из перечисленных в таблице: auto, static и extern. Это в некоторой степени особые термины, и в них не вкладывается много смысла, даже если мы представим себе, что auto — это сокращение от “автома- тический”, a extern — от “внешний”. Полезно знать, что использование слова “авто- матический” было взято из других компьютерных языков, и подразумевает переменную, которая возникла для определенной цели внутри некоторой функции, и не существует в другое время. “Статический”, с другой стороны, предполагает переменную, которая имеет некоторую форму непрерывного существования. “Внешний” означает переменную, ко- торая существует непрерывно, и доступ к которой может получить любая функция. Возвращаясь к классам памяти, отметим, что класс определяет три вещи: область дей- ствия, срок действия и связь данных. Давайте рассмотрим по очереди каждое из этих по- нятий. Табл. 17.2 суммирует рассмотренные моменты для всех возможных комбинаций их использования. Некоторые из них, конечно, используются более часто, чем другие, и мы воспользуемся только отдельными в примере программы этой книги. 17.6.2. Область действия Область действия переменной определяет часть программы, в которой она, перемен- ная, может использоваться. Возможны два типа области действия: • Область действия блока. Переменную можно использовать только в блоке кода, внутри которого она была объявлена, начиная с места объявления. Переменные этого типа называются локальными переменными. В разных блоках программы можно ис- пользовать одинаковые имена для локальных переменных, и эти переменные будут независимыми.
454 Глава 17. Более глубокие знания языка С и его среды окружения • Область действия файла. Такую переменную можно использовать в файле, внутри которого она была объявлена, начиная с места объявления. Объявить переменную нужно снаружи всех блоков. Табл. 17.2. Классы памяти: влияние спецификатора и места объявления Спецификатор класса памяти Объявлен за пределами всех функций Объявлен внутри функции попе Область действия файла Статический срок действия Внешняя связь Область действия блока Автоматический срок действия Нет связи auto — Область действия блока Автоматический срок действия Нет связи static Область действия файла Статический срок действия Внутренняя связь Область действия блока Статический срок действия Нет связи extern Область действия файла Статический срок действия Внешняя связь Область действия блока Статический срок действия Внешняя связь 17.6.3. Срок действия Срок действия переменной может быть одним из следующих двух: • Автоматический срок действия. Автоматическая переменная объявляется внутри бло- ка кода и создается заново каждый раз, когда выполнение программы заходит в этот блок. В конце блока кода переменная прекращает свое существование, а занимаемая ею память освобождается. Зарезервированное слово auto определяет этот срок дей- ствия. Поскольку этот срок действия выбирается по умолчанию, когда переменная объявляется внутри блока, то это зарезервированное слово используется нечасто. • Статический срок действия. Статическая переменная существует на протяжении всего выполнения программы и определяется зарезервированным словом static. Статические переменные могут быть также локальными в блоке, но продолжают существовать снаружи блока. Переменные, объявленные снаружи всех блоков, неза- висимо от того, использовалось зарезервированное слово или нет, считаются стати- ческими. 17.6.4. Связь Как внутри файлов, так и в том случае, когда используются несколько файлов, важно учесть, как имена переменных могут признаваться по отношению к таким же переменным. Итак, существует три возможных типа связи: • Внешняя связь. Если переменная или функция связаны внешне, то они распознаются повсюду в программе, где бы ни были объявлены. Имя распознается компоновщиком. Переменная имеет внешний тип связи, если она объявлена спецификатором класса памяти extern, или если она объявлена снаружи всех функций без указания класса памяти. • Внутренняя связь. Переменная имеет внутренний тип связи, если она объявлена как static снаружи всех функций. Такая переменная остается внутренней для единицы
17.6. Классы памяти и их применение 455 трансляции, но распознается в ней повсюду. Компоновщик о такой переменной “ни- чего не знает”. • Нет связи. Все остальные переменные имеют такой тип связи, например, переменные с автоматическим сроком действия. 17.6.5. Работа с памятью семейства 18 Дальнейшее усложнение, или возможность, появляется в компиляторе С18 в связи с функциональными требованиями памяти. Из-за Гарвардской структуры памяти и ее сво- бодного использования микроконтроллер PIC представляет изменения в том, как С ин- терпретирует распределение памяти. Компилятор С18, вследствие этого, вводит класси- фикаторы памяти far и near. Они функционируют как зарезервированные слова и фак- тически являются специфичными для С18 расширениями языка С. Эти классификаторы памяти указывают микроконтроллеру, что нужно использовать — размер памяти или мар- шрут к памяти. Каждый из них может использоваться с двумя другими зарезервирован- ными словами-расширениями, гот и ram. Последние используются, если тип памяти должен быть задан при объявлении переменной или константы. Когда данные объявля- ются без классификаторов памяти, по умолчанию устанавливаются ram и far. Действие всех этих классификаторов памяти суммируется в табл. А6.8, вместе с кратким описанием. Могут быть также определены две модели памяти, small и large. Свойства каждой из них приведены в табл. А6.9. Модели памяти выбираются с помощью параметров ко- мандной сроки, используя по умолчанию small. Единственное различие между этими моделями в необходимом размере указателя. Модель small, которая устанавливается по умолчанию, необходима для небольших и средних программ. 17.6.6. Примеры классов памяти В первом из двух фрагментов кода из файла с 0181. с, взятых из начала файла, можно увидеть объявление переменных. Здесь явным образом используется слово extern, ука- зывая на то, что переменные имеют внешнюю связь. Все три переменные также присутст- вуют в заголовочном файле 18f242 . h. Использование классификатора near обозначает, что эти переменные должны быть помещены в ОЗУ доступа. Типы данных, которые нам еще не встречались, можно узнать из табл. А6.4. extern volatile near unsigned long short TBLPTR; extern near unsigned FSRO; extern near char FPFLAGS; Второй пример, приведенный ниже, демонстрирует начало функции _do_cinit () с убранными комментариями. В начале функции объявляются четыре переменных. Все они статические, поэтому будут существовать непрерывно, а будучи объявленными внут- ри блока (т.е. внутри функции), они будут локальными для этой функции. void _do_cinit (void) { static short long prom; static unsigned short curr_byte; static unsigned short curr_entry; static short long data_ptr; Значение способа объявления этих переменных исследуем позже, когда будем моде- лировать файл c018i . с в разделе 17.7.3.
456 Глава 17. Более глубокие знания языка С и его среды окружения 17.7. Код начальной загрузки: c018i. с Сейчас мы, наконец, добрались до подробного просмотра файла с018 i . с. Выглядело неожиданным, что при моделировании первой программы на С симулятор не сразу зашел в главную функцию. Без сомнения это то, о чем пишут все учебники: не должна ли глав- ная функция просто начинаться с нулевого вектора? Однако существуют атрибуты, которые необходимо установить еще до начала работы программы — для того чтобы программа на С работала правильно. Они включают все, что может понадобиться для надлежащей ра- боты программы на С — например, программный стек для переноса данных и инициали- зации всех переменных и констант. Эти атрибуты могут быть обусловлены требованиями собственно С, или тем, что значения уже были проинициализированы в программе. Программы инициализации, которые выполняют эти функции, находятся в каждом компиляторе и могут быть малозаметными для программиста. Тем не менее, если мы отче- го-то зависим, то хотя бы немного стоит с этим познакомиться. 17.7.1. Файлы начальной загрузки С18 Компилятор С18 обеспечивает три файла начальной загрузки различного уровня слож- ности. Они доступны как пред-компилированные объектные файлы, которые подключа- ются к главной программе на стадии компоновки. Обычно они подключаются к пользо- вательскому приложению сценарием компоновщика. Исходная версия файла также дос- тупна. Программа начальной загрузки — это программный элемент, который помещается в нулевой вектор, поэтому процессор выполняет ее первой. Она инициализирует програм- мный стек и все данные, для которых задано начальное значение, и затем переходит в главную пользовательскую функцию. Все приведенные до этого времени программы используют файл сО18i . с. Это можно увидеть при моделировании любого примера программ на С с MPSIM , если начать по- шагово выполнять программу. Этот файл предполагается для программ, когда процессор работает в нерасширенном режиме. Версия c018i_e. с предназначена для расширен- ного режима работы процессора. Файл с018 . с является более простой версией файла начальной загрузки. Он просто устанавливает программный стек и переходит в главную программу без инициализации памяти для данных. Более сложная версия файла начальной загрузки — файл c018iz . с, который делает тоже, что и c018i. с, но дополнительно устанавливает все неинициали- зированные переменные в нуль, как требует строгий стандарт ANSI С. Эти две версии пред- назначены для нерасширенного режима работы процессора, их эквиваленты для расши- ренного режима— файлы с018_е . с и c018iz_e . с. 17.7.2. Структура программы c018i. с Первая часть программы с018 i . с уже была приведена в разделе 17.3.1. Первое действие этой программы — проинициализировать FSR1 и FSR2, которые используются для программного стека (и поэтому невидимы для программиста). Затем она вызывает функцию _do_cinit, которая инициализирует переменные в оперативной па- мяти, если есть такие, которые нуждаются в инициализации. В конце этой функции вы- зывается главная функция в строках, приведенных ниже. loop: //Вызвать пользовательскую главную функцию main () ; goto loop; Здесь интересно увидеть, что если функция main когда-нибудь выполнит return, тогда она сразу же вызовется снова.
17.7. Код начальной загрузки: сО18i.c 457 17.7.3. Моделирование c018i. с Если Вы будете моделировать программы из этой книги, то много раз пройдете по сО 18 i . с. Тем не менее, давайте сейчас еще раз зайдем в него и обратим немного больше внимания на то, что там происходит. Этот файл можно также использовать для проверки классов памяти конкретных переменных, которые мы уже видели в примерах. Откройте проект, созданный для примера программы 14.1, и запустите симулятор MPLAB. Откройте окно Watch и выберите переменные, показанные на рис. 17.3. Возвра- тите симулятор в исходное положение. Интересно заметить, что переменные, которые объявлены в исходном коде, по-видимому, действительны, как переменная TBLPTR, объ- явленная вначале программы. Другие переменные в окне Watch, которые объявлены внут- ри функции _do_cinit, обозначены, как можно увидеть на рисунке, “вне области ви- димости” — это соответствует тому, что описано в разделе 17.6.2. Пошагово выполняем программу до тех пор, пока не зайдем в функцию _do_cinit. Заметим, как три перемен- ные внезапно появились в области видимости и получили (нулевое) значение. Если про- должить пошагово выполнять программу, то увидим, что выполнение вернется из функ- ции на более ранний этап — этой простой программе не нужна инициализация. Затем вызовется главная функция. Add SER | jADCONO 3 Add Symbol| jTBLPTR И Watch Address Symbol Name - Bex u • Bins ку!л>. 0F81 PORTB 00 00000000 'П 008А counter 00 00000000 0FF9 PCL 00 00000000 curr byte Out of Scope out of Scope curr entry Out of Scope Out of Scope data ptr Out of Scope Out of Scope 0FF6 TBLPTR 000000 00000000 00000000 00000000 r ~ 1 Watch 1 Watch 21 Watch 3 | Watch 4 Рис. 17.3. Окно Watch для выполнения c018i. о из примера программы 14.1 Теперь переместим объявление переменной counter в строку исходного кода, на- ходящуюся внутри главной функции. unsigned char counter; //определим переменную counter //как беззнаковый символ Снова скомпонуем и смоделируем программу. Заметим, что теперь в начале выпол- нения программы переменная counter находится “вне области видимости”. В результа- те объявления этой переменной внутри функции, она потеряла свою внешнюю связь, как показано в табл. 17.2. Если выполнять программу пошагово, то можно увидеть, как пе- ременная counter появится в области видимости, как только выполнение продвинется в главную функцию. Теперь откроем проект примера программы 16.2, в котором нужно проинициализи- ровать много списков. Настроим окно Watch с переменными, показанными на рис. 17.4. Последние три переменные вначале будут снова “вне области видимости”. Пошагово выполним программу до функции _do_cinit. Как и раньше, последние три переменные получат числовые значения. Продолжая пошаговое выполнение, заметим, что выполнение программы зашло в основной цикл внутри функции. В конечном счете, увидим, что заполненные данными символьные строки будут перемещены из программ- ной памяти в память для хранения данных. Рисунок показывает не полностью завершен- ную строку “Apple”.
458 Глава 17. Более глубокие знания языка С и его среды окружения В Watch Add Sffi | |aDCONO у | Add Symbol] j tmp_0 a Address] Symbol Name | Hex | Binary | Char |.A I 0681) » list DO A3 counter 00 00000000 0088 number 00 00000000 0089 l - iteml 0089 — [0] 41 01000001 A 008A — [1] 70 01110000 P 008B — [2] 70 01110000 P 008C — [3] 00 00000000 008D — [4] 00 00000000 008E [5] 00 00000000 008F e item2 009C curr byte 000D 00000000 00001101 . - 009E curr entry 0001 00000000 00000001 OOAO data_ptr 000038 00000000 00000000 00111000 . .8 * Watch 1 Watch 21 watch 31 Watch 41 Рис. 17.4. Окно Watch для выполнения c018i.о из примера программы 16.2 Символьные строки, на которые мы смотрели, были помещены в память данных толь- ко потому, что это их местоположение “по умолчанию”, как свидетельствует раздел 17.6.5. Теперь исследуем, как можно использовать зарезервированное слово-расширение гот для того, чтобы поместить (или в действительности оставить) одну из этих символьных строк в программной памяти, что намного целесообразнее. В объявлении строки “Apple” в исходном файле, вставим слово гот, как показано ниже: гот char iteml[] = "Apple"; Перекомпонуйте программу и установите симулятор в исходное положение. Теперь заметим (по используемым адресам из рис. 17.5), что строка “Apple” была помещена в про- граммную память. Она мгновенно доступна и не требует никакой инициализации памяти. И Watch Add SFR | jADCONO jrJ Add Symbol 11 tmp_0 V I Address| Symbol Name ] Hex | Binary " | Char ] Л 0088 number 00 00000000 0296 0296 iteml [0] 41 01000001 A 0297 1 [1] 70 01110000 P 0298 —[2] 70 01110000 P 0299 1 [3] 6C 01101100 1 029A — [4] 65 01100101 e 029B [5] 00 00000000 0089 ? 0089 •i item2 —[0] 00 00000000 008A [1] 00 00000000 008B [2] 00 00000000 — 008C [3] 00 00000000 008D [4] 00 00000000 [Watchl Watch2| Watch3|'Watch4| - Рис. 17.5. Окно Watch для примера программы 16.2 — использование зарезервированного слова гот
17.8. Структуры, объединения и битовые поля 459 17.8. Структуры, объединения и битовые поля В следующем разделе мы рассмотрим заголовочные файлы микроконтроллера. Их большая часть использует такие типы данных, которые мы еще не встречали, поэтому сей- час мы их и рассмотрим. И структуры, и объединения являются наборами связанных переменных, определен- ных с помощью зарезервированных слов С struct nunion. С одной стороны они похо- жи на массивы, но могут содержать элементы данных разных типов. Структурные элементы, называемые членами, упорядочиваются последовательно и в памяти располагаются один за другим. Структура объявляется с помощью зарезервиро- ванного слова struct, за которым следует произвольное имя (называемое именем типа структуры), а дальше идет список членов структуры, каждый из которых объявляется. Например: struct resistor {int val; char pow; char tol;}; объявляет структуру с именем типа структуры resistor, которая содержит значение (val), нагрузочную способность (pow) и отклонение резистора (tol). Имя типа может находиться до или после скобок, содержащих список членов структуры. Конкретный элемент структуры определяется указанием имени структуры и имени члена, разделенные точкой. Следовательно, resistor.val определяет первый член структуры, пример которой приведен выше. Как и структуры, объединения могут состоять из данных разных типов, но в отличие от структур, все элементы объединения начинаются с одного адреса. Следовательно, только один из его членов может представлять объединение в каждый момент времени, а размер объединения — это размер наибольшего элемента. Программист должен сам отслеживать, какой тип данных сохранен в данный момент! Объединения описываются таким же обра- зом, как и структуры. Объединения, структуры и массивы могут находиться один внутри другого. Мы уви- дим пример такого расположения в следующем разделе. Во встроенных системах мы очень заинтересованы в определении и доступе к отдель- ным разрядам. Возможность битовых полей С помогает в тех случаях, где битовое поле — это набор смежных разрядов внутри отдельного слова. Битовые поля могут объявлять- ся только как члены структур или объединений. Формат объявления битового поля следу- ющий: type [name]:width Здесь type — это знаковое или беззнаковое целое, width — число разрядов, a name — произвольное имя. 17.9. Заголовочные файлы, специфичные для процессора Заголовочные файлы, специфичные для процессора, очень важны во встроенном С. Они включают определения для всех SFR-регистров и их разрядов, а также некоторых полез- ных дополнений, например дополнительные особенности для работы с ассемблером. По- лезно далее посмотреть на один из заголовочных файлов процессора — выберем файл 18f242 . h. Его можно найти в каталоге mccl8\h программного обеспечения С18. 17.9.1. SFR определения Отрывок из заголовочного файла 18F242 приводится как пример программы 17.4. В нем видно, что был объявлен порт В и его разряды. Первая строка отрывка использует не ме- нее четырех зарезервированных слов С для определения типа для PORTB. Использование беззнакового символа определяет его как отдельный разряд, в то время как volatile
460 Глава 17. Более глубокие знания языка С и его среды окружения указывает на то, что он может быть изменен снаружи управляющей программой, a extern обозначает, что доступ к переменной можно получить снаружи этого файла. Использо- вание зарезервированного слова near указывает на то, что переменная размещается внутри ОЗУ доступа. Внимательно глядя на этот пример программы, можно увидеть, что объявление разря- дов порта делается как объединение с именем PORTBbits, которое включает две струк- туры. Как и порт В, это объединение определяется как extern volatile near. Можно увидеть, что первая структура внутри объединения — это список условных названий разрядов порта, каждый из которых объявлен как одноразрядное битовое поле. Вторая структура описывает альтернативное использование разрядов порта, каждый из которых снова объявляется битовым полем. Поскольку обе эти структуры принадлежат объединению, они фактически занимают одно и то же пространство памяти и могут исполь- зоваться как альтернатива одного к другому. Пример программы 17.4. Объявление порта В — часть из файла 18F242, h, версия 1.6 extern volatile near unsigned char PORTB; extern volatile near union { struct { unsigned RB0:l; unsigned RBI:1; unsigned RB2:1; unsigned RB3:1; unsigned RB4:1; unsigned RB5:1; unsigned RB6:1; unsigned RB7:1; }; struct { unsigned INTOzl; unsigned INT1:1; unsigned INT2:1; unsigned CCP2:1; unsigned :1; unsigned PGM:1; unsigned PGC:1; unsigned PGD:1; }; } PORTBbits; Сейчас мы, наконец, можем понять формат, который использовали в нескольких главах для идентификации порта и других разрядов SFR. Когда пишем, например PORTBbits. RB7 = 1; то теперь мы знаем, что это обращение к члену RB7 (битовому полю) структуры, которая в свою очередь является членом объединения PORTBbits. 17.9.2. Утилиты ассемблера в заголовочном файле Пример программы 17.5 показывает, как директива препроцессора #define исполь- зуется для определения конкретных операторов ассемблера семейства 18. Таким же спо- собом они могут использоваться в программе на С, даже без вызова обычной включаемой процедуры ассемблера. Для стороннего наблюдателя их использование будет выглядеть как функции. Этот прием будет применяться в Главе 19, вместе с операционной системой реального времени Salvo.
17.10. Идем дальше — компоновщик MPLAB и .тар-файл 461 Пример программы 17.5. Часть из файла 18F242.h — утилиты ассемблера #define Nop() {_asm nop _endasm} #define ClrWdtO (_asm clrwdt _endasm} #define Sleep () {_asm sleep _endasm} #define Reset() (_asm reset _endasm} 17.10. Идем дальше — компоновщик MPLAB и .map-файл Как показывает рис. 14.1, компоновщик играет центральную роль в любом процессе сборки программы. В несложных приложениях необязательно понимать, как работает компоновщик. Однако, даже в простых приложениях полезно приближенное представ- ление о компоновщике для понимания того, как программа собирается, особенно для оп- ределения и понимания “скрытых” подключаемых файлов. Для более сложных приложе- ний программист может захотеть изменить или переписать предоставленные файлы ком- поновщика. Этот раздел знакомит с MPLAB-компоновщиком, MPLINK™. Справочную информацию о нем можно найти в документации. 17.10.1. Что делает компоновщик Как показывает процесс компоновки на рис. 14.1, компоновщик связывает вместе объектные файлы для создания исполняемого кода, который может быть загружен в мик- роконтроллер. Он также обеспечивает основную информацию о распределении памяти, и эта информация может использоваться для отладочных целей. Объектные файлы могут быть программным кодом, созданным на С или ассемблере. С другой стороны, они могут быть библиотечными файлами для общих целей. В любом случае, содержащийся в них код достаточно переносимый — это означает, что в памяти адреса как для данных, так и для программ, еще не назначены. Задача компоновщика — расположить все объектные файлы в памяти и обеспечить правильную связь каждого с каждым. Он также управляет распре- делением программного стека. Всеми действиями компоновщика управляет сценарий компоновщика, содержащий существенную информацию о схеме распределения памяти микроконтроллера, который будет использоваться. В задачи компоновщика также входит обнаружение программных ошибок, например, совпадение адресов или неточная инфор- мация. 17.10.2. Сценарий компоновщика Сценарий компоновщика — это текстовый файл, состоящий из последовательности директив, которые предоставляют компоновщику информацию о расположении доступ- ной памяти и то, как ее следует использовать. Таким образом, эти директивы точно вос- производят ресурсы памяти и схему распределения памяти нужного микроконтроллера. В MPLAB предоставлены стандартные сценарии компоновщика для всех доступных микро- контроллеров семейства PIC 18. В стандартной инсталляции С18 их можно найти в ката- логе mcc\lkr. Сценарий для 18F242, файл 18f242 . Ikr, используется в каждом при- мере программы на С в этой книге. Этот файл представлен как пример программы 17.6. В MPLAB инсталляции также можно найти альтернативную, но в тоже время очень похо- жую, версию этого файла, которая не является специфичной для применения в С18. Исследуем этот пример сценария компоновщика. Наша задача — проанализировать, что там написано, а не писать новый файл, следовательно, мы не будем волноваться о точных форматах записи.
462 Глава 17. Более глубокие знания языка С и его среды окружения Пример программы 17.6, Сценарий компоновщика 18F242________ // $Id: 18f242.lkr,v 1.1 2003/12/16 14:53:08 GrosbaJ Exp $ // Файл: 18f242.1kr // Простой сценарий компоновщика для процессора PIC18F242 LIBPATH FILES c018i.o FILES clib.lib FILES pl8f242.1ib CODEPAGE NAME=vectors START=0> <0 END=0> <2 9 PROTECTED CODEPAGE NAME=page START=0> <2A END=0> <3FFF CODEPAGE NAME=idlocs START=0> <200000 END=0> <200007 PROTECTED CODEPAGE NAME=config START=0> <300000 END=0> <30000D PROTECTED CODEPAGE NAME=devid START=0> <3FFFFE END=0> <3FFFFF PROTECTED CODEPAGE NAME=eedata START=(b <F00000 END=0> <F000FF PROTECTED ACCESSBANK NAME=accessram START=0> <0 END=0> <7F DATABANK NAME=gpr0 START=(b <80 END=0j <FF DATABANK NAME=gprl START=(b <100 END=0x1FF DATABANK NAME=gpr2 START = (b <200 END=0j <2FF ACCESSBANK NAME=accesssfr START=(b <F80 END=0j <FFF PROTECTED SECTION NAME=CONFIG ROM=config STACK SIZE=0xl00 RAM=gpr2 • Комментарии компоновщика. Всем комментариям предшествуют символы //. Весь текст строки, который следует за этими символами, игнорируется компоновщиком. Как и можно ожидать, увиденные здесь комментарии предоставляют нам заголовок и информацию о версии. • Директива LIBPATH. Она предоставляет необязательный путь поиска файлов для под- ключения. В этом примере она не используется. • Директива FILES. Эта директива указывает объектные файлы для компоновки. Здесь перечислены три файла: о с018 i . о. Это версия объектного кода файла начальной загрузки, уже описанного в этой главе. о с lib . lib. Файл содержит стандартную библиотеку С, которая поддерживается компилятором С18. о pl8f242. lib. Этот файл содержит специфическую для процессора информа- цию и эффективно работает вместе со специфическим для процессора заголовоч- ным файлом. • Директива CODEPAGE. Эта директива применяется для распределения программной памяти. В данном примере она используется не менее шести раз, главным образом для предоставления схем распределения памяти микроконтроллера. Основной блок па- мяти, в который компоновщик может поместить программный код, расположен, на- чиная с адреса 02Ан до 03FFH. Это согласовывается со схемой распределения памяти на рис. 12.6. Предшествующее этому пространство зарезервировано для векторов. Бло- ки для данных конфигурации и идентификации устройств тоже зарезервированы, см., соответственно, табл. 12.4. Дальнейшее пространство зарезервировано для памяти ти- па EPROM и идентификации объектов. • Директива ACCESSBANK. Эта директива, которая дважды используется в примере, распределяет доступную память для данных. Когда директива используется в первый
17.10. Идем дальше — компоновщик MPLAB и .тар-файл 463 раз, расположенное в доступной памяти ОЗУ обозначается как accessram и правиль- но располагается в диапазоне адресов от 0 до 7Fh. Во второй раз определяется блок памяти для SFR-регистров, и этот блок располагается в схеме распределения памяти и обозначается accesssfr. Этот блок памяти определяется как защищенный, что прекращает его распределение компоновщиком для использования в общих целях, сле- довательно, сохранено абсолютное распределение памяти, сделанное где-либо для SFR-регистров. • Директива DATABANK. Данная директива похожа на ACCESSBANK и использует подоб- ный формат. Она используется для определения объединенной ОЗУ. Как можно уви- деть, реализация этой директивы в примере точно соответствует схеме распределения памяти данных из рис. 12.4. Каждый блок доступен для использования компоновщи- ком, следовательно, никакой их них не защищен. • Директива SECTION. Директива разрешает связывать имя, указанное директивой #pragma в исходном коде, параллельно с блоком памяти, который задан в сценарии компоновщика. В этом случае соединение осуществляется для памяти конфигурации, поэтому данные, созданные с помощью #pragma config (как показано в примере программы 17.2), располагаются в памяти правильно. • Директива STACK SIZE. Эта директива позволяет задать расположение программ- ного стека и его размер. В этом примере можно увидеть, что задается размер стека 100н, размещенный в ОЗУ банка 2. 17.10.3. Файл .тар Результатом работы компоновщика является то, что весь код правильно отображен в разные категории памяти. Как это можно проверить? Ответ находится в файле . тар — необязательной файле, создание которого можно запросить у компилятора. Этот файл по- казывает распределение всей памяти. В данном проекте его можно создать, выполнив следующую команду меню: Project > Build Options > Project > MPLINK Linker > Generate map File. Исходя из того, что проект собран успешно, файл . тар можно найти рядом с другими выходными файлами, с именем project_name.map. Файл .map представляет собой непривлекательное зрелище для стороннего наблюдателя, поскольку он содержит как ад- реса всех используемых символов, так и схему распределения памяти, полученную сцена- рием компоновщика. Тем не менее, этот файл может быть полезен как средство диагно- стики, если кто-то не может решить, как нужно интерпретировать переменную, или если что-то случилось с адресом памяти или блоком памяти. Другой полезной особенностью . map-файла является то, что он показывает размеры используемой памяти, а это, конечно же, становиться очень важным моментом по мере увеличения программы. Фрагменты файла . тар для примера программы 14.1 показаны в примере программы 17.7. Этот пример показывает, где расположены основные части программы, и указывает, что программная память используется скромно, всего на 1 процент! Пример программы 17.7. Фрагменты файла .тар для примера программы 14.1____ Информация о разделе Раздел Тип Адрес Расположение Размер(байты) _entry_scn code 0x000000 program 0x000006 .cinit romdata 0x00002a program 0x000002 _cinit_scn code 0x00002c program 0x00009e code_examplel.о code OxOOOOca program 0x000024 _startup_scn code OxOOOOee program 0x000018
464 Глава 17. Более глубокие знания языка С и его среды окружения Пример программы 17.7. Окончание Использование программной памяти Начало Конец 0x000000 0x000005 0x00002а 0x000105 226 из 16664 программных адресов используются, использование программной памяти — 1% Резюме • Все еще может быть необходимым время от времени выходить за жесткие рамки того, как С использует ассемблер. • Несложно использовать прерывания в С, но требуется понимание того, как опреде- ляются векторы прерываний и как создается служебная программа. • Для работы с большими программами полезно получать дополнительные сведения о различных типах данных и классах памяти. • Разработка программ на С включает в себя намного больше, чем простое написание исходного кода. Можно (и фактически нужно) использовать большой набор других файлов и полезно понимать, какие они, как работают и как связаны между собой. • Компоновщик объединяет различные вспомогательные файлы. Для простых программ полезны знания о компоновщике на уровне понимания. Для написания больших кус- ков программного обеспечения становятся важными подробные знания о компонов- щике. В конце этих четырех глав о С мы достигли начального, но полезного понимания языка программирования С в применении к встроенным системам. Это позволит писать все бо- лее и более сложные программы на С, как это действительно сделано в Главе 19. Были представлены только основы С, в то время как существует много особенностей С, кото- рые не были раскрыты. Более глубокие и обширные знания о С могут быть приобретены из личного опыта в области программирования, изучения хороших примеров программ и чтения доступных книг о С, написанных различными специалистами.
ГЛАВА 18. МНОГОЗАДАЧНОСТЬ И ОПЕРАЦИОННАЯ СИСТЕМА РЕАЛЬНОГО ВРЕМЕНИ Почти каждая встроенная система должна реализовать более одного процесса. Так, например, программа для АУСМ Derbot имеет возможность в получении информации об окружающей среде через соударения и световые датчики, умеет замерять расстояние, ко- торое было пройдено, и на основании полученной информации вычислять и прикладывать управляющие воздействия на электромоторы. По мере роста сложности системы возрас- тает также трудность балансировки требований, предъявляемых различными процессами. Каждый из них будет конкурировать за время ЦП и может, следовательно, вызвать задер- жки в других областях деятельности системы. Программа должна располагать способом распределения своего времени “справедливым образом” между различными задачами, которые в ней выполняются. Важным параллельным аспектом потребности разделения времени ЦП является по- требность гарантировать, что определенные события произойдут вовремя. Это очень важ- но почти для каждой встроенной системы и эта проблема еще более усложняется в усло- виях, когда множественные процессы конкурируют за привлечение внимания процессора. В данной главе рассматриваются требования, предъявляемые к системам, которые дол- жны делать много вещей. В ней также исследуются связанные с этим вызовы и предлагает- ся стратегия их преодоления — использование операционной системы реального времени. Это ведет к полностью новому подходу к программированию, который можно сфор- мулировать так: более нет программной последовательности, которая определяет, что будет дальше — теперь все происходит под управлением операционной системы! Изучив эту главу, вы достигнете хорошего понимания: • вызовов, с которыми связан режим многозадачности; • значение термина “реальное время”; • того, как можно организовать простой режим многозадачности, используя последо- вательное программирование; • принципов, лежащих в основе операционной системы реального времени. Поскольку эта глава является общим введением в программирование для режима ре- ального времени, реальных программных примеров в ней нет. Однако она служит подгото- вительным этапом для усвоения Главы 19, в которой имеется целый ряд важных примеров. 18.1. Основные идеи — вызовы, связанные с многозадачностью и режимом реального времени Многие из нас в этом деловом современном мире ощущают, что их жизнь проходит в среде многозадачности. Так, например, если родителям нужно подготовить утром двух или трех детей к школе, вдруг может оказаться, что один ребенок потерял носок, второй почувствовал себя больным, а третий опрокинул молоко. А тут еще нужно покормить собаку, выкипает кастрюля, молочник стоит у двери и звонит телефон... Нужно выполнить
466 Глава 18. Многозадачность и операционная система реального времени много заданий, однако одновременно мы можем сделать только одно. Микроконтроллер встроенной системы находится в подобном положении. Он может быть окружен многими процессами, каждый из которых требует его внимания. Ему может потребоваться, напри- мер, решить, что нужно делать в первую очередь, а что — немного позже. Давайте начнем эту главу с исследования двух вопросов: сути многозадачного режима и сути режима реального времени. 18.1.1. Многозадачный режим — задачи, приоритеты и сроки выполнения На рис. 18.1 показана упрощенная блок-схема программы, которую мы рассматривали в Главе 16, — программы поиска источника света для АУСМ Derbot. На то время эта про- грамма использовалась прежде всего для иллюстрации некоторых концепций языка про- граммирования С и мы не уделяли время анализу ее структуры. Эта программа предназначена для реализации целого ряда различных видов актив- ности, каждый из которых отражен на упомянутом рисунке. Давайте сразу же возьмем за правило называть эти виды активности “задачами”. Задача — это часть программы пли ее секция, которая имеет четко выраженное назначение и выход. Многозадачность — это термин, который описывает ситуацию, когда нужно выполнять много задач, в идеале — одновременно. В этом примере идентифицировано четыре задачи. Программа структурирована таким образом, что каждая задача включена в главный цикл и выполняются они по очереди. Одна задача — задача отображения (когда данные посылаются на ЖК-индикатор ручного ПУ) выполняется только один раз на каждые 10 итераций цикла. Цикл завершается временной задержкой, которая определяет частоту повторения цикла и, следовательно, влияет на временные характеристики программы. Рис. 18.1. Упрощенная блок-схема программы поиска источника света АУСМ Derbot Это очень простой пример многозадачности. Программа имеет ряд задач. Она выпол- няет их строго поочередно, немного “отдыхая” перед очередным запуском цикла. На прак- тике, конечно же, не все задачи имеют одинаковую важность. В качестве примера опять вернемся к озабоченным родителям: если звонит телефон, то, скорее всего, собаке при- дется немного подождать с завтраком. Таким образом, мы признаем, что различные зада- чи имеют различные приоритеты. Высокоприоритетная задача должна иметь право быть выполненной перед задачей с более низким приоритетом. Каждая задача имеет свой срок
18.2. Обеспечение мультизадачное™ при использовании последовательного программирования 467 выполнения (или же необходимо этот срок для нее определить). Нужно ответить на те- лефонный звонок в течение 30 секунд — в противном случае звонящий положит трубку; дети должны быть готовы выйти из дому в 8 часов 30 минут, иначе они пропустят авто- бус и т.д. Концепция приоритета связана со сроком выполнения задачи. В общем случае задача с более жесткими временными требованиями требует более высокого приоритета — однако, об этом чуть позже. Задачи, выполняемые данной программой (взятой в качестве примера), перечислены в табл. 18.1 совместно с некоторыми предварительными параметрами классификации. Ис- пользуется три уровня приоритета с тремя оценочными значениями сроков выполнения. При установке этих приоритетов срабатывание микропереключателя рассматривалось как аварийное состояние — АУСМ столкнулся с чем-то и имеется вероятность, что электромо- тор остановился. Следовательно, это задача высокого приоритета. По контрасту с этим че- ловек-пользователь вряд ли заметит, что выполнение функции отображения на ЖК-инди- катор задержалось на секунду или две. Следовательно, эта задача может иметь более низ- кий приоритет. 18.1.2. Итак, что же такое “режим реального времени”? Какое отношение имеет программа поиска источника света АУСМ Derbot (или оза- боченные родители, о которых мы говорили) к концепции реального времени? Об этой концепции часто говорят, однако для многих она окутана неким мистическим туманом. Простое и совершенно корректное определение режима реального времени звучит так: система, работающая в режиме реального времени, должна быть способна предоставить правильные результаты в требуемые сроки. Обратите внимание на то, что это определение не подразумевает, что работа в режиме реального времени обязательно связана с высокой скоростью, хотя часто это может помочь. Приведенное определение просто означает, что то, что нам нужно, должно быть готово именно тогда, когда это нужно. Следовательно, если родители собрали всех детей в шко- лу вовремя, покормили собаку до того, как она начала выть, открыли двери почтальону до того, как он ушел и, при этом, ответили на телефонный звонок до того, как звонящий положил трубку, то требования режима реального времени для данной среды были вы- полнены. Аналогичным образом, если АУСМ Derbot обеспечит выполнение всех требо- ваний по срокам, приведенным в табл. 18.1, то он также будет работать в режиме реаль- ного времени. Попытка достижения соответствия приведенному простому определению и всему то- му, что оно предполагает, порождает множество вызовов для программистов-разработчи- ков. Вся оставшаяся часть этой главы представляет собой введение в эти трудности, а также в то, как их преодолеть. Табл. 18.1. Задачи, которые могут быть выделены в программе поиска источников света для АУСМ Derbot Задача Приоритет Срок выполнения (мс) Реакция на срабатывание микропереключателя 1 20 Считывание фоторезистора 2 50 Расчет и установка скорости вращения электромотора 2 50 Отображение данных 3 500 18.2. Обеспечение мультизадачное™ при использовании последовательного программирования Тот вид программирования, который мы использовали до сих пор — вне зависимости, был ли это Ассемблер или С, иногда называют последовательным программированием.
468 Глава 18. Многозадачность и операционная система реального времени Это просто означает, что программа выполняется обычным способом — каждая команда или оператор выполняются после предыдущей, за исключением случаев выполнения ко- манды перехода либо вызова подпрограммы или функции. Позже в этой главе мы отойдем от этого вида программирования. Сейчас же исследуем то, как мы можем оптимизировать последовательное программирование для многозадачных применений, проанализировав некоторые недостатки структуры программы, показанной на рис. 18.1. 18.2.1. Оценка основного цикла Кажется, что данная программа работает достаточно хорошо, однако такое впечат- ление складывается, в основном, из-за того, что данная программа предъявляет не очень жесткие требования. Давайте рассмотрим некоторые из ее недостатков — все они связа- ны между собой: • Время выполнения главного цикла не является постоянным. Время, затрачиваемое на однократное прохождение основного цикла, представляет собой сумму времен, затра- чиваемых на выполнение каждой задачи, плюс время задержки. Очевидно, что общее время однократного выполнения цикла может изменяться. Если, например, сработал микропереключатель, то направление вращения колес АУСМ Derbot реверсируется и механизм разворачивается. Это приводит к особенно длительному времени одно- кратного прохождения цикла, что может неблагоприятно повлиять на какой-либо иной вид активности, выполняемый в рамках основного цикла. • Задачи влияют друг на друга. Как только задача получает шанс быть выполненной, она занимает ЦП и будет удерживать его до тех пор, пока не будет выполнена. Мы, конечно, согласны, что каждая из этих задач пишется так, чтобы, она не занимала ЦП слишком долго. Предположим, однако, что начала выполняться задача отображения данных и в этот момент АУСМ сталкивается со стенкой. В этом случае процессор бу- дет продолжать передавать данные на индикатор, затем он выполнит подпрограмму временной задержки и только затем обнаружит, что произошла аварийная ситуация. • Высокоприоритетные задачи не получают того внимания, которого они требуют. Мы уже признали факт того, что некоторые задачи являются более важными, чем дру- гие. Следовательно, они должны иметь более высокий приоритет, чем другие. Эту концепцию мы уже рассматривали при изучении прерываний. В данной же структуре с непрерывным основным циклом все задачи имеют одинаковый приоритет. Значит, нам нужно найти такой способ структурирования программы, который обес- печивал бы распознавание природы и потребности задач, содержащихся в программах, а также удовлетворял требованиям, предъявляемым ими, к режиму реального времени. 18.2.2. Время-ориентированные и событийно-ориентированные задачи Нетрудно прийти к выводу, что некоторые задачи являются время-ориентированными, а некоторые — событийно-ориентированными. Время-ориентированные задачи запус- каются по истечении некоторого периода времени, обычно их запуск носит периодичный характер. Примером этого может быть задача считывания состояния фоторезисторов, реа- лизованная в данной программе. Событийно-ориентированные задачи запускаются только тогда, когда возникают определенные события. Срабатывание микропереключателя явля- ется хорошим примером такого события.
18.2. Обеспечение мультизадачное™ при использовании последовательного программирования 469 18.2.3. Использование прерываний с приоритетами — структура “передний план/фон” Чтобы в программе поиска источников света решить проблему отсутствия приорите- тов между задачами, можно связать высокоприоритетные задачи с прерываниями. Благо- даря этому они смогут привлекать внимание ЦП сразу же, как только это понадобится, особенно если будет использоваться только одно прерывание. При этом структура прог- раммы приобретет вид, показанный на рис. 18.2. Можно утверждать, что задачи, выполня- емые в цикле, будут время-ориентированными, поскольку они используют частоту повто- рения итераций цикла в качестве временной базы. В то же время, задачи, выполняемые по прерываниям, будут событийно-ориентированными задачами. Рис. 18.2. Использование прерываний для назначения приоритетов в программе поиска источника света для АУСМ Derbot В этой простой программной структуре мы достигли надежной частоты повторения задач и в то же время назначили приоритеты задачам, которые в этом нуждаются. Эту структуру иногда называют программной структурой переднего плана/фона. Задачи с более высоким приоритетом и управляемые по прерываниям выполняются на переднем плане (когда они должны выполняться), в то время как задачи низкого приоритета могут выполняться в цикле — почти непрерывно, так сказать, в фоновом режиме. 18.2.4. Введение тактирующих сигналов времени с целью синхронизации программной активности Чтобы минимизировать влияние переменной длительности выполнения задач на общее время выполнения цикла, можно запускать весь цикл по прерыванию, привязанному ко вре- мени — например, по прерыванию от переполнения таймера. В этом случае программа имела бы структуру, показанную на рис. 18.3. Основной цикл теперь запускается по пере- полнению таймера, поэтому этот запуск происходит с надежно фиксированной частотой. Время-ориентированные задачи могут базировать свою собственную активность исходя из этой частоты повторения. Событийно-ориентированные задачи, через прерывания, могут выполняться тогда, когда это необходимо. Синхронизация задач, конечно же, должна рас- считываться и контролироваться с тем, чтобы цикл имел адекватное время для своего вы- полнения, укладываясь в допустимое время, а событийно-ориентированные задачи не на- рушали бы в слишком большой степени повторяющийся характер синхронизации цикла. Идея регулярного прерывания от таймера, используемого таким способом для синхро- низации программной активности, впервые была представлена в Главе 9 — она иллюстри- руется рис. 9.3. Как там было отмечено, такое прерывание обычно называют “тактирующим
470 Глава 18. Многозадачность и операционная система реального времени сигналом времени”. Хотя эта идея проста, она является фундаментом многих программных структур, которые мы будем рассматривать. Тактирующий сигнал времени не следует пу- тать с самим сигналом от тактового генератора, даже притом, что тактирующий сигнал вре- мени обычно является производной от тактовой частоты. Синхронизованный цикл Рис. 18.3. Использование привязанного ко времени прерывания в программе поиска источника света для АУСМ Derbot Рис. 18.4. Структура универсальной “операционной системы”, использующая последовательное про- граммирование 18.2.5. Универсальная операционная система Структура, отображенная на рис. 18.3, может быть легко преобразована в универсаль- ную “операционную систему”, которая показана в правой части рис. 18.4. На нем показан главный цикл, содержащий серию низко- и средне-приоритетных задач. Главный цикл управляется тактирующими сигналами времени. Общая структура каждой задачи показа- на слева. По мере необходимости каждой задаче поставлен в соответствие флаг разреше- ния (бит в ячейке памяти) и каждая задача имеет счетчик задачи. Задачи, которые должны выполняться по каждому тактирующему сигналу времени, будут это делать. Многие задачи
18.3. Операционная система реального времени (ОСРВ) 471 должны выполняться с интервалом, устанавливаемым значением их счетчика задачи. За- дачи могут разрешаться/запрещаться установкой/сбросом их флага разрешения, выполня- емой либо другими задачами, либо подпрограммами обработки прерываний. Если несколько задач запускаются по прерываниям, то время ожидания обслуживания прерывания, конечно же, страдает, поскольку одна подпрограмма обработки прерываний должна ожидать завершения работы другой. В случаях систем, очень критичных ко вре- мени, такие ситуации должны тщательно анализироваться. 18.2.6. Пределы возможностей последовательного программиро- вания в случае организации многозадачного режима В общем случае только что описанный подход к программированию для многозадач- ного режима может быть приемлемым при условии, что: • задач не очень много; • структура может учитывать приоритеты задач; • задачи хорошо отработаны во всех режимах и не предъявляют чрезмерных требований к ресурсам (например, к времени ЦП), а задачи, запускаемые по прерываниям, не вы- полняются слишком часто; Если перечисленные условия не выполняются, то необходимо рассмотреть возможность использования радикально отличной программной стратегии. В этом случае естественным кандидатом на использование будет настоящая операционная система реального времени. 18.3. Операционная система реального времени (ОСРВ) При использовании настоящей операционной системы мы далеко отходим от предпо- ложений, с которыми связано обычное последовательное программирование, как это под- черкивалось ранее, в подразделе 18.2. Вместо этого мы передаем управление ЦП и всеми системными ресурсами операционной системе. Именно операционная система будет теперь определять, какая секция программы должна работать в текущий момент времени и как долго, а также то, как она будет осуществлять доступ к системным ресурсам. Сама прик- ладная программа подчинена операционной системе и пишется способом, который призна- ет требования операционной системы. Поскольку нас интересует достижение соответствия требованиям режима реального времени, мы будем использовать особый тип операцион- ной системы, обеспечивающий такое соответствие, а именно — операционную систему ре- ального времени (ОСРВ). Программы, которые пишутся для ОСРВ, структурируются с разбиением их на задачи, которым обычно (но не всегда) присваиваются приоритеты, контролируемые операцион- ной системой. ОСРВ выполняет следующие три основные функции: • решает, какая задача должна работать в текущий момент времени и как долго; • обеспечивает информационный обмен и синхронизацию между задачами; • управляет использованием ресурсов, разделяемых между задачами, например памяти и периферийных устройств. Сама ОСРВ представляет собой универсальную программную утилиту. Она адапти- руется для конкретного применения посредством написания под нее задач, а также посред- ством выполнения определенных настроек. Притом что вы, возможно, могли бы написать вашу собственную ОСРВ, необходимо осознавать, что создание операционных систем — это очень специфичный вид деятельности, который в общем случае выполняется специа- листами. Имеется целый ряд компаний, которые разрабатывают и поставляют такие опе- рационные системы, обычно ориентированные на конкретный сегмент рынка и привязан- ные к конкретным типам процессоров. Если вы купите одну из них, то приобретете то, что
472 Глава 18. Многозадачность и операционная система реального времени обычно называют “коммерческой стандартной операционной системой реального време- ни” (КСОСРВ). Применение таких систем мы рассмотрим в Главе 19. 18.4. Диспетчеризация и диспетчер Центральная часть ОСРВ — это диспетчер. Именно он определяет, какой задаче разре- шается работать в конкретный момент времени. Помимо этого, диспетчер должен знать, какие задачи уже готовы работать и их приоритеты (если они имеются). Существует ряд существенно различных стратегий диспетчеризации, которые мы сейчас и рассмотрим. 18.4.1. Циклическая диспетчеризация Циклическая диспетчеризация проста. В любой момент времени каждой задаче разре- шается работать до завершения, прежде чем начнет выполняться следующая задача. Зада- ча не может быть прервана в момент ее выполнения. Это почти то же самое, что и работа по принципу основного цикла, который мы уже рассматривали ранее в этой главе. Схематически отображенный пример циклической диспетчеризации показан на рис. 18.5. Здесь горизонтальная полоса представляет активность ЦП, а пронумерованные блоки — задачи в том порядке, в каком они выполняются. Как видно из рисунка, задачи выпол- няются по очереди, при этом первоначально задача 3 — самая длинная, а 2 — самая корот- кая. Однако на третьей итерации задача 1 выполняется дольше и полное время цикла увели- чивается. Циклической диспетчеризации присущи недостатки последовательного програм- мирования в цикле, о которых мы уже говорили выше. По крайней мере, она хоть проста. Рис. 18.5. Циклическая диспетчеризация — задачи 1,2 и 3 выполняются по очереди 18.4.2. Карусельная диспетчеризация и переключение контекста В случае карусельной диспетчеризации операционная система управляется регуляр- ными прерываниями (“тактирующий сигнал времени”). Задачи выбираются на выполнение в фиксированной последовательности. По каждому тактирующему сигналу времени теку- щая задача прерывается и разрешается выполнение следующей задачи. Все задачи тракту- ются как задачи равной важности и ждут своей очереди на получение части машинного времени ЦП. Задачам не разрешается работать до завершения, — вместо этого они пред- варительно выгружаются, т.е. их выполнение прерывается “на ходу”. Это — пример пред- варительно-выгружающего диспетчера. То, что связано с этим переключением задач с предварительной выгрузкой, а также накладные расходы времени ЦП, не является несущественным и должно быть принято во внимание. Когда задаче разрешается работать снова, она должна быть способна возобно- вить свою работу гладко — без побочных эффектов от предварительной выгрузки. Следо- вательно, при переключении задач должно выполняться полное сохранение контекста (все флаги, регистры и иные ячейки памяти). Критические ко времени фрагменты программы не должны, однако, прерываться и это требование должно быть внесено в саму программу. Схематический пример карусельной диспетчеризации показан на рис. 18.6. Пронуме- рованные блоки опять-таки отображают задачи в том порядке, в каком они выполняются, однако имеется большая разница, по сравнению с рис. 18.5. Теперь каждой задаче выделя- ется квант времени ЦП, который имеет фиксированную длительность. Тактирующий сиг- нал времени, который инициализирует переключение задач, показан на схеме как стрелка. Когда приходит время тактирующего сигнала, ставится на выполнение следующая задача — вне зависимости от того, завершена текущая задача или нет. В одной из показанных на рисунке стадий задача 2 завершается и не нуждается во времени ЦП в течение нескольких
18.4. Диспетчеризация и диспетчер 473 единиц времени. Затем через некоторое время она снова приходит в состояние готовности к выполнению и занимает свое место в очереди в рамках цикла. Задача 2 завершилась Задача 2 переходит в состояние готовности к выполнению Рис. 18.6. Карусельная диспетчеризация Поскольку имеется переключение задач и контекста, то неизбежны непроизводитель- ные затраты времени ЦП, которые представлены на рассматриваемом рисунке как черные полоски. Это время, затрачиваемое на обслуживание требований ОСРВ — оно теряется для прикладных программ. 18.4.3. Состояния задач Стоит на данном этапе сделать паузу, чтобы рассмотреть то, что происходит с задача- ми, которые теперь управляются диспетчером. Очевидно, что в каждый отдельно взятый момент времени может выполняться только одна задача. При этом другие задачи могут иметь потребность в том, чтобы работать, однако они не могут этого сделать в любой мо- мент времени. Иные же должны только отреагировать на некоторый набор условий и, сле- довательно, быть активными в некоторые моменты в течение выполнения программы. Таким образом, следовательно, важно признать, что задачи могут находиться в различ- ных состояниях и переходить из одного состояния в другое. Диаграмма возможных состо- яний задач показана на рис. 18.7. Эти состояния описаны ниже. Однако обратите внима- ние, что используемая терминология и способы определения состояний задач до некоторой степени изменяются от одной ОСРВ к другой. Следовательно, в некоторых случаях для описания одного состояния могут использоваться различные термины. Рис. 18.7. Состояния задач Готовность к выполнению (или готовность к продолжению). Задача готова к работе и будет выполняться, как только ей будет выделено время ЦП. Задача выходит из этого
474 Глава 18. Многозадачность и операционная система реального времени состояния и входит в активное состояние, когда она ставится на выполнение диспет- чером. • Выполнение. Задаче было выделено время ЦП и она выполняется. Целый ряд причин может вызвать то, что задача выйдет из этого состояния. Возможно, что она просто завершилась и больше не нуждается во времени ЦП. Также возможно, что диспетчер выполнил предварительную выгрузку задачи, чтобы могла выполняться другая зада- ча. И, наконец, задача может войти в состояние блокировки или ожидания по причи- нам, описанным ниже. • Блокировка/ожидание/задержка. Это состояние отражает состояние задачи, которая готова выполняться, но по той или иной причине не может этого сделать. Имеется ряд различных причин, почему это может иметь место, и, фактически, это одно состояние на диаграмме состояний может быть заменено несколькими состояниями, если потре- буется большая детализация. Задача может ожидать каких-либо данных или получения доступа к ресурсу, который ей необходим, но в текущий момент времени использует- ся иной задачей, или же она может просто ожидать истечения определенного периода времени. Задача выходит из этого состояния, когда исчезают условия, которые удер- живают ее в нем. • Остановлена/приостановлена/неактивное состояние. В данный момент времени за- дача не нуждается в предоставлении ей времени ЦП. Задача выходит из этого состоя- ния и входит в состояние готовности, если по какой-либо причине она вновь будет ак- тивирована. • Неиниг^иализирована/ликвидирована. В этом состоянии задача, с точки зрения ОСРВ, больше не существует. Отсюда можно также заключить, что нет необходимости в не- прерывном существовании задачи на протяжении всего времени выполнения програм- мы. В общем случае задачи должны создаваться или инициализироваться программой перед тем, как они могут быть запущены на выполнение. Позже, в случае необходимо- сти, они могут быть ликвидированы и, возможно, на смену им могут создаваться дру- гие задачи. Удаление ненужных задач из списка задач упрощает работу диспетчера и снижает требования к памяти. 18.4.4. Диспетчеризация с предварительной выгрузкой, использующая приоритеты Сейчас мы возвращаемся к нашему обзору стратегий диспетчеризации, вооружившись большим пониманием “стиля жизни” задач. Задачи, как мы уже видели, при использова- нии карусельной диспетчеризации подчинены высшей силе — операционной системе. Од- нако в рассмотренной нами схеме все задачи имели одинаковый приоритет, т.е. самая не- значительная задача имела такой же доступ к ЦП, как и задача максимального приоритета. Мы можем изменить этот порядок вещей, присваивая задачам приоритеты. В схеме диспетчеризации с предварительной выгрузкой, использующей приоритеты, задачи имею приоритеты. Высокоприоритетным задачам теперь разрешается завершать свое выполнение до того, как станет возможным предоставление времени ЦП задаче более низкого приоритета. Диспетчер по прежнему управляется тактирующими сигналами вре- мени. По каждому сигналу он проверяет, какая из готовых к выполнению задач имеет наи- высший приоритет. Этой задаче предоставляется доступ к ЦП. Если выполняемая в этот момент задача все еще нуждается во времени ЦП и имеет более высокий приоритет, то она продолжает использовать ЦП. Низкоприоритетная выполняемая задача замещается зада- чей более высокого приоритета, если последняя находится в состоянии готовности к вы- полнению. Высокоприоритетная задача становится “королем спортплощадки”. Почти в любом случае она побеждает. Способ, которым работает эта стратегия диспетчеризации, иллюстрируется примером, показанным на рис. 18.8. На этом рисунке отражен целый ряд концепций ОСРВ, поэтому стоит хорошо в нем разобраться. Приведенная диаграмма показывает три задачи с разными
18.4. Диспетчеризация и диспетчер 475 приоритетами и различным временем выполнения. В начале все задачи готовы к выпол- нению. Вследствие того, что задача 1 имеет самый высокий приоритет, диспетчер выбирает для выполнения ее. По следующему тактирующему сигналу времени диспетчер распознает, что задаче 1 все еще требуется выполнение, поэтому он разрешает ей продолжать работу. То же самое происходит по следующему тактирующему сигналу времени, при этом вы- полнение задачи завершается на протяжении следующего кванта времени. Таким образом, задача 1 более не нуждается во времени ЦП и считается приостановленной. В силу этого по следующему тактирующему сигналу времени диспетчер выбирает готовую к выполне- нию задачу с максимальным приоритетом, каковой теперь является задача 3. Ей также бу- дет разрешено выполняться до завершения. Задача номер 1 переходит в состояние готовности к выполнению Все задачи в неактивном состоянии Задачи 1,2 и 3 готовы к выполнению Задача номер 3 Задача номер 1 завершилась завершилась Задача номер 2 Задача номер 1 предварительно завершилась выгружена Задача номер 2 завершилась Задача номер 1 переходит в состояние готовности к . выполнению tttttttttttttttt Т Синхросигнал времени и возможное переключение контекста Задача Приоритет Длительность (в квантах времени) 1 1 (высший) 2,7 2 3 2,8 3 2 1,5 Рис. 18.8. Диспетчеризация с предварительной выгрузкой, использующая приоритеты Наконец-то задача 2 получает свой шанс на выполнение! Однако, к ее несчастью, во время первого же предоставленного ей кванта времени задача 1 вновь переходит в состо- яние готовности к выполнению. По следующему тактирующему сигналу времени для вы- полнения вновь выбирается задача 1. Опять-таки, диспетчер разрешает ей выполняться до завершения. Когда это происходит, и только в силу того, что нет иных задач, готовых к выполнению, задача 2 может опять выйти на арену и, наконец, завершиться. После этого в течение одного кванта времени не будет активных задач и, следовательно, ЦП будет про- стаивать. Затем задача 1 вновь перейдет в состояние готовности и будет поставлена на вы- полнение вплоть до своего завершения. 18.4.5. Коллективная диспетчеризация Стратегия диспетчеризации, которую мы только что рассматривали — диспетчериза- ция с предварительной выгрузкой, использующая приоритеты, является примером класси- ческой работы ОСРВ. Однако эта схема не лишена недостатков. Диспетчер должен хранить всю информацию о контексте для всех задач, которые подверглись предварительной вы- грузке. В общем случае это делается посредством выделения по одному стеку для каждой задачи и приводит к значительному расходованию памяти. Переключение контекста может быть также связано со значительным расходованием времени ЦП. Более того, задачи долж- ны быть написаны таким образом, чтобы допускалось их переключение в любой момент времени на протяжении их выполнения. Альтернативой диспетчеризации с предварительной выгрузкой является коллективная диспетчеризация. При ее использовании каждая задача должна самостоятельно освобож- дать ЦП в какой-то момент времени на протяжении своего выполнения. Это может выгля- деть так, словно мы блокируем работу операционной системы, однако, если каждая задача будет написана корректно, то этого не произойдет. Преимущество этой схемы состоит в
476 Глава 18. Многозадачность и операционная система реального времени том, что задача освобождает ЦП в тот момент, который она сама выбирает, поэтому она может самостоятельно управлять сохранением своего контекста и дополнительная нагруз- ка на операционную систему не возникает. К несчастью, коллективная диспетчеризация намного более чувствительна к жестким срокам выполнения, чем диспетчеризация с предварительной выгрузкой задач. Однако она требует меньше памяти и обеспечивает более быстрое переключение задач. Это очень важ- но в малых системах — таких как системы, основанные на использовании микроконтрол- леров PIC. 18.4.6. Роль прерываний в диспетчеризации До данного момента мы не упоминали о прерываниях в их связи с ОСРВ. Должны ли подпрограммы обслуживания прерываний сами по себе формировать задачи, как это дела- лось в структурах, аналогичных показанной на рис. 18.4? Ответом будет “нет”. Первей- шим для использования прерываний почти всегда является обеспечение тактирующего им- пульса для сигнала времени через прерывание от таймера по переполнению. Помимо этого, подпрограммы обслуживания прерываний обычно используются для передачи срочной ин- формации задачам или диспетчеру. Прерывание может, например, использоваться для того, чтобы сообщить диспетчеру о том, что произошло некоторое событие, выводя тем самым задачу из состояния блокировки (см. рис. 18.7). Обычно программы обслуживания пре- рываний не используются как задачи. 18.5. Разработка задач Введя понятие задач и того, как они диспетчеризуются, теперь давайте рассмотрим, как они пишутся. 18.5.1. Определение задач Первым интересным требованием к программисту является определение того, какие виды деятельности системы следует выделить в качестве задач. Число созданных задач не должно быть слишком большим. В общем случае большее количество задач подразумевает большую сложность программирования, а каждое переключение задач связано с непроиз- водительными затратами памяти и времени. Полезной отправной точкой может быть рассмотрение того, какие имеются крайние сроки выполнения, а затем каждому сроку выполнения можно поставить в соответствие за- дачу. Набор видов активности, которые близко связаны во времени, вероятно, обслуживает один и тот же крайний срок и должен быть, следовательно, выделен в одну задачу. Набор действий, которые близко связаны по функциям и связаны с большими объемами информа- ционного обмена, также должен быть выделен в одну задачу. Так, например, в программе поиска источников света для АУСМ Derbot по рис. 18.1, ос- новной цикл на одной стадии считывает три датчика освещенности, затем выполняет не- которые вычисления, после чего устанавливает скорость вращения электромотора. Он так- же периодически посылает данные на индикатор. В любое время могут быть активизи- рованы микропереключатели. Сколько же задач ОСРВ следует выделить в этом случае? Основные виды активности близко связаны друг с другом по времени и по функциям, они также разделяют данные. Запись на индикатор может быть выделена как отдельная задача — она выполняется менее часто и имеет сравнительно низкий приоритет. Поскольку чте- ние датчиков освещенности обеспечивает данные непосредственно для вычислений, свя- занных с управлением электромоторами, то все соответствующие виды активности могут быть сгруппированы в одну задачу. Альтернативно, считывание датчиков освещенности может быть выделено в отдельную задачу. И, наконец, реакция на срабатывание микропе- реключателя также могла бы быть выделена в отдельную задачу.
18.6. Защита данных и ресурсов — семафор 477 18.5.2. Программирование задач и установка приоритетов Задачи должны писаться так, словно они будут выполняться непрерывно — как само- достаточные полуавтономные программы даже в случаях, если их выполнение будет пре- рываться диспетчером. Они не имеют доступа к секциям программного кода других про- грамм, однако имеют доступ к общим блокам кодов, например в библиотеках С. Они могут зависеть от обслуживания со стороны других задач, а также могут иметь необходимость в синхронизации друг с другом. В любом случае, ОСРВ имеет специальные функции, обес- печивающие, чтобы это случилось. В самых простых случаях ОСРВ позволяет программисту устанавливать приоритет за- дачи. В случае использования статических приоритетов, они считаются фиксированными. В случае динамических приоритетов, приоритеты могут изменяться во время выполнения программ. Одним из способов определения приоритетов является рассмотрение того, на- сколько важна задача для работы и состояния системы, пользователя и среды. Затем при- оритеты могут быть установлены следующим образом: • самый высокий приоритет: задачи, существенш е для выживания системы; • средний приоритет: задачи, существенные для правильной работы системы; • низкий приоритет: задачи, необходимые для адекватной работы системы — может ока- заться приемлемым снятие этих задач с выполнения, а также задержка их выполнения. Также приоритеты можно рассматривать с точки зрения сроков выполнения задач. В этом случае высокий приоритет устанавливается для задач, которые имеют очень жесткие сроки выполнения. Если, однако, задача имеет жесткие требования по сроку выполнения, однако не является столь уж важной в общей работе системы, то в общем случае ей мож- но присвоить и низкий приоритет. 18.6. Защита данных и ресурсов — семафор Некоторые задачи могут одновременно претендовать на доступ к одному и тому же раз- деляемому ресурсу. Это может быть либо аппаратный объект (включая память или пери- ферийное устройство), либо общий программный модуль. Эта ситуация требует опреде- ленного внимания. Метод выйти из упомянутой ситуации заключается в использовании семафора. Семафор ставится в соответствие каждому разделяемому ресурсу — он исполь- зуется для индикации того, занят в данный момент ресурс или свободен. В случае двухпозиционного семафора, первая задача, которая захочет использовать ресурс, найдет семафор ресурса в состоянии GO (СВОБОДЕН) и изменит его на состояние WAIT (ОЖИДАНИЕ) перед тем, как начнет использовать данный ресурс. Любая .шая зада- ча, которой потребуется данный ресурс в течение того промежутка времени, когда первая задача использует его, должна будет перейти в состояние блокировки (рис. 18.7). Когда первая задача завершит использование ресурса, она возвратит семафор в состояние GO (СВОБОДЕН). Это приводит к концепции взаимного исключения; когда одна задача осу- ществляет доступ к ресурсу, все другие исключаются из списка доступа. Счетный семафор применяется в случае наличия набора идентичных ресурсов, напри- мер — группы принтеров. Теперь семафор первоначально устанавливается на количество единиц ресурса. Если какая-либо задача использует одну единицу ресурса, она декремен- тирует светофор и инкрементирует его вновь после завершения использования единицы ресурса. Таким образом, счетный семафор содержит значение, равное количеству единиц ресурса, которые доступны для использования. Эффект установки светофора в состояние WAIT (ОЖИДАНИЕ) заключается в том, что другая задача переходит в состояние блокировки. Это означает, что светофор может ис- пользоваться как средство синхронизации выполнения задач, а также как средство пере- дачи сигналов между различными задачами. Одна задача может блокировать другую ус- тановкой светофора и освобождать ее сбросом светофора в выбранный момент времени.
478 Глава 18. Многозадачность и операционная система реального времени Помните, как мы говорили в подразделе 18.4.4 о “короле спортплощадки” — высоко- приоритетной задаче? Используя семафор, низкоприоритетная задача может все изменить! Если низкоприоритетная задача установит семафор для ресурса, который необходим вы- сокоприоритетной задаче, то она заблокирует эту задачу. Это приведет к возникновению опасной ситуации, известной как “инверсия приоритетов”. Рассмотрение этой ситуации вы- ходит за рамки данной книги, однако она весьма иллюстративна для многих тонких дета- лей в мире программирования для режима реального времени, которые стоят изучения. 18.7. Куда мы будем двигаться дальше? Теория ОСРВ далеко выходит за рамки того, о чем мы говорили в данной главе, кроме того она может носить специализированный характер для различных видов приложений. Как и во многих других случаях, теория приобретает смысл, когда применяется к реальной ситуации. Именно это мы и будем делать в следующей главе. Резюме • Требование многозадачности, естественное для почти всех встроенных систем, связа- но с некоторыми важными концепциями — задач, сроков выполнения и приоритетов. • Система, работающая в режиме реального времени — это система, которая способна обеспечить соблюдение требуемых сроков выполнения для определенных видов актив- ности. • Простые многозадачные системы реального времени могут быть сформированы при использовании последовательного программирования. • Более сложные многозадачные системы реального времени требуют использования операционной системы реального времени. • Использование операционной системы реального времени требует, чтобы программы были структурированы определенным способом, при этом программист должен отчет- ливо понимать принципы, лежащие в основе работы операционной системы.
ГЛАВА 19. ОПЕРАЦИОННАЯ СИСТЕМА РЕАЛЬНОГО ВРЕМЕНИ SALVO™ Все концепции ОСРВ (операционной системы реального времени), изложенные в Главе 18, будут представлять собой только великолепные теоретические выкладки, если мы не сможем их применить к работающей системе. Предпочтительно, чтобы это была система, которая может работать с Р1С®-базированной встроенной системой. Мы имеем шанс сделать это в случае Salvo™ — “ОСРВ, работающая в малом объеме”. Salvo — это коммерчески доступная ОСРВ, специально предназначенная для малых встроенных сис- тем. Также имеется ее версия, которая работает с компилятором С18 от фирмы Microchip. И что самое замечательное — имеется бесплатная версия Salvo LITE! Это дает нам шанс войти в очень интересный, однако сопряженный с целым рядом вызовов, мир ОСРВ и без каких-либо трудностей написать простые, иллюстративные и надежно работающие программы. Основной целью этой главы является дать вводную информацию об операционной сис- теме Salvo на том уровне, который даст возможность писать эффективные, но простые про- граммы. Целью этого является скорее показать то, как реальная ОСРВ применяется в практических ситуациях, а не то, как стать пользователем-экспертом Salvo. Следователь- но, за более глубокими деталями использования Salvo читателям следует обращаться к руководству пользователя этой системы. Фактически, данная глава построена на базе трех примеров программ, которые разви- ваются дальше благодаря применению к ним ключевых концепций ОСРВ. Достигнув конца главы, вы должны получить хорошее понимание: • основ Salvo — ОСРВ, взятой в качестве примера; • работы реальной ОСРВ с практической точки зрения; • преимуществ и недостатков, связанных с применением ОСРВ. 19.1. Основная идея: Salvo — пример ОСРВ Salvo первоначально была написана на Ассемблере и предназначалась для системы сбора данных гоночного автомобиля. Как только стало ясно, что ее область применения может быть намного шире, она была переписана на С и адаптирована к принципам уни- версальной операционной системы. Целевой областью ее применения являются малые внедренные системы. Сейчас Salvo нужно запускать с компилятором С — с ассемблером она больше не работает. Доступны ее версии для большинства основных современных компиляторов, используемых при создании встроенных систем. Salvo поставляется фир- мой “Pumpkin Real Time Software Inc.” В нижеследующих подразделах приведена избранная информация по Salvo — ее должно быть достаточно для написания некоторых интересных вводных программ. Все детали по Salvo вы сможете найти в технической информации от поставщика, фирмы Pumpkin Inc.
480 Глава 19. Операционная система реального времени SalvoTM 19.1.1. Основные свойства Salvo Salvo может управлять выполнением целого ряда задач, снабженных приоритетами, и работать с коллективным диспетчером. Это одно из ключевых свойств, обуславливаю- щих низкие требования к памяти, — как мы уже обсуждали в подразделе 18.4.5 Главы 18, коллективная диспетчеризация менее требовательна к памяти. Количество задач (в полно- функциональной версии) ограничено только объемом ОЗУ, при этом доступно 16 уровней приоритета. Задачи могут также разделять уровни приоритетов. Salvo поддерживает целый спектр “событий”, включая двухпозиционные и счетные семафоры, сообщения и очереди сообщений. Поставляется Salvo с очень широким набором файлов — исходных файлов, файлов заголовков, файлов библиотек и других. Эти файлы эффективно работают как дополни- тельный сервис, добавляемый к возможностям компилятора хост-компьютера. При этом программист обычным способом работает с компилятором хост-компьютера, однако по мере необходимости включает файлы Salvo. Делая это, он, конечно, должен придержи- ваться требований ОСРВ Salvo. Таким образом, программа, разработанная программи- стом, в конце концов, становится комбинацией оригинального исходного программного кода, а также файлов заголовков и исходных файлов, вводимых Salvo и берущихся из фай- лов библиотек компилятора. Процесс компоновки основных файлов-компонент показан на рис. 19.1. Выходом упомянутого процесса является исполняемый файл, который может быть загружен в память программ. 19.1.2. Версии Salvo и ссылки на источники Имеется целый ряд версий ОСРВ Salvo. При этом на самой вершине этого ряда нахо- дится Salvo Pro — высококонфитурируемая полнофункциональная версия. Бесплатная версия Salvo, называемая Salvo Lite, содержит поднабор функций Salvo. На момент на- писания книги эту версию можно было выгрузить с вебсайта фирмы Pumpkin по адресу http: //www. pumpkininc. сот/ — ее копия имеется также на компакт-диске, прила- гаемом к этой книге. Необходимо выбирать ту версию Salvo, которая соответствует исполь- зуемому компилятору — в нашем случае компилятору С18 от фирмы Microchip. Salvo Lite допускает выполнение трех задач и обеспечивает учет пяти событий. Это может показаться
19.2. Конфигурирование и использование ОСРВ Salvo 481 весьма скромным пределом, однако на практике эти параметры обеспечивают возмож- ность разработки удивительно полезных и функциональных программ. 19.2. Конфигурирование и использование ОСРВ Salvo Одним из принципиальных свойств Salvo является то, что она в высокой степени конфигурируема. В силу этого важно сразу же представлять себе, как происходит это конфигурирование. В данном подразделе излагается вводная информация о некоторых важных свойствах файлов Salvo и конфигурировании, она также призвана обеспечить лучшее понимание процесса компоновки, отображенного на рис. 19.1. 19.2.1. Компоновка приложения Salvo — библиотечная компоновка Имеется два основных способа компоновки приложения Salvo: библиотечная компо- новка и компоновка на уровне исходных кодов Salvo. Последний вариант связан с манипу- лированием исходными кодами Salvo и предназначен только для очень опытных пользо- вателей. В любом случае этот вариант может использоваться только с Salvo Pro, поэтому здесь мы его не рассматриваем. Это оставляет нас с вариантом библиотечной компоновки — т.е. компоновки приложения с использованием имеющихся библиотечных функций. Можно использовать различные библиотеки, каждая из которых обеспечивает свой набор функций. Должна быть выбрана та библиотека, которая в наибольшей степени подходит для данного приложения. Как только это будет сделано, набор библиотечных функций будет зафиксирован. Теперь пользовательские программы будут обращаться к функциям Salvo, содержащимся в выбранной библиотеке. Помимо библиотечных файлов, должны быть включены некоторые другие исходные файлы и файлы заголовков, как показано на рисунке 19.1. Наиболее важные из них перечислены далее. • salvo. h. Это главный файл заголовков Salvo, он должен включаться в любой исход- ный файл, который использует функции Salvo. Он не должен модифицироваться поль- зователем. В свою очередь, этот файл включает в себя файл salvocf g. h. • mem. с. Это главный файл, поставляемый с Salvo. Он содержит глобальные объекты, которые определяют характеристики используемых функций, задач, семафоров и т.д. Он не должен модифицироваться пользователем, хотя на этот файл и оказывает воздей- ствие содержимое файла salvocfg. h. • salvocfg. h. Этот файл, который пишет пользователь, в основном определяет конфи- гурацию системы для приложения. Он задает некоторые ключевые элементы — напри- мер то, какая библиотека должна использоваться, сколько будет задач, сколько собы- тий будут рассматриваться. Дальнейшие подробности приводятся в подразделе 19.4.4. 19.2.2. Библиотеки Salvo Salvo имеет обширный набор стандартных библиотек, который обеспечивает основную часть функциональности ОСРВ. Для каждого компилятора и его версий имеются отдель- ные библиотеки. Они поддерживают различные модели памяти и различные комбинации функций. Один из навыков при конфигурировании приложения Salvo заключается в вы- боре той библиотеки, которая имеет те функции, которые необходимы и ничего больше. К Salvo Lite прилагается набор бесплатных библиотек. Они такие же, как и стандарт- ные, за исключением того, что их функциональные возможности ограничены. Кодировка, используемая для компилятора С18, показана на рис. 19.2. Последняя буква идентификато- ра библиотеки указывает ее “конфигурацию”, которая определяется в табл. 19.1. Библио- тека sfcl8sfa. lib, например, имеет все функции, за исключением функции тайм-аута.
482 Глава 19. Операционная сисгема реального времени SalvoTM Это делает ее сравнительно объемной библиотекой. Если в приложении необходима только многозадачность, то будет лучше использовать библиотеку в конфигурации ш. Это приве- дет к более эффективной кодировке и меньшему объему потребляемой памяти. s f с18 s f a.lib Salvo--------» Бесплатная ______ версия (I = Стандартная) I—— Конфигурация ____ Тип памяти для глобальных объектов Salvo (f = тип far, n = тип near) ------------Модель памяти (I = большая, s = малая) Компилятор С18 Рис. 19.2. Идентификатор библиотеки Salvo для компилятора С18 Табл. 19.1. Библиотечные функции, доступные для каждой библиотечной конфигурации Конфигурация библиотеки а d е ш t Многозадачность + + + + + Временные задержки + + - - + События + - + - + Режим бездействия + + + - + Приоритеты задач + + + - + Тайм-аут - - - - + Примечание: “+” = разрешена; = не разрешена. 19.2.3. Использование Salvo с компилятором С18 При использовании Salvo является важным гарантировать, что используются совмести- мые версии Salvo и компилятора С18 MPLAB® IDE. В данной книге используется MPLAB версии 7.22, С18 версии 3.00 и Salvo версии З.2.З.С. Для установки Salvo она должна быть предварительно загружена с вебсайта Salvo, а затем должна быть выполнена стандартная процедура установки. Установка Salvo приведет к созданию набора папок, показанного на рис. 19.3. : в-О salvo ! ’ В О demo ; ' a 111 doc ; . 1+1CJ ex ; ffl О free Cj inc H О lib Cl src ; : в- Cj tut Рис. 19.3. Папки Salvo Lite 19.3. Написание программ для Salvo Данный подраздел является введением в программирование для ОСРВ Salvo — его следует изучить до того, как переходить к исследованию первого программного примера, приведенного в следующем подразделе.
19.3. Написание программ для Salvo 483 19.3.1. Инициализация и диспетчеризация Много свойств ОСРВ Salvo обусловлены ее функциями, написанными на С, которые сведены в библиотеки Salvo. Часть искусства программирования для Salvo заключается в знании этих функций и понимании того, что они делают. Некоторые примеры этих функ- ций, а именно — тех, которые будут использоваться в нашем первом программном при- мере, приведены в табл. 19.2. В ней приведено наименование функции или сервиса, свод- ка данных по ее действию и параметры (если они есть), которые она принимает. На со- держание этой таблицы мы будем повторно ссылаться на протяжении нескольких по- следующих страниц — там же мы будем более подробно ее рассматривать. Не волнуй- тесь, если не все детали станут вам сразу же понятными. Табл. 19.2. Примеры основных функций Salvo Функция/сервис Действие и параметры OSInit () Инициализирует операционную систему, включая структуры данных, указатели и счетчики. Должна вызываться до вызова какой-либо иной функции Salvo. Параметров нет. OSSched() Диспетчер Salvo. По каждому вызову он выбирает среди готовых к выполнению задач следующую для запуска. Многозадачность может иметь место, когда вызовы диспетчера повторяются. Параметров нет. OS_Yield()* Безусловный возврат в диспетчер. (1 )Метка переключения контекста, которая часто определяется через использование _OSLabel () OSCreateTask(,,) Создает задачу и ставит ее на выполнение (т.е. делает ее готовой к выполнению). (1) указатель на адрес запуска задачи — обычно это имя задачи; (2) указатель на ТСВ (блок управления задачей); (3) приоритет — число от 0 (наивысший) до 15 (самый низкий). OSStartTask() Делает остановленную задачу готовой к выполнению. (1) указатель на ТСВ (блок управления задачей). _OSLabel() Определяет уникальную метку, требуемую для каждого переключения контекста. (1) идентификатор метки. OSTCBP() Определяет указатель на специфицированный блок управления — в данном случае на блок управления задачей. (1) целое число от 1 до OS TASKS, где OS TASKS — переменная, присутствующая в файле salvocfg.hn специфицирующая количество задач. * Может вызвать переключение контекста Некоторые из перечисленных в табл. 19.2. функций могут вызвать переключение кон- текста — посредством этого реализуется коллективная диспетчеризация. Все функции Salvo, которые могут вызываться пользователем, имеют префикс “OS” или “OS_”. Для активирования и инициализации ОСРВ должна быть вызвана функция OS In it () перед вызовом любой иной функции Salvo. Затем могут создаваться задачи посредством вызова OSCreateTask(), при этом следует уделить внимание тому, чтобы все аргумен- ты были правильно специфицированы.
484 Глава 19. Операционная система реального времени SalvoTM Диспетчер содержится внутри функции OSSched (). При каждом вызове эта функция выполняет три перечисленные далее операции: • Она выбирает и запускает наиболее правомочную (т.е. обладающую наивысшим прио- ритетом) задачу. Задачи с одинаковым приоритетом запускаются на карусельной основе. • Она обрабатывает очередь событий, если события используются. Помните, что собы- тия включают семафоры и сообщения. В результате возникновения событий некоторые задачи могут стать готовыми к выполнению. • Она обрабатывает очередь задержек, при этом задержки в Salvo являются важным сред- ством управления тем, когда задача должна выполняться. Опять-таки в результате обработки очереди задержек задача может перейти в состояние готовности к выпол- нению. 19.3.2. Написание задач для Salvo Каждая задача Salvo пишется как функция С, при этом следует придерживаться общей схемы написания задач, рассмотренной в подразделе 18.5 Главы 18. Кроме того имеется ряд дополнительных требований, специфичных для ОСРВ Salvo. Это следующие требования. • Все задачи первоначально “не существуют”. Задачи должны создаваться с использо- ванием функции Salvo OSCreateTask (). Они могут создаваться в любом месте программы. На практике многие задачи создаются заблаговременно в функции main. • В общем случае задачи включают дополнительную инициализацию, за которой должен следовать бесконечный цикл, включающий, по меньшей мере, одно переключение контекста. • Переключение контекста может быть выполнено посредством вызова функции OS_Yield (), хотя имеются и другие функции, которые также могут вызвать это переключение. Посредством этого (либо эквивалентного) вызова задача прекращает доступ к ЦП и возвращает управление диспетчеру. Это основа коллективной диспет- черизации, используемой в Salvo. • Задачи не могут принимать никаких параметров. • Задачи используют переменные типа static, следовательно, данные задачи не изме- няются, когда она не выполняется. Переменные типа auto могут использоваться, ес- ли нет необходимости в сохранении данных после переключения контекста. Рабочие характеристики задачи содержатся в ее блоке управления задачей (ТСВ). Это блок памяти, монопольно выделенный задаче, который содержит (среди прочего) старто- вый адрес задачи, идентификатор ее состояния и приоритета. В общем случае задача может вести себя в соответствии с диаграммой состояний, при- веденной на рис. 18.7, при этом каждое состояние задачи интерпретируется специфичным для ОСРВ Salvo образом. Итак, изложенная информация подводит нас к рассмотрению примера программы для Salvo, который рассматривается на последующих страницах. 19.4. Первый пример программы для Salvo Первый пример программы для ОСРВ Salvo приведен в примере программы 19.1. Он использует функции Salvo, перечисленные в табл. 19.1. Программа, показанная в примере, содержит две задачи одинакового приоритета. Одна из них — Count_Task — инкре- ментирует счетчик. Другая — Display_Task — переносит два разряда значения счет- чика на два бита порта С. В случае использования аппаратных средств АУСМ Derbot два самых младших разряда счетчика передаются на светодиоды АУСМ Derbot, которые под- соединены к битам 5 и 6 порта С.
19.4. Первый пример программы для Salvo 485 Пример программы 19.1. Первое приложение ОСРВ Salvo_______________________ /************************************************************************* rtos_exl Вводный пример программы для Salvo. Имеются две задачи равного приоритета. Одна считает, вторая отображает ре- зультат счета. ОСРВ Salvo Lite, использующая библиотеку sfcl8sfm.lib. В основном предназначена для имитации, однако может быть запущена и на АУСМ Derbot. TJW 21.12.05 ♦include <salvo.h> Тестировано 21.12.05 #undef OSC //необходим для этой версии Salvo, //поскольку он также определяет это имя ♦include <pl8f242.h> ♦pragma config OSC = HS, OSCS = OFF // режим генератора HS, //ключ генератора выкл. ♦pragma config PWRT = ON, BOR = OFF//таймер включения питания вкл., //обнаружение частичной потери питания выкл ♦pragma config WDT = OFF //сторожевой таймер выкл. ♦pragma config STVR = ON, LVP = OFF //сброс по переполнению стека вкл, //низковольтное программирование выкл. //Прототипы функций. Эти функции являются задачами, void Count_Task( void ); void Display_Task( void ); //Определяем метки для переключения контекста _OSLabel(Count_Taskl) _OSLabel(Display_Taskl) //Определяем и инициализируем переменные unsigned char counter = 0; /*****************************.******************************************** Определения задач (конфигурируются как функции) *************************************************************************/ void Count_Task( void ) { for (;;) //бесконечный цикл ( counter++; OS_Yield(Count_Taskl);//переключение контекста } } // void Display_Task( void ) ( for (;;) { PORTC = counter<<5; //сдвиг счетчика влево и перенос в порт С OS_Yield(Display_Taskl); } } /************************************************************************ Main *************************************************************************/
486 Глава 19. Операционная система реального времени SalvoTM Пример программы 19.1. Окончание____________________________________ void main( void ) ( //Инициализация TRISC = 0Ы0000000; //установка всех битов порта С на вывод //информации, исключая разряд 7. PORTC = 0; //установка всех битов порта С в 0 //инициализация ОСРВ OSInit (); //создание задач OSCreateTask(Count_Task, OSTCBP(l), 10); OSCreateTask(Display_Task, OSTCBP(2), 10); //установка бесконечного цикла, внутри которого //будет происходить диспетчеризация for (;;) OSSched(); } 19.4.1. Обзор программы и функция main Если просмотреть листинг программы, приведенной в примере, то на первый взгляд эта программа ничем не будет отличаться от обычной небольшой программы на С. Пер- вое указание на то, что это программа для ОСРВ Salvo, заключается во включении файла salvo . h. Несколькими строками ниже дважды используется макрос _OSLabel. Он обес- печивает средство определения меток, которые используются при переключении контек- ста задачи. В данной программе имеется два переключения контекста — по одному на каж- дую задачу. Можно видеть, что выбранные метки CountTaskl и DisplayTaskl исполь- зуются для этих целей внутри задач. Функция main начинает свою работу достаточно традиционно, при этом выполняется инициализация порта С — единственного порта, который будет использоваться. Затем выполняется вызов функции OSInit (), которая инициализирует операционную систему и настраивает среду выполнения всех будущих действий ОСРВ. Затем, посредством дву- кратного вызова OSCreateTask (), создаются собственно задачи. Сводка данных по формату этих вызовов приведена в табл. 19.1, из которой можно видеть, что необходимо обеспечить три параметра. Адрес запуска задачи идентифицируется просто по имени зада- чи, который берется из ее прототипа функции. Стартовый адрес ТСВ (блока управления задачи) определяется с использованием макроса OSTCBP (). Нумеруя аргументы для этого макроса от 1 и выше, мы присваиваем блок ТСВ каждой задаче. Затем обе задачи уста- навливаются на один и тот же приоритет. Может быть выбрано любое значение из диапа- зона от 1 до 16. В данном случае использовано значение 10. Затем устанавливается беско- нечный цикл, вызывающий повторные обращения к диспетчеру OSSched (). Действие такого обращения заключается в активировании наиболее правомочной задачи. Биты конфигурации могут устанавливаться в программе способом, описанным в Гла- ве 17. В используемой версии Salvo, однако, возникает небольшой конфликт, поскольку имя OSC определено для двух различных целей в salvo.hnpl8F242.h. Фирма Pumpkin Inc. советует не использовать такое определение в случае применения компилятора С18. В силу этого, мы аннулируем одно определение, вызвав в командной строке, идущей до включения файла pl 8F242 . h, директиву препроцессора frundef. 19.4.2. Задачи и диспетчеризация Из рассматриваемого примера можно видеть, что сами задачи написаны как функции. Каждая включает бесконечный цикл, при этом в каждом таком цикле имеется вызов функ-
19.4. Первый пример программы для Salvo 487 ции OS_Yield (). Аргументом этого вызова функции является метка переключения кон- текста, уже определенная в начале программы. Всякий раз, когда задача активируется, она будет выполняться вплоть до достижения вызова функции OS_Yield (). Затем она возвращает управление диспетчеру и задача переходит из состояния “выполнение” в состо- яние “готовность к выполнению” или “правомочность” (см. рис. 18.7). Когда диспетчер вновь активирует задачу, он возобновляет ее выполнение со строки, непосредственно следу- ющей после вызова функции OS_Yield () и возвращает задачу в состояние “выполнение”. 19.4.3. Создание проекта Salvo/C18 Создание проекта для Salvo первоначально выглядит как создание любого иного про- екта С18. Если вы хотите скомпоновать этот проект самостоятельно, то вы должны обыч- ным образом начать с формирования проекта MPLAB. Для данного проекта использовано имя rtos_exl. Создайте папку для этого проекта (в ней будет находиться целый ряд файлов) и скопируйте в нее исходный файл и файл salvocfg.h из соответствующей папки на компакт-диске, прилагаемом к этой книге. Из папки С18 добавьте в созданную вами папку файл сценария 18F242, а из папки Salvo — библиотеку sf cl8sfm. lib. Так- же из папки Salvo добавьте файл vtv. с. Ваше окно проекта MPLAB теперь должно при- обрести вид, показанный на рис. 19.4. Возвратитесь опять к рис. 19.2 и табл. 19.1 для определения характеристик библиотеки sf cl8sfm. lib. Нетрудно определить, что это — бесплатная библиотека для компиля- тора С18, применяющая малую модель памяти, обеспечивающая только режим многоза- дачности. Это подходящий выбор для данной очень простой программы. 11»1!ШШ1,.1-ЕТУ| - rtos_ex1 .mcp Б- Source Files mern.c rtos_ex1 c Header Files : Object Files F 'Library Files sfc18sfrnlib Й Linker Scripts i ' 18f242.lkr Other Files Рис. 19.4. Файлы, использованные в проекте Salvo Exl 19.4.4. Настройка файла конфигурации ОСРВ Salvo для конкретного применения конфигурируется настройкой файла sal- vocfg.h, который модифицируется программистом. Этот файл состоит из серии опе- раторов define языка С. Ограниченный набор этих операторов может использоваться в Salvo Lite, в то время как в полнофункциональных версиях Salvo доступно намного боль- шее количество этих операторов. Для каждой опции конфигурирования установлено зна- чение, принимаемое по умолчанию. При этом некоторые из них (или все) могут адаптиро- ваться. Чем более четко файл конфигурации соответствует реальному приложению, тем выше вероятность того, что результирующие исполняемые коды будут максимально эф- фективны. Так, например, нет никакого смысла настраивать память на шесть задач, если их всего три. Файл salvocfg.h, использованный в проекте rtos_exl, показан в примере прог- раммы 19.2. В нем присутствуют комментарии, поясняющие каждую программную строку.
488 Глава 19. Операционная система реального времени SalvoTM Можно видеть, что настройки в этом простом файле относятся либо к конфигурации биб- лиотеки, либо к свойствам программы (включая задачи), либо к событиям и сообщениям. Первая строка выбирает фундаментальную опцию, указывающую на необходимость ис- пользования предварительно-скомпилированных библиотек. Важно, что последующие опции конфигурирования библиотеки фактически соответствуют библиотеке, которая была выбрана. В данном случае уже выбранная библиотека sfcl8sfm.lib соответству- ет установке кода конфигурации OSM. Пример программы 19.2. Файл salvocfg.h для программы rtos exl______________ /************************************************************************ Файл salvocfg.h для rtos_exl TJW 08.01.06 *************************************************************************/ //Конфигурация библиотеки #define OSUSE_LIBRARY TRUE //Использование предварительно //скомпилированной библиотеки Salvo #define OSLIBRARY_TYPE OSF //Использование бесплатной библиотеки //(OSL — это стандартная библиотека) #define OSLIBRARY_GLOBALS OSF //Объекты Salvo размещаются в памяти типа //far, в области банков памяти ОЗУ #define OSLIBRARY_CONFIG OSM //Установка конфигурации библиотеки, //OSM = поддержка только многозадачности #define OSLIBRARY_VARIANT OSNONE //Варианты библиотеки отсутствуют //Конфигурирование задач, событий и сообщений # define OSEVENTS 0 //установка максимального количества //событий # define OSEVENT_FLAGS 0 //установка максимального количества //флагов событий # define OSMESSAGE_QUEUES 0 //установка максимального количества //очередей сообщений # define OSTASKS 2 //установка максимального количества //задач 19.4.5. Компоновка примера Salvo Компоновка с использованием Salvo выполняется по той же схеме, что и обычная компоновка с С18. Имеется, однако, несколько больше требований, которые должны быть соблюдены для правильной компоновки программы. Помимо необходимости устранения всех ошибок в написании и компоновке программы на С, имеются также требования к кон- фигурированию Salvo. Файлы, показанные на рис. 19.4, должны быть выбраны все. Правильный путь поиска включаемых файлов Salvo должен быть специфицирован в диалоговом окне Build Options (Опции компоновки), как показано на рисунке 19.5 (а). Опции, специфицированные на рис. 19.5 (Ь), также должны быть указаны. Опция SYSE используется Salvo для идентифи- кации компилятора С18, в нескольких файлах общего назначения, написанных под не- сколько компиляторов. Если используются файлы, имеющиеся на компакт-диске, прилагаемом к этой книге, то процесс компоновки должен пройти без каких-либо проблем. Если были все же выда- ны сообщения об ошибках, то возможно, что потребуется обратиться к справочным мате- риалам по Salvo либо зайти на форум пользователей Salvo (на вебсайте фирмы Pumpkin). Стоит также посетить вебсайт, посвященный книгам по встроенным системам (www. em- bedded-knowhow . со. uk).
19.4. Первый пример программы для Salvo 489 (а) (Ь) Рис. 19.5. Установка опций компоновки Salvo: (а) — общих; (Ь) — для MPLAB С18 void Count_Task >’ void 0 fox (;;) //infinite loop counter++,: OS_Yield(Count_Тазк1-; //nontext switch // void Di3play_Task( void , Q for (; ; ) I PORTC ~ counter<У5; //Shift Counter Left., and move to PORT C OS_Yield.Display_Taskl, ; t* * + i t t * -i t + * * + * + + t f t t + i f + * * ♦ t t f * t f M t M -г t t f t t t t Main void main; void ; //Initialise TRISC - ОЫООООООО; //Set all Port C bits to output, except bit 7. PORTC " 0; //Set all Fore C outputs low ‘ //Initialise the RTOS 0 OSInitl); //Create Tasks OSCreateTask;Count Task, OSTCBP 1?, 10) ; OSCreateTask(Display_Task, OSTCBP’2), ID); //Set up continuous loop, within which scheduling will take place. © for (;;) OSSched;); Рис. 19.6. Установка контрольных точек при ОСРВ-имитации
490 Глава 19. Операционная система реального времени SalvoTM 19.4.6. Имитация выполнения программы Salvo Этот первый пример ОСРВ-программы может имитироваться точно так же, как любой другой. Успешно скомпоновав программу, выберите MPLAB SIM. Откройте окно Watch (Наблюдение) и выберите счетчик и порт С для отображения. Вставьте контрольные точки, показанные на рис. 19. 6. Они размещены в ключевых точках этой простой ОСРВ-программы. Затем запустите имитатор до первой контрольной точки, которая установлена непосредственно перед инициализацией ОСРВ. Запустите имита- тор снова, что приведет вас к вызову OS Scheel (). Следующий пуск приведет вас к задаче Count_Task, которая будет выполнена первой, поскольку она была первой создана. Если вы продвинетесь на один шаг от этой точки, то увидите, что управление до тех пор будет оставаться внутри задачи, пока не будет достигнуто обращение к функции OS_Yield (). Дальнейшие пуски будут приводить к тому, что управление будет передаваться от од- ной задаче к другой, попадая между каждым вызовом задачи к OSSched (). Каждый раз, когда управление возвращается к задаче, оно попадает точно туда, где оно было оставле- но. Поскольку задачи имеют равный приоритет, они выполняются по схеме карусельной диспетчеризации. Всякий раз, когда выполняется задача Count_Task, значение счетчика в окне Watch (Наблюдение) инкрементируется, и всякий раз, когда выполняется задача Display_Task, значение порта С обновляется. В терминах функциональности мы не достигли ничего впечатляющего. В терминах же способа выполнения программ — это большой шаг вперед. Данная программа может работать также и на аппаратных средствах АУСМ Derbot. Однако такое ее выполнение не принесет нам ничего интересного. Поскольку она будет работать фактически без какой-либо синхронизации, возникнет впечатление, что свето- диоды постоянно включены. 19.5. Использование прерываний, задержек и семафоров при работе с Salvo Главной особенностью любой операционной системы реального времени, конечно же, является ее способность управлять процессами, протекающими в масштабе реального вре- мени. Чтобы достигнуть этого, более или менее существенным является формирование непрерывной последовательности тактирующих сигналов времени, следующих на фикси- рованной и надежно воспроизводимой частоте. Эти тактирующие сигналы могут исполь- зоваться для формирования временной базы, относительно которой будут отсчитываться моменты реализации иных событий. Как только мы сформируем тактирующие сигналы времени, многие функции Salvo станут доступными. Чтобы сформировать тактирующий сигнал времени, мы должны использовать преры- вание по таймеру, кроме того мы должны использовать функции счета и реакции на исте- чение интервалов времени, основанной на подсчете тактирующих сигналов времени. В табл. 19.3 приведены примеры функций Salvo, связанных с прерываниями и синхрониза- цией, которые мы будем использовать. 19.5.1. Пример программы, использующей тактирующие сигналы времени, основанные на прерываниях Пример программы 19.3 с именем rtos_ex2, является развитием нашего первого примера программы для ОСРВ. Он сохраняет те же самые две задачи, также имеющие одинаковый приоритет, однако в нем вводятся тактирующие сигналы времени (управляе- мые по прерываниям), временная задержка, а также двухпозиционный семафор. Каждая из названных позиций подробно обсуждается в нижеследующих подразделах. В примере,
19.5, Использование прерываний, задержек и семафоров при работе с Salvo 491 который следует далее, вводится подпрограмма обслуживания прерывания для тактирую- щего сигнала времени. Табл. 19.3. Пример функций и сервисов Salvo, которые могут использоваться с прерываниями, таймерами и задержками Фупкция/сервис Действие и параметры OSTimer( ) Проверяет, не наступил ли тайм-аут какой-либо задержанной или ожидающей задачи. Если это так, то она считается готовой к выполнению. В случае задержки она должна быть вызвана по нужному тактирующему сигналу времени, требуется использование функций обслуживания тайм-аута или истечения временного интервала. Параметров нет. OS_Delay( , )* Инициализирует передачу управления от текущей выполняемой задачи к диспетчеру и специфицированную временную задержку. Требует использования функции OSTimer (). (1) Целое число, указывающее требуемую временную задержку в системных периодах тактовой частоты; (2) Метка переключения контекста, часто определяется через использование функции _OSLabel (). OSEi ( ) Разрешает прерывания (устанавливает биты GEI и PEIE в регистре INTCON; смотрите рис. 12.8). OSDi( ) Запрещает прерывания. * Может вызвать переключение контекста Программа структурирована способом, который должен быть вам уже знаком, даже притом что в программу добавлены новые возможности. Функция main инициализирует микроконтроллер через вызов функции Micro_Init (). После этого следует инициализа- ция ОСРВ через вызов OSInit () . После создания задач и семафора программа входит в цикл диспетчеризации, наличие которого вы, наверное, уже предполагали. Пример программы 19.3. Использование временных задержек и семафоров_________ /************************************************************************* rtos_ex2 Еще один пример программы для Salvo. Программа использует прерывания от таймера, тактирующие сигналы времени, задержки и двухпозиционный семафор. В программе имеются две задачи равного приоритета. Одна выполняет подсчет, вторая отображает результат счета. Используется ОСРВ Salvo Lite с библиотекой sfcl8sfa. Может быть выполнена как на имитаторе, так и на аппаратных средствах АУСМ Derbot. TJW 28.12.05 ' Тестирована 30.12.05 ********* ******************* ******** *************************************/ ♦include <salvo.h> ♦undef OSC //Необходимо для этой версии Salvo, //поскольку она тоже определяет это имя ♦include <pl8f242.h> ♦include <timers.h> ♦pragma config OSC = HS, OSCS = OFF //режим генератора HS, генератор выкл. ♦pragma config PWRT = ON, BOR = OFF //таймер включения питания вкл., //обнаружение частичной потери питания выкл. ♦pragma config WDT = OFF //сторожевой таймер выкл. ♦pragma config STVR = ON, LVP = OFF //разрешение сброса по переполнению //стека, низковольтное программирование выкл.
492 Глава 19. Операционная система реального времени SalvoTM Пример программы 19.3. Продолжение__________________________________________ ♦define BINSEM_Display OSECBP(l) //Прототипы функций, void Micro_Init(void); //Эти функции являются задачами. void Count_Task( void ); void Display_Task( void ); //Определяем и инициализируем переменные unsigned char counter; //Определяем метки для переключения контекста _OSLabel(Count_Taskl) _OSLabel(Display_Taskl) /************************************************************************* Функции, определяемые пользователем, включая задачи ОСРВ *************************************************************************/ void Count_Task(void) { for (;;) { //бесконечный цикл counter+t; OSSignalBinSem(BINSEM_Display) ; OS_Delay (20,Count_Taskl); //Переключение задачи, //задержка на 20 х Ю мс, (200 мс) //Используем меньшую задержку для имитации } void Display_Task(void) { for (;;) { //бесконечный цикл OS_WaitBinSem(BINSEM_Display, 100, Display_Taskl); PORTC = counter<<5; //сдвиг счетчика влево и перенос в порт С OS_Yield(Display_Taskl); } } void Micro_Init(void) I //Initialise Port C TRISC = 0Ы0000000; PORTC = 0; //Выходы выкл. /* Инициализация TMRO: прерывание разрешено, 16-разрядный режим работы, внутренний тактовый генератор, коэффициент деление предварительного делителя на 16, следовательно (при тактовой частоте в 4 МГц) период входной тактовой частоты будет равен 16 мкс */ OpenTimerO (TIMER_INT_ON & T0_SOURCE_INT & T0_16BIT & T0_PS_l_16); counter = 0; } у************************************************************************* Main *************************************************************************/ void main( void ) I //Инициализация микроконтроллера
19.5. Использование прерываний, задержек и семафоров при работе с Salvo 493 Пример программы 19,3. Окончание___________________________________________ Micro_Init(); //Инициализация ОСРВ OSInit () ; OSCreateTask(Count_Task, OSTCBP(l), 10); //Создаем задачу Count_Task OSCreateTask(Display_Task, OSTCBP(2), 10);//Создаем задачу Display_Task OSCreateBinSem(BINSEM_Display, 0); //Создаем двухпозиционный семафор //Разрешение прерываний OSEi () ; //цикл диспетчеризации for (;;) OSSched(); 19.5.2. Выбор библиотеки и конфигурирование В примере rtos_exl была использована библиотека sfcl8sfa. lib. Сейчас, од- нако, мы хотим ввести задержки и семафоры, последнее относится к типу “событие”. Если посмотреть на табл. 19.1, то можно видеть, что суффикс библиотеки “m” suffix более не является адекватным. Самое лучшее, что мы можем сделать — это перейти к использованию библиотеки с суффиксом “а”, хотя это и обеспечивает ненужные нам пока возможности перехода в состояние бездействия и использования приоритетов. При использовании другой библиотеки и наличии новых функций, новый файл sal- vocf g. h необходим для данного проекта. Он будет таким же, как и для rtos_exl, за исключением двух отличий: изменения идентификатора библиотеки и включения сема- фора (“событие”). Показанные далее командные строки должны быть вставлены на место эквивалентных строк в файл, который был приведен ранее. Полная версия файла приве- дена на компакт-диске, прилагаемом к этой книге. ♦define OSLIBRARY_CONFIG OSA //устанавливаем конфигурацию библиотеки, //OSA = поддержка многозадачности, //задержек и событий ♦define OSEVENTS 1 //определяем максимальное количество событий 19.5.3. Использование прерываний и формирование тактирующих сигналов времени Прерывания могут быть введены в программу для Salvo посредством добавления в окне макроопредений USE_INTERRUPTS (рис. 19.5 (b)). Эта запись идентифицирует для Salvo, что файл, называемый is г. с, работает как системная подпрограмма обслуживания прерываний. Затем прерывания обрабатываются как обычно, как это было описано в под- разделе 17.4 Главы 17. Пример программы 19.4 демонстрирует подпрограмму обслуживания прерываний для rtos_ex2. Она повторяет пример программы 17.3, за исключением того, что включает важное обращение к OSTimer (). Эта функция, показанная в табл. 19.3, позволяет рабо- тать привязанным ко времени функциям Salvo. Переменная tick_counter также ин- крементируется по каждой итерации подпрограммы обслуживания прерываний. Она используется в процессе имитации. Период следования тактирующих сигналов времени для данного примера програм- мы был выбран равным 10 мс (до некоторой степени произвольно). Они формируются в результате использования прерывания от таймера 0 по переполнению. Это прерывание разрешается и конфигурируется через вызов OpenTimerO () с настройками, описанными
494 Глава 19. Операционная система реального времени SalvoTM в комментариях. При тактовом генераторе, обеспечивающем тактовую частоту в 4 МГц, и предварительном делителе, установленном на коэффициент 16, период входной тактовой частоты таймера будет равен 16 мкс. Следовательно, теоретически необходимо отсчитать 625 циклов для получения периода, равно 10 мс. Таким образом, значение, предварительно загружаемое в таймер, должно быть равным 65536 минус 625 или что равно 64911. После того, как программа была испытана на имитаторе и были проведены измерения с исполь- зованием функции секундомера, указанное число было подкорректировано в сторону уве- личения, чтобы принять во внимание неучтенное время ожидания прерывания, которое наблюдалось на практике. Прерывание от таймера разрешается вызовом OpenTimerO (). Разрешение глобально- го прерывания устанавливается в пределах вызова OSEI () в функции main. Нет ничего в этом макросе, что было бы Salvo-специфичным, здесь он используется просто для удобства. Пример программы 19.4. Подпрограмма обслуживания прерываний для тактирующего сигнала времени_____________________________________________________________ /**************************************** ************************* ******** Подпрограмма обслуживания прерываний для rtos_ex2 Прерывание от таймера 0 является высокоприоритетным источником прерываний. Перезагружаем таймер и вызываем OSTimer() TJW 30.12.05 Тестировано 30.12.05 *************************************************************************/ ♦include <salvo.h> ♦include <pl8F242.h> ♦include <timers.h> //Прототипы функций void timer0_isr (void); static unsigned int tick_counter = 0; //Определяем высокоприоритетный вектор прерывания по адресу 0008h ♦pragma code high_vector=0x08 void interrupt (void) ( _asm GOTO timer0_isr _endasm //переход на подпрограмму //обслуживания прерываний } ♦pragma code //Возврат в секцию кода, используемого по умолчанию //Функция timerO isr специфицируется как высокоприоритетная подпрограмма //обслуживания прерываний ♦pragma interrupt timer0_isr //timer0_isr function. void timer0_isr (void) ( WriteTimerO (64918); //Перезагружаем значение, дающее 625 циклов //до переполнения, без компенсации латентности //прерывания OSTimer (); tick counter++; //инкрементируем счетчик тактирующих сигналов //времени (для имитации) INTCONbits.TMROIF = 0; //Очищаем флаг прерывания TMR0 2___________________________________________________________________________
19.5. Использование прерываний, задержек и семафоров при работе с Salvo 495 Хотя сейчас мы установили полезную, если не важнейшую, функцию генерирования тактирующих сигналов времени, следует помнить, что в этой форме она будет носить только приблизительный характер. Обычно ОСРВ блокирует прерывания, например, во время отработки функции OSSched (). Это загрубляет период латентности прерывания и вызывает задержку в реакции на обслуживание прерывания от таймера со стороны подпрог- раммы обслуживания прерываний. Таймер, имеющий аппаратные средства перезагрузки, обеспечит более точную временную базу. В любом случае сформированная временная база будет всего лишь приблизительной, ибо по причине использования коллективной диспет- черизации, задачи могут реагировать на тактирующие сигналы времени только тогда, ко- гда это разрешено действиями других задач. Мы сможем реально оценить масштабы это- го приближения в ходе имитации, которую мы скоро выполним. 19.5.4. Использование временных задержек Теперь, когда мы имеем тактирующие сигналы времени, мы можем синхронизировать по ним задачи. Один из способов сделать это — использовать функцию OS_Delay () с параметрами в соответствии с табл. 19.3. Эта функция при ее вызове инициализирует переключение контекста и может таким образом заменить функцию OS_Yield(). Она также вводит временную задержку до того момента, когда задача сможет выполняться. Эта задержка задается установкой первого параметра. Вызов функции OS_Delay (), который можно видеть в задаче Count_Task, пока- занной в примере программы 19.3, теперь реализуется следующим образом: OS_Delay (20,Count_Taskl); //Переключение задач, //задержка на 20 х 10 мс, (200 мс) //Используем меньшую задержку для имитации Как указано в комментарии, использование данной задержки приводит к тому, что задача Count_Task будет выполняться периодически каждые 200 мс. 19.5.5. Использование двухпозиционного семафора Концепция семафора была представлена в подразделе 18.6 Главы 18. Он может исполь- зоваться или для защиты ресурса или для передачи сигналов между задачами. Семафор — это мощная возможность, поскольку он представляет собой фактически самый простой способ формирования связи между задачами. В примере программы 19.3 используется двоичный семафор. Семафоры Salvo, как и задачи, должны сначала создаваться в программе. Это при- водит к выделению им в памяти управляющего блока события (ЕСВ — event control block), подобно ТСВ для задач. В нем хранится существенная информация о семафоре. При этом состояние семафора может устанавливаться одной задачей, а ожидаться — дру- гой. Функции, которые выполняют упомянутые три действия, перечислены в табл. 19.4. В нашем примере программы используется один семафор. Поскольку он представляет собой единственное событие, рассматриваемое в программе, то функцией OSECB (1) опре- деляется один ЕСВ-указатель. ЕСВ-указатель используется более чем одним ТСВ-указа- телем в вызовах функций, поэтому стоит определить ему имя. Следующая командная строка программы присваивает ему имя BINSEM_Display: #define BINSEM_Display OSECBP(l) Семафор создается функцией main () сразу же после создания задач командной строкой: OSCreateBinSem(BINSEM_Display, 0);
496 Глава 19. Операционная система реального времени SalvoTM Табл. 19.4. Пример функций и сервисов Salvo для двухпозиционных семафоров Функция Действие и параметры OSCreateBinSem( , ) Создает двухпозиционный семафор. (1) Указатель на ЕСВ (блок управления событием). (2) Исходное значение (0 или 1). OSSignalBinSem( ) Сигнализация двухпозиционным семафором. Если никакая задача не ожидает сигнала, то семафор инкрементируется. Если ожидает одна либо большее число задач, то задача с наивысшим приоритетом переводится в состояние готовности к выполнению. (1) Указатель на ЕСВ семафора. OS_WaitBinSem( , , )* Задача ожидает (в состоянии “ожидания”) момента, когда будет подан сигнал двухпозиционным семафором. Задача выходит из состояния ожидания после сигнала семафора или в случае истечения периода тайм-аута. Затем семафор автоматически сбрасывается. Период тайм-аута должен быть специфицирован. (1) Указатель на ЕСВ. (2) Значение тайм-аута (в периодах системной тактовой частоты). (3) Метка переключения контекста OSECB ( ) Определяет указатель на специфицированный блок управления, в данном случае — на блок управления событием. Аналогично OSTCB () в табл. 18.2. Целое число от 1 до OSEVENTS, где OSEVENTS определяет количество событий в файле salvocfg. h. OSNO_TIMEOUT Используется для указания величины тайм-аута, если тайм-аут не должен использоваться * Может вызвать переключение контекста В приведенной командной строке используется имя указателя ЕСВ, которое было предварительно определено. Семафор первоначально устанавливается в 0. Фактический механизм этого простого использования двухпозиционного семафора мо- жет быть понят, если рассматривать две задачи. Прежде всего, помните, что Count_Task запускается только через каждые 20 тактирующих сигналов времени из-за использования OS_DELAY (). Когда она выполняется, то сигнализирует семафору через вызов OSSIG- NALBINSEM (). Действие передачи сигнала семафору устанавливает его единичное зна- чение. Если задача ждет семафора, то она становится готовой к выполнению, а семафор сбрасывается. Таким образом, задача Display—Task ждет установки единичного значения сема- фора благодаря командной строке: OS_WaitBinSem(BINSEM_Display, 100, Display_Taskl); Эта командная строка указывает имя ожидаемого семафора, значение тайм-аута и метку переключения контекста. Значение тайм-аута также должно быть указано и тогда, когда оно не используется (как в этом случае). Общий эффект будет заключаться в том, что, как только значение отсчета в Count—Task изменится, оно будет отображено задачей Dis- play-Task.
19.5. Использование прерываний, задержек и семафоров при работе с Salvo 497 Таким образом, благодаря только что выполненным шагам, мы сформировали простую межзадачную связь и установили синхронизацию. Это большой шаг вперед, но с этим связано еще одно преимущество. Задача, которая ждет семафор, не активирована каким либо образом диспетчером. Следовательно, использование ЦП становится намного бо- лее эффективным. 19.5.6. Имитация выполнения программы Очень интересно выполнить эту программу на имитаторе и понаблюдать, как взаимо- действуют тактирующие сигналы времени, задачи и семафор. Скопируйте исходный файл и файл salvocfg.h с компакт-диска, прилагаемого к этой книге, создайте вокруг них проект и выполните компоновку. Далее рекомендуется установить следующие параметры имитации. Выберите MPLAB SIM в качестве отладчика и вставьте три контрольных точки — по одной внутри каждой задачи и одну в программе обслуживания прерывания. Откройте окно Watch (Наблюде- ние) и для отображения выберите переменные, показанные на рис. 19.7. На инструмен- тальной панели выберите Debugger (Отладчик) > Settings (Настройки) > Osc/Trace (Отслеживание генератора) и установите частоту генератора на 4 МГц. Откройте из раз- ворачивающегося меню Debugger (Отладчик) окно Stopwatch (Секундомер), показанное в верхней половине рис. 19.7. В Stopwatch Processor frequency (MHz) х Stopwatch • Total Simulated Synch J Instruction Cycles | 199970 | 1248919 | gero | T,rne (mSecs) f 199.970000 | 1248919000 4000000 AddSER] |ADCON0 •r | Add Symbol | tmp_0 Address | Symbol Name Hex |l Decimal} Binary } * 0FF2 INTCON c4 100 01100100 0FD6 TMRO FD90 64920 11111101 10011000 0F82 PORTC 40 64 U1UUU0U0 00В5 counter 02 2 00000010 ООВЗ tick counter 0015 21 00000000 00010101 'r | Watch 1 Watch 2 | Watch зД Watch 41 » Рис. 19.7. Окна Watch (Наблюдение) и Stopwatch (Секундомер), используемые для отслеживания тактирующих сигналов времени ОСРВ Используя органы управления имитатора, запустите программу. Она остановится на первой встреченной ею контрольной точке. Если предположить, что прерывание по тай- меру еще не произошло, то это будет контрольная точка внутри задачи Count_Task. Эта задача была создана первой, и временная задержка на нее не воздействует до первой ите- рации OSDELAY (). Значение счетчика инкрементируется и становится равным 1. Затем устанавливается семафор, дальнейшее выполнение программы приведет к достижению контрольной точки в задаче Display_Task. Значение порта С в данном случае устанав- ливается программой на 20н- Следующий шаг выполнения программы приведет к дос- тижению контрольной точки в подпрограмме обслуживания прерываний от таймера.
498 Глава 19. Операционная система реального времени SalvoTM На данный момент времени в окне Stopwatch (Секундомер) отображается нулевое значение времени. Последующие пуски будут неоднократно возвращать управление под- программе обслуживания прерываний таймера. Это отражает формирование тактирую- щих сигналов времени. Можно видеть, что значение времени в окне Stopwatch (Секундо- мер) каждый раз будет увеличиваться почти точно на 10 мс. Интересно отметить, что погрешность не является постоянной, но зависит от других действий программы, которые являются асинхронными по отношению к таймеру. Это отражает факт аппроксимации, который обсуждался в подразделе 19.5.3. После 20 тактирующих сигналов времени, временная задержка Count_Task завершается, а управление вновь переходит к задаче. В свою очередь она устанавливает семафор и выполняется Display_Task. Как можно заметить в окне Stopwatch (Секундомер), оба отмеченные действия происходят внутри одного кванта времени. Общая схема поведения программы, которая была только что описана, иллюстрируется на рис. 19.8. Он демонстрирует общую последовательность действий внутри программы; точный масштаб по горизонтальной оси времени не подразумевается. Display ...Task anBSS-OGDODODGDOOODOODDOUD □□□ обслуживания прерываний от таймера 0) Рис. 19.8. Вхождение контрольных точек при имитации выполнения программы Учебная задача Два снимка экрана, показанные на рис. 19.7, сделаны в процессе имитации выполне- ния программы. На основании данной информации, сделайте максимально подробный анализ того, когда выполнение программы было остановлено. 19.5.7. Выполнение программы Если у вас есть АУСМ Derbot, загрузите в него рассмотренную программу и запус- тите ее. Светодиоды начнут вспыхивать регулярным образом. Когда вы увидите это, то помните: каждое изменение состояния светодиода происходит из-за накопления такти- рующих сигналов времени, приводящего по цепочке к снятию с выполнения текущей за- дачи, инкрементированию счетчика, переключению семафора и переключению состояния светодиодного индикатора. Мы достигли очень простого результата, но элегантность и мощность реализованного процесса чрезвычайно впечатляет. Эта элегантность и мощность может быть также использована в намного более сложных приложениях. 19.6. Использование сообщений Salvo и повышение сложности ОСРВ Следующий шаг, который мы сделаем, включает изучение еще одного нового Salvo ресурса — сообщений. И это приведет нас к созданию программ значительно большей сложности, чем раньше. В этих программах мы сможем реализовать возможности ОСРВ более практичным и реалистичным образом.
19.6. Использование сообщений Salvo и повышение сложности ОСРВ 499 Сообщения обеспечивают удобный способ как обмена данными между задачами, так и синхронизации действий между ними. Некоторые их характеристики подобны семафо- рам — они должны быть созданы, а затем могут брать фрагмент данных из одной точки программы и передавать его в другую, возможно, в то же самое время, снимая задачу с выполнения. Терминология, связанная с сообщениями, может немного запутать. Мы можем создать “сообщение” (то есть структуру Salvo, несущую данные), которая может затем нести лю- бое число сообщений (т.е. фрагментов данных, перемещаемых из одной части программы в другую). Следовательно, фактически мы называем функцию Salvo “сообщением”, а за- тем говорим о “передаче сигналов” сообщением, когда к нему присоединяется фрагмент данных. Табл. 19.5. Примеры функций и сервисов Salvo, предназначенных для работы с сообщениями Фупкция/сервис Действие и параметры OSCreateMsg( , ) Создает сообщение, с указателем на ЕСВ (блок управления событием) и исходным значением. (1) Указатель на ЕСВ сообщения. (2) Указатель на сообщение. OSSignalMsg( , ) Сигнализирует сообщением, т.е. присоединяет к нему элемент данных. Если ожидает одна либо большее число задач, то задача с наивысшим приоритетом переводится в состояние готовности к выполнению. (1) Указатель на ЕСВ сообщения. (2) Указатель на сообщение. OS_WaitMsg(,,,)* Задача ожидает (в состоянии “ожидания”) момента подачи сигнала сообщением. Затем она формирует указатель сообщения, указывающий на данное сообщение (параметр 2). Затем ожидающая задача продолжает свое выполнение. Задача продолжает выполняться в случае тайм-аута. Значение тайм-аута должно быть указано. (1) Указатель на ЕСВ сообщения. (2) Указатель на сообщение. (3) Значение тайм-аута (в периодах системной тактовой частоты). (4) Метка. OSECB ( ) Как в таблице 19.4. OSNO_TIMEOUT Как в таблице 19.4. OStypeMsgP Определяет тип данных как указатель на сообщение. Это один из заранее определенных типов данных Salvo, он должен использоваться соответствующим образом. * Может вызвать переключение контекста В Salvo сам сигнал сообщения может иметь любой тип данных — от символьного до массива. Информация, которая фактически передается — это указатель на сигнал. Это входит в область ответственности программиста — гарантировать, что он указывает на требуемые данные при подаче сигнала и что он будет правильно трактоваться на прием- ном конце. Обратите внимание на то, что сообщение может быть послано из любой точки программы. Таким образом, например, прерывание может сигнализировать сообщением, которое будет затем получено задачей. Примеры функций и сервисов Salvo, работающих с сообщениями, приведены в табли- це 19.5. Все они будут применяться и в примере программы 19.5. Поскольку сообщение
500 Глава 19. Операционная сисгема реального времени SalvoTM Salvo имеет тип “событие”, то для каждого сообщения устанавливается ЕСВ — точно так же, как в случае семафора. 19.7. Пример программы с сообщениями В примере программы 19.5 приведен листинг достаточно реальной Salvo-базирован- ной программы. Она создана на основе программы “слепой навигации” АУСМ Derbot, рассмотренной в примере программы 15.3, но включает использование датчика ультра- звука типа, описанного в подразделе 8.6.5 Главы 8. Он был установлен с ориентацией вверх, как показано на рис. 19.9. Обратите внимание на то, что этот датчик разделяет разряды порта со светодиодами, поэтому в этой программе они недоступны. Данная программа работает как программа “слепой навигации”, за исключением того, что когда АУСМ Derbot перемещается под нависающим объектом — например стулом, он распознает это, пово- рачивает и уезжает. Рис. 19.9. АУСМ Derbot с ориентированным вверх ультразвуковым датчиком Данная программа имеет две задачи, теперь уже разного приоритета, и два прерывания, также разного приоритета. В отличие от предыдущих примеров, каждая задача формирует значительный блок кодов и каждая из них включает более одного переключения контек- ста. Определяется одно “сообщение”; оно используется для передачи сигналов задаче управления электромоторами — как по прерываниям, так и от другой задачи. Также ис- пользуется ряд задержек.
19.7. Пример программы с сообщениями 501 Функция main очень похожа на эту же функцию из предыдущего примера програм- мы, за исключением того, что вместо семафора создается сообщение. Пример программы 19.5. Программа “слепой навигации” АУСМ Derbot с развернутым вверх ультразвуковым датчиком____________________________________________________ /****************************************************** ****** *****^*^** rtos_ex3 Реализует режим “слепой навигации” АУСМ Derbot, при ориентированном вверх ультразвуковом датчике, что имеет целью обнаружения факта перемещения АУСМ под нависающими объектами Имеются следующие задачи: ультразвуковой датчик (высокий приоритет), Motor_set (низкий приоритет). Прерывания: от микропереключателя (низкий приоритет) и от таймера 0 (высо- кий приоритет, для формирования тактирующего сигнала времени). Также используется одно сообщение и различные временные задержки. Используется Salvo LITE с библиотекой sfcl8sfa. Может выполняться либо на аппаратных средствах Derbot, либо может имитироваться. TJW 03.01.06 Тестировано 04.01.06 ******t*tt*tt*****tit*******t*****t****t*t*t**t******t**i***t**t**xt*t*** I //Тактовая частота равна 4 МГц #include <salvo.h> #undef OSC //необходим для этой версии Salvo, //поскольку он также определяет это имя #include <pl8f242.h> #include <timers.h> //заголовочный файл для задержек ♦include <delays.h> //заголовочный файл для задержек ♦include <pwm.h> //заголовочный файл для ШИМ ♦pragma config OSC = HS, OSCS = OFF //режим генератора HS, //ключ генератора выкл. ♦pragma config PWRT = ON, BOR = OFF //обнаружение //таймер включения питания вкл., частичной потери питания выкл. ♦pragma config WDT = OFF //сторожевой таймер выкл. ♦pragma config STVR = ON, LVP = OFF //разрешение сброса по переполнению //стека, низковольтное программирование выкл. //прототипы функций, определяемых пользователем. void Micro_Init(void); void leftmot_fwd(void); void rtmot_fwd(void); void leftmot_rev(void); void rtmot_rev(void); Line 32 //Эти функции являются задачами void Motor Task(void); //Настраивает электромотор в соответствии //с принятыми сообщениями void USnd_Task(void); //Периодически включает ультразвуковой //датчик //Определение меток для переключения контекста _OSLabel(Motor_Taskl) _OSLabel(Motor_Task2) _OSLabel(Motor_Task3) _OSLabel(Motor_Task4) _OSLabel(Motor_Task5) OSLabel(USnd Taskl)
502 Глава 19. Операционная система реального времени SalvoTM Пример программы 19.5. Продолжение__________________________________________ _OSLabel(USnd_Task2) _OSLabel(USnd_Task3) _OSLabel(LED_Taskl) _OSLabel(LED_Task2) I/Передача сообщений от микропереключателя и ультразвукового датчика #define Msg_to_Motor OSECBP(l) char Hole = 0x18; //Это значение используется, //однако никогда не проверяется Line 53 /************************************************************************* Функции, определяемые пользователем, включая задачи ОСРВ. //Эта задача контролирует работу электромотора, задаваемую сообщениями, //поступающими из любого места программы void Motor_Task( void ) ( static char msge; //содержит принятое сообщение OStypeMsgP msgP; //объявляет msgP специальным типом указателя Salvo for (;;) //устанавливает бесконечный цикл задачи ( rtmot_fwd (); //Задает вращение электромоторов вперед, leftmot fwd (); //Это обычный режим до прибытия сообщения //ожидание сообщения OS_WaitMsg(Msg_to_Motor,&msgP,OSNO_TIMEOUT, Motor_Taskl) ; // Строка 67 Обрабатывается по прибытии сообщения msge = *(char*)msgP; PORTAbits.RA5 - 0; //останов электромоторов на 500 мс PORTAbits.RA2 = 0; OS_Delay (50,Motor_Taskl); if( (msge == 0x80)| | (msge == 0x01) ) //сообщение от //микропереключателя? { rtmot_rev (); //Да, поэтому оба мотора реверсируются leftmot__rev (); OS_Delay (100,Motor_Task2); if(msge == 0x80) //соударение с левым микропереключателем? ( leftmot_fwd (); //Да, поэтому поворачиваем вправо OS_Delay (80,Motor_Task3); } else //соударение с правым микропереключателем? ( rtmot_fwd (); //Да, поэтому поворачиваем влево OS_Delay (80,Motor_Task4); } } Line 86 else //Мы под перекрытием, поэтому поворачиваемся на месте { rtmot_rev (); leftmot_fwd (); OS_Delay (200,Motor_Task5) ; } } //конец цикла "for" }
19.7. Пример программы с сообщениями 503 Пример программы 19.5. Продолжение____________ Line 93 /*Эта задача периодически включает ультразвуковой датчик и посылает сооб- щение, если обнаружено перекрытие над АУСМ. В этом случае она прекращает периодически включать датчик, давая возможность Derbot выйти из-под навеса*/ void USnd_Task(void) { int echo_time = 0; //подсчитывает единицы замера дистанции for (;;) //устанавливает бесконечный цикл задачи { OS_Delay (20,USnd_Taskl); //переключение задачи и //задержка на 20 х 10 мс, (200 мс) OSDi(); //запрет прерываний, этот замер является критичным ко времени echo_time = 0; PORTCbits.RC5 - 1; //выдача ультразвукового импульса DelaylOTCYx (2); //задержка, приблизительно равная 20 мкс, //задает ширину импульса PORTCbits.RC5 = 0; DelaylOTCYx(30); //пауза для установки выхода в состояние //логической 1; т.е. пропуск 5 см Line 107 //Значения в этом цикле были настроены экспериментально для формирования //порога распознавания, приблизительно равного 30 см while (echo_time < 50) //предел замеров для близких объектов {DelaylOTCYx(1); //задержка в 10 мкс echo_time++; //инкрементирование счетчика if(PORTCbits.RC6 =- 0) //передача сообщения, //если обнаружен объект { OSSignalMsg(Msg_to_Motor,(OStypeMsgP)&Hole); OSEi(); //разрешение прерываний перед задержкой OS_Delay (250,USnd_Task2);//Пауза в работе датчика ультразвука, //чтобы дать возможность Derbot выйти из-под навеса OS_Delay (250,USnd_Task3) ; break; } } OSEi(); //разрешение прерываний OS_Yield(USnd_Task2) ; } //конец цикла "for" } //Строка 126 Эта функция инициализирует периферийные устройства //микроконтроллера void Micro_Init(void) { I/Инициализация портов TRISA = 0Ь00000000; //Все биты устанавливаются как выходы, 2 и 5 //используются для активирования электромоторов. TRISB = ОЬООИОООО; //На вход работают только биты 5 и 4 //(микропереключатели) TRISC = 0Ы1000000; //Все биты устанавливаются как выходы, //за исключением 7 (переключение режима) //и 6 (ультразвуковой эхо-сигнал), //1 и 2 используются для ШИМ ADCON1 = ОЬОООООНО;//Установка порта А на дискретный ввод-вывод //Выключение всех выходов PORTA = PORTB = PORTC = 0; Line 137
504 Глава 19. Операционная система реального времени SalvoTM Пример программы 19.5. Окончание____________________________________________ /* Инициализация таймера 0: прерывание разрешено, 16-разрядный режим работы, внутренний тактовый генератор, предварительный коэффициент деления равен 16, следовательно (при тактовой частоте, равной 4 МГц) период входной частоты будет равен 16 мкс */ OpenTimerO (TIMER_INT_ON & TO_SOURCE_INT & T0_16BIT & T0_PS_l_16); WriteTimerO (64918); //и инициализация //Инициализация ШИМ OpenTimer2 (TIMER_INT_OFF & T2_PS_1_1 & T2_POST_1_1); OpenPWMl (OxFF); //Разрешение ШИМ1 и установка периода OpenPWM2 (OxFF); //Разрешение И1ИМ2 и установка периода //Установка прерывания по изменению состояния порта В на низкий приоритет RCONbits . IPEN = 1; //Разрешение низкоприоритетных прерываний INTCON2bits.RBIР = 0; //Установка прерывания по изменению //состояния бита порта на низкий приоритет INTCONbits.RBIE = 1; //Разрешение прерывания по изменению //состояния порта В на низкий приоритет } Line 151 /********************************************** ****** ****** ** ****** Main *********************** **************************************************/ void main( void ) { //Инициализация микроконтроллера Micro_Init(); DelaylOKTCYx (250); //пауза 2.5 секунд с обычной задержкой //Инициализация ОСРВ OSInit () ; //Создание задач и сообщения OSCreateTask(Motor_Task, OSTCBP(l), 4); OSCreateTask(USnd_Task, OSTCBP(2), 2); OSCreateMsg(Msg_to_Motor, (OStypeMsgP)0); //Разрешение глобальных прерываний OSEi () ; //Цикл диспетчеризации for (;;) OSSched(); } у************************************************************************* Функции управления электромоторами *************************************************************************/ (Те же самые функции управления электромоторами, что и в примере программы 15.3.) 19.7.1. Выбор библиотеки и конфигурации Если говорить о конфигурации, то эта программа не отличается от предыдущей. Они обе имеют две задачи и одно событие. В данном случае событием является сообщение. Следовательно, библиотека sfcl8sfa.lib остается правильным выбором для исполь- зования и файл salvocfg.h из rtos_ex2 может быть скопирован в этот проект.
19.7. Пример программы с сообщениями 505 19.7.2. Задача USnd_Task Эта задача периодически включает датчик ультразвука, чтобы обнаружить, имеется ли навес над AGV. Если навес обнаружен, она посылает сообщение, которое получается задачей Motor_Task. Поскольку работа электромоторов зависит от замеров, выполняе- мых этой задачей, ей, соответственно, присваивается высший приоритет. Структура USnd_Task является развитием примера программы 9.7, в ней использу- ются программные временные задержки, чтобы сначала сгенерировать импульс, а затем отвести время на реакцию. Эта задача начинается со строки 96 листинга. Задача использу- ет функцию OS_Delay (), помещенную в начало “бесконечного” цикла, чтобы обеспе- чить вхождение функции через каждые 20 тактирующих сигналов времени. Когда период временной задержки истечет, она выводит импульс, устанавливая разряд 5 порта С в со- стояние логической 1, вызывает временную задержку на 20 мкс, а затем вновь устанав- ливает этот разряд в состояние логического 0. Цикл синхронизации замеров, начинающийся со строки НО, должен быть только приблизительным и используется только для ближних замеров. Таким образом, в цикл “while” включен эффективный тайм-аут, длительностью в 50 периодов. Если эхо- импульс (порт С, разряд 6) в течение этого цикла синхронизации становится низким, то генерируется сообщение. В этом случае задача отрабатывает значительную временную задержку. Она использует две итерации функции OS_Delay (), поскольку может исполь- зовать только 8-разрядные значения временной задержки. При этом запрещается работа ультразвукового датчика на время, необходимое для поворота Derbot (при управлении от другой задачи) и его отъезда из-под обнаруженного навеса. Если, однако, эхо-импульс не спадает, то в этом случае отрабатывается выход из цикла синхронизации по тайм-ауту, а задача возвращает управление диспетчеру через вызов OS_Yield () . 19.7.3. Задача Motor_Task Задача Motor_Task выполняет все настройки электромоторов, делая это на основа- нии сообщений, полученных ею по прерыванию от порта В, и задачи USnd_Task. Она начинается в листинге со строки 58. Задача открывается объявлением переменной msge, в которой входящее сообщение будет сохранено. Затем она определяет указатель сообще- ния msgP, используя специальный тип данных Salvo OSTypeMsgP (см. табл. 19.5). Запустив два электромотора, задача ожидает прибытия сообщения посредством вызова функции OS_WaitMsg (). В зависимости от характера принятого сообщения, управление передается на отработку различных состояний. При установке нового состояния электромо- тора отрабатывается временная задержка посредством вызова функции OS_Delay (). На протяжении ожидания (как сообщения, так и задержки), задача является совершенно неак- тивной, поскольку именно диспетчер должен сначала принять сообщение и определить, должна ли задача быть переведена в состояние готовности к выполнению. 19.7.4. Использование сообщений Часть потенциала этой программы связано с использованием сообщений. Далее вос- произведены самые существенные для этого командные строки. В каждом случае они ис- пользуют функции, перечисленные в табл. 19.5. Создается только одно сообщение Salvo, Msg_to_Motor, однако оно используется для передачи различных сообщений из разных мест программы. Все они принимаются функцией Motor_Task. //Передает сообщения от микропереключателя и ультразвукового датчика #define Msg_to_Motor OSECBP(l) From main
506 Глава 19. Операционная система реального времени SalvoTM OSCreateMsg(Msg_to_Motor, (OStypeMsgP)0); From Motor_Task Function static char msge; //содержит принятое сообщение OStypeMsgP msgP; //объявляет msgP специальным типом указателя Salvo //Ожидание сообщения OS_WaitMsg(Msg_to_Motor,&msgP,OSNO_TIMEOUT,Motor_Taskl); //Продолжение работы после прибытия сообщения msge = * (char*)msgP; В начале листинга программы (строка 50) определяется имя сообщения — это Msg_to_Motor. Как и в случае семафора, это фактически указатель на ЕСВ, который был поименован, ибо он используется для идентификации сообщения во всех трех ис- пользуемых функциях Salvo. Сообщение создается в функции main, используя вызов OSCreateMsg (). Намного раньше, при первом вызове Motor_Task (), управление выполнением программы дос- тигает вызова OS_WaitMsg (). Это вызывает переключение контекста и заставляет за- дачу ожидать идентификации сообщения и сигнализации сообщением Msg_to_Motor. Явным образом тайм-аут не используется благодаря вызову OSNO_TIMEOUT. Указатель на сигнал входящего сообщения специфицируется как msgP, этот идентификатор объяв- ляется в начале функции. Сигнализация сообщением производится из функции uswitch_isr (один этому пример приведен ниже) и из функции USnd_Task. Его формат соответствует показан- ному выше. Предварительно определенное имя, Msg_to_Motor, опять-таки использует- ся для передачи указателя на сообщение. Значение сигнала сообщения с именем Rt_usw было определено ранее. Затем указатель на сигнал сообщения передается с использовани- ем специального типа данных Salvo — OStypeMsgP. Из функции uswitch_isr char Rt_usw = 0x01; if (PORTBbits.RB4 == 0) //Проверка правого переключателя OSSignalMsg(Msg_to_Motor,(OStypeMsgP)&Rt_usw); //Передача сообщения 19.7.5. Использование прерываний и подпрограмм обслуживания прерываний Это был первый (и единственный) пример в книге, когда использовались как высокий, так и низкий приоритеты прерываний семейства 18. Так что стоит изучить соответству- ющие установки. Прерывание от таймера 0 используется точно так же, как в примере про- граммы 19.3 для формирования 10-миллисекундного тактирующего сигнала времени. К этому добавлено прерывание по изменению состояния порта В, чтобы обнаружить сра- батывание микропереключателя. Прерывания сконфигурированы главным образом в конце функции Micro_Init(). Использованные регистры показаны на рис. 12.8-12.10, а роль бита IPEN отражена на рис. 12.7. Этот бит сначала устанавливается в состояние логической 1 (строка 147), фор- мируя путь прохождения низкоприоритетного прерывания. В следующих двух строках разрешается прерывание по изменению состояния порта, оно устанавливается на низкий приоритет. Глобальное прерывание разрешается через вызов OSEI () в функции main. Две подпрограммы обслуживания прерываний показаны в примере программы 19.6. Подпрограмма обслуживания прерывания от микропереключателя, uswitch__isr (),
19.7. Пример программы с сообщениями 507 начинается с вызова временной задержки на 8 мс, чтобы позволить микропереключателю прийти в устойчивое состояние. Затем оба переключателя тестируются. Если какой либо из них сработал, то генерируется соответствующее сообщение. Вполне возможно, что ни один из них не сработал, так как подпрограмма обслуживания прерывания вызывается как по срабатыванию, так и по отпусканию микропереключателя. Подпрограмма обслужива- ния прерывания завершается очисткой флага прерывания. Пример программы 19.6. Подпрограмма обслуживания прерывания для примера программы 19,5____________________________________________________________ /************************************************************************* Подпрограмма обслуживания прерывания (ПОП) для rtos_ex3 Имеются два источника прерываний: Высокий приоритет: таймер 0 для "тактирующего сигнала времени", Низкий приоритет: микропереключатель (изменение порта В) в случае коллизии TJW 03.01.06 Тестировано 05.01.06 о***********************************************************************/ ♦include <salvo.h> ♦include <pl8F242.h> ♦include <timers.h> ♦include <delays.h> //заголовочный файл для таймеров //заголовочный файл для задержек //прототипы функций void timer0_isr (void); void uswitch_isr (void); static unsigned int tick_counter = 0; //Значения сообщений char Rt_usw = 0x01; char Left_usw = 0x80; //Передает сообщения от микропереключателя и датчика ультразвука ♦define Msg_to_Motor OSECBP(l) /********************************************** о************************* Прерывание от таймера (высокий приоритет) *************************************************************************/ //Определяем высокоприоритетный вектор прерываний по адресу 0008h ♦pragma code high_vector=0x08 void interrupt_at_high (void) ( _asm GOTO timer0_isr _endasm //переход к ПОП } ♦pragma code //Возврат к кодовой секции, используемой по умолчанию //Функция timerO isr специфицируется как высокоприоритетная ПОП ♦pragma interrupt timer0_isr //Функция timer0_isr void timer0_isr (void) ( WriteTimerO (64918); //Значение предварительной загрузки таймера, //дающее 625 периодов до переполнения с //небольшой компенсацией латентности прерывания OSTimer();
508 Глава 19. Операционная система реального времени SalvoTM Пример программы 19.6. Окончание___________________________________________ tick_counter++; //инкрементирование счетчика тактирующих //сигналов времени (для имитации) INTCONbits.TMR0IF = 0; //Очистка флага прерывания TMR0 } /************************************************* ********************^* Прерывание от микропереключателя (низкий приоритет) *************************************************************************/ //Определяем низкоприоритетный вектор прерываний по адресу 0018h #pragma code low_vector=0xl8 void interrupt_at_low (void) { _asm GOTO uswitch_isr endasm //переход к ПОП } #pragma code // Возврат к кодовой секции, используемой по умолчанию //Функция uswitch_isr специфицируется как низкоприоритетная ПОП #pragma interruptlow uswitch_isr //Функция uswitch_isr. void uswitch_isr (void) { DelaylKTCYx (8); //Задержка 8мс, гарантирующая установку //устойчивого состояния микропереключателя if (PORTBbits.RB4 == 0) //Проверка правого микропереключателя OSSignalMsg(Msg_to_Motor,(OStypeMsgP)&Rt_usw); //Посылка сообщения if (PORTBbits.RB5 == 0) // Проверка левого микропереключателя OSSignalMsg(Msg_to_Motor,(OStypeMsgP)&Left_usw); //Посылка сообщения //вполне возможно попасть в это место программы, когда ни один //микропереключатель не работал, ибо прерывание могло быть вызвано //освобождением микропереключателя. INTCONbits.RBIF = 0; //Очистка флага прерывания от порта В } 19.7.6. Имитация или запуск программы Прежде всего, рекомендуется запускать эту программу на АУСМ Derbot. При ее зави- симости от ультразвукового датчика и интенсивном использовании задержек, данную программу весьма трудно успешно выполнить на имитаторе. 19.8. Накладные издержки ОСРВ Данная глава имела целью дать введение в потенциал использования ОСРВ. Однако необходимо признать, что используя Salvo Lite, мы используем только ограниченный поднабор того, что Salvo может предложить, или того, что доступно в обширном мире ОСРВ. Признавая большой потенциал этого типа программирования, важно давать себе от- чет в его издержках. Их можно разделить на три категории: (1) Финансовые затраты. Как только мы выйдем за рамки использования бесплатной ОСРВ типа Salvo Lite или ее эквивалента, станет необходимо либо приобрести коммер- чески доступную ОСРВ, либо затратить время (а, следовательно, и деньги) на разра- ботку с нуля своей собственной ОСРВ. (2) Издержки, связанные с размерами программы. Программы, написанные для ОСРВ, неизбежно будут занимать больший объем памяти.
19.8. Накладные издержки ОСРВ 509 (3) Издержки, связанные со временем выполнения программы. При значительно большем числе исполняемых кодов, а также ввиду дополнительной нагрузки на ЦП со стороны ОСРВ, программа будет выполняться медленнее. Эти издержки подобны тем, которые имели место при переходе от Ассемблера к про- граммированию на С. Методика программирования более мощна, но ее реализация связана с издержками. Последние два пункта вышеприведенного списка, конечно же, определяют фактическую эффективность программы. Желательно, но отнюдь не просто, определить их количественно. Трудность заключается в факте того, что и объем программного кода, и время его выполнения зависят от точной реализации программы. Нельзя, например, просто говорить, что программа для ОСРВ занимает вдвое больше памяти, чем обычная последовательная программа, или же что она выполняется на поло- винной скорости. Практикой, которая иногда применяется, является использование “эта- лонных” программ, позволяющих сделать сравнения, которые будут относиться к разным программным реализациям, дающим одинаковый функциональный результат. Руководство пользователя Salvo имеет полезную главу, посвященную “Эффектив- ности”. В ней приведены с некоторыми деталями характеристики эффективности ОСРВ Salvo и ее компонент. Что касается тем этой книги, то мы имеем совсем мало программ, которые могли бы использоваться как неформальные эталонные тесты. Программа “слепой навигации” АУСМ Derbot сначала появилась в версии на Ассемблере, как пример программы 8.4, и на С, как пример программы 15.3, хотя и с разным микроконтроллером. Управляемая по прерываниям программа “мигающих светодиодов” появилась первоначально в обычной С-версии, как пример программы 17.3, а затем в ОСРВ-базированной версии, как пример программы 19.3. Одно простое сравнение может быть сделано между каждой из этих пар, если рассматривать использование ими памяти, что отражено в их . map-файлах, описан- ных в подразделе 17.10.3 Главы 17. Если вы желаете этого, то возможно захотите пойти дальше и оптимизировать или обычные С-версии, или ОСРВ-базированные версии. В обоих случаях имеются широкие возможности в этом направлении, при наличии опций, описанных как в руководстве по компилятору С, так и в руководстве по Salvo. Резюме • Salvo — это эффективная операционная система реального времени для среды малых внедренных систем; она практическим способом иллюстрирует все ключевые возмож- ности ОСРВ и очень хорошо подходит для среды PIC. • Работа с ОСРВ ведет к новому подходу к программированию, когда задачи, приори- теты и события становятся главными особенностями. • Имеются издержки, связанные с использованием ОСРВ, включая финансовые, по использованному объему памяти и времени выполнения. Их необходимо понимать и правильно оценить перед принятием решения о необходимости использования ОСРВ.
ЧАСТЬ 5. ВЗАИМНЫЕ СВЯЗИ И СЕТИ В заключительной главе приведен обзор методов создания взаимных связей и формирования сетей — важного поля деятельности в мире современных встроенных систем.
ГЛАВА 20. ВЗАИМНЫЕ СВЯЗИ И СЕТИ Несмотря на все, что было рассмотрено в предшествующих 19 главах, остались некото- рые важные области в мире встроенных систем, которые почти не рассматривались. Одна из таких областей настолько важна, что эта заключительная глава посвящена именно ей. Если вы используете ручной ПУ с АУСМ Derbot и, возможно, у вас есть иное 12С-ус- тройство, то у вас уже есть небольшая сеть. Такой подход используется во многих ситуа- циях, в которых различные системы или подсистемы осуществляют друг с другом инфор- мационный обмен. Дома, на работе, в автомобиле, на предприятии и по всему миру — все мыслимые и немыслимые вещи объединяются в сети. Средства связи, используемые в этих сетях, становятся все более и более разнообразными — сейчас они уже имеют не толь- ко электрическую природу, используются оптоволоконные кабели, инфракрасные и радио- устройства и т.д. В этой главе рассматриваются вопросы, связанные со связью и организацией сетей — коммуникационные среды, используемые для создания каналов связи, а также средства фактического форматирования данных, перемещения и интерпретации данных в этих ка- налах связи. Фактически, эта глава представляет собой обзор некоторых методов и техно- логий организации связи. Как и в случае всех форм жизни, населяющих Землю, мы увидим, что механизмы сетей чрезвычайно разнообразны — каждый из них адаптирован к кон- кретной среде. В этой главе вы узнаете: • о некоторых концепциях формирования сетей; • об альтернативах организации связи, включая беспроводные инфракрасную и радио- связь; • о ряде сетевых протоколов; • о том, как микроконтроллеры PIC® могут быть использованы в названных областях. Поскольку каждая из упомянутых тем представляет сама по себе обширнейшее поле деятельности, в данной главе не ставиться цель их исчерпывающего рассмотрения. В ней просто приведен краткий обзор соответствующих тем и идей относительно их исследо- вания. Также в этой главе не приводятся конкретные примеры разработок. 20.1. Основная идея: сети и связь Имеется много ситуаций, когда нам необходимо обеспечить связь между различными системами или подсистемами. Что касается домашней среды, то сейчас автоматизирован- ное домашнее хозяйство находится на грани реализации. При этом различное хозяйствен- ное оборудование и всяческие технические новинки могут быть объединены вместе, на- пример через Интернет. Имеется также потребность в организации сетей и в других облас- тях. Современный автомобиль может содержать дюжины встроенных систем, каждая из которых вовлечена в очень специфический вид деятельности, однако все они должны быть связаны вместе. В случае домашнего хозяйства или автомобиля связи могут быть длительными и стабильными. Однако некоторые сети и связи носят временный характер — например при выгрузке данных из персонального организатора в ноутбук по беспро- волочному каналу связи. Все упомянутые случаи представляют интерес для разработчика
512 Глава 20. Взаимные связи и сети встроенных систем, при этом они выдвигают перед ним очень разнообразные и сложные задачи. Традиционным средством обеспечения связи между компонентами сетей являются кабельные соединения, через которые электрические сигналы передаются от одной подсис- темы к другой. Компьютер, на котором я сейчас пишу эту книгу, уже не новый, обвешен кабелями, которые соединяют его с мышкой, принтером, сканером, колонками, Интернет- провайдером и всеми этими PIC-инструментами разработчика! Наиболее обычными аль- тернативами кабельным соединениям является или оптическая связь, или радиосвязь. Имеется большое количество вариаций каждого из этих видов связи. Мы уже давно ис- пользуем пульты управления телевизорами, в которых связь осуществляется при помощи инфракрасных лучей. Также много лет уже известна радиосвязь; она была очень эффек- тивно адаптирована для создания линий связи в компьютерных средах. Создание сети —- это нечто большее, чем просто формирование связей, хотя послед- нее и является наиболее важным. В сложной системе также важно полностью понимать, как выполняется форматирование и интерпретирование данных, как выполняется адре- сация и как достигается коррекция ошибок. Все эти темы в достаточной степени незави- симы от физической реализации взаимосоединений. Для того чтобы отдельные узлы сети могли осуществлять между собой информационный обмен, должны быть установлены четкие правила создания и интерпретации сообщений. При рассмотрении стандартов ти- па 12С мы уже рассматривали некоторые аспекты этого вопроса. Этот набор правил на- зывается протоколом — корни этого термина восходят к дипломатическим и юридиче- ским сферам. Давайте подробнее рассмотрим концепцию протокола. 20.1.1. Мир протоколов В случае больших сетевых систем протоколы могут стать очень сложными, определяя каждый аспект работы линии связи. Одни из этих аспектов являются очевидными, в то вре- мя как другие — нет. Чтобы обеспечить помощь в деле определения протоколов, Между- народная Организация Стандартов (ISO) определила “протокол для протоколов”, назван- ный моделью взаимосвязи открытых систем (OSI) и показанный на рис. 20.1. Модель OSI простирается от мирского и физического (определяя, какой тип соединительных разъемов нужно использовать и какие напряжения распознавать) до более абстрактного (определяя, например, как должны кодироваться данные и как должна выполняться коррекция ошибок). Рис. 20.1. Модель взаимосвязи открытых систем ISO Каждый слой модели OSI предоставляет определенный набор сервисов для вышеле- жащего слоя и каждый, следовательно, зависит от сервисов, предоставляемых нижеле- жащим слоем. Самые нижние три слоя базируются на сети как таковой и иногда называ- ются слоями среды. Физический слой определяет физический и электрический канал свя- зи, специфицируя, например, какие соединительные разъемы должны использоваться и
20.2. Инфракрасная связь 513 как данные должны представляться при помощи электрических сигналов. Слой инфор- мационного канала предназначен для того, чтобы обеспечить надежный поток данных, он охватывает такие виды активности, как контроль и коррекцию ошибок. Слой сети поме- щает данные в контекст сети, он охватывает такие виды активности, как адресация узлов. Все верхние слои модели OSI реализуются программно. Это обычно происходит в хост- компьютере, а сами упомянутые слои иногда называют хост-слоями. Названную про- граммную реализацию иногда называют "'стеком протокола". Для данного протокола и аппаратной среды он может поставляться в форме стандартного программного пакета. Разработчику, адаптирующему стек протокола, может понадобиться сформировать интерфейс с ним снизу, обеспечив физические взаимосоединения, а также сверху, обес- печив программный интерфейс с приложением. Эта модель формирует среду, в которой могут определяться новые протоколы, а также определяться точки отсчета, полезные при изучении других, уже имеющихся про- токолов. На практике маловероятно, чтобы один какой-либо протокол мог быть постав- лен в соответствие каждому слою модели OSI, вероятнее всего, что он будет соответст- вовать OSI только приблизительно. Целый ряд сетевых протоколов и средств организации взаимосоединений будут рас- смотрены в подразделе, который следует далее. Для реализации какого-либо из этих про- токолов, конечно же, потребуются соответствующие физические и программные системы. Мы рассмотрим некоторые варианты их реализации, сфокусировав свое внимание на дос- тупных аппаратных подсистемах и доступных программных драйверах. 20.2. Инфракрасная связь Мы используем инфракрасный (IR) информационный обмен уже на протяжении мно- гих лет — наиболее широкое распространение он получил сначала в форме таких приме- нений, как пульты дистанционного управления телевизорами. Инфракрасные сигналы легко генерируются и распознаются с использованием недорогих полупроводниковых устройств. Вследствие того, что эти сигналы лежат за пределами видимого спектра, отно- сительно нетрудно использовать оптические фильтры, полностью исключающие видимый свет и, следовательно, исключающие интерференцию. Отличительной чертой всех инфракрасных линий связи является то, что информа- ционный обмен выполняется в них при помощи модулированного пучка света. Таким образом, такая линия должна формироваться в пределах расстояния прямой видимости. В общем случае инфракрасные линии связи работают на коротких дистанциях, а инфор- мационный обмен выполняется между двумя устройствами. В данной простой характе- ристике инфракрасных линий связи заключен целый ряд интересных преимуществ, а также недостатков. Вследствие того, что эти линии являются направленными и локаль- ными, риск интерференции невелик и безопасность канала связи находится на высоком уровне. Однако, поскольку инфракрасная связь осуществляется только в диапазоне пря- мой видимости, возможность формирования с ее помощью более широких сетей является ограниченной. Инфракрасная связь может быть очень недорогой, кроме того у нее есть такое преимущество, как отсутствие регулирования со стороны закона. В то время как первые применения инфракрасной связи, в основном, были в области управления — как в случае телевизионных пультов дистанционного управления — одна- ко было ясно, что инфракрасная связь хорошо подходит для информационного обмена. Эта область стала быстроразвивающейся областью технологии, особенно для ситуаций, в ко- торых можно заменить один кабель в компьютере, например или при передаче данных от ручного устройства (типа персонального организатора или цифровой камеры), или при передаче данных между компьютером и принтером. Ассоциация Инфракрасного Информационного обмена (IrDA) — это группа изгото- вителей, которая определила ряд стандартов для инфракрасных линий связи, имеющих диапазон от простого управления до интенсивного информационного обмена.
514 Глава 20. Взаимные связи и сети 20.2.1. IrDA и микроконтроллеры PIC Инфракрасный информационный обмен — это естественная область активности для малых встроенных систем. Фирма Microchip предлагает несколько микросхем инфракрас- ных кодеров/декодеров. Их примером может быть микросхема МСР2122, разводка выво- дов которой показана на рис. 20.2. Она предназначена для формирования интерфейса ме- жду микроконтроллерами, с одной стороны, и инфракрасными передатчиками/приемни- ками, с другой стороны. При этом вывод TXIR может непосредственно управлять свето- диодом инфракрасного излучения, в то время как RXIR может подключаться к инфра- красному датчику. Требуются четыре соединения с хост- микроконтроллером: ТХ, RX, Reset (Сброс) и 16х Clock (Шестнадцатикратная тактовая частота). Линии ТХ и RX под- ключаются к USART хост-микроконтроллера, как это было описано в подразделе 10.10 Главы 10. Требуется также источник синхроимпульсов, работающий на частоте, которая в 16 раз превосходит требуемую частоту передачи данных. Он подключается к линии 16х Clock. Указанная частота может быть сгенерирована модулем ССР микроконтроллера. Вход Reset позволяет хост-микроконтроллеру привести данную микросхему в исходное состояние. 16х Clock Е На микроконтроллер USART ТХ Е RX Е □ VDD □ TXIR □ RXIR V На оптический передатчик и приемник VSS Е □ Сброс МСР2122 Рис. 20.2. Инфракрасный кодер/декодер МСР2122 фирмы Microchip Предыдущий параграф показал, что физическое подключение инфракрасного порта к микроконтроллеру PIC может быть очень простым. Начиная с этапа подключения, меж- ду двумя упомянутыми узлами может быть создана информационная связь. Ее обычным применением является реализация информационного обмена в соответствии со стандар- том IrDA. Рассмотрение деталей этого стандарта находится за пределами возможностей этой книги, однако оно может быть найдено в целом ряде рекомендаций по применению изделий фирмы Microchip. 20.3. Радиосвязь В то время как инфракрасная связь имеет ряд ярко выраженных преимуществ, во мно- гих случаях она демонстрирует значительные недостатки. На этом фоне радиолинии пред- ставляют очень большой интерес. Маломощная система радиосвязи может обеспечивать локальные связи и может выполнять информационный обмен через стены и другие (не- проводящие) преграды. Вместе с тем теперь уже нет зоны прямой видимости и возникает значительный риск интерференции между сетями, которые, возможно, работают поблизо- сти. Вообразите себе место, например холл гостиницы, заполненный людьми, имеющими коммуникационные устройства, использующие радиосвязь. Как избежать риска возникно- вения взаимных помех? В данном подразделе рассматриваются два возможных подхода. 20.3.1. Блутус (Bluetooth) Главный новый игрок на поле информационной радиосвязи — это Блутус, который ответил на вызовы информационной радиосвязи интересным способом. Разработка Блу- тус контролируется группой изготовителей электроники — Специальной Группой Изго- товителей, заинтересованных в Блутус. Блутус работает на частотах, лежащих между 2,402 и 2,480 ГГц — это полоса частот, первоначально зарезервированная в соответствии
20.3. Радиосвязь 515 с международным соглашением для индустриального, научного и медицинского (ISM) применения, однако теперь она также широко используется для создания локальных бес- проволочных сетей передачи данных. Блутус обеспечивает каналы связи между такими устройствами, как сотовые телефо- ны, компьютеры, цифровые камеры или наушники. Блутус имеет следующие отличитель- ные свойства: • маломощная радиолиния — потребляемая мощность около 1 мВт. Сравните с 3 Вт мобильного телефона; • типичный радиус действия равен 10 м; • скорость передачи данных, первоначально равная 1 Мбит/с, теперь возросла до 3 Мбит/с (версия Блутус 2.0); • одновременно могут связываться до восьми устройств; • используется скачкообразное переключение частоты с расширенным спектром, при этом передатчик изменяет свою частоту псевдо-случайным образом 1600 раз за одну секунду. Когда Блутус-устройства обнаруживают друг друга, они определяют автоматически, должны ли они взаимодействовать друг с другом, например через обмен данными. Этот процесс не требует какого-либо вмешательства пользователя. Каждое устройство имеет свой адрес и именно через адрес оно определяет, представляет ли для него интерес обна- руженное им другое Блутус-устройство. Блутус-системы, входя упомянутым способом в контакт между собой, формируют так называемую пиконет. Как только информационный обмен установлен, члены пиконет синхронизуют свои частоты так, чтобы оставаться в контакте друг с другом. Переключения в пиконет происходят синхронно. Для случаев мгно- венных коллизий имеется программное обеспечение, которое может обнаружить и анну- лировать разрушенные данные. В Блутус заключен значительный интеллектуальный потенциал, если говорить о спо- собе, которым он может автономно конфигурировать сеть и поддерживать высокие ско- рости передачи данных. Это, однако, делает его дорогостоящим и сложным для малых или простых систем. В силу этого сейчас мы рассмотрим альтернативу Блутус — Zigbee. Ему присущи некоторые свойства Блутус, но он значительно проще. 20.3.2. Стандарт Zigbee Zigbee — это один из самых последних стандартов, разработанный членами “Обще- ства Zigbee”. Этот стандарт черпает свое вдохновение из стандарта Блутус, однако имеет целью быть проще и дешевле в реализации, будучи менее требовательным к программной избыточности. Он также использует стандарт Низкоскоростной Беспроволочной Персо- нальной Локальной Сети — IEEE 802.15.4. Как и Блутус, этот стандарт использует по- лосу радиочастот ISM. Zigbee в особенности подходит для систем домашней автоматизации, а также некото- рых измерительных систем и систем управления, при этом он дает возможность использо- вать небольшие дешевые микроконтроллеры. Скорость информационного обмена явля- ется относительно небольшой, а потребление электроэнергии — минимальным. Имеется три типа узлов Zigbee: • Координатор Zigbee — каждая сеть имеет только один координатор — это наиболее мощный тип узла Zigbee. Он может осуществлять информационный обмен с другими сетями, а также сохранять информацию о своей сети. • Полнофункциональное устройство (FFD) — это устройство может передавать данные от других устройств, играя в силу этого роль маршрутизатора. • Устройство сниженной функциональности (RED) — это самое простое устройство. Оно может осуществлять информационный обмен с сетью, однако не может делать ничего другого.
516 Глава 20. Взаимные связи и сеги По мере снижения потенциальных возможностей устройства снижаются его потреб- ности в памяти и вычислительной мощности, а, следовательно, и его стоимость. Минимизация потребностей в электропитании стала возможной вследствие того, что подчиненные узлы большую часть своего времени проводят в состоянии бездействия. На короткий промежуток времени они активизируются только для того, чтобы подтвердить факт своего присутствия в сети. 20.3.3. Zigbee и микроконтроллеры PIC Zigbee — это развивающийся стандарт, который интересен сам по себе. Кроме того, он является естественным кандидатом на использование с микроконтроллерами PIC. Воз- можная физическая реализация узла Zigbee иллюстрируется на рис. 20.3. Рис. 20.3. Возможная PIC-базированная реализация узла Zigbee Радиоканал реализуется за счет использования приемо-передатчика радиосигналов на одной микросхеме, например Chipcon СС2420 Микроконтроллер взаимодействует с ним через линию SPI и несколько линий управ- ления. Фирма Microchip предлагает “стек протокола”, который может быть адаптирован для реализации протокола Zigbee. Он позволяет реализовать устройство-координатор Zigbee, а также устройство сниженной функциональности. 20.4. Локальная управляющая сеть (CAN) и локальная сеть взаимосоединений (LIN) Мы уже встречались в Главе 10 с тремя основными “рабочими лошадками” последо- вательного информационного обмена в мире встроенных систем — SPI, 12С и асинхронным информационным обменом. Это вполне успешные стандарты, однако, каждому из них присущи свои собственные ограничения. В особенности следует отметить, что ни один из них не предусматривает коррекцию ошибок. В этом подразделе рассматриваются два стан- дарта последовательной связи, которые были разработаны в расчете на очень специфиче- ские применения, в которых ключевым требованием является высокая надежность. 20.4.1. Локальная управляющая сеть (CAN) Концепция CAN была разработана как ответ на все возрастающие потребности в ин- формационном обмене для сред типа автомобильного оборудования. При наличии высокого уровня электромагнитных помех, широком диапазоне температур и влажности, эти среды вряд ли можно назвать доброжелательными для любых электрических сигналов и, конечно же, для каких-либо электронных устройств. При этом выдвигаются требования к очень высокой надежности процесса информационного обмена. Стандарты последовательного
20.4. Локальная управляющая сеть (CAN) и локальная сеть взаимосоединений (LIN) 517 информационного обмена, разработанные для мягких условий дома или офиса, оказались совершенно непригодными для автомобильных и иных подобных применений, поэтому возникла потребность в разработке нового стандарта. Первоначально CAN был разработан немецкой фирмой Bosch. Опа опубликовала версию 2.0 этого стандарта в 1991, а в 1993 эта версия была принята ISO (Международная Организация Стандартов) в качестве между- народного стандарта — ISO 11898. На момент написания этой киш и версия 2.0 могла быть загружена, например, с вебсайта фирмы Bosch. Стандарт CAN охватывает только два нижних слоя модели IS0/0S1, показанной на рис. 20.1, однако делая это, он использует в значительной степени революционный подход. При обеспечении очень высокого уровня безопасности данных, данный стандарт весьма сложен и мы не будем здесь вникать во все его детали. Данный стандарт обладает следую- щими основными чертами: • Информационный обмен является асинхронным полудуплексным с фиксированной (для данной системы) скоростью информационного обмена. Максимальная скорость информационного обмена равна 1 Мбит/с. • Конфигурация носит характер “равный с равным”, т.е. все узлы трактуются как рав- ноправные. Имеется, однако, механизм приоритетов. Схема “ведущий — подчинен- ный” не используется. • Логические значения на шине определяются как “доминантное” и “рецессивное”, при этом доминантное состояние подавляет рецессивное. Никакие иные требования к фи- зическим соединениям стандартом не определяются. • Доступ к шине носит гибкий характер. Поскольку все узлы являются равными, то любой из них может начать передачу сообщения. В случае попытки одновременного доступа со стороны нескольких узлов, используется оригинальная схема арбитража, не приводящая к потере времени или данных. В процессе арбитража используются приоритеты. • Может быть неограниченное количество узлов. • Узлы шины не имеют адресов, однако используют “фильтрацию сообщений” для то- го, чтобы определить, имеют ли к ним отношение данные, присутствующие на шине. • Данные передаются в виде фреймов, имеющих сложный формат. Фрейм начинается битами идентификации, на протяжении передачи которых может выполняться про- цесс арбитража. На каждый фрейм допускается использование восьми информацион- ных байтов. • Обеспечивается исключительно высокий уровень безопасности данных с исчерпыва- ющим контролем ошибок. Узел, который распознал свое сбойное состояние, может отключиться от шины. CAN очень широко сейчас используется в автомобильных средах. Рис. 20.4 показыва- ет блок-схему части гипотетической сети автомобиля. Каждый из показанных блоков отображает небольшую встроенную систему — радио, двери, сидения и т.д. Одну из этих подсистем, — подсистему двери мы уже встречали в начале книги, она показана на рис. 1.2. Все подсистемы объединены в сеть через шину CAN. Другая сеть, не показанная на рисунке, также подсоединена к модулю центрального управления. Она управляет переме- щением автомобиля, например, режимом двигателя, тормозами и трансмиссией. 20.4.2. CAN и микроконтроллер PIC До сих пор мы встречались с микроконтроллерами PIC, имевшими порты 12С и SP1, однако имеются и другие — со встроенными модулями CAN. Доступная в настоящее время версия модуля CAN от фирмы Microchip называется ECANTM, что расшифровывается как “Усовершенствованный модуль CAN”, что отличает его от более ранних модулей CAN фирмы Microchip. Примером микросхемы, включающей этот модуль, является микросхема PIC 18F2480. Ее спецификация содержит детальные сведения по модулю ECAN.
518 Глава 20. Взаимные связи и сети Рис. 20.4. Часть сети управления оборудованием автомобиля Модуль ECAN достаточно сложен, он реализует функции, начиная от буферизации данных, до форматирования их требуемым способом и контроля ошибок. Он имеет ряд регистров управления. Написание программы для его работы “с нуля” было бы чрезвычай- но длительным делом, поэтому Microchip поставляет набор программ на С, которые могут непосредственно использоваться для компоновки программ. Какой бы микроконтроллер не использовался, он должен подключаться к физической шине, удовлетворяя электрические требования соединений. Обычно это достигается при помощи специального интерфейса IC, примером которого может служить МСР2551 от фирмы Microchip. Разводка ее выводов показана на рис. 20.5. Использованная реализация шины CAN носит дифференциальный характер, соответствующие линии подключаются к выводам CANH и CANL. Внешний резистор, подключаемый к выводу Rs, управляет мак- симальной скоростью нарастания выходного напряжения, при этом более медленная ско- рость нарастания напряжения используется для минимизации электромагнитных помех. Микроконтроллер подключается через свой модуль ECAN к выводам RXD и TXD. 20.4.3. Локальная сеть взаимосоединений (LIN) В то время как CAN обеспечивает реализацию высоконадежного информационного обмена, он весьма сложен и дорог. Не все линии связи в автомобиле на самом деле требуют использования всех возможностей CAN. В силу этого был разработан стандарт LIN (Ло- кальная сеть взаимосоединений), призванный работать совместно с CAN. Данный стандарт контролируется консорциумом LIN. Впервые стандарт был опубликован в 1999, сейчас доступен LIN версии 2.0. Шина LIN предназначена для того, чтобы быть компактной и медленной, осуществляя информационный обмен, в основном, между интеллектуальными датчиками и исполни- тельными устройствами. Топология сети является фиксированной. Имеется один ведущий узел, а все остальные узлы являются подчиненными. Ведущий узел имеет большую вычис- лительную мощность. Подчиненные узлы должны располагать только очень ограниченной
20.4. Локальная управляющая сеть (CAN) и локальная сеть взаимосоединений (LIN) 519 вычислительной мощностью либо же они могут быть просто выполнены как специализи- рованные аппаратные средства. Это делает их потенциально очень недорогими. Интерес- ным способом минимизации расходов является использование в подчиненных узлах про- стых RC-генераторов, непрерывно взаимосинхронизующихся по мере обмена данными. Максимальная скорость информационного обмена является весьма средней и равна 20 Кбит/с. Ведущий узел инициализирует все операции передачи данных, при этом от- ветить ему может только один подчиненный узел. При этом отсутствует механизм, кото- рый мог бы справиться с ситуациями множественных одновременных попыток доступа к шине. Линия связи реализована как один провод, при этом соответствующая концепция иллюстрируется рис. 20.6. Как и на шине CAN, на шине LIN определяется рецессивное логическое состояние (логическая единица) и доминантное логическое состояние (логи- ческий ноль). TXD с □ Rs VSS С □ CANH VDD С □ CANL RXD С 3 VREF МСР2551 Рис. 20.5. Приемопередатчик CAN МСР2551 Рис. 20.6. Физический интерфейс LIN Фрейм данных LIN состоит из заголовка и ответа. Заголовок всегда формируется ве- дущим узлом, а ответ — одним подчиненным узлом. Скорость информационного обмена может выбираться в диапазоне от 1 до 20 Кбод. Заголовок состоит из: • поля прерывания, которое информирует подчиненные узлы о приходящем сообщении; • байта синхронизации, идущего на требуемой частоте, содержащего значение 55н, по которому подчиненные узлы калибруют свои собственные тактовые частоты; • идентификатора, который идентифицирует подчиненный узел или узлы, а также спе- цифицирует действие, которое должно быть выполнено. Ответом является сообщение, содержащее не более 8 байтов, которое размещается на шине только одним подчиненным узлом. За ним следует поле контрольной суммы. В бо- лее ранних версиях шины контролировались только информационные байты; в последней же версии контролируется также идентификатор. Имеется два состояния шины: состояние бездействия и активное состояние. Узлы входят в состояние бездействия по истечении периода таймаута и могут быть реактиви- рованы фреймом активирования. Интересно, что стандарт LIN охватывает также программные элементы. LIN API (При- кладной Интерфейс Программиста) обеспечивает набор стандартных вызовов функций С, которые и реализуют всю функциональность LIN. Это облегчает разработку программ- ного обеспечения и последующую его отладку.
520 Глава 20. Взаимные связи и сеш Для многих сред шина LIN может быть спроектирована для взаимодействия с систе- мами, использующими шину CAN. Возможная LIN/CAN система показана на рис. 20.7. Ее центральным пунктом является микроконтроллер, например 18F2480, который реали- зует как функцию поддержки CAN, так и USART. Показанный на рисунке микрокот рол- лер работает как ведущее устройство LIN, а также как равноправный узел шины CAN. Рис. 20.7. Коммуникационная система, использующая шины CAN и LIN 20.4.4. UN и микроконтроллер PIC Все, что нужно для аппаратной реализации ведущего либо подчиненного узла LIN — это микроконтроллер с функцией USART и шинный интерфейс IC. Примером может служить микросхема МСР201 от фирмы Microchip, показанная на рис. 20.8. RXD С О □ FAULT/SLPS CS/WAKE С □ VBAT VREG С □ LIN TXD Е □ VSS МСР201 Рис. 20.8. Пример микросхемы интерфейса МСР201 Она осуществляет буферизацию, показанную на рис. 20.6. Соединение выполняется между USART хост-микроконтроллера и штырьками RXD и TXD МСР201. Напряжение питания на микросхему МСР201 подается через штырек VBAT. В микросхеме имеется внутренний стабилизатор напряжения и микросхема МСР201 способна подавать напряже- ние электропитания через штырек VREG на хост-микроконтроллер. Штырек Fault/SLPS используется как для индикации ошибки, когда он работает как выход, так и для установки активного фронта сигнала данных. Линия LIN соединяется с шиной LIN. Полные техни- ческие данные этой микросхемы могут быть найдены в документации. Как и в случае с большинством других уже рассмотренных нами стандартов, Microchip опубликовала примеры программ, которые могут служить отправной точкой для разра- ботки прикладных программ. В документации на драйвер, совместимый с LIN 2.0 и исполь- зующийся в микроконтроллерах семейства PIC18, приведен программный код как для ве- дущего, так и для подчиненного узла для последней на данный момент времени версии шины (версия 2.0).
20.5. Встроенные системы и Internet 521 20.5. Встроенные системы и Internet Излишне говорить о том, что за последние десять лет Internet оказала огромное влия- ние на обмен информацией в мировом масштабе. Интерес данной книги в значительной степени связан с малыми встроенными системами, в то же самое время обычно Internet рассматривается как нечто, подключаемое к настольным персональным компьютерам. Имеют ли малые встроенные системы и Internet нечто общее между собой? Для некоторых ответ может прозвучать неожиданно: конечно же! Является возможным подключить малую встроенную систему к Internet и, следовательно, подключить к сети устройства, находящиеся под контролем встроенной системы. Как только связь будет установлена, она может быть использована для многих вещей: например, для проверки состояния или выпол- нения управления, либо даже для выгрузки данных или программ. Примеры могут вклю- чать стиральную машину, которая способна сигнализировать в ремонтную мастерскую об угрозе отказа, торговый автомат, сообщающий в ш таб-квартиру компании о том, что он пуст, изготовителя, который может загрузить новую версию программного обеспечения в уже установленную охранную систему или, наконец, владельца дома, который может, например, либо еще из офиса включить отопительную систему, либо проверить, закрыта ли дверь гаража. При осуществлении информационного обмена через Internet используется целый набор протоколов, которые коллективно все вместе называются по имени наиболее важного из них — TCP/IP (Протокол Управления Передачей/Протокол Internet). Пример стека прото- кола Internet показан на рис. 20.9. Связь стека с моделью ISO/OSI на рисунке также отра- жена. Прикладной слой Транспортный слой Протокол передачи файлов Система доменного имени Протокол передачи гипертекста Протокол контроля передачи Протокол передачи управляющих сообщений Internet Слой сети Слой информаци- онного канала .............. ..................... V,....,? Протокол прямой рвя V I'*- Internet Рис. 20.9. Стек протокола Internet 20.5.1. Подключение к Internet при помощи микроконтроллера PIC Протокол Internet — это наиболее сложный из всех протоколов, которые упоминались в этой главе. Microchip, однако, обеспечивает хорошую поддержку для оборудования, ко- торое в терминах Рекомендаций по применению называется “демонстрационным обору- дованием” (плата PICDEM.net™) и, что очень важно, модульному стеку TCP/IP. Это прог- раммное обеспечение написано на С и предназначено для микроконтроллеров семейства 18. Оно может быть выгружено с вебсайта Microchip. Большим преимуществом является то, что у пользователя нет необходимости вникать в топкие детали протокола. Стек фор- мирует набор утилит, обслуживающих требования протокола TCP/IP, формируя эквивалент рис. 20.9. Он несет ответственность как за пользовательские программы, так и на внеш- них подключениях. Стек имеет объем, примерно равный 20 Кбайт. Для того чтобы хорошо освоить подключение микроконтроллеров PIC к Internet, реко- мендуется использовать плату PICDEM.net и/или сопровождающую ее документацию. 20.6. Заключение В предыдущих 19 главах мы изучили довольно много материала. Начав почти с нуля, мы постепенно изучили сложную картину структуры микроконтроллера. Мы программи-
522 Глава 20. Взаимные связи и сети ровали работу микроконтроллера как на Ассемблере, так и на С, организуя его взаимодей- ствие с целым рядом датчиков и исполнительных устройств, а также связывая его с другим микроконтроллером, который, в свою очередь, был связан с другим микроконтроллером, формируя, тем самым, небольшую сеть. Мы адаптировали наши программы под операци- онную систему реального времени. Мы успешно запитали все наши аппаратные средства от небольшой аккумуляторной батареи. Все взятое вместе представляет собой значитель- ное достижение и если вы следовали всем рекомендациям, приведенным в данной книге, то вы поступали правильно. В данной последней главе были описаны некоторые возмож- ные направления вашей дальнейшей деятельности. Автор надеется, что вам понравилось это развивающее путешествие в мир встроенных систем, он желает вам успехов, когда вы перейдете к разработке, формированию и прог- раммированию многих “разумных вещей” по своему усмотрению. Резюме • Современные системы предъявляют высокие требования в отношении информаци- онного обмена и формирования сетей. Характеристики выбранной сети должны соот- ветствовать требованиям приложения. Учет необходимой гибкости, надежности, лег- кости в использовании, скорости информационного обмена, потребляемой мощности и стоимости также является весьма важными факторами. • Встроенные системы часто, однако не всегда, нуждаются в использовании низкоско- ростных коммуникационных систем, обеспечивающих информационный обмен с не- большими объемами данных. Высокая надежность является существенно важным фак- тором в целом ряде ситуаций. • Традиционно взаимные связи имеют электрическую природу, однако возможно исполь- зование и иных методов, которые часто имеют преимущества перед чисто электричес- кими. В их состав входит инфракрасная и радиосвязь. • В некоторых ситуациях встроенные системы нуждаются в доступе к малым и локаль- ным сетям, а в других — к большим сетям, включая Internet. • Малые сети могут быть специализированными и фиксированными, как сети LIN, или же они могут быть гибкими и, возможно, временными, как сети Блутус или Zigbee. • Очень высокая надежность, сопряженная с некоторой сложностью, обеспечивается в сетях CAN. • Фирма Microchip обеспечивает поддержку реализации целого диапазона сетей и взаи- мосоединений в форме микросхем микроконтроллеров со специализированными ком- муникационными модулями, схемными рекомендациями и бесплатно публикуемым программным обеспечением.
ПРИЛОЖЕНИЕ 1. НАБОР КОМАНД МИКРОКОНТРОЛЛЕРОВ PIC® 16 Табл. А1.1. Набор команд микроконтроллеров PIC 16 Мнемоника, операнды Описание Циклы 14-разрядный код операции Влияние на флаги Прим. MSb LSb Байт-ориентироваиные операции с файловым регистром ADDWF f,d Сложение W и f 1 00 0111 dfff ffff C,DC,Z 1,2 ANDWF f,d Логическое умножение W на f 1 00 0101 dfff ffff Z 1,2 CLRF f Обнуление f 1 00 0001 Ifff ffff Z 2 CLRW Обнуление W 1 00 0001 Oxxx xxxx Z COMF f,d Дополнение f 1 00 1001 dfff ffff Z 1,2 DECF f,d Декремент f 1 00 0011 dfff ffff z 1,2 DECFSZ f,d Декремент f с пропуском следующей команды, если 0 1(2) 00 1011 ffff ffff 1,2,3 INCF f,d Инкремент f 1 00 1010 dfff ffff z 1,2 INCFSZ f,d Инкремент f с пропуском следующей команды, если 0 1(2) 00 1111 dfff ffff 1,2,3 IORWF f,d Логическое сложение W с f 1 00 0100 dfff ffff z 1,2 MOVF f,d Запись в f 1 00 1000 dfff ffff z 1,2 MOVWF f Запись из W в f 1 00 0000 Ifff ffff NOP Нет операции 1 00 0000 OxxO 0000 RLF f,d Циклический сдвиг f влево через флаг переноса 1 00 1101 dfff ffff c 1,2 RRF f,d Циклический сдвиг f вправо через флаг переноса 1 00 1100 dfff ffff c 1,2 SUBWF f,d Вычитание W и f 1 00 0010 dfff ffff C,DC,Z 1,2 SWAPF f,d Перестановка местами полубайтов в f 1 00 1110 dfff ffff 1,2 XORWF f,d Исключающее “ИЛИ” для W и f 1 00 0110 dfff ffff Z 1,2 Бит-орнентированные операции с файловым регистром BCF f,b Обнуление бита в f 1 01 OObb bfff ffff U BSF f,b Установка бита в f 1 01 Olbb bfff ffff U BTFSC f,b Проверка бита в f, пропуск команды, если равен 0 1(2) 01 lObb bfff ffff 3 BTFSS f,b Проверка бита в f, пропуск команды, если равен 1 1(2) 01 llbb bfff ffff 3 Операции с константами и управляющие команды ADDLW k Сложение константы с W 1 11 lllx kkkk kkkk C,DC,Z ANDLW k Логическое умножение константы на W 1 11 1001 kkkk kkkk Z CALL k Вызов подпрограммы 2 10 Okkk kkkk kkkk CLRWDT - Обнуление сторожевого таймера 1 00 0000 0110 0100 TO, PD GOTO k Переход по адресу 2 10 Ikkk kkkk kkkk IORLW k Логическое сложение константы с W 1 11 1000 kkkk kkkk Z MOVLW k Запись константы в W 1 11 OOxx kkkk kkkk RETFIE - Возврат из прерывания 2 00 0000 0000 1001 RETLW k Возврат с константой в W 2 11 Olxx kkkk kkkk RETURN - Возврат из подпрограммы 2 00 0000 0000 1000 SLEEP Переход в режим ожидания 1 00 0000 0110 0011 TO, PD SUBLW k Вычитание W из константы 1 11 HOx kkkk kkkk C,DC,Z XORLW k Исключающее “ИЛИ” для константы и W 1 11 1010 kkkk kkkk Z Примечания. 1. Когда регистр ввода-вывода модифицируется согласно одной из своих функций (например, MOVF PORTB, 1), используемое значение будет соответствовать представленному на самих выводах. Например, если для вывода, сконфигурированного как вход со срабатыванием по низкому уровню сигнала от внешнего устройства, считана “ 1 ”, то данные будут записаны в виде “0s’. 2. Если эта команда выполняется над регистром TMR0 (и где применимо условие d = 1), то предварительный делитель, назначенный модулю TimerO, будет обнулен. 3. Если модифицирован счетчик команд или выполняется условие проверки, то команда требует два цикла. Второй цикл выполняется как команда NOP.
ПРИЛОЖЕНИЕ 2. ЭЛЕКТРОННЫЙ НАСТОЛЬНЫЙ ТЕННИС Эта небольшая встроенная система представляет собой игру для двух игроков, каждый из которых оснащен “кнопкой-ракеткой”. Любой из игроков может начать игру, нажав свою кноп- ку. Мяч, представляемый линейкой из восьми светодиодов, летит на половину противника, который должен нажать свою кнопку только в тот момент, когда включится последний свето- диод с его стороны — ни мгновением раньше. Мяч сохраняется в игре до тех пор, пока один из игроков не нарушит правила. Как только это случится, игроку, не нарушившему правила, начис- ляется очко, на что указывает кратковременное включение соответствующего светодиода. Си- туация, когда мяч находится вне игры, также индицируется с помощью отдельного светодиода. Фотография устройства в собранном виде показана на рис. 1.3, а его схема соединений — на рис. А2.1. Код программы представлен в листинге А2.1. Рис. А2.1. Схема соединений электронного настольного тенниса
Разработка встроенных систем с помощью микроконтроллеров PIC. Принципы и практические примеры 525 Листинг А2.1. Программа электронного настольного тенниса /ЭЛЕКТРОННЫЙ НАСТОЛЬНЫЙ ТЕННИС! /Эта программа управляет игрой "Настольный теннис". /Фиксированная скорость, один режим игры. /TJW 21.06.01 /Частота генератора - примерно 800 кГц (RC-генератор) /Порт А 4 правая "ракетка" (ip) / 3 левая "ракетка" (ip) / 2 Светодиод "Вне игры" (ор) / 1 Светодиод "Очко в пользу левого игрока" (ор) / 0 Светодиод "Очко в пользу правого игрока" (ор) /Port В 7-0 "игровые" светодиоды (все ор) /Слово конфигурации: RC-генератор, сторожевой таймер выкл., /таймер включения питания вкл., защита кода выкл., /прерывания не используются list p=16F84A /Определение регистров специального назначения status equ 03 porta equ 05 trisa equ 0 5 portb equ 0 6 trisb equ 06 t /Определение констант led_durn equ 20 /время на проход внутреннего цикла, т.е. /время свечения каждого светодиода /Определение ячеек памяти delcntrl equ 10 /используется в подпрограмме задержки на 5 мс delcntr2 equ 11 /используется в подпрограмме задержки на 500 мс led_posn equ 12 /хранит текущее положение мяча loop_cntr equ 13 /загружается значением led_durn для каждого /включения светодиода и постепенно уменьшается /до 0, после чего мяч продолжает двигаться org 00 goto start / **Состояние "Инициализация" / Инициализация start org 0010 /Выбор банка памяти 1 /Порт А согласно описанной выше с,<еме bsf status,5 movlw B'00011000' movwf trisa movlw 00 /Используются все разряды /Выбор банка 0 порта В movwf trisb bcf status,5 t ;**Состояние "Ожидание"** /Определение исходной схемы свечения светодиодов wait movlw 04 movwf porta movlw 00 /Включение светодиода "Вне игры"
526 Приложение 2. Электронный настольный теннис Листинг А2.1. Продолжение _____* ________________________________________ movwf portb ;Все "игровые" светодиоды отключены /Перед началом игры необходимо убедиться, что ни одна из кнопок не нажата btfss porta,4 /Правая кнопка нажата? goto wait /Если да, то ожидаем btfss porta,3 /Левая кнопка нажата? goto wait /Если да, то ожидаем / /Готовы к действию. Ожидаем нажатия кнопки waitl btfss porta,4 /Правая кнопка нажата? goto r_to_l /Если да, то начинаем игру btfss porta,3 /Левая кнопка нажата? goto l_to_r /Если да, то начинаем игру goto waitl f /**Состояние "Справа налево"** /Игра началась r_to_l movlw 00 /Отключаем светодиод "Вне игры" movwf porta /Переходим movlw 80 movwf led_posn сюда каждый раз, когда /Определяем стартовую позицию мяча необходимо сменить светодиод rtl_0 /Переходим movlw led_durn movwf loop_cntr movf led_posn,w movwf portb сюда n раз для каждого /Предустановленная длительность свечения /светодиода /Выводим новую позицию мяча светодиода, где n = led_durn. /Проверяем нарушение правил. Если мяч в начале или в конце, /то применяем специальные условия rtl_l btfss led_posn,7 /Мяч в начале? (т.е. позиция = 7) ? rtl_2 goto / Е ели btfss goto goto btfss rtl_2 /Если нет, то летит дальше да, все нормально, если правая кнопка нажата porta,3 /Левая кнопка нажата? rt_myscore /Если да, то начисляем очко rtlend led_posn,0 /Мяч в конце (т.е. позиция = 0) ? /Если мяч goto - в конце, rtl_3 /Если нет, то летит дальше , то левая кнопка может изменить направление его полета /Здесь - rtl_3 /В конце rtlend btfss porta,3 /Левая кнопка нажата? goto l_to_r /Если да, то изменяем направление - ;**выход из состояния** btfss porta,4 /Правая кнопка нажата? goto rt_yrscore /Если да, то засчитываем очко игроку слева goto rtlend ни стартовая, ни конечная позиция btfss porta,4 /Правая кнопка нажата? goto score_left /Если да, то начисляем очко btfss porta,3 /Левая кнопка нажата? goto rt_myscore /Если да, то начисляем очко каждого цикла организовываем задержку call delay5 deefsz loop_cntr /Декрементируем счетчик цикла. /Проверка, должен ли мяч двигаться дальше goto rtl_l /Здесь, если мяч двигается дальше bcf status,О
Разработка встроенных систем с помощью микроконтроллеров PIC. Принципы и практические примеры 527 Листинг А2.1. Продолжение rrf led_posn,1 btfsc status,0 / Мяч покинул конечную позицию? goto rtjnyscore / Если да, то игроку справа засчитывается очко goto rtl 0 /**Выход из состояния* * rt_myscore goto score right rt_yrscore goto score_left / **Состояние "Слева направо"** 1 to г movlw 00 Отключаем светодиод "Вне игры" movwf porta movlw 01 Определяем стартовую позицию мяча movwf led posn Itr 0 movlw led durn movwf loop_cntr / Определяем длительность t свечения светодиода /Проходим этот цикл "длительность" раз для каждой позиции мяча ltr_l movf led posn,w / Выводим новую позицию мяча movwf portb btf ss led_posn,0 / Мяч в начале (т.е. позиция =0)? goto ltr_2 ; Если нет, то продолжаем /Если да, то все нормально, если левая кнопка нажата ; (т.е. проверяем только правую кнопку) btf ss porta,4 / Правая кнопка нажата? goto lft_myscore / Если да, то зачисляем очко goto Itrend ltr_2 btf ss led_posn,7 / Мяч в конце (т.е. позиция = 7)? goto ltr_3 / Если нет, то продолжаем /Если мяч - в конце , то правая кнопка изменяет направление полета /если нажата левая кнопка, то зачисляем очко игроку справа btf ss porta,4 / Правая кнопка нажата? goto r_to_l / Если да, то изменяем направление btf ss porta,3 / Левая кнопка нажата? goto lft_yrscore / Если да, то зачисляем очко игроку справа goto Itrend /Здесь - ни начальная, ни конечная позиция ltr_3 btf ss porta,4 / Права кнопка нажата? goto lft_myscore / Если да, то зачисляем очко btf ss porta,3 / Левая кнопка нажата? goto lft_yrscore ; Если да, то зачисляем очко Itrend call delay5 decfsz loop_cntr /Декрементируем счетчик цикла. Проверяем, /должна ли произойти смена светодиода goto ltr_l /Мяч продолжает двигаться bcf status,0 /Обнуляем флаг переноса, поскольку rlf /выполняет циклический сдвиг через этот / флаг rlf led posn,1 btfsc status,0 /Мяч покинул конечную позицию? goto 1ft myscore /Если да, то засчитываем очко игроку слева goto ltr_0 /**Выход из состояния** 1ft myscore goto score left Ift_yrscore goto score_right
528 Приложение 2. Электронный настольный леннис Листинг А2Л. Окончание___________ ;**Состояние "Зачисление очка"** ;Зачисление очка игроку слева score_left movlw 00 ;Зачисление score_right movwf portb ;Все "игровые" светодиоды отключены bsf porta,1 call delay500 bcf porta,1 goto wait очка игроку справа movlw 00 movwf portb ;Bce "игровые" светодиоды отключены bsf porta,0 call delay500 bcf porta,0 goto wait ПОДПРОГРАММЫ ;Задержка delay5 примерно на 5 мс. Командный цикл - 5 мкс. movlw D'200' ;200 вызовов цикла, ;каждый длительностью 5 х 5 = 25 мкс movwf delcntrl dell nop ;5 циклов в этом цикле пор decfsz delcntrl,1 goto dell return ;Задержка delay500 del2 примерно на 500 мс - 100 вызовов delay5 movlw D'100' movwf delcntr2 call delay5 decfsz delcntr2,l goto de!2 return end
ПРИЛОЖЕНИЕ 3. ПОДРОБНОСТИ АППАРАТНОЙ РЕАЛИЗАЦИИ АУСМ DERBOT 6'ААА1к. Выключатель питания LP295O 100U.10V Вправо 2 12k .Шина «1 СЗ 820R импульс Правый Рптдеи 1/6’1 16F873A Ультразвуковой эхо-сигнал R4 24k R17 11k ICD2 conn. Двигатель правый •«5 * •: О 6 (пс) Диагностические светодиоды Ультразвуковой R171)k СоеДеиительный разъем питания Вспомогательный источник питания О Влево DERBOT TJW Rev. 10.2.06 1 мкФ ТЯП37-4 левый R15 Еп1 4 VLS Ini In3 Out1 Out3 0V OV 0V OV Out2 Out4 Ш2 In4 VOS En2 L293D ,0 V Правый микропереключатели SDA SCL 4 MHz г 91R Левый R14 100п .Оптрон! 1 [Левый ZVN4206 ZVN4206 TR1 TR2 Пьезо- зуммер Переключатель режима Отражательный оптический датчик типа ОРВ608А MCLR RAO RAI RA2 RA3 RA4 RA5 Vss 0 scl Osc2 RCO RC1 RC2 RC3 RB/ RB6 RB5 RB4 RB3 RB2 RBI RBO Vdd Vss RC7 RC6 RC5 RC4 ТР1 R16 10k Sk6 Рис. АЗЛ. Схема соединений устройства Derbot
530 Приложение 3. Подробности аппаратной реализации АУСМ Derbot Пулы управления Derbot Светодиодный/ЖК-дисплей. Тест. 22.06.05 Примечание. Можно использовать как светодиодный, так и ЖК-дисплей "° 8к2 RAO RB6 RAI RB5 RA2 RB4 RA3 RB3 RA4 RB2 RA5 RBI Oscl Vdd Osc2 Vss RCO RC7 RC1 RC6 RC2 RCS RC3 RC4 16F873A +5VO-* SCL о GPI/O Int. SDA О 100р 100п 7'22к Vdo Vss Vo DBO DB1 DB2 DB3 DB4 DB5 DB6 DB7 R/W Е RS 2*8 разрядов LCD Display Powertip PC 0802-A 4 1k2 Рис. A3.2. Схема соединений пульта управления для устройства Derbot
Разработка встроенных систем с помощью микроконтроллеров PIC. Принципы и практические примеры 531 Рис. АЗ.З. Устройство Derbot с установленным пультом управления (разъем пульта отсоединен, чтобы было видно устройство сопряженного разъема) Инкрементирующий шифратор углового положения в Derbot В Главе 8 рассматривается применение отражательного оптического датчика для соз- дания простого инкрементирующего шифратора углового положения. Были показаны три варианта: для 8, 16 и 32 циклов чередования черных и белых полос (рис. АЗЛ). Рис. А3.4. Шаблоны для инкрементирующего шифратора углового положения: 8 циклов, 16 циклов и 32 цикла Можно воспользоваться любым из них, однако в случае 32-циклового варианта следует очень внимательно следить за расстоянием между белым шаблоном и датчиком. Во всех образцах диаметр колеса составляет 56 мм, что соответствует длине окружности 176 мм.
532 Приложение 3. Подробности аппаратной реализации АУСМ Derbot Таким образом, белые шаблоны обеспечивают разрешение при движении в прямом на- правлении, соответственно, 176 / 8 = 22 мм; 176 /16=11 мм и 176 / 32 = 5,5 мм. Кроме того, если колесо вращается со скоростью п об/мин, то в случае использования 16-цикло- вого диска частота работы шифратора углового положения составляет 16 х и / 60. Согласно справочным данным для двигателя, задействованного в опытном образце системы Derbot (табл. А3.1 и табл. АЗ.2), скорость двигателей при питании 9 В составляет 210 об/мин. Таким образом, максимальная частота работы шифратора углового положения с 16-цикловым диском равна 16 х 210/ 60 = 56Гц. На практике скорость вращения авто- номного внутрисхемного двигателя с питанием 9 В составила 154 об/мин, что соответст- вует максимальной частоте работы шифратора 41 Гц. Тот факт, что скорость меньше зна- чения, предполагаемого для питания 9 В, в первую очередь объясняется падением напря- жения на микросхеме управления L293D. Табл. АЗЛ. Официальные данные для двигателя/редуктора MFA/Como типа 918D30112 — характеристики двигателя RE280/1 Рабочее напряжение Без нагрузки При максимальном КПД Коэффициент трансформации крутящего момента (г/см) Скорость (об/мин) Ток (А) Скорость (об/мин) Ток (А) Крутящий момент (г/см) Выход (Вт) кпд (%) 12В 8400 0,1 6300 0,3 25,0 1,62 45 100 Табл. А3.2. Официальные данные для двигателя/редуктора MFA/Como типа 918D30112 — изменение скорости для различных напряжений питания (редуктор 30.1) 6В 12 В 18 В 24 В 140 280 420 560
ПРИЛОЖЕНИЕ 4. ОСНОВНЫЕ СВЕДЕНИЯ ОБ АУСМ DERBOT В данном приложении изложены некоторые вводные сведения об автономно-управ- ляемом само движущемся механизме (АУСМ), поскольку они являются существенно важ- ными при разработке проектов с использованием устройства АУСМ Derbot. Перемещение и расположение колес Перед тем как говорить об оптимальном расположении колес в маленьком АУСМ, будет интересно сказать несколько слов о самодвижущихся механизмах, в окружении ко- торых мы живем. Можно сразу же отметить, что колеса — это не единственный вариант приведения механизма в движение — имеются также различные гусеничные и шагающие механизмы, однако в наших целях они либо слишком сложны, либо совершенно неэффек- тивны для применения. Наиболее обычная схема размещения колес, конечно же, исполь- зуется в автомобилях. В общем случае в них имеется два ведущих колеса — сзади, и два управляемых колеса — спереди. Такая схема дает очень высокую устойчивость, что явля- ется привлекательным свойством для средств перевозки людей. Она также дает среднюю, однако не выдающуюся, маневренность — вспомните, например, о трудностях парковки автомобиля в тесном месте. Из многих возможных конфигураций размещения колес для АУСМ Derbot была выб- рана очень популярная схема (рис. А4.1). Механизм опирается на три точки. Два задних колеса имеют независимый привод, а третье представляет собой ролик или ползунок. По- следний может быть заменен просто стабилизирующим литым выступом, однако в этом случае появляется тенденция к уводу механизма, поэтому этого решения лучше избегать. Центр тяжести находится сзади колес. Расстояние между центральными линиями колес обозначим переменной А. Преимуществом этой конфигурации является ее простота в соединении с чрезвычайно высокой маневренностью. Недостатком же — ограниченная устойчивость. При наличии только трех опорных точек механизм не так уж трудно перевернуть. Второй ролик может быть на противоположной стороне механизма — спереди колес. В этом случае, если меха- низм наклонится вперед, то его передняя часть будет также устойчива. Электромотор, редуктор и колеса В качестве привода АУСМ Derbot использует небольшие электромоторы постоянного тока. Шаговые моторы, которые могли бы быть альтернативой, потребляют больше элек- троэнергии и вследствие этого не применялись. Электромоторы постоянного тока в общем случае работают на оборотах, которые слишком высоки для целей нашего применения. Вследствие этого используется понижающий редуктор. Общая схема передачи движения изображена на рис. А4.2. В АУСМ использованы электромоторы, работающие с постоянной скоростью сот радиан/с, при коэффициенте понижения редуктора N и радиусе колеса г — это обеспечит перемещение АУСМ вперед с постоянной скоростью у, определяемой как: v = (com / N) х г (м/с)
534 Приложение 4. Основные сведения об АУСМ Derbot Рис. А4.1. Схема расположения колес АУСМ Derbot (а) (Ь) Колесо Рис. А4.2. Передача движения от электромотора через редуктор на колесо Геометрия поворота Обобщенная схема выполнения поворота АУСМ Derbot, за счет вращения колес с разными скоростями, показана на рис. А4.3. Как видно из рисунка, колеса проходят различ- ные расстояния, при этом левое колесо проходит расстояние dL, а правое — Jr. Результа- том этого является то, что АУСМ движется по дуге окружности радиуса R с центром в точ- ке О. Он поворачивается на угол 0. Поскольку d[_ и Jr являются переменными величинами, которые могут контролироваться ведущими колесами, полезно будет связать с ними ос- тальные переменные. Рис. А4.3. АУСМ Derbot разворачивается на угол 0 (конечная позиция ползунка не показана)
Разработка встроенных систем с помощью микроконтроллеров PIC. Принципы и практические примеры 535 Поскольку противолежащие углы дуг dt и dR являются одинаковыми, то можно запи- сать: dL/(R + А / 2) = dR/(R - А / 2) = 0 откуда: dL(R-A/2) = dR(R + А/2) и, наконец: R = (A/2) ((dL + dR)/(dL — dR)) Кроме того, зная что 0 = dL/(R + А/2) и подставив значение R, получим: 0 = (dL — dR) / А Кроме того, если рассмотреть треугольник OTS, то можно видеть, что расстояние, пройденное “вперед” от точки отсчета координат — Xf будет равно 7?sin0. В этом повороте имеются два особых случая, которые иллюстрируются на рис. А4.4. Один из них связан с тем, что поворачивается только одно колесо и при этом АУСМ пово- рачивается приблизительно вокруг другого колеса. Для поворота на 90 dL должна быть равна лА/2, a dR будет равным нулю. Приближение возникает по причине ассиметрии массы АУСМ относительно центра поворота и сопротивления ползунка, которое может вызвать некоторый перекос. На рисунке показан поворот на 90 , хотя в итоге может быть реализован любой другой угол. (а) (Ь) Рис. А4.4. АУСМ Derbot, поворачивающийся на 90°: (а) — поворот вокруг одного колеса; (Ь) — поворот на месте — колеса вращаются одинаково (конечная позиция шасси и ползунка в обоих случаях не показана) Вторым специальным случаем поворота, показанным на рисунке А4.4 (Ь), является слу- чай, когда оба колеса вращаются с одинаковой скоростью в противоположных направле- ниях. Опять-таки, может иметь место некоторый перекос. В этом случае АУСМ теорети- чески вращается вокруг точки, находящейся посередине между колесами, при этом dr = -dR. В текущей реализации АУСМ Derbot расстояние А равно 16 см. Для поворота на месте на 180 , R = 0, a dL = -dR = лА/2 = 25,1 см (для АУСМ Derbot). Одометрия Одометрия — это методика замера расстояния, пройденного механизмом, посредством измерения числа оборотов колес. Устройство кодирования угла поворота вала, описанное в Приложении 3, способно замерять угол поворота колеса. Зная размеры колес, нетрудно вычислить фактически пройденное расстояние. Это простой и достаточно точный метод.
536 Приложение 4. Основные сведения об АУСМ Derbot Однако он не принимает во внимание пробуксовку колеса, неточности размеров колес или любые другие неточности в измерительной цепочке. Одометрия может быть использована как для замеров при движении вперед, так и для управления поворотами, как было описа- но выше. В Приложении 3 было вычислено, что длина окружности колеса АУСМ Derbot равна 176,0 мм. При применении 16-ти секторного кодирующего круга, использованного в са- модельном устройстве кодирования угла поворота вала, каждый результирующий импульс соответствует перемещению АУСМ вперед на 11 мм. При использовании этих данных может осуществляться как управляемое движение вперед, так и управление поворотами. При отработке поворотов используются описанные выше формулы.
ПРИЛОЖЕНИЕ 5. НАБОР КОМАНД МИКРОКОНТРОЛЛЕРОВ PIC® 18 (НЕ РАСШИРЕННЫЙ) Табл. А5.1. Набор команд микроконтроллеров PIC 18 Мнемоника, операнды Описание Циклы Поразрядный код операции Влияние на флаги Прим. MSb LSb Байт-ориентироваппые операции с файловым регистром ADDWF f, d, a Сложение WREG и f 1 0010 Olda ffff ffff C, DC, Z, OV, N 1,2 ADDWFC f, d, a Сложение WREG и флага переноса с f 1 0010 00da ffff ffff C, DC, Z, OV, N 1,2 ANDWF f, d, a Логическое умножение WREG на f 1 0001 Olda ffff ffff Z,N 1,2 CLRF f, a Обнуление f 1 оно 101a ffff ffff Z 2 COMF f, d, a Дополнение f 1 0001 llda ffff ffff Z,N 13 CPFSEQ f, a Сравнение f с WREG, пропуск команды, если = 1 (2 или 3) оно 001a ffff ffff Her 4 CPFSGT f, a Сравнение f с WREG, пропуск команды, если > 1 (2 нли 3) оно 010a ffff ffff Нет 4 CPFSLT f, a Сравнение f с WREG, пропуск команды, если < 1 (2 или 3) оно 000a ffff ffff Нет 1,2 DECF f, d, a Декремент f 1 0000 Olda ffff ffff C, DC, Z, OV, N 133,4 DECFSZ f, d, a Декремент f, пропуск команды, если 0 1 (2 или 3) 0010 llda ffff ffff Нет 13,3,4 DCFSNZ f, d, a Декремент f, пропуск команды, если не 0 1 (2 или 3) 0100 llda ffff ffff Нет 13 INCF f, d, a Инкремент f 1 0010 lOda ffff ffff C, DC, Z, OV, N 1,23,4 INCFSZ f, d, a Инкремент f, пропуск команды, если 0 1 (2 нли 3) ООН llda ffff ffff Her 4 INFSNZ f, d, a Инкремент f, пропуск команды, если нс 0 1 (2 или 3) 0100 lOda ffff ffff Her 13 IORWF f, d, a Лоптчсскос сложение WREG с f 1 0001 OOda ffff ffff Z,N 1,2 MOVF f, d, a Запись в f 1 0101 OOda ffff ffff Z,N I MOVFF fs, fa Запись fs (источник) в fj (приемник). Первое слово 2 1100 ffff ffff ffff Her Второе слово 1111 ffff ffff ffff Her MOVWF f, a Запись WREG в f 1 оно Illa ffff ffff Her MULWF f, a Перемножение WREG с f 1 0000 001a ffff ffff Her NEGF f, a Инверсирование f 1 оно 110a ffff ffff C,DC,Z,OV,N 13 RLCF f, d, a Циклический сдвиг f влево через флаг переноса 1 ООН Olda ffff ffff C,Z,N RLNCF f, d, a Циклический сдвиг f влево (без флага переноса) 1 0100 Olda ffff ffff Z,N 1,2 RRCF f, d, a Циклический сдвиг f вправо через флаг переноса 1 ООН OOda ffff ffff C, Z,N RRNCF f, d, a Циклический сдвиг ('вправо (без флага переноса) 1 0100 OOda ffff ffff Z,N SETF f, a Установка f 1 оно 100a ffff ffff Нет SUBFWB f, d, a Вычитание Гиз WREG с засмом 1 0101 Olda ffff ffff C, DC, Z, OV, N 1,2 SUBWF f, d, a Вычитание WREG из f 1 0101 llda ffff ffff C, DC, Z, OV, N SUBWFB f, d, a Вычитание WREG из f с заемом 1 0101 lOda ffff ffff C,DC,Z,OV,N 13 SWAPF f, d, a Перестановка местами полубайтов в f 1 ООН lOda ffff ffff Hot 4 TSTFSZ f, a Проверка f, пропуск следующей команды, если 0 1 (2 или 3) оно 011a ffff ffff Her 13 XORWF f, d, a Исключающее “ИЛИ” для WREG и f 1 0001 lOda ffff ffff Z,N Бит-ориеитировапиые one рации с файловым регистром BCF f, b, a Обнуление бита в f 1 1001 bbba ffff ffff Her 13 BSF f, b, a Установка бита в f 1 1000 bbba ffff ffff Her 1,2 BTFSC f, b, a Проверка бита в f, пропуск команды, если = 0 1(2 или 3) 1011 bbba ffff ffff Her 3,4 BTFSS f, b, a Проверка бита в f, пропуск команды, если = 1 1(2 или 3) 1010 bbba ffff ffff Her 3,4 BTG f, d, a Инвертирование бита в f 1 0111 bbba ffff ffff Her 13 Управляющие команды вс n Переход, если перенос 1(2) 1110 0010 nnnn nnnn Нет BN n Переход, если озрицатсльный результат 1(2) 1110 0110 nnnn nnnn Her BNC n Переход, если нет переноса 1(2) 1110 0011 nnnn nnnn Her BNN n Переход, если нс отрицательный результат 1(2) 1110 0111 nnnn nnnn Her BNOV n Переход, если нет переполнения 1(2) 1110 0101 nnnn nnnn Her BNZ n Переход, если не 0 2 1110 0001 nnnn nnnn Her BOV n Переход, если переполнение 1(2) 1110 0100 nnnn nnnn Нет BRA n Безусловный переход 1(2) 1101 Onnn nnnn nnnn Нет BZ n Переход, если 0 1(2) 1110 0000 nnnn nnnn Нел CALL n, s Вызов подпрограммы. Первое слово 2 1110 110s kkkk kkkk Нет Второе слово 1111 kkkk kkkk kkkk
538 Приложение 5. Набор команд микроконтроллеров PIC® 18 (не расширенный) Табл. А5.1. Окончание Мнемоника, операнды Описание Циклы 16-разрядпый код операции Влияние на флаги Прим. MSb LSb Управляющие команды CLRWDT - Обнуление сторожевого таймера 1 0000 0000 0000 0100 TO, PD DAW - Десятичная коррекция WREG 1 0000 0000 0000 0111 C GOTO n Переход i ю адресу. Первое слово. 2 1110 1111 kkkk kkkk Her Второе слово 1111 kkkk kkkk kkkk NOP - Нет операции 1 0000 0000 0000 0000 Her NOP - Her операции 1 1111 хххх ХХХХ xxxx Her 4 POP - Считывание с вершины стека 1 0000 0000 0000 0110 Her PUSH - Помещение в стек 1 0000 0000 0000 0101 Her RCALL n Относительный вызов 2 1101 lnnn nnnn nnnn Her RESET - Про1"раммный сброс устройства 1 0000 0000 1111 1111 Bee RETFIE s Разрешение возврата из прерывания 2 0000 0000 0001 000s GIE/GIEN, PEIE/GIEL RETLW k Выход с константой в WREG 2 0000 1100 kkkk kkkk Her RETURN s Выход из подпрограммы 2 0000 0000 0001 001s Her SLEEP - Переход в “спящий” режим 1 0000 0000 0000 0011 TO, PD Операции с константами ADDLW k Сложение константы с WREG 1 0000 1111 kkkk kkkk C, DC, Z, OV, N ANDLW k Логическое перемножение констан ты с WREG 1 0000 1011 kkkk kkkk Z,N IORLW k Логическое сложение константы с WREG 1 0000 1001 kkkk kkkk Z,N LFSR f.k Запись константы (12 бнт) Второе cj юво 2 1110 1110 OOff kkkk Нет в FSRx. Первое слово 1111 0000 kkkk kkkk MOVLB k Запись константы в BSR<3:0> 1 0000 0001 0000 kkkk Her MOVLW k Запись константы в WREG 1 0000 1110 kkkk kkkk Her MULLW k Перемножснне конст анты с WREG 1 0000 1101 kkkk kkkk Her RETLW k Возврат с константой в WREG 2 0000 1100 kkkk kkkk Her SUBLW k Вычитание константы из WREG 1 0000 1000 kkkk kkkk C, DC, Z, OV, N XORLW k Исключающее “ИЛИ” для константы и WREG 1 0000 1010 kkkk kkkk Z,N Операции обмена между памятью данных и памятью программ TBLRD* Табличное чтение 2 0000 0000 0000 1000 Her TBLRD*+ Табличное чтение с пост пнкрсментом 0000 0000 0000 1001 Her TBLRD*- Табличное ч тение с постдскрсмснтом 0000 0000 0000 1010 Hci TBLRD+* Табличное чтение с прсинкрсмснтом 0000 0000 0000 1011 Her TBLWT* Табличная запись 2(5) 0000 0000 0000 1100 Her TBLWT*+ Табличная запись с пост инкремен том 0000 0000 0000 1101 Her TBLWT*- Табличная запись с постдскрсмснтом 0000 0000 0000 1110 Her TBLWT+* Табличная запись с прсинкрсмснтом 0000 0000 0000 1111 Her Примечания. 1. Когда регистр PORT модифицируется согласно одной из своих функций (например, movf portb, 1, 0), использован- ное значение будет соответствовать представленному на самих выводах. Например, если для вывода, сконфигуриро- ванного как вход со срабатыванием по низкому уровню сигнала от внешнего устройства, считана “1”, то данные будуг записаны в виде “0”. 2. Если эта команда выполняется над регистром TMR0 (и где применимо условие d = 1), то предварительный делитель (если он назначен) будет обнулен. 3. Если модифицирован счетчик команд или выполняется условие проверки, то команда требует два цикла. Второй цикл выполняется как команда NOP. 4. Некоторые команды занимают два слова. В таком случае второе слово выполняется как nop, если только первое сло- во команды не извлекает информацию, записанную в эти 16 разрядов. Это гарантирует, что каждая ячейка памяти программ содержит корректную команду. 5. Если начинается цикл табличной записи во внутреннюю память, то процесс записи будет продолжаться до тех пор, пока не будет прерван. Табл. А5.2. Условные обозначения в кодах операций Символ Описание (значения, принятые в ассемблере MPLAB по умолчанию, подчеркнуты) a Бит доступа к оперативной памяти: а = 0 — ячейка памяти в Access RAM; а = 1 — банк памяти, заданный регистром BSR (Bank Select Register) b Номер разряда в байте d Бит выбора адресата: d = 0 — результат сохраняется в регистре W; d — 1_ — результат сохраняется в файловом регистре (т.е. в ячейке памяти данных) f 8-разрядный адрес ячейки в памяти данных fd 12-разрядный адрес ячейки в памяти данных, адрес приемника при перемещении данных
Разработка встроенных систем с помощью микроконтроллеров PIC. Принципы и практические примеры 539 Табл. А5.2. Окончание Символ Описание (значения, принятые в ассемблере MPLAB по умолчанию, подчеркнуты) fs 12-разрядный адрес ячейки в памяти данных, адрес источника при перемещении данных к Литеральное значение, константа или метка (8, 12 или 20 разрядов) п Относительный адрес (с дополнением до двух) для команд относительного перехода или прямой адресации в командах Call и Return S Бит быстрого выбора режима вызова подпрограммы или выхода из подпрограммы: s = 0— не выполнять обновления данных в теневых регистров (или данными из теневых регистров); s = 1 — выполнить обновление регистров W, Status и BSR данными из теневых регистров (или теневых регистров данными из регистров W, Status и BSR)
ПРИЛОЖЕНИЕ 6. ОСНОВЫ ЯЗЫКА С Это приложение содержит обобщенную информацию об основных аспектах языка программирования С. Примеры использования и объяснение большинства из этих средств можно найти в Главах 14-19. Табл. А6.1. Ключевые слова, имеющие отношение к типам данных и определениям сгруюур Слово Обобщенное описание Слово Обобщенное описание char Отдельный символ (обычно 8 бит) signed Квалификатор, применяемый со словами char или int (квалификатор по умолчанию для этих слов) const Немодифицируемые данные sizeof Возвращает размер заданного элемента (переменной, выражения или массива) в байтах double Число с плавающей запятой двойной точности struct Позволяет определять структуры данных enum Определяет переменные, которые могут принимать только определенные целочисленные значения typedef Создает новое имя для существующего типа данных float Число с плавающей запятой одинарной точности union Блок памяти, используемый совместно двумя или большим числом переменных или любым типом данных int Целое число unsigned Квалификатор, применяемый со словами char или int (квалификатор по умолчанию для этих слов — signed) long Расширенное целое значение. Если используется отдельно, подразумевается целое число void Отсутствие значения или типа short Короткое целое значение. Если используется отдельно, подразумевается целое число volatile Переменная, которая может быть изменена факторами, отличными от программного кода Табл. А6.2. Ключевые слова, имеющие отношение к управлению выполнением программы Слово Обобщенное описание Слово Обобщенное описание break Принудительный выход из цикла for Определяет цикл, повторяемый до тех пор, пока выполняется условие цикла case Определяет варианты выбора внутри оператора switch goto Переход к указанной метке continue Позволяет программе сразу перейти в конец оператора for, while или do if Начало условного оператора. Если условие возвращает значение true, то выполняется соответствующий блок операторов default Определяет вариант по умолчанию в операторе switch на тот случай, если не было найдено ни одного соответствия return Возврат в вызывающую подпрограмму, что также приводит к возврату любых данных, заданных функцией do Используется совместно со словом while для организации цикла, в котором оператор, следующий после do, повторяется до тех пор, пока выражение после while дает значение true switch Используется совместно со словом case для выбора из нескольких альтернатив. После этого слова указывают выражение, результат которого оценивается со значениями, указанными в ветках case else Используется совместно со словом if. Расположено перед оператором, который выполняется в том случае, если условное выражение не дает значения true while Определяет цикл, который выполняется до тех пор, пока условное выражение дает значение true
Разработка встроенных систем с помощью микроконтроллеров PIC. Принципы и практические примеры 541 Табл. А6.3. Ключевые слова, имеющие отношение к классу хранения данных Слово Обобщенное описание Слово Обобщенное описание auto Переменная существует только внутри блока, в котором она определена. Это — класс по умолчанию register Переменная должна сохраняться в регистре ЦП. Таким образом, оператор адреса & не действует extern Объявляет данные, определенные где-то в другом месте s tatic Объявляет переменную, существующую на протяжении всего выполнения программы. Размещение ее объявления влияет на то, в какой части программы к ней можно обращаться Табл. А6.4. Типы данных С, поддерживаемых компилятором MPLAB С18 С Тип данных Описание Длина (в байтах) Диапазон значений char Символ 1 -128..+ 127 signed char Символ -128..+ 127 unsigned char Символ 1 0..255 int Целое число 2 -32768..+32767 unsigned int Целое число 2 0..65 535 short Целое число 2 -32768..+32767 unsigned short Целое число 2 0..65 535 short long Целое число 3 -8 388 608..8 388 607 unsigned short long Целое число 3 0..16 777215 long Целое число 4 -2 147 483 648..2 147 483 647 unsigned long Целое число 4 0..4 294 967 295 float Число с плавающей запятой 4 1,1 7549 х 10-38..6,80565 х ю+38 double Число с плавающей запятой, двойная точность 4 1,1 7549 х 10-38..6.80565 х Ю+38 Табл. А6.5. Операторы С Приоритетность и порядок выполнения Операция Сим- вол Приоритетность и порядок выполнения Операция Сим- вол Скобки и оператор доступа к элементам массива 1, слева направо Вызов функции О 1, слева направо Указатель на поле X->Y 1, слева направо Индексы [] 1, слева направо Выбор поля X.Y Арифметические 4, слева направо Сложение X+Y 3, слева направо Умножение X*Y 4, слева направо Вычитание X-Y 3, слева направо Деление XfY 2, справа налево Унарный плюс +Х 3, слева направо Модуль % 2, справа налево Унарный минус -X Сравнения 6, слева направо Больше X>Y 6, слева направо Меньше или равно X<=Y 6, слева направо Больше или равно X>=Y 7, слева направо Равно X==Y 6, слева направо Меньше X<Y 7, слева направо Не равно X!=Y Логические 11, слева направо “И” (1, если X и Y не равны 0) X&&Y 2, справа налево “НЕ”(1, если Х=0) !X 12, слева направо “ИЛИ” (1, если X или Y не равно 0) Х| |Y Поразрядные 8, слева направо Побитовое“И” X&Y 2, слева направо Дополнение до единицы (побитовое “НЕ”) ~X
542 Приложение 6. Основы языка С Табл. А6.5. Окончание Приоритетность и порядок выполнения Операция Сим- вол Приоритетность и порядок выполнения Операция Сим- вол 10, слева направо Побитовое “ИЛИ” Х|У 5, слева направо Сдвиг вправо. X сдвигается вправо Y раз X»Y 9, слева направо Побитовое исключающее “ИЛИ” ХЛУ 5, слева направо Сдвиг влево. X сдвигается влево Y раз X«Y Присваивания 14, справа налево Присваивание Х=У 14, справа налево Побитовое “И” с присваиванием X&=Y 14, справа налево Сложение с присваиванием Х+=У 14, справа налево Побитовое “ИЛИ” с присваиванием X|=Y 14, справа налево Вычитание с присваиванием Х-=У 14, справа налево Побитовое исключающее “ИЛИ” с присваиванием X~=Y 14, справа налево Умножение с присваиванием Х*=У 14, справа налево Сдвиг вправо с присваиванием X»=Y 14, справа налево Деление с присваиванием Х/=У 14, справа налево Сдвиг влево с присваиванием X«Y 14, справа налево Вычисление остатка с присваиванием Х%=У Операторы инкрементирования и декрементирования 2, справа налево Преинкремент ++Х 2, справа налево Пост-инкремент X++ 2, справа налево Предекремент —X 2, справа налево Пост-декремент X— Условные операторы 13, справа налево Оценка: X (если Z^O) или Y (если Z=0) Z?X:Y 15, слева направо Оценка вначале X, а затем — Y X,Y Операторы "интерпретации данных" 2, справа налево Объект или функция, на которые указывает X *х 2, справа налево Адрес X &X 2, справа налево Приведение типа для значения X скалярного типа (тип)Х 2, справа налево Размер X в байтах Sizeof X Табл. А6.6. Директивы препроцессора Директива Обобщенное описание Директива Обобщенное описание* #if Используется для условной компиляции кода на основании оценки связанного выражения. Должна заканчиваться директивой #endif #define Определяет строковые константы, используемые в исходном коде, которые подставляются до компиляции строки программы #ifdef Аналогична #if, однако проверяет, был ли определен заданный символ. Заканчивается директивой #endif #error Генерирует определенное пользователем сообщение об ошибке #i fndef Идентична #ifdef, однако проверяет, не был ли определен заданный символ #include Включает в позиции своего размещения весь текст из заданного файла, который может содержать неограниченный объем С-кода, который компилируется вместе с исходной программой #else Используется совместно с #if для обеспечения альтернативного раздела для компиляции #line Позволяет пользователю задать номер строки внутри кода
Разработка встроенных систем с помощью микроконтроллеров PIC. Принципы и практические примеры 543 Табл. А6.6. Окончание Директива Обобщенное описание Директива Обобщенное описание #elif Используется внутри раздела # i f для проверки нового выражения #pragma Позволяет передать препроцессору дополнительную директивную информацию (обычно — специфическую для компилятора) #endif Заканчивает раздел #if #unde f Выполняет действие, обратное директиве # de fine, для заданной строковой константы Табл. А6.7. Некоторые варианты применения знаков препинания Символ Применение Пример Окончание метки loop : Используется в отделении битовых полей (см. также таб... А6.5) unsigned RBO:1; Окончание оператора или объявления unsigned RBO:1; Используется для обозначения поля структуры (см. та 'же табл. А6.5) PORTAbits.RA2 = 1; \ Следующая строка является продолжением текущей - {) Определяют блок кода - Табл. А6.8. Дополнительные квалификаторы памяти MPLAB С18 ||(И1111|1М ram far Переменная может размещаться в любом месте памяти программ Переменная может размешаться в любом месте памяти данных. Необходим доступ к команде переключения банков. Комбинация по умолчанию — far и ram near Переменная — в памяти программ с адресом < 64К Переменная — в памяти Access RAM Табл. А6.9. Модели памяти MPLAB С18 Модель памяти Размер указателя Квалификатор ROM по умолчанию Объем памяти small (по умолчанию) 16 бит near Память программ < 64К large 24 бита far Память программ > 64К