Текст
                    ИЗДАНИЕ
2 ИЗДАНИЕ
на языке
ЛД для AVRnPIC
I v-и микроконтроллеров

Программирование на языке С для AVR и PIC микроконтроллеров Издание 2-е, переработанное и дополненное Киев, “МК-Пресс” СПб, “КОРОНА-ВЕК" 2011
ББК 32.973-04 Ш83 УДК 004.312 Ш83 Программирование на языке С для AVR и PIC микроконтролле- ров. Изд. 2-е, переработанное и дополненное./ Сост. Ю.А. Шпак — К.: “МК-Пресс”, СПб.: “КОРОНА-ВЕК”, 2011. —544 с., ил. ISBN 978-5-7931-0842-3 (“КОРОНА-ВЕК”) ISBN 978-966-8806-67-4 (“МК-Пресс”) В книге рассмотрено программирование на языке С микроконтроллеров AVR с использованием компиляторов WinAVR и CodeVisionAVR, а также микрокон- троллеров PIC с использованием компиляторов CCS-PICC, mikroC и С30/32. Крат- ко рассмотрена архитектура и аппаратное обеспечение как традиционных вось- миразрядных микроконтроллеров AVR и PIC, так и новых семейств ATxmega, PIC24 и PIC32. Дано описание средств программной разработки, включая эмуля- цию программ с помощью AVR Studio и MPLAB. Кратко рассмотрен стандартный синтаксис языка С и директивы препроцессора, а также особенности программи- рования на этом языке для микроконтроллеров. Книга содержит программные примеры на С, а также — справочник с описанием системы ассемблерных команд микроконтроллеров AVR (включая ATxmega) и PIC (включая PIC24). ББК 32.973-04 Программирование на языке С для AVR и PIC микроконтроллеров Издание 2-е, переработанное и дополненное Подписано в печать 06.08.2010. Формат 70 х 100 1/16. Бумага газетная. Печать офсетная. Усл. печ. л. 44,1. Уч.-изд. л. 28,6. Тираж 1000 экз. Заказ 350 СПД Савченко Л.А., Украина, г.Киев, тел./ф.: (044) 362-04-38; e-mail: info@mk-press.com. Свидетельство о внесении субъекта издательского дела в Государственный реестр издателей, производителей и распространителей издательской продукции: серия ДК №51582 от 28.11.2003г. ISBN 978-5-7931-0842-3 (“КОРОНА-ВЕК”) ISBN 978-966-8806-67-4 (“МК-Пресс”) ©“МК-Пресс”, 2011
Краткое оглавление 3 Краткое оглавление Часть I. Архитектура микроконтроллеров AVR.......................15 Глава 1. Восьмиразрядные микроконтроллеры AVR....................16 Глава 2. Семейство AVR ATxmega...................................97 Часть II. Компиляторы и средства разработки для МИКРОКОНТРОЛЛЕРОВ AVR.......................................... 140 Глава 3. Компилятор WinAVR.................................... 141 Глава 4. Среда разработки AVR Studio............................146 Глава 5. Среда разработки CodeVisionAVR.........................158 Глава 6. Программаторы для микроконтроллеров AVR................175 Часть III. Архитектура микроконтроллеров PIC....................184 Глава 7. Восьмиразрядные микроконтроллеры PIC...................185 Глава 8. Семейство PIC18F.......................................219 Глава 9. Семейство PIC24........................................231 Глава 10. Семейство PIC32.......................................248 Часть IV. Компиляторы и средства разработки для микроконтроллеров PIC...........................................260 Глава 11. Компилятор CCS-PICC................................. 261 Глава 12. Эмуляция и отладка программ в среде MPLAB.............275 Глава 13. Компилятор mikroC.....................................282 Глава 14. Компиляторы СЗО и С32.................................294 Глава 15. Программаторы для микроконтроллеров PIC...............297 ЧАСТЬ V. ЯЗЫК С И ДИРЕКТИВЫ ПРЕПРОЦЕССОРА.......................302 Глава 16. Основы языка С........................................303 Глава 17. Функции и макросы языка С для различных компиляторов..361 Часть VI. Программные примеры для микроконтроллеров AVR............412 Глава 18. Примеры для компилятора WinAVR...........................413 Глава 19. Примеры для компилятора CodeVisionAVR....................430 Часть VII. Программные примеры для микроконтроллеров PIC...........435 Глава 20. Примеры для компилятора CCS-PICC......................436 Глава 21. Примеры для компилятора mikroC...........................446 Глава 22. Примеры для компилятора СЗО..............................453 Глава 23. Примеры для компилятора С32...........................470 Часть VIII. Приложения.............................................477 Приложение А. Таблица символов ASCII...............................478 Приложение Б. Преобразование из одной системы счисления в другую...479 Приложение В. Система команд микроконтроллеров AVR.................482 Приложение Г. Система команд микроконтроллеров PIC.................498 Приложение Д. Область ввода/вывода микроконтроллеров AVR ATxmega А.519
4 Содержание Предисловие ко 2чиу изданию.........................13 Введение............................................14 ЧАСТЬ I. АРХИТЕКТУРА МИКРОКОНТРОЛЛЕРОВ AVR 15 Глава 1. Восьмиразрядные микроконтроллеры AVR.......................16 Семейства восьмиразрядных микроконтроллеров AVR..................18 Отладочная плата.................................................19 Платы STK500 и STK600......................................... 19 Схема базового монтажа...........................................21 Структура микроконтроллеров AVR..................................22 Организация памяти.............................................22 Память SRAM.................................................23 Память программ.............................................33 Память данных типа EEPROM.................................. 34 Порты..........................................................36 Подтягивающее сопротивление.................................37 Регистры управления портом..................................39 Таймеры/счетчики...............................................39 T/C0........................................................40 T/C1........................................................41 T/C2....'...................................................47 Сторожевой таймер..............................................48 Обработка прерываний...........................................49 Управление прерываниями.....................................52 Сброс..........................................................54 “Спящие”режимы процессора......................................55 Последовательный ввод/вывод....................................56 Приемопередатчик UART.......................................57 Приемопередатчик USART......................................60 Синхронная передача данных по интерфейсу SPI................65 Работа приемопередатчика USART в режиме SPI.................69 Синхронная передача данных по интерфейсу I2C (TWI)..........70 Универсальный последовательный интерфейс US1................75 Модули последовательного ввода/вывода в семействах AT90S, ATtiny и ATmega....................................................79 Аналого-цифровое преобразование................................80 Встроенный аналоговый компаратор...............................86 Программирование памяти..........................................87 Разряды предохранения..........................................89 Параллельное программирование................................ 89 Переход в режим параллельного программирования..............91 Очистка кристалла...........................................91 Программирование и чтение памяти программ...................92 Программирование разрядов блокировки и предохранения........93 Последовательное программирование..............................93 Технология picoPower.............................................96
Содержание 5 Глава 2. Семейство AVR ATxmega....................................97 Обзор возможностей микроконтроллеров ATxmega а..................97 Организация памяти семейства ATxmega............................99 Область ввода/вывода семейства ATxmega......................100 Арбитраж шины данных........................................100 Память программ,............................................101 Контроллер прямого доступа к памяти............................102 Система обработки событий......................................109 Генерирование событий вручную...............................114 Фильтрация..................................................114 Квадратурный дешифратор.....................................115 Система синхронизации..........................................117 Выбор источника тактового сигнала системной синхронизации...120 Счетчики реального времени.....................................122 Счетчик RTC............................................... 123 Счетчик RTC32...............................................123 Модуль питания от батареи......................................123 Обработка прерываний...........................................124 Немаскируемые прерывания....................................125 Регистр управления контроллером прерываний..................125 Аналого-цифровое преобразование................................126 Конфигурирование АЦП........................................127 Выбор разрешения преобразования...........................127 Выбор очередности преобразований в каналах................127 Выбор режима измерения....................................127 Выбор опорного напряжения.................................129 Выбор коэффициента деления частоты тактирования...........130 Результаты измерения........................................130 Прерывание от АЦП...........................................130 ЦИФРО-АНАЛОГОВОЕ ПРЕОБРАЗОВАНИЕ............................... 131 Начало преобразования.......................................132 Ограничения на время преобразования.........................133 АНАЛОГОВЫЙ КОМПАРАТОР......................................... 134 Режимы работы компаратора...................................135 Средства шифрования............................................136 Модуль шифрования AES.......................................137 Модуль обмена данными по инфракрасному каналу..................138 ЧАСТЬ II. КОМПИЛЯТОРЫ И СРЕДСТВА РАЗРАБОТКИ ДЛЯ МИКРОКОНТРОЛЛЕРОВ AVR 140 Глава 3. Компилятор WinAVR................................141 Глава 4. Среда разработки AVR Studio......................146 Эмуляция................................................148 Окно Memory.............................................151 Окно Register............................................152 Окно Watch..............................................152 Отладка программы.......................................152
6 НАСТРОЙКА ПАРАМЕТРОВ ИМИТАТОРА...........................153 Создание проекта и компиляция программы..................153 Компиляция проекта.....................................156 Глава 5. Среда разработки CodeVisionAVR....................158 КОМПИЛЯЦИЯ И ПОСТРОЕНИЕ ПРОЕКТА..........................159 Создание проекта с помощью мастера CodeWizardAVR.........164 Сохранение и открытие проекта CodeWizardAVR............171 Создание новых файлов с исходным кодом...................172 Отладка программы........................................173 Использование терминала................................174 Глава 6. Программаторы для микроконтроллеров AVR...........175 Программные средства для программирования микроконтроллеров.179 Программирование устройства в среде A VR Studio 4......179 Программирование устройства в среде CodeVisionAVR......181 ЧАСТЬ III. АРХИТЕКТУРА МИКРОКОНТРОЛЛЕРОВ PIC 184 Гдава 7. Восьмиразрядные микроконтроллеры PIC.....................185 Общие аспекты архитектуры восьмиразрядных МИКРОКОНТРОЛЛЕРОВ PIC....................................... 186 Организация памяти...........................................186 Организация тактирования.....................................188 Порты........................................................190 Таймеры......................................................192 TMR0 и сторожевой таймер...................................192 TMR1.......................................................194 TMR2.......................................................195 Модуль ССР.................................................197 Обработка прерываний.........................................198 Микроконтроллеры серии Р1С17Сх.............................199 Микроконтроллеры серии Р1С18Сх.............................200 Сброс........................................................202 Последовательный обмен данными...............................202 Приемопередатчик USART.....................................203 Синхронная передача данных по интерфейсу SPI...............204 Синхронная передача данных по интерфейсу 12С...............206 Аналого-цифровое преобразование..............................207 Встроенный аналоговый компаратор...........................209 Семейство микроконтроллеров PIC16...............................210 Микроконтроллер 16F84A.......................................211 Регистр состояния.............................,............212 Организация памяти.........................................213 Слово конфигурации.........................................215 Память EEPROM..............................................215 Микроконтроллеры серии 12F50X...................................216
Содержание 7 Глава 8. Семейство PIC18F.........................................219 Организация памяти..............................................221 Конфигурационные регистры....................................222 Организация тактирования........................................225 Внутренний осциллятор........................................226 Переключение источника тактирования...................................................... 226 Таймеры.........................................................227 TMR0.........................................................227 TMR1.........................................................228 TMR3.........................................................228 АЦП:............................................................229 Обработка прерываний............................................229 Глава 9. Семейство PIC24..........................................231 Порты...........................................................234 Таймеры.........................................................236 Прерывания......................................................236 Вложение прерываний..........................................238 Системные прерывания.........................................239 Окно Program Space Visibility...................................239 Интерфейс SPI...................................................240 ПортРМР.........................................................241 АЦП.............................................................241 МОДУЛЬ CTMU.....................................................244 Измерение заряда конденсатора................................245 Измерение времени............................................245 Формирование импульсных последовательностей и задержек.......246 Глава 10. Семейство PIC32.........................................248 Порты...........................................................250 Таймеры.........................................................251 Системная шина..................................................251 Организация памяти..............................................252 Прерывания и исключения.........................................254 Система тактирования............................................258 Интерфейс SPI...................................................258 ПортРМР.........................................................258 АЦП.............................................................259 Модуль сравнения на выходе......................................259 ЧАСТЬ IV. КОМПИЛЯТОРЫ И СРЕДСТВА РАЗРАБОТКИ ДЛЯ МИКРОКОНТРОЛЛЕРОВ PIC 260 Глава 11. Компилятор CCS-PICC...............................261 Создание проектов CCS-PICC вручную........................261 Создание проектов CCS-PICC с помощью PIC wizard..........265 Создание проектов CCS-PICC с помощью PIC24 Wizard.........271 Открытие и добавление в проект файлов с исходным кодом....272 КОМПИЛЯЦИЯ ПРОЕКТА.......................................272
8 Меню Tools..............................................274 Глава 12. Эмуляция и отладка программ в среде MPLAB.......275 Рабочая область и проект MPLAB..........................276 Компиляция под управлением MPLAB........................277 Настройка режима отладки/эмуляции.......................277 Работа в режиме отладки/эмуляции........................279 ОКНА ОТЛАДЧИКА........................................ 280 Глава 13. Компилятор mikroC............................. 282 Создание проекта mikroC.................................283 Компиляция проекта......................................285 Добавление в проект файлов с исходным кодом.............287 Эмуляция выполнения программы...........................288 вспомогательные инструменты среды mikroC................290 Глава 14. Компиляторы СЗО и С32...........................294 Компилятор СЗО..........................................294 Компилятор С32..........................................296 Глава 15. Программаторы для микроконтроллеров PIC.........297 Программные средства для программирования микроконтроллеров.298 Программирование устройства в среде mikroC............300 ЧАСТЬ V. ЯЗЫК С И ДИРЕКТИВЫ ПРЕПРОЦЕССОРА 302 Глава 16. Основы языка С........................................303 Вводные понятия...............................................303 Структура программы на С......................................304 Типы данных, переменные, константы............................306 Правила преобразований из одной системы счисления в другую.308 Тип char...................................................309 Пользовательские типы......................................309 Переменные.................................................310 Область видимости переменных.............................310 Константы..................................................311 Перечислимые типы..........................................311 Приведение типов...........................................312 Оператор sizeof............................................312 Функции.......................................................312 Возвращаемые значения......................................313 Прототипы функций..........................................314 IGiaccbi памяти при объявлении локальных переменных........314 Рекурсия...................................................315 Структуры.....................................................316 Указатели и адреса переменных.................................318 Передача в функции параметров по ссылке....................318 Указатели на структуры.....................................319 МАССИВЫ И СТРОКИ..............................,...............320
Содержание 9 Строки.........................................................321 Многомерные массивы...................................>...... 321 Операторы ветвления...............................................321 Оператор if-else...............................................322 Условные выражения.............................................322 Оператор switch-case...........................................322 Циклические конструкции...........................................323 Конструкция while............................................ 323 Конструкция for.............................................. 324 Конструкция do-while...........................................324 Организация бесконечных циклов............................... 325 Операторы break и continue.....................................325 Стандартные функции ввода/вывода..................................325 Ввод/вывод символов с помощью функций getcharQ и putcharQ......326 Функции вывода строк puts 0 и printfO..........................327 Функции ввода строк gets 0 и scanfO.......................... 328 Директивы препроцессора...........................................329 Директива ^include.............................................329 Директива ^define..............................................329 Директивы условной компиляции............................,.....331 Директива tterror..............................................333 Директива ftpragma компилятора CodeVisionA VR..................333 Директивы, характерные для компилятора CCS-PICC................333 Директива #bit...............................................334 Директива #byte..............................................334 Директива #case..............................................334 Директива ^device............................................334 Директива #fiise.............................................335 Директива #locate............................................336 Директива #org...............................................336 Директива #opt...............................................337 Директива #priority..........................................337 Директива #reserve...........................................338 Директива #rdm...............................................338 Директива #type..............................................338 Директива #use delay........................................*338 Директива #use xxxio.........................................338 Директива #use i2c...........................................339 Директива #use rs232.........................................340 Директива #zero_ram..........................................341 Обработка прерываний..............................................341 Обработка прерываний в среде WinAVR............................341 Обработка прерываний в среде CodeVisionAVR.....................343 Обработка прерываний в среде CCS-PICC..........................343 Обработка прерываний в среде mikroC............................345 Обработка прерываний в среде С30............................... 345 Обработка прерываний в среде С32............................... 347 Исполнение ассемблерного кода.....................................353 Использование ассемблера в компиляторе WinAVR..................353
10 Ассемблерный код.............................................354 Входные и выходные операнды..................................355 Резервирование регистров.....................................356 Использование ассемблера в компиляторе CodeVisionAVR............358 Использование ассемблера в компиляторе CCS-PICC.................358 Использование ассемблера в компиляторе mikroC...................359 Использование ассемблера в компиляторах СЗО и С32...............360 Глава 17. Функции и макросы языка С для различных компиляторов. 361 Стандартные функции языка С.......................................361 Функции для работы со строками..................................363 Функции для работы с символами..................................365 Функции для работы со случайными числами........................367 Функции для работы с памятью....................................367 Функции и макросы компилятора WinAVR..............................368 Математические макросы и функции................................368 Функции для работы со строками..................................369 Функции для работы с символами..................................373 Макросы и функции для организации ввода/вывода..................373 Функции управления микроконтроллером............................378 Макросы для работы со сторожевым таймером.......................379 Функции для работы со случайными числами........................380 Функции для работы с памятью....................................380 Макросы для обработки прерываний................................381 Макросы и функции для работы с памятью EEPROM...................382 Функции и макросы компилятора CodeVisionAVR.......................383 Математические макросы и функции................................383 Функции для работы со строками................................................................. 384 Функции для работы с символами..................................387 Функции управления микроконтроллером............................387 Функции для организации ввода/вывода............................387 Функции для работы с памятью....................................388 Функции для работы с интерфейсом 12С............................389 Функции и макросы компилятора CCS-PICC............................389 Математические макросы..........................................389 Функции для работы со строками..................................390 Функции для организации ввода/вывода............................391 Функции управления микроконтроллерам............................394 Функции для работы с таймерами и модулем ССР....................396 Функции для работы с разрядами и памятью........................398 Функции для работы с памятью EEPROM.............................400 Функции для работы с интерфейсом SPI............................401 Функции для работы с интерфейсом PSP............................402 Функции для работы с интерфейсом fC........................... 402 Функции для работы с аналоговыми сигналами......................403 Функции компилятора mikroC........................................405 Математические функции..........................................405 Функции для работы со строками..................................405 Функции преобразований..........................................407 Функции управления микроконтроллером.......................... 407
Содержание 11 Функции для работы с периферийными устройствами.......408 Функции для работы с памятью EEPROM и Flash...........409 Функции для работы с интерфейсом 12С..................410 Функции для работы с интерфейсом SPI...................410 ЧАСТЬ VI. ПРОГРАММНЫЕ ПРИМЕРЫ ДЛЯ МИКРОКОНТРОЛЛЕРОВ AVR 412 Глава 18. Примеры для компилятора WinAVR.................413 Управление ЖК-дисплеем.................................413 GPS-навигатор..........................................418 Глава 19. Примеры для компилятора CodeVisionAVR..........430 Управление аналого-цифровым преобразованием............430 Измерение температуры..................................433 ЧАСТЬ VII. ПРОГРАММНЫЕ ПРИМЕРЫ ДЛЯ МИКРОКОНТРОЛЛЕРОВ PIC 435 Глава 20. Примеры для компилятора CCS-PICC.................436 Отображение состояния выводов порта.................... 436 Управление частотой мерцания светодиодов с помощью различных ТАЙМЕРОВ.................................................437 Управление светофорами на перекрестке....................438 Обмен данными в режиме PSP...............................442 Контроль предельной скорости вращения двигателя..........444 Глава 21. Примеры для компилятора mikroC...................446 Игральные “кости”........................................446 Вольтметр с ЖК-дисплеем..................................448 Калькулятор............................................ 450 Глава 22. Примеры для компилятора СЗО......................453 Использование порта РМР..................................453 Небольшая библиотека функций для доступа к ЖК-модулю...453 Расширенное управление ЖК-дисплеем.....................456 Работа с АЦП.............................................460 Считывание уровня напряжения с потенциометра...........461 Измерение температуры..................................465 Глава 23. Примеры для компилятора С32......................470 Работа с интерфейсом SPI.................................470 Работа с модулем UART....................................473 ЧАСТЬ VIII. ПРИЛОЖЕНИЯ 477 Приложение А. Таблица символов ASCH......................478 Приложение б. Преобразование из одной системы счисления в другую.................................................479
12 Приложение В. Система команд микроконтроллеров AVR..........482 Наличие команд в различных микроконтроллерах AVR..........495 Команды по категориям................................... 497 Приложение Г. Система команд микроконтроллеров PIC..........Д98 Команды восьмиразрядных микроконтроллеров.................498 Команды по категория*!..................................509 Система команд микроконтроллеров' PIC24...................510 Приложение Д. Область ввода/вывода микроконтроллеров AVR ATxmega а...............................................519 Список литературы.........................................532 Содержимое прилагаемого к книге компакт-диска.............533
Предисловие ко 2-му изданию 13 Предисловие ко 2-му изданию Второе издание книги “Программирование на языке С для AVR и PIC микро- контроллеров”, по сравнению с первым, претерпело ряд существенных изменений и дополнений: • в описании восьмиразрядной архитектуры микроконтроллеров AVR и PIC были учтены особенности современных устройств от компаний Atmel и Microchip; • рассмотрено новое семейство микроконтроллеров AVR ATxmega; • кратко затронуты основные аспекты новых технологий PIC24 и PIC32; • кроме компилятора WinAVR, для микроконтроллеров AVR рассмотрена среда разработки CodeVisionAVR; • дано описание современной версии среды разработки CCS-PICC; • кроме компилятора CCS-PICC, для микроконтроллеров PIC рассмотрена среда разработки mikroC, а также — новые компиляторы СЗО и С32, рассчитанные на 16-разрядную технологию PIC24 и 32-разрядную PIC32, соответственно; • кратко затронуты разновидности программаторов для AVR и PIC; • перечислены основные библиотечные функции и макроопределения языка С компиляторов WinAVR, CodeVisionAVR, CCS-PICC и mikroC; • даны примеры программ для всех рассмотренных в книге компиляторов; • рассмотрена система команд микроконтроллеров ATxmega и PIC24. Следует отметить, что с учетом критических отзывов, высказанных читателями в отношении примеров программ, представленных в первом издании книги, соста- вители постарались использовать проекты из достоверных источников. Со списком литературы, использованной в процессе работы над этим изданием, можно ознако- миться в конце книги. Кроме перечисленных первоисточников, в работе над мате- риалом также использовались официальные документы Atmel и Microchip.
14 Введение Однокристальные микроконтроллеры находят широкое применение в самых разнообразных сферах: от измерительных приборов, фотоаппаратов и видеокамер, принтеров, сканеров и копировальных аппаратов до изделий электронных развлече- ний и всевозможной домашней техники. Со времени появления первых микропроцессоров в 1970-х годах их сложность постоянно возрастала за счет появления новых аппаратных решений и добавления новых команд, предназначенных для решения новых задач. Так постепенно сложи- лась архитектура, получившая впоследствии название CISC (Complex Instruction Set Computers — компьютеры co сложным набором команд). В дальнейшем обозначи- лось и нашло активное развитие еще одно направление: архитектура RISC (Reduced Instruction Set Computers — компьютеры с сокращенным набором команд). Именно к этой архитектуре относятся микроконтроллеры AVR от компаний Atmel и PIC от компании Microchip, которым посвящена эта книга. На заре возникновения микропроцессоров разработка программного обеспече- ния происходила исключительно на том или ином языке ассемблера, ориентирован- ном на конкретное устройство. По сути, такие языки представляли собой символь- ные мнемоники соответствующих машинных кодов, а перевод мнемоники в машин- ный код выполнялся транслятором. Однако главный недостаток ассемблерных язы- ков заключается в том, что каждый из них привязан к конкретному типу устройств и логике его работы. Кроме того, ассемблер сложен в освоении, что требует доста- точно больших усилий для его изучения, которые, к тому же, оказываются потра- ченными впустую, если впоследствии потребуется перейти на использование мик- роконтроллеров других производителей. Язык С, являясь языком высокого уровня, лишен подобных недостатков и мо- жет использоваться для программирования любого микропроцессора, для которого есть компилятор с языка С. В языке С все низкоуровневые операции, выполняемые компьютерами, представлены в виде абстрактных конструкций, позволяющих раз- работчикам сосредоточиться на программировании одной лишь логики, не заботясь о машинном коде. Изучив язык С, можно легко переходить от одного семейства микроконтроллеров к другому, тратя гораздо меньше времени на разработку. В этой книге рассмотрены основы программирования на языке С микрокон- троллеров AVR с использованием компиляторов WinAVR и CodeVisionAVR, а так- же микроконтроллеров PIC с использованием компиляторов CCS-PICC, C3O/32 и mikroC. Надеемся, представленные здесь программные проекты помогут читателю быстро и легко освоить азы программирование микроконтроллеров для конкретных областей применения. Желаем успехов в освоении вселенной под названием “Программирование мик- роконтроллеров”. Надеемся, эта книга станет хорошим подспорьем в преодолении нелегкого пути проб и ошибок. Через тернии к звездам...
ЧАСТЬ I Архитектура микроконтроллеров AVR
Глава 1 Восьмиразрядные микроконтроллеры AVR Все восьмиразрядные микроконтроллеры AVR спроектированы для работы в составе очень производительной, маломощной архитектуры RISC. Микропроцес- соры первого поколения обладали жестко “прошитой” логикой декодирования ко- манд. В то время технология создания запоминающих устройств сильно “хромала” по сравнению с технологией изготовления процессоров, т.е. более скоростным про- цессорам приходилось долго ожидать считывания следующей команды для декоди- рования из медленнодействующего запоминающего устройства. Поэтому, с целью эффективного использования этого периода ожидания, возникла идея заполнить время до поступления следующей команды. В результате возникли команды, которые выполняли последовательно несколь- ко внутрипроцессорных операций до тех пор, пока не поступала следующая внеш- няя команда. Так появились процессоры CISC (Complex Instruction Set Computer — компьютер co сложным набором команд). Типичными представителями этой архи- тектуры процессоров являются семейства 80x86 и процессор Pentium компании Intel или семейства 680x0 компании Motorola. Практически все процессоры CISC работают по принципу микропрограммиро- вания, т.е. каждая машинная команда последовательно обрабатывается микропро- граммой, которая выполняется внутри кристалла процессора. Однако, если'взгля- нуть на существующие программы через призму статистики, то обнаружится, что из большого набора команд процессоров CISC (у некоторых типов — свыше 300) ис- пользуется только небольшая, постоянно повторяющаяся часть в размере около 20 процентов. В дополнение к этому, комплексную программу можно зачастую заме- нить несколькими эффективными командами, которые в состоянии справиться с поставленной задачей быстрее. Со временем изготовителям модулей памяти удалось резко-сократить время доступа, в результате чего в середине 1980-х годов произошел возврат “к истокам”, и была разработана архитектура RISC. Возникли компьютеры с сокращенным набо- ром команд, у которых команды, как и в процессорах первых поколений, снова де- кодировались посредством “жесткой прошивки”. Перечислим характерные особенности архитектуры RISC: • как следует из самого названия, самой примечательной особенностью является ограниченное количество эффективных команд; • отсутствие классического накапливающего сумматора в пользу большего числа равноправных рабочих регистров; • организация диапазонов памяти по Гарвардской модели; • единый интерфейс с запоминающими устройствами за счет исключительного применения команд вида “Загрузка/Сохранение”;
17 • обработка почти всех команд в течение единственного машинного такта; • оптимизация аппаратного обеспечения и набора команд с целью применения программирования на языках высокого уровня. Поначалу использование архитектуры RISC было ограничено мощными ком- пьютерами, выступающими в роли рабочих станций, однако вскоре были открыты преимущества этой архитектуры для однокристальных микроконтроллеров, что до- казывают устройства AVR компании Atmel. Представители семейства AVR обладают ограниченным набором высокоэффек- тивных команд (от 89 до 135, в зависимости от модели). Благодаря особой архитек- туре микропроцессоров AVR, исключен ярко выраженный недостаток обычных процессоров, у которых все арифметические и логические операции выполняются исключительно в так называемом накапливающем сумматоре. Вследствие этого, как правило, после завершения собственно вычислительных операций требуются опе- рации обращения к вспомогательным регистрам или промежуточным запоминаю- щим устройствам. У микроконтроллеров AVR этот недостаток отсутствует, по- скольку в вычислениях, кроме накапливающего сумматора, задействованы 32 рав- ноправных рабочих регистра, напрямую связанных с арифметико-логическим уст- ройством (АЛУ). Микроконтроллеры AVR работают по Гарвардской архитектуре, что подразу- мевает разделение памяти для программ и данных. Они используют одноступенча- тую конвейерную обработку. Это означает, что во время выполнения команды вы- полняется загрузка следующей команды из памяти программ (рис. 1.1). Благодаря этому, достигается возможность выполнения команды в течение одного тактового цикла. Рис. 1.1. Конвейерная обработка при выборке и выполнении команды в 8-разрядных микроконтроллерах AVR Первая команда программы выполняется на один тактовый цикл дольше, чем та же команда в другом месте программы, поскольку в этом случае выборка не может быть осуществлена параллельно с выполнением предыдущей команды. В микроконтроллерах AVR используются несколько команд загрузки/сохране- ния, с помощью которых к переменным и константам можно обратиться в различ- ных режимах адресации. У большинства обычных процессоров и контроллеров такт, сгенерированный кварцевым осциллятором, делится на заранее заданный коэффициент для получения собственно системного такта. Так, например, в контроллере 8051, работающем с частотой кварца 12 МГц, при внутреннем коэффициенте деления минимальное
18 Глава 1. Восьмиразрядные микроконтроллеры AVR время выполнения команд составляет всего лишь одну секунду, причем “минималь- ное время” в данном случае подразумевает, что для выполнения некоторого количе- ства команд потребуется больше времени. Однако в случае с микроконтроллерами AVR такого не происходит. В них действительно почти все команды выполняются в течение одного периода частоты кварцевого генератора, что, например, при мак- симально допустимой частоте 12 МГц означает всего лишь 83,33 нс. Другими сло- вами, достигается быстродействие до 12 MIPS (Million Instructions Per Second), т.е. 12 миллионов выполненных команд в течение одной секунды! И, за немногими исключениями, микроконтроллеры AVR действительно обрабатывают любую ко- манду в течение единственного системного такта. После того как в однокристальных микроконтроллерах для выполнения про- грамм все больше начали использоваться языки высокого уровня (прежде всего, язык программирования С), архитектура AVR была оптимизирована для эффектив- ного взаимодействия аппаратного и программного обеспечения, написанного на языках высокого уровня. К примеру, микроконтроллеры AVR специально для рабо- ты с указателями предоставляют в распоряжение программиста команды с функ- циями автоматического инкремента и декремента. Семейства восьмиразрядных микроконтроллеров AVR Компания Atmel предоставляет обширный набор восьмиразрядных микрокон- троллеров AVR, разбитых на несколько семейств в соответствии с их характеристи- ками и областью применения. Рассмотрим основные семейства: • AT90S — “классические” микроконтроллеры AVR, которые в данное время компанией Atmel для использования не рекомендуются, и заменимы другими, более современными устройствами: ► AT90S1200 и AT90S2313 — на ATtiny2313; ► AT90S2323 и AT90S2343 — на ATtiny25; ► AT90S4433 — на ATmega8; ► AT90S4414 и AT90S8515 — на ATmega8515; ► AT90S8535 — на ATmega8535; • ATtiny — привлекательные по цене микроконтроллеры с урезанным количест- вом каналов ввода-вывода и уменьшенной памятью, что позволяет снизить по- требление энергии и размеры корпуса; • ATmega — высокопроизводительные устройства с достаточным объемом памя- ти и набором каналов ввода-вывода, что позволяет применять йх в самых раз- нообразных сферах; • ATxmega — новое семейство микроконтроллеров AVR с расширенными ресур- сами и возможностями, наподобие контроллера прямого доступа к памяти, сис- темы обработки событий, высокоскоростных ЦАП и АЦП и др. Компания Atmel предоставляет и другие семейства микроконтроллеров AVR, ориентированные на какие-либо специфические задачи: применение в автомобилях, управление ЖК-дисплеями и осветительными приборами, организация подключе- ний по интерфейсу CAN и USB и др. Хотя все эти сферы, безусловно, интересны, рассмотрение подобных устройств выходит за тематические рамки данной главы, посвященной только общим архитектурным аспектам микроконтроллеров AVR. За дополнительной информации обращайтесь к специализированным изданиям или на Web-сайт компании Atmel (www. atmel. com).
Отладочная плата 19 В этой главе мы рассмотрим общие аспекты архитектуры семейств AT90S, АТ- tiny и AT mega, а в следующей — особенности нового семейства ATxmega микро- контроллеров AVR. Отладочная плата Сам по себе микроконтроллер ничего не может. Он требует определенной схе- мы базового монтажа, которая обычно состоит из кварцевого генератора и несколь- ких конденсаторов. Без этого микроконтроллер просто не начнет выполнять про- грамму, которую, впрочем, тоже необходимо каким-то образом в него записать. От- сюда возникает потребность в каком-либо программаторе — специальном адаптере для переноса исполняемого кода с компьютера в память микроконтроллера. Кроме того, если требуется использовать последовательный интерфейс, на арену выходит преобразователь логического уровня (например, МАХ232) и соответствующий разъем (например, RS232). Таким образом, у нас есть две возможности: • приобрести по отдельности все компоненты для базового монтажа и подключе- ния программатора и собрать все вручную; • обзавестись готовой отладочной платой, что гораздо проще. В типичную отладочную плату уже интегрирован интерфейс программирова- ния, несколько кнопок и светодиодов. Кроме того, такие платы зачастую реализуют какой-либо последовательный интерфейс. Платы STK500 и STK600 Компания Atmel предлагает хорошо продуманные, приемлемые по цене отла- дочные платы (например, STK500 и STK600) и множество дополнительных модулей расширения к ним. Так, плата STK500 (рис. 1.2) предоставляет: • разъемы для установки процессоров в корпусах DIP с числом выводов 8, 20, 28 и 40; • низковольтное программирование через интерфейс SPI (в том числе микрокон- троллеров, установленных во внешнем устройстве); • высоковольтное программирование (с доступом к любым разрядам конфигура- ции); • встроенный источник питания: вход — постоянное напряжение 10.. 15 В; 0,5 А; выход — устанавливается из среды программирования (по умолчанию — 5 В); • встроенный источник опорного напряжения; • тактовый генератор, частота которого устанавливается из среды программиро- вания (до 3,68 МГц) или внешним кварцевым резонатором; • формирователь сигналов интерфейса RS232; • восемь кнопок и светодиодов; • связь с ПК по интерфейсу RS232. Вместе с платой поставляются кабели для подключения. Все порты процессо- ров, кнопки и светодиоды выведены на разъемы и могут быть соединены в произ- вольном порядке. Плата STK500 поддерживает все микроконтроллеры AVR се-
20 Глава 1. Восьмиразрядные микроконтроллеры AVR мейств ATtiny и ATmega, кроме ATmega 103. Возможно программирование любых микроконтроллеров AVR, установленных во внешнем устройстве. Рис. 1.2. Отладочная плата STK500 Возможности новой отладочной платы STK.600 (рис. 1.3) гораздо шире: • стабилизированный источник питания с программно управляемым выходным напряжением; • преобразователи уровней сигналов RS232, LIN и CAN; • разъемы интерфейсов USB (Device), mini-USB (host), RS-232, CAN; • программно управляемый источник опорного напряжения; • восемь кнопок и светодиодов; • источник тактовых сигналов с регулируемой частотой до 32 МГц; • связь с ПК п<? интерфейсу USB. Рис. 1.3. Отладочная плата STK600 Вместе с платой поставляются кабели для подключения. Плата STK600 под- держивает все микроконтроллеры AVR семейств ATtiny, ATmega, ATxmega, а так- же — новые 32-разрядные устройства семейства AVR32 UC3 (в этой книге не рас- сматриваются). Существуют и другие отладочные платы для микроконтроллеров AVR (как от компании Atmel, так и от сторонних разработчиков), перечислять которые мы здесь не будем. Другими словами, предоставляем право выбора подходящего комплекта самому читателю.
Схема базового монтажа 21 Схема базового монтажа Любой микроконтроллер AVR должен быть включен в некоторую базовую схе- му, иначе он просто не будет работать. Пример такой схемы для устройства АТ- mega8 показан на рис. 1.4. Рис. 1.4. Схема базового монтажа для микроконтроллера АТтедав В данном случае используются следующие компоненты: • конденсатор С1 — 100 нФ; • конденсаторы С7 и С8 — по 22 пФ; • кварц на 3,686 МГц (или на 4, 8, 16 МГц). Микроконтроллер АТтеда8, как и все другие, по умолчанию сконфигурирован на работу от внутреннего тактового генератора, из-за чего внешний кварц он просто проигнорирует. Для переключения на внешнее тактирование необходимо установить соответствующие конфигу- рационные разряды предохранения (fuse bits), которые рассматривают позже в этой же главе. Питание микроконтроллера можно обеспечить напрямую от сети через стаби- лизирующий сетевой блок или (что более удобно и безопасно) — с помощью любо- го блока питания на 9.. 12 В. Для этого потребуется стабилизатор напряжения, кото- рый можно легко включить в базовую схему согласно рис. 1.5. сз С2 & OW - I £1 .. ей Рис. 1.5. Схема включения стабилизатора напряжения
22 Глава 1. Восьмиразрядные микроконтроллеры AVR В данном случае используются следующие компоненты: • IC1 —стабилизатор напряжения 5 В (7805); • электролитический конденсатор С1 — 10 мкФ (соблюдайте правильную поляр- ность!); • конденсаторы С2 и СЗ — на 100 нФ; • диод D1 — 1N4001. Этот стабилизатор преобразовывает входное напряжение в диапазоне 9.. 12 В в требуемое микроконтроллерам AVR напряжение питания 5 В. Кроме того, данная схема отчасти предохраняет устройство от возможных перенапряжений. Структура микроконтроллеров AVR В общем случае структура всех восьмиразрядных микроконтроллеров AVR со- ответствует схеме, показанной на рис. 1.6. Рис. 1.6. Обобщенная структура восьмиразрядных микроконтроллеров AVR Процессорное ядро включает в себя систему управления (счетчик команд и схема декодирования команд, извлекаемых из памяти программ) и операционное устройство, отвечающее за выполнение арифметических и логических операций. Операционное устройство, как правило, состоит из арифметико-логического уст- ройства (АЛУ), накапливающего сумматора и нескольких вспомогательных регист- ров. В классической программе почти половина всех команд — это команды пере- сылки для передачи данных от вспомогательных регистров к накапливающему сум- матору и обратно. В микроконтроллерах AVR накапливающий сумматор становится не столь критически важным, благодаря применению 32-х рабочих регистров, свя- занных с блоком АЛУ. В результате арифметические и логические операции могут быть выполнены в течение единственного такта. Операции АЛУ можно разделить на три основные категории: арифметические, логические и поразрядные. Каждой из этих категорий соответствуют мощные ко- манды. Новые микроконтроллеры AVR имеют также аппаратные умножители в ари- фметическом блоке АЛУ. Организация памяти В запоминающих устройствах, соответствующих классической концепции фон Неймана, данные и команды хранятся в одной памяти. В противоположность этому, память по Гарвардской архитектуре, используемой в восьмиразрядных микрокон- троллерах AVR, состоит из нескольких компонентов. В данном случае разделены память команд и память данных, т.е. обращение к командам осуществляется незави- симо от доступа к данным.
Структура микроконтроллеров AVR 23 В микроконтроллерах AVR отдельные сегменты памяти отличаются также и физической реализацией. • Внутренняя память для энергозависимых данных (т.е. данных, которые будут потеряны после отключения рабочего напряжения) представляет собой статиче- скую память RAM (SRAM). Ее преимущество заключается в том, что отпадает всякая необходимость во внутренней регенерации как в случае с некоторыми другими процессорами, которые используют динамическую память. По этой причине микроконтроллеры AVR могут работать с тактами вплоть до 0 Гц. В дополнение к этому, некоторые микроконтроллеры AVR для увеличения объ- ема обрабатываемых данных могут работать с подключаемой внешней памятью SRAM. Для этого, однако, приходится жертвовать выводами портов. • Для данных, которые должны сохраниться после отключения рабочего напря- жения, в распоряжении имеется память EEPROM (Electrically EPROM — элек- трически стираемое ППЗУ), данные в которую можно записывать непосредст- венно во время выполнения программы. Для области EEPROM также не обяза- тельно программирующее устройство. • Память программ реализована на основе программируемой и электрически сти- раемой Flash-технологии. Во всех восьмиразрядных микроконтроллерах AVR она — 16-разрядная (двухбайтная) и всегда встроена в кристалл. Расширение памяти программ с помощью блоков EPROM или Flash невозможно. Память SRAM Статическое ОЗУ (SRAM) микроконтроллеров AVR семейств AT90S, ATtiny и ATmega представляет собой блок со сквозной адресацией, состоящий из двух или трех (в зависимости от модели микроконтроллера) подобластей (рис. 1.7). Самый верхний адрес внутренней памяти SRAM, обозначенный на рис. 1.7 как “RamEnd”, зависит от построения ОЗУ соответствующего микроконтроллера. Размеры SRAM для различных восьмиразрядных микроконтроллеров AVR показаны в табл. 1.1. В ряде микроконтроллеров можно увеличивать пространство памяти SRAM пу- тем подключения внешних блоков вплоть до 64 Кбайт, однако для этого приходится пожертвовать выводами портов А и С, которые в таком случае применяются в каче- стве шин передачи данных и адресов. Таблица 1.1. Размеры памяти SRAM восьмиразрядных микроконтроллеров AVR Микроконтроллер Объем памяти SRAM, байт Адрес “RamEnd” AT90S1200 — $005F AT90S2313 128 $00DF AT90S2323 128 $00DF AT90S2343 128 $00DF AT90S4414 256 $015F AT90S4433 128 $00DF AT90S8515 512 $025F AT90S8535 512 $025F ATtiny 11 — $005F ATtiny 12 — $005F ATtiny 13А 64 $009F ATtiny 15L — $005F ATtiny2313 128 $00DF
Глава 1. Восьмиразрядные микроконтроллеры AVR Таблица 1.1. Продолжение Микроконтроллер Объем памяти SRAM, байт Адрес “RamEnd” ATtiny24 128 $00DF ATtiny25 128 $00DF ATtiny26 128 $00DF ATtiny261 128 $00DF ATtiny28L 128 $00DF ATtiny44A 256 $015F ATtiny45 256 $015F ATtiny461 256 $015F ATtiny48 256 , $015F ATtiny84 512 $025F ATtiny85 512 $025F ATtiny861 512 $025F ATtiny88 512 $025F ATmega128 4096 $105F ATmega1280 8192 $205F ATmega1281 8192 $205F ATmega1284P 16384 $405F ATmega16 1024 $045F. ATmega16A 1024 $045F ATmega162 1024 $045F ATmega164P 1024 $045F ATmega165P 1024 $045F ATmega168 1024 $045F ATmega168P 1024 $045F ATmega169 1024 $045F ATmega2560 8192 $205F ATmega2561 8192 $205F ATmega32A 2048 $085F ATmega324PA 2048 $085F ATmega325 2048 $085F ATmega325P 2048 $085F ATmega3250 2048 $085F ATniega3250P 2048 $085F ATmega328P 2048 $085F ATmega48PA 512 $025F ATmega64 4096 $105F ATmega640 8192 $205F ATmega644 4096 $105F ATmega644P 4096 $105F ATmega645 4096 $105F ATmega6450 4096 $105F ATmega8 1024 $045F ATmega8515 512 $025F ATmega8535 512 $025F ATmega88PA 1024 $045F
Структура микроконтроллеров AVR 25 (б ш 1 ш ш co о Ф $3F $ЗЕ $3D $ЗС $ЗВ SREG _______SEU________1 SPL t •> (зарезервировано) QI ms к 2 Адреса 0 SRAM $FFFF "т- Внешнее ОЗУ *)Т- — RamEnd+1 Ram End m о ₽• $04 $03 $02 $01 $00 (зарезервировано; (зарезервировано зарезервировано зарезервировано ^зарезервировано' Внутреннее ОЗУ *) $1F. $1Е $1D $1С $1В $1А $19 r 31 =£er Z старший.-) гЗО =Per Z младший r29 = Per.Y старший») г 28 =Per.Y младший») г 27 = Per X старший») г 26 =Per X младший») Per, вв/выв 63 Per. ввУвыв 62 Per, вв/выв. 61 Область ввода/вывода Per. вв./выв 1 Per. ввУвыв. 0 г 25 Ill $060 $05F $020 $01F $04 $03 $02 $01 $00 Область регистров Х4. £2 И Ы г 1 г0 1000 ф « о ф 7 1 *) В некоторых микроконтроллерах AVR отсутствует Рис. 1.7. Организация памяти SRAM микроконтроллеров AVR семейств AT90S, ATtiny и ATmega Регистровый файл Самая нижняя область памяти SRAM образует регистровый файл с 32 рабочими регистрами, которые все связаны с АЛУ и доступ к которым может быть выполнен в течение единственного такта системной синхронизации. Это означает, что за вре- мя такта в арифметико-логическое устройство вводятся два операнда из регистрово- го файла, выполняется операция, а результат запоминается в регистре назначения (рис. 3.3). Такт системной синхронизации ф Общее время выполнения команды Обращение АЛУ к регистру-операнду Выполнение операции АЛУ Сохранение результата в памяти Рис. 1.8. Диаграмма выполнения однотактной операции Хотя рабочие регистры с физической точки зрения не являются ячейками памя- ти, им, как показано на рис. 1.7, поставлены в соответствие 32 самых нижних адреса от $00 до $1F в памяти SRAM, поэтому их можно адресовать как обычные ячейки.
26 Глава 1. Восьмиразрядные микроконтроллеры AVR Регистры двойной длины X, Y и Z Шесть рабочих регистров от R26 до R31 могут применяться в качестве регист- ров двойной длины X, Y и Z шириной 16 бит с возможностью доступа к обеим по- ловинам (рис. 1.9). 15 0 Регистр X |7 0 |7 _0j 15 R27 ($1В) R26 ($1A) 0 Регистр Y lz_ 0|7 _oj 15 R29 ($1D) R28($1C) 0 Регистр Z U_ 0 |7 —ll R31 ($1F) R30 ($1E) Рис. 1.9. Структура регистров двойной длины X, Y и Z Благодаря специальным командам, их можно использовать в качестве указате- лей, что при косвенной адресации позволяет очень эффективно обращаться к ячейкам памяти SRAM. Дополнительно к этому, с помощью регистра Z из памяти программ можно извлекать восьмиразрядные константы. Область ввода/вывода семейств AT90S, ATmega и ATtiny В этой области памяти SRAM размещены все регистры для программирования, управления и сигнализации о всех периферийных функциях восьмиразрядных мик- роконтроллеров AVR. Типичный их набор для микроконтроллеров семейств AT90S, ATmega и ATtiny перечислен в табл. 1.2. В некоторых моделях часть указанных в табл. 1.2 регистров может отсутствовать или размещаться в области ввода/вывода по другим адресам. Кроме того, в современных микроконтроллерах область вво- да/вывода может превышать адрес $5F в пространстве SRAM. Например, в ATmega- 640 она завершается адресом 0x1 FF. В любом случае, всегда сверяйтесь с техниче- ским описанием конкретного микроконтроллера. Таблица 1.2. Область ввода/вывода восьмиразрядных микроконтроллеров AVR Адрес Название Функция $3F ($5F) SREG Регистр состояния $3E ($5E) SPH Указатель стека, старший байт $3D ($5D) SPL Указатель стека, младший байт $30 ($5C) OCRO Регистр сравнения на выходе таймера/счетчика Т/СО $3B ($5B) GIMSKnon GICR Общий регистр маски прерываний или общий регистр управле- ния прерываниями $3A ($5A) GIFR Общий регистр флагов прерываний $39 ($59) TIMSK Регистр маски прерываний таймера/счетчика $38 ($58) TIFR Регистр флагов прерываний от таймеров/счетчиков $37 ($57) SPMCR Регистр управления операциями начальной загрузки из памяти программ $36 ($56) TWCR Регистр управления двухпроводным интерфейсом l2C (TWI) $35 ($55) MCUCR Регистр общего управления микроконтроллером $34 ($54) MCUSR (MCUCSR) Регистр, содержащий информацию об источнике сброса микро- контроллера $33 ($53) TCCRO Регистр управления таймером/ счетчиком Т/СО $32 ($52) TCNTO Счетный регистр таймера/счетчика Т/СО (8 бит) $31 ($51) OSCCAt Регистр калибровки осциллятора $30 ($50) SFIOR Регистр специальных функций ввода-вывода $2F ($4F) TCCR1A Регистр управления А таймера/счетчика Т/С1
Структура микроконтроллеров AVR 27 Таблица 1.2. Продолжение Адрес Название Функция $2Е ($4Е) TCCR1B Регистр управления В таймера/счетчика Т/С1 $2D($4D) TCNT1H Счетный регистр Т/С1, старший байт $2С ($4С) TCNT1L Счетный регистр Т/С1, младший байт $2В($4В) OCR1AH Регистр сравнения А таймера/счетчика Т/С1, старший байт $2А ($4А) OCR1AL Регистр сравнения А таймера/счетчика Т/С1, младший байт $29 ($49) OCR1BH Регистр сравнения В таймера/счетчика Т/С1, старший байт $28 ($48) OCR1BL Регистр сравнения В таймера/счетчика Т/С1, младший байт $27 ($47) ICR1H Регистр захвата на входе таймера/счетчика Т/С1. младший байт $26 ($46) ICR1L Регистр захвата на входе таймера/счетчика Т/С1, старший байт $25 ($45) TCCR2 Регистр управления таймера/счетчика Т/С2 $24 ($44) TCNT2 Счетный регистр таймера/счетчика Т/С2 $23 ($43) OCR? Регистр сравнения на выходе таймера/счетчика Т/С2 $22 ($42) ASSR Регистр состояния асинхронного режима работы таймера/счет- чика Т/С2 $21 ($41) WDTCR Регистр управления сторожевым таймером $20 ($40) UBRRH или UCSRC Регистр скорости передачи данных через USART (старший байт) или регистр управления и состояния USART $1F($3F) EEARH Регистр адреса EEPROM, старший байт $1Е($ЗЕ) EEAR(L) Регистр адреса EEPROM, младший байт $1D($3D) EEDR Регистр данных EEPROM $1С ($ЗС) EECR Регистр управления EEPROM $1В($ЗВ) PORTA Регистр данных порта А $1А ($ЗА) DDRA Регистр направления передачи данных порта А $19 ($39) PINA Выводы порта А $18 ($38) PORTB Регистр данных порта В $17 ($37) DDRB Регистр направления передачи данных порта В $16 ($36) PINB Выводы порта В $15 ($35) PORTC Регистр данных порта С $14 ($34) DDRC Регистр направления передачи данных порта С $13 ($33) PINC Выводы порта С $12 ($32) PORTD Регистр данных порта D $11 ($31) DDRD Регистр направления передачи данных порта D $10 ($30) PIND Выводы порта D $0F ($2F) SPDR или USIDR Регистр ввода/вывода данных через интерфейс SPI или регистр данных универсального последовательного интерфейса $0Е ($2Е) SPSR или USISR Регистр состояния интерфейса SPI или регистр состояния уни- версального последовательного интерфейса $0D ($2D) SPCR или USICR Регистр управления интерфейсом SPI или регистр управления универсальным последовательным интерфейсом $0С ($2С) UDR Регистр данных UART $0В ($2В) USR или UCSRA Регистр состояния UART или регистр А управления и состояния USART 7 $0А ($2А) UCR или UCSRB Регистр управления UART или регистр В управления и состоя- ния USART $09 ($29) UBRR или UBRRL Регистр скорости передачи данных через UART или регистр ско- рости передачи данных через USART (младший байт) $08 ($28) ACSR Регистр управления и состояния аналогового компаратора $07 ($27) ADMUX Регистр выбора мультиплексора АЦП $06 ($26) ADCSR(A) Регистр (А) управления и состояния АЦП $05 ($25) ADCH Регистр данных АЦП, старший байт $04 ($24) ADCL Регистр данных АЦП, младший байт $03 ($23) TWDR Регистр данных интерфейса l2C (TWI)
28 Глава 1. Восьмиразрядные микроконтрЬллеры AVR Таблица 1.2. Окончание Адрес Название Функция $02 ($22) TWAR Регистр адреса (подчиненного устройства) для передачи данных по интерфейсу гС (TWI) $01 ($21) TWSR Регистр состояния интерфейса lzC (TWI) $00 ($20) TWBR Регистр скорости передачи данных по интерфейсу lzC (TWI) ПРИМЕЧАНИЕ Li 1»:» kt А .1к А >' 1 А. к. i »k A k k k kf a kkiikk' *» frrt kk tk if *k Art '«? k kVkkk; kkk'^kkkk kkk ?:.y. ik. .tk kk?:?kk k 1 kk?;?; ’Л ;k< Ячейкам в области ввода/вывода назначены адреса с $00 по $3F, которые должны приме- няться в случае использования специальных ассемблерных команд in, out, sbi, obi, sbis и sbiс. Если регистр ввода/вывода адресуется как ячейка в памяти SRAM в целом, то к адресу ввода/вывода необходимо добавить $20, Так, например, регистру состояния SREG соответствует адрес $3F внутри области ввода/вывода и адрес $5F относительно всей памя- ти SRAM. Как видим, к регистрам ввода/вывода относятся регистры разрешения/запрета отдельных прерываний, а также указатель стека, регистры состояния для указания результатов арифметических и логических операций, регистры управления работой многочисленных компонентов аппаратного обеспечения и периферии (порты, тай- мер, UART/USART, интерфейсы SPI и I2C (TWI), аналоговый компаратор, стороже- вой таймер, режимы пониженного энергопотребления), а также регистры для обра- щения к памяти EEPROM. Для доступа к регистрам ввода/вывода лучше всего использовать ассемблерные команды ввода/вывода микроконтроллеров AVR: in и out. Команда оис выдает один байт из одного из 32-х рабочих регистров в регистр ввода/вывода, а команда in считывает байт из одного регистра ввода/вывода в один из 32-х рабочих регист- ров. У регистров ввода/вывода в области с $00 по $1F ($20..$3F) отдельные разряды могут быть изменены напрямую с помощью ассемблерных команд sbi и cbi. Кро- ме того, содержимое отдельных разрядов этих регистров может быть напрямую оп- рошено с помощью ассемблерных команд sbis и sbiс (Система команд микрокон- троллеров AVR рассматривается в приложении В). Регистр состояния SREG Регистр состояния SREG содержит разряды условий (флаги) микроконтролле- ров AVR (рис. 1.10). Он располагается в области ввода/вывода по адресу $3F ($5F), доступен для чтения и записи и после подачи сигнала сброса инициализируется ну- лями. Разряд 76543210 $3F($5F) I i |t|h|s|v|n|z|c| Рис. 1.10. Регистр состояния SREG микроконтроллеров AVR В микроконтроллерах AVR для обозначения результата выполнения операций используются восемь различных разрядов условий. Все они могут быть проверены с помощью ассемблерных команд, определяющих последующий ход выполнения программы (например, brcs, brhc, brtc, brie и т.д.). При входе в подпрограмму обработки прерывания рекомендуется сохранить ре- гистр состояния и суова его восстановить при выходе для того, чтобы после возвра- та в прерванную программу работать с корректными битами условий. Значения отдельных разрядов условий (флагов) в микроконтроллерах AVR:
Структура микроконтроллеров AVR 29 • С —- указывает на переполнение (перенос) после выполнения арифметической или логической операции; • Z — всегда устанавливается в 1, если результат арифметической или логиче- ской операции равен нулю, и обнуляется, если результат операции не равен ну- лю; • N — указывает на отрицательный результат после выполнения арифметической или логической операции; • V — флаг переполнения при вычислениях в дополнительных кодах (арифмети- ка кодов с дополнением до двух); устанавливается в 1, если при выполнении соответствующей операции происходит переполнение, в противном случае — обнуляется; • S — связь флагов N и V с помощью операции “Исключающее ИЛИ”; флаг знака может применяться для определения фактического результата арифметической операции; • Н — указывает на переполнение в младшем полубайте (разряды 0...3 байта дан- ных); устанавливается в 1, когда происходит перенос из младшего полубайта в старший, в противном случае — обнуляется; • Т — флаг копирования, предназначенный для свободного использования про- граммистом (например, в качестве буфера); • I — общее разрешение прерываний. Если прерывания должны быть разрешены, то устанавливается в 1. Регистр управления микроконтроллером MCUCR Регистр MCUCR содержит разряды управления общими функциями микрокон- троллера. Наряду с разрешением доступа к внешней памяти SRAM, он также управ- ляет “спящим” режимом и характером срабатывания внешних прерываний. Регистр MCUCR находится в области ввода/вывода ро адресу $35 ($55). Он доступен для чтения и записи, а после подачи сигнала сброса инициализируется нулями. Набор, обозначение и последовательность разрядов в этом регистре может от- личаться в зависимости от модели микроконтроллера, поэтому рассмотрим их в общем виде. Точные обозначения уточняйте по техническому описанию устройст- ва. • SRE (External SRAM Enable) — если этот разряд установлен в 1, то разрешен доступ к внешней памяти SRAM (при наличии таковой); • SRW (External SRAM Wait State) — если этот разряд установлен в 1, то в после- довательность обращения к внешней памяти SRAM будет добавлено состояние ожидания продолжительностью один системный такт. Если разряд SRW содер- жит 0, то доступ к внешней памяти SRAM выполняется за два обычных такто- вых цикла. • SE (Sleep Enable) — этот разряд должен быть установлен в 1 для того, чтобы сделать эффективной ассемблерную команду sleep. Если он содержит 0, то по- сле выполнения команды sleep центральный процессор (ЦП) останется актив- ным. Во избежание непреднамеренного перевода процессора в ждущий режим или в режим пониженного энергопотребления непосредственно перед выполне- нием команды sleep рекомендуется установить разряд SE в 1. • SM (Sleep Mode) — выбор между различными состояниями пониженного энер- гопотребления.
30 Глава 1. Восьмиразрядные микроконтроллеры AVR • ISC11 и ISCIO (Interrupt Sense Control 1) — определяют способ активизации обработки внешнего прерывания 1, когда в регистре SREG установлен флаг 1, а в регистре GIMSK (GICR) — разряд INT1: по нарастающему или ниспадаю- щему фронту сигнала, или же по уровню лог. 0 на выводе INT1. Возможные комбинации ICS11 и ICS10 показаны в табл. 1.3. Если разряды ISC11 и ISC10 должны быть изменены, то вначале необходимо запретить прерывание 1, обну- лив разряд INT1 в регистре GIMSK (GICR). В противном случае непреднаме- • ренное изменение этих разрядов может привести к вызову внешнего прерыва- ния 1. Таблица 1.3. Выбор способа активизации прерывания INT1 ISC11 ISC10 Описание 0 0 Прерывание возникает по уровню лог. 0 на входе INT1 0 1 Эта комбинация в некоторых моделях микроконтроллеров AVR не исполь- зуется, в то время как в других означает прерывание по любому измене- нию логического уровня на входе INT1 1 0 Прерывание возникает по ниспадающему фронту сигнала на входе INT1 1 1 Прерывание возникает по нарастающему фронту сигнала на входе INT1 • ISC01 и ISCOO (Interrupt Sense Control 0) — устанавливают способ активизации внешнего прерывания 0, когда в регистре SREG будет установлен флаг I, а в ре- гистре GIMSK (GICR) — разряд INTO: по нарастающему или ниспадающему фронту сигнала, или же по уровню лог. 0 на выводе INTO. Возможные комбина- ции ICS01 и ICS00 показаны в табл. 1.4. Таблица 1.4. Выбор способа активизации прерывания INTO ISC01 ISC00 Описание 0 0 Прерывание возникает по уровню лог. 0 на входе INTO 0 1 Эта комбинация в некоторых моделях микроконтроллеров AVR не ис- пользуется, в то время как в других означает прерывание по любому из- менению логического уровня на входе INTO 1 0 Прерывание возникает по ниспадающему фронту сигнала на входе INTO 1 1. Прерывание возникает по нарастающему фронту сигнала на входе INTO Если разряды ISC01 и ISC00 должны быть изменены, то сначала необходимо запретить прерывание INTO, обнулив разряд INTO в регистре GIMSK (GICR). В противном случае непреднамеренное изменение этих разрядов может привести к вызову внешнего прерывания 0. Внутренняя память SRAM Данные и переменные, используемые в программах, как правило, хранятся во внутренней памяти SRAM микроконтроллеров AVR (т.е. в области с адресами выше $005F). К этим данным можно обращаться из программы прямо или косвенно. В памяти SRAM также размещается стек (если только он не реализован аппаратно). На рис. 1.11 символически показаны графики синхронизации при обращении к внутренней памяти SRAM. Внешняя память SRAM Если объема внутренней памяти SRAM недостаточно, то в некоторых микро- контроллерах AVR его можно увеличить до 64 Кбайт путем подключения внешних
Структура микроконтроллеров AVR 31 блоков памяти. Для этого в регистре MCUCR следует установить в 1 разряд SRE, в результате чего порты А и С будут выступать в качестве шины адреса и шины данных, а выводы 7 и 6 порта D — в качестве управляющих сигналов чтения /RD и, соответственно, записи /WR для внешней памяти SRAM (рис. 1.12), независимо от того, какие направления передачи данных установлены для этих портов в соответ- ствующих регистрах направления передачи данных. Такт системной синхронизации Ф Внутренняя шина адреса— Внутренняя шина данных Внутренний сигнал /RD Чтение из SRAM Т1 АО п <D£7 Запись в SRAM Т1 Т2 АО п DO 7 X Внутренний сигнал /WR Рис. 1.11. Синхронизация при обращении к внутренней памяти SRAM Рис. 1.12. Пример подключения внешнего блока памяти для расширения статической памяти SRAM до 32 Кбайт Дальнейшее обращение к внешней статической памяти может осуществляться с помощью тех же команд, что и при обращении к внутренней памяти. При обраще-
32 Глава 1. Восьмиразрядные микроконтроллеры AVR нии к адресам SRAM, которые находятся в области внутренней статической памяти, передача данных выполняется автоматически как во внутреннюю память SRAM, так и из нее, даже при установленном в 1 разряде SRE. В этом случае управляющие сигналы чтения /RD и записи ZWR остаются неактивными на протяжении всего цик- ла. Обращение к внешней памяти будет выполнено только тогда, когда адрес будет больше, чем “RarnEnd”, а также если в регистре управления MCUCR будет установ- лен в 1 разряд SRE. На тот случай, если используемые внешние блоки статической памяти окажутся недостаточно быстродействующими для циклов записи/чтения микроконтроллера AVR, установив разряд SRW (разряд 6) в регистре MCUCR, можно активизировать состояние ожидания. Благодаря введению этого дополнительного состояния дли- тельностью в один такт системной синхронизации, длина сигналов передачи данных и команд /RD и, соответственно, /WR увеличивается, чтобы предоставить достаточ- но времени для передачи данных блокам памяти, работающим медленнее. Благодаря чрезвычайно коротким маршрутам прохождения сигналов внутри кристалла, обращение к внутренней памяти RAM в значительной степени более свободно от сбоев, чем обращение к внешней памяти через шину. Если при этом принять во внимание, что из-за подсоединения внешнего запоминающего устройст- ва теряются 18 выводов, то следует тщательно взвешивать: действительно ли под- соединение внешней памяти — это наилучшее решение для данного случая приме- нения. Кроме того, многие современные восьмиразрядные микроконтроллеры пре- доставляют довольно большие объемы внутренней памяти SRAM, поэтому при не- хватке памяти в текущей модели, возможно, имеет смысл выбрать какую-либо дру- гую модель AVR. Стек Стек служит для хранения адресов возврата при вызове подпрограмм, а также для передачи параметров в подпрограммы. Кроме того, зачастую в стеке, как в буфере, временно хранятся переменные и промежуточные результаты. Реализация стека в разных моделях микроконтроллеров AVR может отличаться. Возможные ва- рианты: • стек размещается во внутренней или внешней памяти SRAM на выбор разра- ботчика; • стек всегда находится во внутренней памяти SRAM; • аппаратный стек (например, в микроконтроллере AT90S1200). В этом.случае он ограничен жестко заданным числом уровней. При выполнении ассемблерной команды г call или при поступлении запроса на прерывание все адреса, вве- денные в аппаратный стек, смещаются на один уровень вниз (адрес, помещен- ный до этого на уровень 2, теряется, а находящийся на уровне 1 перемещается на уровень 2; адрес, ранее записанный на уровне 0, будет перемещен на уровень 1). После этого соответствующий адрес возврата помещается на уровень 0 аппа- ратного стека. При выходе из обычной подпрограммы или подпрограммы обра- ботки прерывания адрес, находящийся на нулевом уровне, извлекается в счет- чик команд как адрес возврата, и все уровни аппаратного стека перемещаются на одну позицию вверх (уровень 1 — на уровень 0, уровень 2 — на уровень 1). Если глубина аппаратного стека составляет, например, три уровня, то при глу- бине вложения вызовов 4 (и более) подпрограмм необходимо соблюдать осторож-
Структура микроконтроллеров AVR 33 ность, поскольку в этом случае теряется адрес возврата, введенный в память пер- вым, вследствие чего возврат становится невозможным! Большинство восьмиразрядных микроконтроллеров AVR используют восьми- или 16-разрядный указатель стека, состоящий из одного регистра SP или двух вось- миразрядных регистров SPH и SPL. Их адреса в области ввода/вывода $ЗЕ ($5Е) и $3D ($5D). Указатель стека после подачи сигнала сброса обнуляется, и доступен для чтения и записи. Указатель стека позволяет обращаться к сегменту данных в области, зарезерви- рованной для стека, и должен быть инициализирован до начала выполнения про- граммы перед выполнением подпрограммы или разрешения прерывания, поскольку указатель стека после подачи сигнала сброса будет снова обнулен. В микроконтрол- лерах AVR стек заполняется “сверху вниз”, т.е. при выполнении ассемблерной ко- манды push соответствующий байт будет скопирован по адресу, на который в на- стоящее время ссылается указатель стека, после чего указатель стека уменьшается на 1 (декрементируется). Это целесообразно потому, что при инициализации до на- чала выполнения программы указатель стека позволяет ссылаться на ячейку памяти с наибольшим адресом. Когда байт с помощью ассемблерной команды pop извлекается из стека, то вна- чале указатель стека инкрементируется на 1, а затем байт, извлеченный по соответ- ствующему адресу, копируется в регистр назначения. При прерывании или вызове подпрограммы (команда call) в качестве адреса возврата в стек будет помещен адрес следующей команды из выполняемой про- граммы. Команда выхода из подпрограммы ret увеличивает указатель стека на 1, и соответствующий адрес будет скопирован в счетчик команд. Другими словами, после выполнения команды ret ход программы будет продолжен, начиная с коман- ды, следующей после call. Ассемблерная команда reti выполняет ту же функцию, что и команда ret, с тем отличием, что она применяется для возврата из подпрограммы обработки пре- рывания и дополнительно к этому устанавливает флаг I (разряд 7) в регистре со- стояния SREG для того, чтобы снова разрешить дальнейшие прерывания. Память программ Отличительной особенностью микроконтроллеров AVR является то, что у них в качестве памяти программ используется одна и та же память типа Flash, которая может свободно программироваться пользователем и опять вытираться электри- ческим способом. Объемы Flash-памяти в различных восьмиразрядных микрокон- троллерах AVR перечислены в табл. 1.5. Компания Atmel предоставляет в распоряжение пользователей очень эффектив- ную возможность как параллельного программирования, так и последовательного через интерфейс SPI с применением адаптеров-программаторов. Так, программа может быть “записана” во Flash-память и снова вытерта непосредственно в составе схемы, в которой работает микроконтроллер. Схема программирования уже интег- рирована в кристалл. Вспомогательное напряжение Vpp= +12 В необходимо только при программировании в параллельном режиме. Так или иначе, это напряжение ис- пользуется в большинстве электрических схем (например, для последовательного интерфейса). Как несложно заметить, первые цифры в маркировке микроконтроллеров обо- значают именно объем их памяти программ.
34 Глава 1. Восьмиразрядные микроконтроллеры AVR Таблица 1.5. Объемы Flash-памяти в восьмиразрядных микроконтроллерах AVR 1 Кбайт 2 Кбайт 4 Кбайт 8 Кбайт 16 Кбайт AT90S1200 ATtinyl 1 ATtiny 12 ATtinyl ЗА ATtinyl 5L AT90S2313 AT90S2323 AT90S2343 ATtiny2313 ATtiny24 ATtiny25 ATtiny26 ATtiny261 ATtiny28L AT90S4414 AT90S4433 ATtiny44A ATtiny45 ATtiny461 ATtiny48 ATmega48PA AT90S8515 AT90S8535 ATtiny 84 ATtiny85 ATtiny 861 ATtiny88 ATmega8 ATmega8515 ATmega8535 ATmega88PA ATmega16 ATmega16A ATmega162 ATmega164P . ATmega165P ATmega168 ATmega168P ATmega169 32 Кбайт 64 Кбайт 128 Кбайт 256 Кбайт ATmega32A ATmega324PA ATmega325 ATmega325P ATmega3250 ATmega3250P ATmega328P ATmega64 ATmega640 ATmega644 ATmega644P ATmega645 ATmega6450 ATmega128 ATmega1280 ATmega1281 ATmega1284P ATmega2560 ATmega2561 Память данных типа EEPROM Все восьмиразрядные микроконтроллеры AVR семейств AT90S, ATmega и ATtiny, кроме ATtiny28L, оснащены памятью типа EEPROM объемом от 64 до 4096 байт для хранения энергонезависимых данных и констант (табл. 1.6). Это очень удобно, например, при калибровке измерительных приборов, работающих под управлением микроконтроллеров AVR, у которых в памяти EEPROM в процес- се настройки сохраняются параметры корректировки. Благодаря этому, в боль- шинстве случаев полностью отпадает необходимость в настроечных потенциомет- рах и триммерах. Следует учитывать, что срок службы памяти EEPROM ограничен примерно 100 000 циклами записи/чтения, поэтому использовать ее как обычную память SRAM нельзя. По этой причине некоторые производители комбинируют память ти- па EEPROM с SRAM. При таком варианте содержимое памяти переносится при прекращении подачи рабочего напряжения в память EEPROM, благодаря чему при нормальных условиях эксплуатации достигают короткого цикла записи, не приво- дящего к износу. В микроконтроллерах AVR преобразователи напряжения, используемые для выработки напряжения программирования и питания таймера, определяющего дли- тельность программирования, интегрированы в кристалл. Кроме того, реализовано распознавание провалов напряжения для предотвращения записи при понижении рабочего напряжения ниже минимально допустимого значения. Благодаря этому, для программирования одного байта достаточно всего лишь записать в соответствующий регистр адрес и байт данных, а затем активизировать процесс записи с помощью регистра управления. Дальнейший процесс протекает автономно, без вмешательства пользователя: целевой байт вначале будет стерт (обнулен), а затем в него запишется новое значение. Этот процесс контролируется внутренне и его продолжительность, в зависимости от подведенного рабочего напряжения, со- ставляет 2,5-4 мс.
Структура микроконтроллеров AVR 35 Таблица 1.6. Объемы памяти EEPROM в восьмиразрядных микроконтроллерах AVR 64 байта 128 байт 256 байт 512 байт AT90S1200 ATtiny 11 ATtiny 12 ATtiny 13А ATtiny 15L ATtiny48 ATtiny88 AT90S2313 AT90S2323 AT90S2343 ATtiny2323 ATtiny24 ATtiny25 ATtiny26 ATtiny261 AT90S4414 AT90S4433 ATtiny44A ATtiny45 ATtiny461 ATmega48PA AT90S8515 AT90S8535 ATtiny84 ATtiny85 ATtiny861 ATmega16 ATmega16A ATmega162 ATmega164P ATmega165P ATmega168 ATmega168P ATmega169 ATmega8 ATmega8515 ATmega8535 ATmega88PA 1024 байт 2048 байт 4096 байт ATmega32A ATmega324PA ATmega325 ATmega325P ATmega3250 ATmega3250P ATmega328P ATmega64 ATmega644 ATmega644P ATmega645 ATmega6450 ATmega128 ATmega1280 ATmega1281 ATmega1284P ATmega2560 ATmega2561 ATmega640 Для программирования памяти EEPROM микроконтроллеров AVR нет необхо- димости применять внешний программатор, поскольку в каждую ячейку в данном случае можно записать значение непосредственно во время выполнения пользова- тельской программы. Для программирования используются три регистра памяти EEPROM, располо- женные в области ввода/вывода памяти SRAM (см. табл. 1.2): • восьмиразрядный регистр адреса EEAR или два регистра EEARH и EEARL; • восьмиразрядный регистр данных EEDR; • восьмиразрядный регистр управления EECR. В процессе записи в память EEPROM подлежащий программированию байт, адресуемый регистром EEAR, загружается в регистр EEDR. В процессе чтения из памяти EEPROM в регистр EEDR записывается содержимое ячейки EEPROM, адре- суемой регистром EEAR. Для управления процессом чтения используется разряд EERE (EEPROM Read Enable — разрешение чтения памяти EEPROM) управляющего регистра EECR. По- сле записи корректного адреса в регистр EEAR процесс чтения активизируют уста- новкой этого разряда в 1. Распознав 1 в разряде EERE, аппаратное обеспечение считает требуемый байт в регистр EEDR, после чего уже нет необходимости вновь опрашивать разряд EERE, поскольку считывание длится только один цикл системного такта.
36 Глава 1. Восьмиразрядные микроконтроллеры AVR После того как разряд EERE установлен в 1, центральный процессор будет задержан на два такта системной синхронизации прежде, чем будет выполнена следующая команда. Перед началом операции чтения программа пользователя должна постоянно оп- рашивать разряд EEWE (EEPROM Write Enable — разрешение записи в память EEPROM) регистра EECR в ожидании появления в нем 0. Если во время програм- мирования памяти EEPROM в соответствующий регистр ввода/вывода будут запи- саны новый адрес или данные, то еще продолжающийся процесс программирования будет прерван и результат будет неопределенным! Запись в память EEPROM восьмиразрядных микроконтроллеров AVR контро- лируется разрядом EEWE регистра EECR. Для записи байта в память EEPROM раз- ряд его необходимо установить в 1, если в регистре EEAR находятся корректный адрес памяти EEPROM, а в регистре EEDR — байт данных, подлежащий програм- мированию. Для предотвращения непреднамеренной записи в память EEPROM раз- ряд EEWE может быть установлен в 1 только в том случае, если установлен также и разряд EEMWE того же регистра EECR. Если во время обращения к памяти EEPROM на запись происходит системный сброс, то ре- зультат будет неопределенный, поскольку регистр адреса EEAR будет обнулен. По этой при- чине могут содержаться ошибочные данные по адресу, подлежащему программированию, или в байте с адресом 0 памяти EEPROM! Для программирования памяти EEPROM должны быть выполнены следующие действия. 1. Дождаться окончания процесса программирования памяти EEPROM (если он активен), т.е. пока разряд EEWE не возвратится в состояние 0. 2. Записать новый адрес в регистр EEAR. 3. Записать требуемый байт данных в регистр EEDR. 4. Установить разряд EEMWE в 1. 5. На протяжении следующих четырех периодов системного такта после установ- ки разряда EEMWE должна быть записана лог. 1 в разряд EEWE. Тем самым будет запущен процесс программирования. По окончанию цикла программирования (типичная продолжительность — 2,5 мс при рабочем напряжении Vcc = 5 В и 4 мс при Vcc = 2,7 В), разряд EEWE ап- паратно автоматически обнуляется. Программа пользователя должна непрерывно опрашивать этот разряд, ожидая появления 0, прежде чем приступить к программи- рованию следующего байта. После установки разряда EEWE в 1 центральный процессор будет задержан на два такта системной синхронизации, после чего он может выполнять следующую команду. Порты Порт — это группа линий передачи данных (от трех до восьми), обозначенная буквой латинского алфавита (А, В, С ...). Набор и разрядность портов отличается
Структура микроконтроллеров AVR 37 в зависимости от микроконтроллера. Распределение портов для некоторых моделей AVR представлено в табл. 1.7. Таблица 1.7. Порты в некоторых восьмиразрядных микроконтроллерах AVR Микроконтроллер ПортА Порт В Порт С ПортО Порт Е Порт F Портб AT90S1200 — 8 бит — 7 бит — — — AT90S2313 — 8 бит — 7 бит — — — AT90S2323 — 3 бита — — — — — AT90S2343 — 5 бит — — — — — AT90S4414 8 бит 8 бит 8 бит 8 бит — — — AT90S4433 — 6 бит 6 бит 8 бит — — — AT90S8515 8 бит 8 бит 8 бит 8 бит — — — AT90S8535 8 бит 8 бит 8 бит 8 бит — — — ATtiny 11 — 6 бит — — — — — ATtiny 12 — 6 бит — — — — — ATtiny 15L — 6 бит — — — — — ATtiny24 8 бит 4 бита — — — — — ATtiny26 8 бит 8 бит — — — — — ' ATtiny28 4 бита 8 бит — 8 бит — — — ATmega128 8 бит 8 бит 8 бит 8 бит 8 бит 8 бит 5 бит ATmega16 8 бит 8 бит 8 бит 8 бит — — — ATmega32 8 бит 8 бит 8 бит 8 бит — — — ATmega64 8 бит 8 бит 8 бит 8 бит 8 бит 8 бит 5 бит ATmega8 — 8 бит 7 бит 8 бит — — — Передача по линиям данных допускается в двух направлениях: на ввод и на вы- вод. При этом следует помнить об одной особенности портов микроконтролдеров AVR: перед тем как выполнить запись или чтение по линии, необходимо задать на- правление передачи. Для этой цели с каждым портом сопоставляется особый ре- гистр, разряды которого задают направление передачи по соответствукццим выво- дам. Обозначение таких регистров начинается с аббревиатуры DDR (Data Direction Register). Значению 0 в разряде регистра DDR соответствует работа вывода как входа, а значению 1 — как выхода. Предположим, регистр DDRA содержит двоичное зна- чение 11110000 (шестнадцатеричное F0). Это означает, что младшие четыре вывода порта A (PA0..PA3) работают как входы, а старшие (РА4..РА7) — как выходы. Подтягивающее сопротивление Что происходит фактически, когда в какую-то линию данных выдается значе- ние 0 или 1? Или какое состояние будет распознавать микроконтроллер на входе, если линия “висит в воздухе” (т.е. не подключена к “земле”, и на нее не подается напряжение)? Ответ на эти дает подтягивающее сопротивление, назначение которо- го — поддерживать на выводе напряжение 0 В (“земля”) или 5 В (или около того). К счастью, микроконтроллеры AVR оснащены так называемыми внутренними под- тягивающими резисторами. Таким образом, если в схеме присутствует кнопка, для считывания ее состояния требуется подтягивающее сопротивление (рис. 1.13). Когда кнопка нажата, состояние однозначно определено: это — 0 В, т.е. мы по- лучаем на входе значение 0. Но что происходит, когда кнопка не нажата? В этом случае (если активен внутренний.подтягивающий резистор) на вход подается на-
38 Глава 1. Восьмиразрядные микроконтроллеры AVR пряжение 5 В, что соответствует состоянию лог. 1. Если бы не подтягивающее со- противление, то состояние входа оказалось бы совершенно неопределенным. Внутренний подтягивающий резистор Внешний подтягивающий резистор Рис. 1.13. Применение подтягивающего сопротивления Каким же образом микроконтроллер распознает необходимость активизации внутреннего подтягивающего резистора? Для этого с помощью регистра DDRx не- обходимо переключить порт на ввод данных. Затем в регистр порта (например, PORTB) записывается битовая маска, в которой единицам соответствуют выводы с активными подтягивающими резисторами. Естественно, все это имеет смысл только в том случае, если порт сконфигурирован на прием данных. Если к порту необходимо подключить светодиод, существует два варианта. Со- гласно первой схеме (рис. 1.14, слева), при выводе в линию лог. О, на выводе уста- навливается напряжение О В (“земля”), ток течет от точки высокого потенциала (ра- бочее напряжение) через резистор, и светодиод светится. Если в линию выдается лог. 1, то выход находится в высокоомном состоянии, и ток не протекает, т.е. свето- диод не светится. Новичков это иногда путает, поскольку кажется нелогичным, что О включает, а 1 выключает светодиод, тем не менее к такому подходу необходимо Рис. 1.14. Два варианта подключения светодиода На отладочной плате STK500
Структура микроконтроллеров AVR 39 В случае использования отладочной платы, наподобие STK.500, светодиоды можно подключить к непосредственно к выводам микроконтроллера через сопро- тивление (рис. 1.14, справа). Таким образом, светодиод соединен не только с напря- жением Vcc, как в рассмотренном ранее варианте, но и с “землей”. В результате ток течет от микроконтроллера. Следует также отметить, что большинство выводов портов, кроме собственно ввода-вывода данных, выполняют и другие, альтернативные функции, указываемые на схемах в круглых скобках. Так, например, у микроконтроллера ATmega8 вывод PD0 — это не только линия 0 порта D, но и линия приема бита при последователь- ном обмене данными. Различные альтернативные функции портов будут рассмотре- ны далее по мере изучения периферийных устройств микроконтроллеров AVR. Регистры управления портом Выше мы уже упоминали регистры DDRx и PORTx, участвующие в конфигури- ровании портов. Каждому порту поставлен в соответствие еще один регистр: PINx. Рассмотрим подробнее назначение каждого из этих регистров. • Регистр направления передачи данных DDRx (DDRA, DDRB и т.д.) определяет назначение выводов порта: входы или выходы. Если разряд “п” в регистре DDRx содержит 0, то соответствующий вывод сконфигурирован как вход. Если при этом в соответствующем разряде регистра PORTx находится 1, то к выводу подключается подтягивающее сопротивление. Если разряд “п” в регистре DDRXn содержит 1, то соответствующий вывод сконфигурирован как выход. • Если вывод выполняет роль выхода, то в соответствующий разряд регистра PORTx записывается выводимое битовое значение. • Логический уровень на выводах в режиме входа можно считать по адресу реги- стра PINx. Регистры DDRx и PORTx доступны как для записи, так и для чтения, а регистр PINx — только для чтения. Таймеры/счет чики Таймеры/счетчики — это, наверное, наиболее часто используемые модули мик- роконтроллеров. С их помощью можно измерять промежутки времени и частоту, определять ширину импульсов, вычислять скорость и т.д. Хотя они и используются для измерения времени, на самом деле речь идет об обычных двоичных счетчиках. В семействах AT90S, ATtiny и ATmega микроконтроллеров AVR используются восьми- и 16-разрядные таймеры/счетчики. Разрядность определяет момент пере- полнения счетчика (возврат в нулевое состояние). Так, для восьмиразрядного счет- чика переполнение наступает, когда счет достигает 255, а*для 16-разрядного — 65535. Количество таймеров/счетчиков и их разрядность в микроконтроллерах отлича- ется в зависимости от модели, и потому в данном подразделе будут рассмотрены только общие вопросы, имеющие отношение^ использованию таймеров/счетчиков. Если таймер/счетчик функционирует в качестве счетчика, то он подсчитывает число импульсов, поступающих на определенный вход микроконтроллера. В этом случае соответствующий вывод должен быть сконфигурирован в инициализацион- ной части программы как вход. В случае использования в качестве таймера частота тактирования таймера/счет- чика является производной величиной от такта системной синхронизации внутрен-
40 Глава 1. Восьмиразрядные микроконтроллеры AVR него кварцевого осциллятора. При этом таймеры/счетчики используют в качестве тактового сигнала разделенный такт системной синхронизации. Коэффициент деле- ния предварительного делителя частоты может настраиваться индивидуально для каждого из таймеров с помощью мультиплексора, управляемого разрядами из реги- стра управления таймера/счетчика. В микроконтроллерах AVR используются следующие таймеры/счетчики: • восьми- или 16-разрядный Т/СО; • 16-разрядный Т/С 1; • восьми-или 16-разрядный Т/С2; • 16-разрядные Т/СЗ, Т/С4 и Т/С5. Регистры управления в этом случае называются TCCRO, TCCR2 и т.д. (распо- ложены в области ввода/вывода), а режим работы и коэффициент деления частоты осциллятора определяется с помощью разрядов CSx2, CSxl и CSxO этих регистров. К примеру, для таймеров/счетчиков Т/СО и Т/Cl выбор режима и входного такта можно определить с помощью комбинаций разрядов, представленных в табл. 1.8. Таблица 1.8. Выбор режима и входного такта для Т/СО и Т/С1 микроконтроллеров AVR CSx2 CSx1 CSxO Описание 0 0 0 Останов 0 0 1 Режим “Таймер”, такт = такт системной синхронизации 0 1 0 Режим “Таймер”, такт = такт системной синхронизации / 8 0 1 1 Режим “Таймер”, такт = такт системной синхронизации / 64 1 0 0 Режим “Таймер”, такт = такт системной синхронизации / 256 1 0 1 Режим “Таймер”, такт = такт системной синхронизации /1024 1 1 0 Режим “Счетчик”, такт — внешний на входе ТО (Т1), активный фронт сигнала — ниспадающий 1 1 1 Режим “Счетчик”, такт — внешний на входе ТО (Т1), активный фронт сигнала — нарастающий Для Т/С2, Т/СЗ, Т/С4 и Т/С5 комбинации разрядов CS22, CS21 и CS20 могут иметь разное значение для различных моделей микроконтроллеров. Так, например, для восьмиразрядного таймера Т/С2 микроконтроллера ATmega640, разряды CS20- CS22 управляющего регистра TCCR2B, определяют режимы деления, перечислен- ные в табл. 1.9, в то время как для Т/СЗ, Т/С4 и Т/С5 они соответствуют табл. 1.8. Таблица 1.9. Выбор режима и входного такта для Т/С2 микроконтроллера АТтеда640 CS22 CS21 CS20 Описание 0 0 0 Останов 0 0 1 Такт = такт системной синхронизации 0 1 0 Такт = такт системной синхронизации / 8 0 1 1 Такт = такт системной синхронизации / 32 1 0 0 Такт = такт системной синхронизации / 64 1 0 1 Такт = такт системной синхронизации /128 1 1 0 Такт = такт системной синхронизации / 256 1 1 1 Такт = такт системной синхронизации /1024 Т/СО Схема работы таймера/счетчика Т/СО, представлена на рис. 1. 15.
Структура микроконтроллеров AVR 41 Как только с помощью разрядов CSOO, CS01 и CS02 регистра управления TCCR0 для делителя частоты будет установлена комбинация, отличная от ООО, тай- мер/счетчик Т/СО по каждому импульсу, поступающему на тактовый вход, начинает увеличивать на единицу содержимое регистра TCNT0. Когда состояние счетчика в регистре TCNT0 изменяется с $FF на $00, в регистре TIFR устанавливается флаг переполнения TOVO. ПРИМЕЧАНИЕ Кроме разрядов CSOO, CS01 и CS02 регистра TCCR0 (разряды 0-2), никакие другие разряды этого регистра не используются. Таймер/счетчик Т/СО хорошо подходит для оценки временных интервалов. Для этого в ходе выполнения программы в регистр TCNT0 записывается исходное зна- чение. Затем может быть запущен Т/СО с требуемым входным тактом. Программа ожидает появления в регистре TIFR флага переполнения TOVO, указывающего на то, что требуемое время истекло. Предположим частота системной синхронизации составляет 4 МГц, а некоторое действие должно выполняться программой каждые 0,5 с. В этом случае можно вос- пользоваться делением частоты на 8, что соответствует частоте тактирования 500 кГц или 2 мкс. Таким образом, на подсчет 256 тактовых импульсов счетчику потребуется 512 мкс. Это значение должно быть кратно 500 мкс,* чтобы с помощью множителя 1000 в программе можно было реализовать требуемое действие в точности с периодом 500 мс. Для этого в счетчик перед началом каждого счета должно быть загружено значение 6, чтобы до переполнения выполнялся подсчет не 256, а только 250 тактовых импульсов. Т/С1 16-разрядный таймер/счетчик Т/Cl гораздо сложнее Т/СО (рис. 1.16). В допол- нение к счетному регистру и регистру управления, он содержит регистр захвата по входу (ICR1) и два 16-разрядных регистра сравнения на выходе (в некоторых моде- лях микроконтроллеров регистр сравнения В отсутствует).
42 Глава 1. Восьмиразрядные микроконтроллеры AVR Запрос на Запрос на Запрос на Запрос на прерывание при прерывание при прерывание при прерывание при переполнении Т/С1 совпадении с А совпадении с В захвате входа Рис. 1.16. Схема таймера/счетчика Т/С1 Рассмотрим назначение отдельных регистров: • TCNT1 — счетный регистр (содержимое счетчика); • TCCR1А — регистр управления для определения реакции выводов ОС 1 А/ ОС1В в случае совпадения состояния счетчика в регистре TCNT1 с регистрами сравнения OCR1A/OCR1B, а также для выбора режима широтно-импульсной модуляции; • TCCR1В — регистр управления для настройки делителя частоты, для разреше- ния подачи сигнала сброса для регистра TCNT1 и для управления захватом; • ICR1 — регистр захвата по входу (при появлении на выводе ICP фронта вход- ного сигнала, определенного как активный, текущее состояние счетчика будет перенесено в этот регистр);
Структура микроконтроллеров AVR 43 • OCR 1 A, OCR 1В — регистры сравнения; их содержимое постоянно сравнивает- ся с состоянием счетчика. В случае совпадения выполняются действия, опреде- ленные регистром TCCR1 А. Регистр управления TCCR1A (рис. 1.17) находится в области ввода/вывода по адресу $2F. 7 6 5 4 3 2 1 О СОМ1А1 СОМ 1 АО СОМ1В1 СОМ1В0 — PWM11 PWM10 Рис. 1.17. Регистр TCCR1A таймера/счетчика Т/С1 • ПРИМЕЧАНИЕ Структура рассмотренных здесь регистров в некоторых современных микроконтроллерах мо- жет отличаться. Так, например, для микроконтроллера ATmega640, задействованы разряды 2 и 3: СОМ1СО и СОМ1С1. Их функция аналогичная двум другим парам: СОМ1АО: СОМ1А1 и СОМ1ВО:СОМ1В1, — но для канала С модуля сравнения на выходе. Кроме того, разряды О и 1 в данной модели называются не PWM10 и PWM11, a WGM10 и WGM11. Разряды СОМ1А1/СОМ1 АО и СОМ1В1/СОМ1ВО определяют состояние вывода ОС1А/ОС1В при совпадении содержимого регистра сравнения A/В с содержимым счетчика. Возможные настройки для режима сравнения показаны в табл. 1.10. Таблица 1.10. Возможные варианты для работы в режиме сравнения СОМ 1x1 СОМ 1x0 Действия в случае совпадения 0 0 Выходное значение отсутствует 0 1 При совпадении ОС1х переключается в другое состояние 1 0 При совпадении на выходе ОС1х устанавливает лог. 0 1 1 При совпадении на выходе ОС1х устанавливает лог. 1 В случае активизации режима ШИМ, разряды 4-7 в регистре TCCR1A имеют значения, отличные от указанных в табл. 1.10. Когда регистр управления TCCR1A определяет работу в конфигурации широтно-импульсного модулятора, то Т/С 1 ра- ботает как суммирующий и вычитающий счетчик, осуществляя циклические пере- ходы от $0000 к максимальному значению ТОР, и затем снова возвращаясь к $0000. При запрограммированной разрешающей способности ШИМ в N разрядов значение ТОР рассчитывается как TOP = 2n-1. Частота 1шим, с которой повторяются циклы ШИМ, вычисляется по формуле: fpwM = fr/ci / (2N+I - 2), причем частота таймера/счетчика fr/ci выбирается с помощью разрядов CS10-CS12 регистра TCCR1B, а разрешающая способность N — с помощью разрядов PWM10 и PWM11 регистра TCCR1 А. Соответствующие взаимосвязи показаны в табл. 1.11. Таблица 1.11. Выбор режима ШИМ с помощью разрядов PWM11 и PWM10 PWM11 PWM10 Разрешающая способность | Значение ТОР | | Частота ШИМ 0 0 Режим ШИМ не активен 0 1 8 разрядов $00FF(255) fT/ci/510 1 0 9 разрядов $01FF (511) fT/c, /1022 1 1 10 разрядов $03FF (1023) fT/ci / 2046
44 Глава 1. Восьмиразрядные микроконтроллеры AVR Когда состояние счетчика в регистре TCNT1 совпадает со значением 10-ти младших разрядов регистра OCR1A/OCR1B, то, в зависимости от состояния разря- дов COMIА1/СОМ1 АО или СОМ1В1/СОМ1ВО регистра TCCR1A, вывод ОС1А/ ОС1В последующим тактовым импульсом устанавливается или сбрасывается. Со- ответствующие взаимосвязи показаны в табл. 1.12. Таблица 1.12. Возможности выбора для режима сравнения при работе ШИМ СОМ1х1 СОМ 1x0 Действие в случае совпадения 0 0 На выводе ОС1х нет никакого сигнала 0 1 На выводе ОС1х нет никакого сигнала 1 оа Неинвертирующий широтно-импульсный модулятор. В случае соответствия, при суммирующем подсчете на выводе ОС1х уста- навливается лог. 0, а при подсчете с вычитанием — лог. 1 1 1 Инвертирующий широтно-импульсный модулятор. В Случае соот- ветствия, при суммирующем подсчете на выводе ОС1х устанав- ливается лог. 1, а при подсчете с вычитанием — лог. 0 В случае неинвертирующего широтно-импульсного модулятора, коэффициент заполнения g прямоугольного сигнала на выводе с ШИМ соответствует значению n / (2N - 1), где п — значение в соответствующем регистре OCR, a N — разрешаю- щая способность ШИМ в разрядах (рис. 1.18). и ин :--- ------------- ------------ Uav Ul tH tL т Период T = tH+ tL Коэффициент заполнения g = tH / Т Среднее Uav = (Uh х tn + * k)/ T Рис. 1.18. Определение периода Т, коэффициента заполнения g и среднего арифметического UAv прямоугольных импульсов напряжения U Если регистр сравнения OCR1A/OCR1B содержит значение ТОР или 0, то на соответствующем выводе, в соответствии с правилами, показанными в табл. 1.13, постоянно поддерживаются уровень лог. О или лог. 1. Таблица 1.13. Вывод ШИМ для особых случаев OCR1x = ТОР или OCR1x = О СОМ 1x1 СОМ 1x0 OCR1x Вывод ОС1х 1 0 0 0 1 0 ТОР 1 1 1 0 1 1 1 ТОР 0 На рис. 1.19. на примере фиктивной трехразрядной ШИМ показано формирова- ние неинвертированного и инвертированного выходного ШИМ-сигнала на выходе ОС1В. На диаграмме А показан примерный вид ступенчатого сигнала, соответст- вующий состоянию счетчика TCNT1, на диаграмме В — неинвертированный, а на диаграмме С — инвертированный выходной сигнал. Продолжительность периода Tpwm в этом случае вычисляется в соответствии с рассмотренным выше уравнением TpwmI= Тт/ci * (2N+1 - 2). Таким образом, при N = 3 период ШИМ-сигнала состоит из 14 периодов тактового сигнала fr/ci на входе TCNT1.
Структура микроконтроллеров AVR 45 Состояние счетчика TCNT1 ШИМ-вывод ОС1В Высокий 1 СОШ ВО = О уровень Низкий____ _____ ________ уровень 0123456789 10 15 ."f"~l—г 20 t х f т/ci ШИМ-вывод ОС1В ( Высокий уровень с СОМ1ВО=1 уровень 012345678910 20 25 t х f т/d Рис. 1.19. Способ формирования неинвертированных и инвертированных выходных ШИМ-сигналов В данном примере регистр сравнения OCR1B содержит значение 5. В регистре TCNT1, учитывая тот факт, что его исходное значение равно 0, значение 5 появля- ется после пяти тактовых импульсов. На следующем тактовом импульсе, после рас- познания совпадения на выводе ОС1В устанавливается уровень лог. 0 (рис. 1.19, В). Регистр TCNT1 инкрементируется далее до тех пор, пока не будет достигнуто значение ТОР, которое при трехразрядной ШИМ составляет 7. Как только достиг- нуто значение ТОР, направление счета меняется на обратное, и регистр выполняет вычитание. После девятого тактового импульса, начиная от стартового значения 0, содержимое регистра TCNT1 опять совпадает с содержимым регистра OCR1B. На следующем тактовом импульсе на выходе ОС1В устанавливается уровень лог. 1. Регистр TCNT1 декрементируется далее до тех пор, пока опять не будет дос- тигнуто значение 0. Это происходит после в общей сложности четырнадцати тактр- вых импульсов, считая от начального значения 0. Таким образом завершается пери- од ШИМ-сигнала, направление счета вновь меняется на обратное, и регистр TCNT1 опять выполняет сложение. Как видно на рис. 1.19 (В), “высокая” составляющая выходного сигнала составляет 6 тактовых периодов, а “низкая” — 4. Таким образом, коэффициент заполнения g = 6/10 или g = 3/5. Аналогично, диаграмма С на рис. 1.19 показывает соотношения для инвертированного выходного ШИМ-сигнала. В режиме ШИМ устанавливается флаг переполнения TOV1, если счетчик при достижении состояния 0 меняет направление счета на обратное. Это прерывание по Т/С 1 при переполнении, как и при нормальной работе в режиме счетчика, вызыва- ется в том случае, если установлен флаг общего разрешения прерываний I в регист-
46 Глава 1. Восьмиразрядные микроконтроллеры AVR ре состояния SREG, а также флаг TOIE1 в регистре TIMSK.. В соответствии с этим, прерывания при совпадении регистров TCNT1 и OCR1A/OCR1B вызываются тогда, когда в регистре TIMSK установлен флаг общего разрешения прерываний и флаг OCIE1A/OCIE1B. В отношении таймера/счетчика Т/Cl осталось рассмотреть еще регистр управ- ления TCCR1B (адрес $2Е в области ввода/вывода, адрес $4Е в SRAM). Структура регистра TCCR1В показана на рис. 1.20. 7______6______5 4______3 2______1______0 ICNC1 ICES1 а — — СТС1 CS12 CS11 CS10 Рис. 1.20. Регистр TCCR1B таймера/счетчика Т/С1 HWHWWHK...................................................... '.... Структура регистра TCCR1B в современных микроконтроллерах AVR может отличаться от представленной на рис. 1.20. Так, например, для микроконтроллера ATmega640, задейство- ваны по-другому разряды 3 и 4: WGM12 и WGM13. Совместно с разрядами WGM10 и WGM11 регистра TCCR1А они задают режим работы таймера: обычный, СТС (Clear Timer on Compare Match — обнуление таймера при совпадении содержимого счетного регистра с содержимым регистра OCR1A или ICR1) или режим ШИМ (табл. 1.14). Как уже было сказано ранее, разряды 0-2 используются для выбора частоты тактирования Т/Cl (см. табл. 1.9). Если разряд СТС1 установлен в лог. 1, то Т/С1 возвращается в состояние $0000 по импульсу такта системной синхронизации, сле- дующего после совпадения содержимого счетчика и регистра сравнения А. При ра- боте в режиме ШИМ этот разряд на процесс работы никак не влияет. Разряд ICES1 определяет, каким образом должна осуществляться передача со- стояния счетчика в регистр захвата ICR1: по нарастающему (ICES 1=1) или по нис- падающему фронту (ICES 1=0), — а разряд ICNC1 — должно ли быть активизирова- но подавление помех (если ICNC 1 = 0, то подавление помех отключено). Для подав- ления кратковременных импульсов помех, которые могут привести к ошибочному запуску, входной сигнал зондируется на протяжении четырех периодов такта сис- темной синхронизации. Только после того как будут распознаны четыре последова- тельных низких или высоких уровня входного сигнала, что определяется разрядом ICES 1, при активном подавлении помех будет выполнена запись текущего состоя- ния счетчика в регистр ICR1. Таблица 1.14. Режимы работы таймера/счетчика Т/С1 микроконтроллера ATmega640 WGM13 WGM12 (СТС1) WGM11 (PWM11) WGM10 (PWM10) Режим Значение ТОР Обновление OCR1x 0 0 0 0 Обычный SFFFF Сразу же 0 0 0 1 ШИМ с корректной фазой, 8 разрядов SOOFF Достижение ТОР 0 0 1 0 ШИМ с корректной фазой, 9 разрядов $01FF Достижение ТОР 0 0 1 1 ШИМ с корректной фазой, 10 разрядов $03FF Достижение ТОР 0 1 0 0 СТС OCR1A Сразу же 0 1 0 1 ШИМ (только нарастаю- щий фронт), 8 разрядов $OOFF Достижение BOTTOM 0 1 1 0 ШИМ (только нарастаю- щий фронт), 9 разрядов $01 FF Достижение BOTTOM
Структура микроконтроллеров AVR 47 Таблица 1.14. Режимы работы таймера/счетчика Т/С1 микроконтроллера ATmega640 WGM13 WGM12 (СТС1) WGM11 (PWM11) WGM10 (PWM10) Режим Значение ТОР Обновление OCR1X 0 1 1 1 ШИМ (только нарастаю- щий фронт), 10 разрядов $03FF Достижение BOTTOM 1 0 0 0 ШИМ с корректной фазой и частотой ICR1 Достижение BOTTOM 1 0 0 1 ШИМ с корректной фазрй и частотой OCR1A Достижение BOTTOM 1 0 1 0 ШИМ с корректной фазой ICR1 Достижение ТОР 1 0 1 1 ШИМ с корректной фазой OCR1A Достижение ТОР 1 1 0 0 СТС ICR1 Сразу же 1 1 0 1 Зарезервирован 1 1 1 0 ШИМ (только нарастаю- щий фронт) ICR1 Достижение BOTTOM 1 1 1 1 ШИМ (только нарастаю- щий фронт) OCR1A Достижение BOTTOM Т/С2 Таймер/счетчик Т/С2 обычно имеет разрядность 8 бит и реализует функции сравнения на выходе и ШИМ, аналогичные Т/Cl. Основная особенность Т/С2 за- ключается в том, что в качестве источника тактовых импульсов он может использо-. вать генератор, независимый от системного. Для управления Т/С2 используются два регистра: ASSR (рис. 1.21) hTCCR2 (рис. 1.22). 7 6 5 4 3 2 1 О — — — — AS2 TCN2UB OCR2UB TCR2UB Рис. 1.21. Регистр ASSR таймера/счетчика Т/С2 Г 1РИМЕЧАНИЕ В некоторых современных микроконтроллерах AVR (например, ATmega640) регистр ASSR может быть связан с другим таймером/счетчиком (например, Т/СО). Соответственно, будут называться по-другому его разряды (например, ASO, TCNOUB, OCROUB и TCR0UB). Если установить в лог. 1 разряд AS2, то в качестве источника тактовых импуль- сов можно использовать внешний осциллятор. Оставшиеся три разряда (0-2) ис- пользуются в программах для проверки того, что данные не записываются в регист- ры Т/С2 в тот момент, когда они обновляются аппаратно. Такая проверка необхо- дима по той причине, что осциллятор Т/С2 работает асинхронно по отношению к системному осциллятору. 7 6 5 4 3 2 1_______0 — PWM2 СОМ21 СОМ20 СТС2 CS22 CS21 CS20 ) Рис. 1.22. Регистр TCCR2 таймера/счетчика Т/С2 Установка в лог. 1 разряда PWM2 переводит Т/С2 в режим ШИМ. Назначение разрядов СОМ21 и СОМ20 идентично назначению разрядов COMlxl и СОМ 1x0 таймера/счетчика Т/С1 — выбор режима сравнения на выходе.
48 Глава 1. Восьмиразрядные микроконтроллеры AVR Разряд СТС2 определяет, должен ли счетчик сбрасываться в нуль при совпаде- нии его содержимого с регистром сравнения. Разряды 0-2 определяют частоту так- тового сигнала, полученного с помощью предварительного делителя частоты такта системной синхронизации. Сторожевой таймер Сторожевой таймер (watchdog timer) — встроенный таймер, тактируемый внут- ренним RC-осциллятором, который автоматически сбрасывает микроконтроллер при переполнении своего счетного регистра. В частности, он используется для пре- дотвращения перехода микроконтроллера в режим бесконечного цикла, когда на не- го невозможно повлиять извне. Обобщенная структурная схема сторожевого тайме- ра показана на рис. 1.23. Рис. 1.23. Структурная схема сторожевого таймера Управление сторожевым таймером в различных моделях микроконтроллеров AVR может несколько отличаться. Так, для этого может использоваться регистр управления WDTCR или WDTCSR (рис. 1.24). 7______6 5 4 3 2 1 0 WDTCR WDTCSR — — — WDTOE WDE WDP2 WDP1 WDPO 7 6 5 4 3 2 1 0 WDIF WDIE WDP3 WDCE WDE WDP2 WDP1 WDPO Рис. 1.24. Регистры WDTCR и WDTCSR микроконтроллеров AVR Назначение отдельных разрядов регистров WDTCR и WDTCSR: • WDP0-WDP3 — выбор коэффициента деления частоты следования сигналов сброса (при этом период до наступления сброса зависит от рабочего напряже- ния процессора — табл. 1.15); • WDE — включение/отключение сторожевого таймера (1 — включен); • WDTOE (или WDCE) — если сторожевой таймер должен быть отключен, сле- дует установить этот разряд в лог. 1. После установки этого разряда он в течение четырех периодов такта системной синхронизации остается в состоя- нии лог. 1, а затем аппаратно сбрасывается в лог. 0. Программа пользователя имеет возможность отключить сторожевой таймер посредством записи лог. 0 в разряд WDE только во время этих четырех тактов системной синхронизации. В регистре WDTCSR разряд WDIF устанавливается в 1, когда истекает период до сброса. Это вызывает прерывание (см. следующий подраздел), после обработки которого разряд WDIF автоматически обнуляется аппаратно.
Структура микроконтроллеров AVR 49 Таблица 1.15. Назначение разрядов WDP0-WDP2 регистра WDTCR WDP3 WDP2 WDP1 WDPO Коэффициент де- ления Период до сброса (при Vcc = 5 В) 0 0 0 0 1 16 мс 0 0 0 1 2 32 мс 0 0 1 0 4 64 мс 0 0 1 1 8 128 мс 0 1 0 0 16 256 мс 0 1 0 1 32 512 мс 0 1 1 0 64 1 с 0 1 1 1 128 2,1 с 1 (b 0 0 256 4 с 1 0 ‘ 0 1 512 8с Если разряд WDIE установлен в 1, то установка в 1 разряда I в регистре SREG разрешает прерывание по переполнению сторожевого таймера. В комбинации с разрядом WDE он определяет режим работы сторожевого таймера (табл. 1.16). Таблица 1.16. Режимы работы сторожевого таймера WDE WDIE Режим Действие по истечении периода ожидания 0 0 Отключен — 0 1 Режим прерывания Прерывание 1 0 Режим системного сброса Сброс 1 1 Режим прерывания и сис- темного сброса Прерывание, а после его обработки — систем- ный сброс В системе команд AVR сторожевой таймер сбрасывается в исходное состояние по команде wdr. Обработка прерываний Прерывания — это вызовы определенных функций, генерируемые, главным об- разом, аппаратной частью микроконтроллера. В результате прерывания выполнение программы останавливается, и происходит переход к соответствующей подпро- грамме обработки прерывания. Прерывания бывают внутренними и внешними. Источниками внутреннего пре- рывания являются встроенные модули микроконтроллера (например, таймер/ счет- чик или сторожевой таймер). Внешние прерывания вызываются сбросом (сигнал на выводе RESET) или сигналами заданного уровня на выводах INT. Например, харак- тер сигналов на выводах INTx, вызывающих прерывание, определяется с помощью разрядов регистра управления MCUCR (в ряде старых моделей‘микроконтроллеров AVR) или EICRx (в новых моделях): ISCxO и ISCxl (табл. 1.17). Таблица 1.17. Выбор способа активизации прерывания по входу INTx ISCxl ISCxO Описание 0 0 Прерывание вызывается по уровню лог. 0 на входе INTx 0 1 Прерывание вызывает любым изменением уровня на входе INTx 1 0 Прерывание вызывается по ниспадающему фронту сигнала INTx 1 1 Прерывание вызывается по нарастающему фронту сигнала INTx
50 Глава 1. Восьмиразрядные микроконтроллеры AVR В микроконтроллерах AVR всем прерываниям, включая сброс, поставлен в соответствие собственный вектор прерывания — адрес в начальной области памя- ти программ, по которому компилятор размещает команду перехода к подпрограм- ме обработки прерывания. Перечень векторов прерывания в некоторых старых мо- делях микроконтроллеров AVR может соответствовать табл. 1.18. Таблица 1.18. Векторы прерываний в некоторых старых микроконтроллерах AVR Адрес в памя- ти программ Источник прерывания Описание $0000 RESET Сигнал сброса $0001 ’into Внешний запрос на прерывание по входу INTO $0002 INT1 Внешний запрос на прерывание по входу INT1 $0003 Т/С1 Захват по таймеру/счетчику Т/С1 $0004 Т/С1 Совпадение с регистром сравнения А таймера Т/С1 $0005 Т/С1 Совпадение с регистром сравнения В таймера Т/С1 $0006 Т/С1 Переполнение таймера/счетчика Т/С1 $0007 Т/СО Переполнение таймера/счетчика Т/СО $0008 SPI Завершение передачи данных по интерфейсу SPI $0009 UART Прием байта приемопередатчиком UART завершен $000А UART Регистр данных приемопередатчика UART пуст $000В UART Передача данных приемопередатчиком UART завершена $000С ANA_COMP Прерывание от аналогового компаратора Пример векторов прерывания для ряда новых моделей микроконтроллеров AVR показан в табл. 1.19. Таблица 1.19. Векторы прерываний в некоторых новых микроконтроллерах AVR Адрес в памя- ти программ Источник пре- рывания Описание $0000 RESET Сигнал сброса $0002 INTO Внешний запрос на прерывание по входу INTO $0004 INT1 Внешний запрос на прерывание по входу INT1 $0006 INT2 Внешний запрос на прерывание по входу INT2 $0008 INT3 Внешний запрос на прерывание по входу INT3 $000А INT4 Внешний запрос на прерывание по входу INT4 $000С INT5 Внешний запрос на прерывание по входу INT5 $000Е INT6 Внешний запрос на прерывание по входу INT6 $0010 INT7 Внешний запрос на прерывание по входу INT7 $0012 PCINTO Внешний запрос на прерывание по изменению уровня сигнала на входе INTO $0014 PCINT1 Внешний запрос на прерывание по изменению уровня сигнала на входе INT1 $0016 PCINT2 Внешний запрос на прерывание по изменению уровня сигнала на входе INT2 $0018 WDT Прерывание от сторожевого таймера $001А TIMER2_COMPA Совпадение с регистром сравнения А таймера Т/С2 $001С TIMER2_COMPB Совпадение с'регистром сравнения В таймера Т/С2 $001Е TIMER2_OVF Переполнение таймера Т/С2 $0020 TIMER1_CAPT Событие захвата таймера Т/С1
Структура микроконтроллеров AVR 51 Таблица 1.19. Окончание Адрес в памя- ти программ Источник пре- рывания Описание $0022 TIMER1_COMPA Совпадение с регистром сравнения А таймера Т/С1 $0024 TIMER1_COMPB Совпадение с регистром сравнения В таймера Т/С1 $0026 TIMER1_COMPC Совпадение с регистром сравнения С таймера Т/С1 $0028 TIMER1_OVF Переполнение таймера Т/С1 $002А TIMER0_COMPA Совпадение с регистром сравнения А таймера Т/СО $0020 TIMERO-COMPB Совпадение с регистром сравнения В таймера Т/СО $002Е TIMEROJDVF Переполнение таймера Т/СО $0030 SPI-STC Передача по интерфейсу SPI завершена $0032 USART0_RX Прием данных по LISART0 завершен $0034 USARTOJJDRE Регистр данных USART0 пуст $0036 USART0_TX Передача данных по LISART0 завершена $0038 ANALOG_COMP Прерывание от аналогового компаратора $003А ADC Завершено аналого-цифровое преобразование $003С EE_READY Память EEPROM готова $003Е TIMER3_CAPT Событие захвата таймера Т/СЗ $0040 TIMER3_COMPA Совпадение с регистром сравнения А таймера Т/СЗ $0042 TIMER3_COMPB Совпадение с регистром сравнения В таймера Т/СЗ $0044 TIMER3_COMPC Совпадение с регистром сравнения С таймера Т/СЗ $0046 TIMER3_OVF Переполнение таймера Т/СЗ $0048 USART1_RX Прием данных по USART1 завершен $004А USART1JJDRE Регистр данных USART 1 пуст $0040 USART1_TX Передача данных по USART1 завершена $004Е TWI Прерывание от интерфейса TWI (аналог 12С) $0050 SPM_READY Готовность к сохранению в памяти программ $0052 TIMER4_CAPT Событие захвата таймера Т/С4 $0054 TIMER4_COMPA Совпадение с регистром сравнения А таймера Т/С4 $0056 TIMER4_COMPB Совпадение с регистром сравнения В таймера Т/С4 $0058 TIMER4_COMPC Совпадение с регистром сравнения С таймера Т/С4 $005А TIMER4_OVF Переполнение таймера Т/С4 $0050 TIMER5_CAPT Событие захвата таймера Т/С5 $005Е TIMER5_COMPA Совпадение с регистром сравнения А таймера Т/С5 $0060 TIMER5_COMPB Совпадение с регистром сравнения В таймера Т/С5 $0062 TIMER5_COMPC Совпадение с регистром сравнения С таймера Т/С5 $0064 TIMER5_OVF Переполнение таймера Т/С5 $0066 USART2_RX Прием данных по USART2 завершен $0068 USART2JJDRE Регистр данных USART2 пуст $006А USART2_TX Передача данных по USART2 завершена $006С USART3_RX Прием данных по USART3 завершен $006Е USART3JJDRE Регистр данных USART3 пуст $0070 USART3_TX Передача данных по USART3 завершена В микроконтроллерах AVR все прерывания имеют одинаковый приоритет и в случае одновременного возникновения двух прерываний первым обрабатывается прерывание с меньшим номером вектора. Определять, какое именно прерывание требует обслуживания, задача программиста, и многие компиляторы с языка С
52 Глава 1. Восьмиразрядные микроконтроллеры AVR предоставляют для этой цели готовые функции, освобождающие от необходимости самому “вычислять” источник прерывания. В момент возникновения прерывания в стек помещается адрес возврата — ад- рес команды, которая должна быть выполнена первой после выхода из подпрограм- мы обработки прерывания. В результате выполнения последней ассемблерной ко- манды подпрограммы обработки прерывания (для микроконтроллеров AVR — это команда reti) адрес возврата извлекается из стека в счетчик команд, и выполнение программы продолжается. Управление прерываниями В микроконтроллерах AVR за управление прерываниями отвечают, главным образом, четыре вида регистров: • GIMSK (General Interrupt Mask Register) или EIMSK (External Interrupt Mask Register) — разрешение или запрет внешних прерываний по входу INTx; • G1FR (General Interrupt Flag Register) или EIFR (External Interrupt Flag Register) — регистр флагов внешних прерываний; • TIMSKx (Timer/Counter Interrupt Mask Register) -г- регистр маскирования пре- рываний от таймера/счетчика Т/Сх; • TEFRx (Timer/Counter Interrupt Flag Register) — регистр флагов прерываний от таймера/счетчика Т/Сх; • PCICR (Pin Change Interrupt Control Register) — регистр управления прерыва- ниями по изменению состояния входа; • PCIFR (Pin Change Interrupt Flag Register) — регистр флагов прерываний по из- менению состояния входа; • PCMSKx (Pin Change Mask Register) — регистр маскирования прерываний по изменению состояния входа. О состоянии прерывания сигнализирует соответствующий флаг, который уста- навливается или сбрасывается в регистре флагов. Даже если в регистре маски пре- рываний установлен соответствующий отдельный разряд разрешения прерывания, то прерывания могут активизироваться только тогда, когда в регистре состояния SREG установлен разряд общего разрешения прерываний I (разряд 7). Если это име- ет место, и наступает прерывание, то выполнение программы ответвляется по соот- ветствующему адресу (см. табл. 1.18 и табл. 1.19), и разряд общего разрешения пре- рываний I в регистре SREG сбрасывается в состояние лог. О, блокируя тем самым последующие прерывания. Если требуется прервать подпрограмму другим преры- ванием, то после входа в подпрограмму обработки прерывания программа пользо- вателя должна установить флаг I в лог. 1. Вместе с входом в подпрограмму обработки прерывания аппаратно сбрасывает- ся также и соответствующий флаг, вызвавший прерывание. Некоторые флаги пре- рываний могут быть сброшены самим пользователем посредством установки соот- ветствующего флага в лог. 1. Регистры GIMSK и EIMSK Регистры GIMSK (в старых моделях микроконтроллеров AVR) и EIMSK (в новых моделях) (рис. 1.25) используются для разрешения внешних прерываний.
Структура микроконтроллеров AVR 53 7 6 5 4 3 2 1 0 GIMSK INT1 INTO — — — — — — 7 6 5 4 3 2 1 0 EIMSK INT7 INT6 INT5 INT4 INT3 INT2 INT1 INTO Рис. 1.25. Структура регистров GIMSK и EIMSK микроконтроллеров AVR Если разряд INTx установлен в лог. 1, то внешнее прерывание по входу INTx будет разрешено до тех пор, пока установлен в лог. 1 разряд I в регистре состояния SREG. Регистры GIFR и EIFR Состояние внешнего прерывания определяется по регистру GIFR (в старых мо- делях микроконтроллеров AVR) или EIFR (в новых моделях) (рис. 1.26). 7 6 5 4 3 2 1 0 GIFR INTF1 INTFO — — — — — — 7 6 5 4 3 2 1 0 EIFR INTF7 INTF6 INTF5 INTF4 INTF3 INTF2 INTF1 INTFO Рис. 1.26. Структура регистров GIFR и EIFR микроконтроллеров AVR Флаг INTFx устанавливается в лог. 1, если возникает внешнее прерывание по сигналу на выводе INTx. При входе в подпрограмму обработки прерывания этот разряд переводится аппаратно в исходное состояние лог. 0. Регистры TIMSKx и TIFRx Регистр TIMSKx (его “классический” вариант показан рис. 1.27) используется для разрешения прерываний от таймера/счетчика Т/Сх. 7 6 5 4 3 2 1 О TOIE1 OCIE1A OCIE1B — TICIE1 — TOIEO — Рис. 1.27. Структура регистра TIMSK старых моделей микроконтроллеров AVR, когда один регистр управлял двумя таймерами/счетчиками Состояние прерываний, имеющих отношение к таймерам/счетчикам микрокон- i роллеров AVR, определяется по регистру TIFRx (его “классический” вариант пока- зан на рис. 1.29). 7 6 5 4 3 2 1 *0 TOV1 OCF1A OCF1B — ICF1 — TOVO — Рис. 1.28. Структура регистра TIFR микроконтроллеров AVR В новых микроконтроллерах AVR каждому таймеру/счетчику сопоставлен от- дельная пара регистров TIMSKx и TIFRx, суть разрядов в котором аналогична сути азрядов в традиционных регистрах TIMSK и TIFR: • когда разряд TOIEx и разряд I в регистре состояния SREG установлены в лог. I, то разрешено прерывание при переполнении Т/Сх; в случае переполнения в регистре TIFRx устанавливается флаг TOVx;
54 Глава 1. Восьмиразрядные микроконтроллеры AVR • если разряд OCIExA и разряд I в регистре состояния SREG установлены в лог. 1, то разрешено прерывание при совпадении содержимого регистра срав- нения А с текущим состоянием Т/Сх; в случае совпадения, в регистре TIFRx ус- танавливается флаг OCFxA; • если разряд OCIExB и разряд I в регистре состояния SREG установлены в лог. 1, то разрешено прерывание при совпадении содержимого регистра срав- нения В с текущим состоянием Т/Сх; в случае совпадения, в регистре TIFRx ус- танавливается флаг OCFxB; • если разряд OCIExC и разряд I в регистре состояния SREG установлены в лог. 1, то разрешено прерывание при совпадении содержимого регистра срав- нения С с текущим состоянием Т/Сх; в случае совпадения, в регистре TIFRx ус- танавливается флаг OCFxC; • если разряд (Т)1С1Е1 и разряд I в регистре состояния SREG установлены в лог. 1, то разрешается прерывание при выполнении условия захвата; когда возникает срабатывание по захвату, в регистре TIFRx устанавливается флаг ICFx; • если разряд TOIEx и разряд I в регистре состояния SREG установлены в лог. 1, то разрешается прерывание при переполнении таймера/счетчика Т/Сх. В таком случае, в регистре TIFRx устанавливается флаг TOVx. Установка в лог. 1 одного из фЛагов в регистре TIFRx приводит к переходу по соответствующему вектору прерывания. При входе в подпрограмму обработки пре- рывания, флаг в регистре TIFRx аппаратно сбрасывается в лог. 0. Регистры управления прерываниями по изменению состояния входа Если какой-либо из разрядов в регистре PCICR (РС1Е0:РС1Е2) установлен в лог. 1, и флаг I в регистре SREG также установлен в лог. 1, то разрешено соответ- ствующее прерывание по изменению состояния входов. Маскирование таких пре- рываний осуществляют с помощью регистров PCMSK. Когда возникает прерыва- ние, устанавливается соответствующий флаг в регистре PCIFR. Сброс Сброс — это, по сути, одна из форм прерываний, вызывающая перезапуск мик- роконтроллера (аппаратная инициализация всех регистров управления и перифе- рийных устройств и выполнение программы, начиная с адреса $0000). Вектор сбро- са всегда расположен самым первым. Возможны следующие основные варианты сброса: • сбро^ при включении питания (т.е. когда питающее напряжение падает ниже определенного, заданного уровня Урот); • внешний сброс (сигнал низкого уровня подается на вывод /RESET микрокон- троллера); • сброс по провалу напряжения, когда питающее напряжение падает ниже опре- деленного, заданного уровня УВог, при активном детекторе провалов (присутст- вует не во всех микроконтроллерах AVR); • сброс от сторожевого таймера (микроконтроллер сбрасывается по истечению времени, заданного сторожевым таймером, если этот таймер активен). В этой книге затрагивается только сброс от сторожевого таймера, поэтому рас- сматривать данный вопрос подобно мы не будем. Отметим только, что управление
Структура микроконтроллеров AVR 55 источниками сброса в современных микроконтроллерах AVR осуществляется с по- мощью регистра MCUSR (MCUCSR) (адрес $34 в области ввода/вывода или $54 в адресном пространстве SRAM). Флаги, содержащиеся в этом регистре, указывают на источник сброса. При этом следует помнить, что любой разряд регистра MCUSR, установленный в 1, автоматически не обнуляется. Таким образом, отслеживать со- стояние данного регистра — задача программиста. “Спящие”режимы процессора Микроконтроллер^ AVR допускают переход в “спящий” режим, когда проис- ходит временное отключение генератора тактовых импульсов. В таком режиме по- требление энергии сведено к минимуму, а выход из него осуществляется при полу- чении запроса на прерывание. Переход в “спящий” режим реализуется по ассемблерной команде sleep. При этом должен быть предварительно установлен в лог. 1 разряд SE регистра управле- ния MCUCR. или SMCR (в ряде новых микроконтроллеров AVR). Когда во время режима пониженного энергопотребления происходит прерыва- ние, центральный процессор выходит из “спящего” режима, выполняет подпро- грамму обработки прерывания и продолжает выполнение программы с команды, следующей после sleep. Если во время режима пониженного энергопотребления поступает сигнал сброса, то центральный процессор выходит из “спящего” режима и продолжает выполнение программы с команды, расположенной по адресу $000 в программной области. Для современных микроконтроллеров AVR может быть выбран один из двух “спящих” режимов: • Ждущий режим (Idle Mode). Работа процессора приостанавливается, но тайме- ры/счетчики, сторожевой таймер, система прерываний и тактирования, после- довательные интерфейсы, аналоговый компаратор и АЦП остаются активными. Благодаря этому, центральный процессор может быть возвращен в обычный режим работы с помощью соответствующего прерывания. • Режим пониженного энергопотребления (Power-down Mode). Системный ос- циллятор (а значит и весь микроконтроллер) находится в отключенном состоя- нии. В таком режиме с помощью внутреннего RC-генератора колебаний может включаться лишь сторожевой таймер cq своим собственным обеспечением так- товой частотой. Активный сторожевой таймер по истечении времени задержки опять переводит микроконтроллер в нормальное состояние. Если сторожевой таймер также отключен, то в нормальное состояние его может перевести только внешний сигнал сброса или внешнее прерывание. • Режим снижения шума для АЦП (ADC Noise Reduction Mode). В этом режиме процессор отключен, однако разрешено аналого-цифровое преобразование и внешние прерывания. Кроме того, продолжают работать таймеры/счетчики и сторожевой таймер. Это снижает уровень помех для АЦП, что позволяет полу- чить более точные результаты преобразования. Если АЦП включен, но преобра- зование начинается автоматически сразу же после перехода в данный “спящий” режим. Выход из него осуществляется по прерыванию при скончании аналого- цифрового преобразования или по любому другому разрешенному прерыванию. • Экономный режим (Power-save Mode). Идентичен режиму пониженного энер- гопотребления за тем исключением, что, кроме сторожевого, работает еще один из таймеров (например, Т/С2).
56 Глава 1. Восьмиразрядные микроконтроллеры AVR • Дежурный режим (Standby Mode). Доступен только в том случае, когда актив- но тактирование от внешнего кварца или резонатора. Этот режим аналогичен режиму пониженного энергопотребления за тем исключением, что продолжает работать осциллятор. Выход из режима ожидания происходит после шести так- товых циклов. • Расширенный дежурный режим (Extended Standby Mode). Аналогичен режи- му ожидания за тем исключением, что остается активным один из тайме- ров/счетчиков (например, Т/С2). В старых моделях микроконтроллеров AVR были доступны только два “спя- щих” режима: ждущий и пониженного энергопотребления. Выбор одного из них осуществлялся с помощью разряда SM регистра управления MCUCR. Если разряд SM установлен в лог. 1, то микроконтроллер переводится в режим пониженного энергопотребления последующей командой sleep, если же он был обнулен, то мик- роконтроллер переводится в ждущий режим в том случае, если ранее в регистре MCUCR был установлен разряд SE. В современных микроконтроллерах AVR для выбора “спящего” режима служит регистр управления SMCR (Sleep Mode Control Register), который, кроме SE, содер- жит разряды SM0:SM2 (табл. 1.20). Таблица 1.20. Выбор “спящего” режима с помощью разрядов SMx регистра SMCR SM2 SM1 SM0 Режим 0 0 0 Ждущий 0 0 1 Снижения шума для АЦП 0 1 0 Пониженного энергопотребления 0 1 1 Экономный 1 0 0 Зарезервировано 1 0 1 Зарезервировано 1 1 0 Дежурный 1 1 1 Расширенный дежурный Кроме того, в современных микроконтроллерах AVR используются регистры PRRx (Power Reduction Register), разряды которых позволяют отключать с целью снижения энергопотребления отдельные периферийные устройства (например, тай- меры/счетчики, АЦП или последовательные интерфейсы). При этом текущее состо- яние отключаемого устройства фиксируется, а связанные с ним регистры в области ввода/вывода блокируются от изменений. Для его возврата в рабочее состояние не- обходимо обнулить соответствующий разряд в регистре PRRx. Устройство сразу же возвратится в состояние до отключения. Последовательный ввод/вывод В отличие от параллельного обмена данными, в случае последовательного вво- да/вывода используется только одна информационная линия. При этом передача данных бывает асинхронной и синхронной. При синхронном последовательном вводе/выводе передача отдельных битов данных синхронизируется с помощью одновременно передаваемого тактового сиг- нала. Синхронная последовательная передача данных применяется, главным обра- зом, на уровне печатных плат, в том числе — для обмена данными между различ-
Структура микроконтроллеров AVR 57 ными интегрированными блоками в составе схемы микроконтроллера и различными периферийными схемами (например, для обработки видеосигнала). В противоположность этому, при асинхронной передаче данных передается не тактовый сигнал, а старт-бит и стоп-бит, определяющие начало и завершение пе- редачи слова данных (рис. 1.29). Рис. 1.29. Типичный формат асинхронной передачи данных (в данном примере — байта 10000010) Главной областью применения асинхронной передачи, как правило, является не обмен данными в составе схемы, а коммуникация между блоками, разделенными пространственно и обладающими признаками собственного интеллекта. В качестве примера можно назвать связь между персональным компьютером и принтером, мо- демом, программирующим устройством или регистратором данных. В микроконтроллерах AVR семейств AT90S, ATtiny и ATmega асинхронная пе- редача данных осуществляется с помощью приемопередатчика UART (или USART), а для синхронного ввода/вывода используется особый режим приемопередатчика USART, а также интерфейсы SPI и 12С (аналог — TWI). Кроме того, новые микро- контроллеры AVR семейства ATmega оснащаются универсальным последователь- ным интерфейсом USI, объединяющим в себе функции SPI и TWI. Рассмотрим пе- речисленные средства подробнее. Приемопередатчик UART В старых моделях микроконтроллеров AVR использовался приемопередатчик UART. Для его работы были выделены в общей сложности четыре регистра: • регистр управления UCR (адрес в области ввода/вывода — $0А, адрес SRAM — $2А) — предназначен для управления функциями приемопередатчика и для разрешения/запрета прерываний от UART (рис. 1.30); 7_____6 5 4_____3 2______1_____0 RXCIE TXCIE UDRIE RXEN TXEN CHR9 RXB8 ТХВ8 Рис. 1.30. Регистр управления UCR микроконтроллеров AVR • регистр состояния USR (адрес в области ввода/вывода — $0В, адрес SRAM — $2В)(рис. 1.31); 7______6 5 4______3 2______1______0 RXC ТХС UDRE FE OR — — — Рис. 1.31. Регистр состояния USR микроконтроллеров AVR • регистр данных UDR (адрес в области ввода/вывода — $0С, адрес SRAM — $2С) — физически состоит из двух регистров, обращение к которым осуществ-
58 Глава 1. Восьмиразрядные микроконтроллеры AVR ляется по одному и тому же адресу; один из них используется для передачи, а другой — для приема данных; • регистр UBRR (адрес в области ввода/вывода — $09, адрес SRAM — $29) — применяется для настройки требуемой скорости передачи данных с помощью встроенного контроллера, позволяющего устанавливать наиболее распростра- ненные скорости передачи по стандарту RS232C. Рассмотрим разряды регистра UCR. • Если разряд RXCIE и разряд общего разрешения прерываний I в регистре со- стояния SREG установлены в лог. 1, то разрешается прерывание по завершению приема через UART. • Если разряд TXCIE и разряд общего разрешения прерываний I в регистре со- стояния SREG устанбвлены в лог. 1, то разрешается прерывание по завершению передачи через UART. • Если разряд UDRIE и разряд общего разрешения прерываний I в регистре со- стояния SREG установлены в лог. 1, то разрешается прерывание по опустоше- нию регистра данных UART. • Если разряд RXEN установлен в лог. 1, то происходит разблокирование прием- ника, и вывод 0 порта D становится входом UART. Если разряд RXEN содержит лог. 0, то принимающий элемент приемопередатчика UART блокируется, и вывод 0 порта D может использоваться в качестве обычного входа/выхода. Если разряд RXEN содержит лог. 0, то флаги OR и FE регистра состояния USR не могут быть установлены. Если эти флаги все же установлены, то они с по- мощью RXEN не сбрасываются. • Если разряд TXEN установлен в лог. 1, то передатчик деблокируется, а вывод 1 порта D становится выходом UART. Если разряд TXEN содержит лог. 0, то пе- редающий элемент UART блокируется, и вывод 1 порта D может использовать- ся в качестве обычного входа/выхода. Если разряд TXEN во время процесса пе- редачи устанавливается в лог. 0, то передатчик не блокируется до тех пор, пока текущий символ в сдвиговом регистре, а также символ, возможно, ожидающий на передачу в регистре UDR не будут полностью переданы. • Если разряд CHR9 установлен в лог. 1, то слова данных, подлежащие переда- че/считыванию имеют длину 11 бит (9 разрядов данных плюс стартовый и стоп- бит). Девятый бит из разряда ТХВ8 при передаче попадает в UCR, а при прие- ме — в разряд RXB8 регистра UCR. Девятый бит может быть использован для размещения дополнительных информационных данных, например, в качестве бита четности или второго стоп-бита. Если разряд CHR9 установлен в лог. 0, то слова данных, подлежащие передаче/считыванию имеют длину 10 бит (8 разря- дов данных плюс стартовый и стоп-бит). Регистр состояния USR информирует программу пользователя о состоянии приемопередатчика UART. • Флаг RXC устанавливается в лог. 1, если принятое слово данных было перене- сено из сдвигового регистра в регистр UDR (без учета возможных ошибок кад- рирования, которые могли возникнуть во время передачи данных). После чте- ния регистра UDR флаг RXC автоматически сбрасывается в лог. 0. • Флаг ТХС будет установлен в лог. 1, если символ в сдвиговом регистре был пе- редан полностью (то есть, включая стоп-бит), и из регистра UDR не ожидается новый байт данных. Флаг очень полезен в полудуплексном режиме работы, ко-
Структура микроконтроллеров AVR 59 гда непосредственно после передачи необходимо переключиться в режим при- ема. При входе в подпрограмму обработки прерывания флаг завершения пере- дачи ТХС аппаратно сбрасывается в лог. 0. • Флаг UDRE устанавливается в лог. 1, если содержимое регистра UDR было пе- ренесено в сдвиговой регистр. С его помощью пользователь получает уведом- ление о том, что приемопередатчик готов к передаче нового байта. Соответст- вующая подпрограмма обработки прерывания выполняется до тех пор, пока ус- тановлен флаг UDRE. Флаг UDRE сбрасывается при записи байта данных в ре- гистр UDR. В случае сброса при включении питания флаг UDRE устанавлива- ется в лог. 1, чтобы показать, что приемопередатчик готов к передаче нового байта данных. • Флаг FE устанавливается в лог. 1 при обнаружении ошибки кадрирования. Это происходит,‘если при трех сканированиях стоп-бита был более одного раза об- наружен лог. 0, и тем самым стоп-бит был распознан как сигнал низкого уровня. Флаг FE сбрасывается, когда стоп-биту соответствует сигнал высокого уровня. Пользовательская программа должна постоянно проверять флаг FE перед чте- нием регистра UDR, чтобы можно было распознать потенциально некоррект- ный символ в регистре приема. • Флаг OR устанавливается в лог. 1, если один из символов, переданных в ре- гистр UDR из сдвигового регистра, не был прочитан перед следующим посту- пившим символом. Этот флаг обновляется после считывания действительного символа из регистра UDR, поэтому пользовательская программа должна всегда проверять флаг OR после чтения регистра UDR, чтобы распознать потерю одно- го поступившего символа. Флаг OR сбрасывается при переносе считанного символа в регистр UDR. Настройка скорости передачи данных через UART В приемопередатчик UART встроен специальный контроллер скорости переда- чи данных, представляющий собой делитель частоты для определения скорости пе- редачи данных на основании такта системной синхронизации. Скорость передачи может быть вычислена по следующему уравнению: fBaud = <I>/(16(UBRR+l)) где feaud — скорость передачи в бодах, Ф — такт системной синхронизации; UBRR— содержимое 8-разрядного регистра UBRR (0...255). Значения, записывае- мые в регистр UBRR для наиболее распространенных скоростей передачи данных, представлены в табл. 1.21. Все значения, для которых погрешность получается меньше 2%, в табл. 1.21 выделены полужирным шрифтом. Таблица 1.21. Значения регистра UBRR для наиболее распространенных скоростей пе- редачи данных и частоты работы кварцевого осциллятора Скорость передачи данных, бод 1,8432 МГц Погреш- ность t (%) 3,6864 МГц Погреш- ность (%) 4 МГц Погреш- ность (%) 1200 UBRR = 95 0,0 UBRR = 191 0,0 UBRR = 207 0,2 2400 UBRR = 47 0,0 UBRR = 95 0,0 UBRR = 103 0,2 4800 UBRR = 23 0,0 UBRR = 47 0,0 UBRR = 51 0,2 9600 UBRR = 11 0,0 UBRR = 23 0,0 UBRR = 25 0,2 14400 UBRR = 7 0,0 UBRR = 15 0,0 UBRR = 16 2,1
60 Глава 1. Восьмиразрядные микроконтроллеры AVR Таблица 1.21. Окончание Скорость передачи данных, бод 1,8432 МГц Погреш- ность (%) 3,6864 МГц Погреш- ность (%) 4 МГц Погреш- ность (%) 19200 UBRR = 5 0,0 UBRR = 11 0,0 UBRR = 12 0,2 2400 UBRR = 207 0,2 UBRR = 287 — UBRR = 312 — 4800 UBRR = 103 0,2 UBRR = 143 0,0 UBRR = 155 0,2 9600 UBRR = 51 0,2 UBRR = 71 0,0 UBRR = 77 0,2 14400 UBRR = 34 0,8 UBRR = 47 0,0 UBRR = 51 0,2 19200 UBRR =.25 0,2 UBRR = 35 0,0 UBRR = 38 0,2 Значения, выделенные курсивом, превышают 255, и потому не могут быть ус- тановлены в регистре UBRR, имеющем длину всего восемь разрядов. Если потребу- ется соответствующая скорость передачи данных, то необходимо переходить на бо- лее низкие частоты колебаний кварцевого осциллятора. Приемопередатчик USART В современных микроконтроллерах AVR вместо UART используются приемо- передатчики USART. Принципы их работы в общем случае сходны. Отличия за- ключаются, в основном, в структуре и названии управляющих регистров. Так, ре- гистр UBRR, задающий скорость обмена данными, теперь — 16-разрядный и фак- тически состоит из двух регистров: UBBRH и UBRRL. Это позволяет задать ско- рость передачи до 1 Мбод (см. табл. 1.22). Регистру USR теперь соответствует регистр управления и состояния А (UCSRA). Кроме рассмотренных выше разрядов, в нем также задействованы также разряды 0-2. • МРСМ (Multi-processor Communication Mode) — если этот разряд содержит 1, то все кадры, поступающие на приемник USART без информации об адресе, иг- норируются. В режиме вывода этот разряд нс используется. • U2X — установка этого разряда в 1 удваивает скорость передачи в асинхронном режиме (в синхронном режиме работы USART этот разряд должен содержать 0). Влияние значения U2X на скорость и погрешность передачи показано в табл. 1.22. Все значения UBRR, для которых погрешность получается меньше 2%, в табл. 1.22 выделены полужирным шрифтом. • UPE (USART Parity Error) — этот разряд устанавливается в 1, если активна про- верка четности, и символ, поступивший в буфер приемника, содержит ошибку четности. При записи в регистр UCSRA всегда обнуляйте этот разряд. Таблица 1.22. Значения регистра UBRR для наиболее распространенных скоростей пе- редачи данных через USART и частоты кварцевого осциллятора Частота, МГц Скорость, бод U2X = 0 U2X=1 UBRR Погрешность, % UBRR Погрешность, % 1 2400 25 0,2 51 0,2 4800 12 0,2 25 0,2 9600 6 -7 12 0,2 14400 3 8,5 8 -3,5 19200 2 8,5 6 -7 28800 1 8,5 3 8,5 38400 1 -18,6 2 8,5
Структура микроконтроллеров AVR 61 Таблица 1.22. Продолжение Частота, МГц Скорость, бод U2X = 0 U2X = 1 UBRR Погрешность, % UBRR Погрешность, % 1 57600 0 8,5 1 8,5 76800 — — 1 -18,6 115200 — — 0 8,5 1,8432 2400 47 0 95 0 4800 23 0 47 0 9600 11 0 23 0 14400 7 0 15 0 19200 5 0 11 0 28800 3 0 7 0 38400 2 0 5 0 57600 1 0 3 0 76800 1 -25 2 0 115200 0 0 1 0 230400 — — 0 0 2 2400 51 0,2 103 0,2 4800 25 0,2 51 0,2 9600 12 0,2 25 0,2 14400 8 -3,5 16 2,1 19200 6 -7 12 0,2 28800 3 8,5 8 -3,5 38400 2 8,5 6 -7 57600 1 ' 8,5 3 8,5 76800 1 -18,6 2 8,5 115200 0 8,5 1 8,5 250000 — — 0 0 3,6864 2400 95 0 191 0 4800 47 0 95 0 9600 23 0 47 0 14400 15 0 31 0 19200 11 0 23 0 28800 7 0 15 0 38400 5 0 11 0 57600 3 0 7 0 76800 2 0 5 0 115200 1 0 3 0 230400 0 0 1 0 250000 0 -7,8 1 -7,8 500000 — — 0 -7,8 4 2400 103 0,2 207 0,2 4800 51 0,2 103 0,2 9600 25 0,2 51 0,2 14400 16 2,1 34 -0,8 19200 12 0,2 25 0,2 28800 8 -3,5 16 2,1
62 Глава 1. Восьмиразрядные микроконтроллеры AVR Таблица 1.22. Продолжение Частота, МГц Скорость, бод U2X = 0 U2X = 1 UBRR Погрешность, % UBRR Погрешность, % 4 38400 6 -7 12 0,2 57600 3 8,5 8 -3,5 76800 2 8,5 6 -7 115200 1 8,5 3 8,5 230400 0 8,5 1 8,5 250000 0 0 1 0 500000 — — 0 0 7,3728 2400 191 0 383 0 4800 95 0 191 0 9600 47 0 95 . 0 14400 31 0 . 63 0 19200 23 0 47 0 28800 15 0 31 0 38400 11 0 23 0 57600 7 0 15 0 76800 5 0 11 0 115200 3 0 7 0 230400 1 0 3 0 250000 1 -7,8 3 -7,8 500000 0 -7,8 1 -7,8 1000000 — — 0 -7,8 8 2400 207 0,2 416 -0,1 4800 103 0,2 207 0,2 9600 51 0,2 103 0,2 14400 34 -0,8 68 0,6 19200 25 0,2 51 0,2 28800 16 2,1 34 -0,8 38400 12 0,2 25 0,2 57600 8 -3,5 16 2,1 76800 6 -7 12 0,2 115200 3 8,5 8 -3,5 230400 1 8,5 3 8,5 250000 1 .0 3 0 500000 0 0 1 0 1000000 — — 0 0 11,0592 2400 287 < 0 575 0 4800 143 0 287 0 9600 71 0 143 0 14400 47 0 95 0 19200 35 0 71 0 28800 23 0 47 0 38400 17 0 35 0 57600 11 0 23 0 76800 8 0 17 0
Структура микроконтроллеров AVR 63 Таблица 1.22. Продолжение Частота, МГц Скорость, бод U2X = 0 U2X = 1 UBRR Погрешность, % UBRR Погрешность, % 11,0592 115200 5 0 11 0 230400 2 0 5 0 250000 2 -7,8 5 -7,8 500000 — — 2 -7,8 14,7456 2400 383 0 767 0 4800 191 0 383 0 9600 95 0 191 0 14400 63 0 127 0 19200 47 0 95 0 28800 31 0 63 0 38400 23 0 47 0 57600 15 0 31 0 76800 11 0 23 0 115200 7 0 15 0 230400 3 0 7 0 250000 3 -7,8 6 5,3 500000 1 -7,8 3 -7,8 1000000 0 -7,8 1 -7,8 16 2400 416 -0,1 832 0 4800 207 0,2 416 -0,1 9600 103 0,2 207 0,2 14400 68 0,6 138 -0,1 19200 51 0,2 103 0,2 28800 34 -0,8 68 0,6 38400 25 0,2 51 0,2 57600 16 2,1 34 -0,8 76800 12 0,2 25 0,2 115200 8 -3,5 16 2,1 230400 3 8,5 8 -3,5 250000 3 0 7 0 500000 1 0 3 0 1000000 0 0 1 0 18,432 2400 479 0 959 0 4800 239 0 479 0 9600 119 0 239 0 14400 79 0 159 0 19200 59 0 119 0 28800 39 0 79 0 38400 29 0 59 0 57600 19 0 39 0 76800 14 0 29 0 115200 9 0 19 0 230400 4 0 9 0 250GO0 4 -7,8 8 2,4
64 Глава 1. Восьмиразрядные микроконтроллеры AVR Таблица 1.22. Окончание Частота, МГц Скорость, бод U2X = 0 U2X = 1 UBRR Погрешность, % UBRR Погрешность, % 18,432 500000 — — 4 -7,8 20 2400 520 0 1041 0 4800 259 0,2 520 0 9600 129 0,2 259 0,2 14400 86 -0,2 173 -0,2 19200 64 0,2 129 0,2 28800 42 0,9 86 -0,2 38400 32 -1,4 64 0,2 57600 21 -1,4 42 0,9 76800 15 1,7 32 -1,4 115200 10 -1,4 21 -1,4 230400 4 8,5 10 -1,4 250000 4 0 9 0 500000 — — 4 0 Регистру UCR в случае приемопередатчика USART соответствует регистр управления и состояния В (UCSRB). Его отличие заключается только в том, что разряд CHR9 был заменен разрядом UCSZ2, который совместно с разрядами UCSZ0 и UCSZ1 регистра UCSRC определяет количество бит в кадре данных (см. ниже). Для управления USART используется еще один регистр управления и состоя- ния: UCSRC (рис. 1.32). 7 6 5 4 3 2 1 О UMSEL1 UMSELO UPM1 UPM0 USBS UCSZ1 ucszo UCPOL Рис. 1.32. Регистр управления и состояния С приемопередатчика USART Рассмотрим разряды регистра UCSRC. • UCPOL (Clock Polarity) — задает соотношение между изменением данных на выходе или опросом данных на входе и тактом синхронизации ХСК (только в синхронном режиме передачи; в асинхронном режиме этот разряд должен со- держать 0) (табл. 1.23). Таблица 1.23. Значение разряда UCPOL регистра UCSRC UCPOL Изменение выводимых данных (на выходе TxD) Опрос принимаемых данных (на входе RxD) 0 Нарастающий фронт сигнала ХСК Ниспадающий фронт сигнала ХСК 1 Ниспадающий фронт сигнала ХСК Нарастающий фронт сигнала ХСК • UCSZ1:UCSZO (Character Size) — эти разряды в сочетании с разрядом UCSZ2 из регистра UCSRB задают количество бит данных в передаваемом кадре (табл. 1.24). • USBS (Stop Bit Select) — выбор количество стоп-битов, вставляемых в кадр пе- редатчиком (приемник значение этого разряда игнорирует): 0 — 1 бит; 1 — 2 бита. • UPM1:UPMO (Parity Mode) — активизация и конфигурирование контроля чет- ности (табл. 1.25).
Структура микроконтроллеров AVR 65 • UMSEL1 :UMSEL0 (USART Mode Select) — выбор режима работы USART (табл. 1.26). Таблица 1.24. Определение размера символа данных UCSZ2 UCSZ1 UCSZ0 Размер символа 0 0 0 5 бит 0 0 1 6 бит 0 1 0 7 бит 0 1 1 8 бит 1 0 0 Зарезервировано 1 0 1 Зарезервировано 1 1 0 Зарезервировано 1 1 1 9 бит Таблица 1.25. Управление контролем четности в USART UPM1 UPM0 Контроль четности 0 0 Отключен 0 1 Зарезервировано 1 0 Включен, проверка на четность 1 1 Включен, проверка на нечетность Таблица 1.26. Выбор режима работы USART UMSEL1 UMSEL0 Режим 0 0 Асинхронный USART 0 1 Синхронный USART 1 0 Зарезервировано 1 1 Ведущее устройство в режиме SPI (MSPIM) Следует отметить, что в ряде микроконтроллеров AVR реализовано более одно- го приемопередатчика USART. В таком случае управляющие регистры и их разряды содержат соответствующий номер (например, для USART 1 — UCSR1A, UCSR1B, UCSR1C, UBRR1H, UBRR1L и т.д.). Синхронная передача данных по интерфейсу SPI Интерфейс SPI (Serial Peripheral Interface) служит для обмена данными с пери- ферийными устройствами. В качестве таких устройств могут выступать простые сдвиговые регистры или буквенно-цифровые модули индикации, а также сложные микропроцессорные системы или системы регистрации данных. Многие компании- изготовители предлагают большой выбор устройств с интерфейсом SPI. В случае обмена данными по интерфейсу SPI микроконтроллер работает в режиме ведущего устройства (Master), взаимодействуя с одним или несколькими ведомыми блоками (Slave). Схема передачи данных по интерфейсу SPI микрокон- троллеров AVR показана на рис. 1.33 (MSB — старший разряд, a LSB — младший разряд передаваемого байта). Ведущее устройство берет на себя активную часть обмена данными, вызывая передачу и управляя процессом. Ведомое устройство не может само быть активным. Оно принимает и передает данные только тогда, когда происходит его активизация со стороны ведущего устройства по линии /SS. Ведущее устройство также генери- рует такт для передачи по выходной линии SCK. Для ведомого блока вывод SCK
66 Глава 1. Восьмиразрядные микроконтроллеры AVR является входом, через который он получает от Master-устройства тактирующие сигналы. Сдвиговой регистр MASTER Рис. 1.33. Схема передачи данных по интерфейсу SPI микроконтроллеров AVR/PIC Если ведомое устройство активизируется ведущим по линии /SS, то начинается обмен данными: Master записывает подлежащий передаче байт в свой сдвиговой ре- гистр данных (для микроконтроллеров AVR семейств AT90S, ATtiny и ATmega — ре- гистр SPDR). С помощью каждого выработанного тактового импульса Master пере- мещает один бит данных на выход MOSI, a Slave одновременно в обратном направле- нии передает один бит на вход MISO ведущего блока. Таким образом, в течение цик- ла SPI, состоящего из восьми тактовых импульсов, Master и Slave обмениваются бай- том данных. По окончании передачи данных в регистре состояния интерфейса SPI устанав- ливается флаг соответствующего запроса на прерывание. Этот флаг указывает на окончание передачи и вызывает запрос на прерывание после того как в регистре управления SPI будет установлен разряд разрешения на прерывание от интерфейса SPI. В режиме “Master” текущая передача данных может быть преждевременно за- вершена выдачей в линию /SS сигнала лог. 1. К интерфейсу SPI ведущего устройства можно подключать несколько ведомых устройств (пример для микроконтроллеров AVR — на рис. 1.34), однако активным будет только то из них, на вход /SS которого будет подан уровень лог. 0. Выходы MISO незадействованных ведомых блоков находятся в высокоомном состоянии и не влияют на процесс передачи данных. В примере на рис. 1.34 устройство G2, с точки зрения ведущего устройства, яв- ляется только блоком передачи (например, ЦАП с интерфейсом SP1), а устройство G3 — только блоком приема. В качестве линий SPI используются выводы порта В, например: • /SS — разряд 4 или 0 порта В; • MOSI — разряд 5 или 2 порта В; • MISO — разряд 6 или 3 порта В; • SCK — разряд 7 или 1 порта В. Распределение линий зависит от модели микроконтроллера AVR. Регистр управления SPCR интерфейса SPI в микроконтроллерах AVR показан на рис. 1.35. По окончании передачи данных через интерфейс SPI аппаратная часть устанав- ливает в регистре состояния SPCR разряд SPIF (флаг прерываний от интерфейса SPI). Этот флаг указывает на завершение передачи, и приводит к запросу на преры-
Структура микроконтроллеров AVR 67 вание как только в регистре управления SPCR будет установлен разряд SPIE, а в ре- гистре состояния SREG — флаг общего разрешения прерываний I. Рис. 1.34. Подключение нескольких ведомых устройств к одному ведущему по SPI 7 6 5 4 3 2 1 О SPIE SPE DORD MSTR CPOL СРНА SPR1 SPR0 Рис. 1.35. Регистр управления SPCR микроконтроллеров AVR Разряд SPE активизирует интерфейс SPI (лог. 1) или отключает его (лог. 0). По- сле поступления сигнала сброса этот разряд принимает значение лог. 0, и тем самым система SPI отключается. Если разряд DORD содержит лог. 0, то сначала будет передан старший разряд байта данных. При DORD = 1 первым передается младший разряд. Когда разряд MSTR содержит лог. 0, то система SPI определяется как ведомая (Slave), а при MSTR = 1 она будет определена как ведущая (Master). Когда линия /SS в режиме Master сконфигурирована как вход, то разряд MSTR при низком уров- не сигнала на выводе /SS сбрасывается в лог. 0, и тем самым интерфейс SPI опреде- ляется как Slave. В этом случае в регистре состояния устанавливается флаг SPIF. Когда разряд CPOL содержит лог. 0, то на выходе SCK в неактивном состоянии находится сигнал низкого уровня. Если CPOL = 1, то на SCK в неактивном состоя- нии находится сигнал высокого уровня. С помощью этого разряда, а также разряда СРНА (выбор фазы синхронизации) устанавливается один из четырех режимов пе- редачи данных по интерфейсу SPI (табл. 1.27). . Разряды SPR1 и SPR0 при работе интерфейса SPI в режиме Master служат для выбора тактовой частоты для линии SCK. Если система SPI сконфигурирована как Slave, то эти разряды не имеют никакого значения. Взаимосвязь между разрядами SPR1, SPR0 и частотой импульсов в линии SCK показана в табл. 1.28. В регистре состояния SPSR интерфейса SPI используются только разряды 6, 7 и 0 (в новых микроконтроллерах AVR). • Разряд 0 — SPI2X — когда он содержит 1, то в режиме Master удваивается ско- рость передачи. В режиме Slave частота тактирования приема не превышает 1/4 частоты системной синхронизации (см. табл. 1.28).
68 Глава 1. Восьмиразрядные микроконтроллеры AVR Таблица 1.27. Режимы передачи данных по интерфейсу SPI в микроконтроллерах AVR 0 0 Master переводит линию /SS в состояние лог. 0. Для соответствующего ве- домого блока передача начинается по ниспадающему фронту этого сигнала. Его выход MISO переходит из высокоомного в активное состояние, и старший разряд байта, находящегося в его регистре данных SPDR, появляется на вы- ходе MISO. Собственно передачу данных Master начинает записью подле- жащего передаче байта данных в свой регистр SPDR. Вслед за этим на вы- ходе MOSI ведущего блока появляется старший разряд. На протяжении пер- вой половины первого тактового импульса тактовая линия еще остается в сосуоянии покоя для того, чтобы обеспечить стабильную установку на со- ответствующем входе бита данных. По нарастающему фронту первого и ка- ждого последующего тактового импульса принимаются биты, расположен- ные на входах Master и Slave, а по ниспадающему фронту следующий бит сдвигается дальше. После восьмого тактового импульса передача данных завершена, флаги SPIF в регистрах состояния ведущего и ведомого блоков установлены, а содержимое сдвиговых регистров будут перенесено в соот- ветствующие приемные буферы. Выход MOSI ведущего блока возвращается в состояние покоя (лог. 1), а на выходе MISO ведомого блока, как правило, находится старший разряд байта, только что принятого ведущим блоком. Одновременно со сбросом линии /SS в исходное состояние (лог. 1) Master завершает передачу, Slave становится неактивным, а его выход*MISO пере- ходит в высокоомное состояние 0 1 Аналогично описанному выше случаю с той разницей, что состояние покоя тактовой линии здесь устанавливается при лог. 1, биты данных принимаются по первому и каждому последующему тактовому импульсу, а сдвиг осущест- вляется по нарастающему фронту сигнала 1 0 Для того чтобы при этом режиме начать передачу данных, Master, как и в первом случае, переводит линию /SS в состояние лог. 0. Блок Slave разбло- кирован, и его выход MISO переходит из высокоомного в активное состояние. Логический уровень на MISO для этого случая не определен, но, как правило, на MISO находится младший разряд байта, переданного во время предыду- щей передачи от Slave к Master. Собственно передачу данных Master в этом режиме начинает посредством записи байта данных, подлежащего передаче, в регистр SPDR. Для ведомого блока передача начинается по нарастающему фронту тактового сигнала. Старшие разряды подлежащих передаче байтов в ведущем и ведомом блоках с помощью нарастающего фронта первого так- тового импульса устанавливаются на выходе MOSI ведущего блока (выходе MISO ведомого блока). По ниспадающему фронту первого и каждого после- дующего тактового импульса они переносятся на входы Master и Slave, а по нарастающему фронту следующий разряд сдвигается. После восьмого так- тового импульса передача данных завершается, устанавливаются флаги SPIF в регистрах состояния интерфейсов Master и Slave, а содержимое их сдвиговых регистров переносится в соответствующие буферы приема. Вы- ход MOSI ведущего блока возвращается в состояние покоя (лог. 1), на выхо- де MISO ведомого блока остается младший разряд байта, только что пере- данного ведущему блоку. Одновременно с возвратом в исходное состояние линии /SS (лог. 1) Master завершает передачу в целом, Slave становится не- активным, а его выход MISO переходит в высокоомное состояние. 1 1 Аналогично описанному выше случаю с той разницей, что состоянием покоя тактовой линии здесь является лог. 1, а биты данных сдвигаются по ниспа- дающему фронту первого и каждого последующего такторого импульса, а принимаются по нарастающему фронту • Разряд 6 — флаг WCOL — устанавливается в том случае, когда во время пере- дачи данных через интерфейс SPI предпринимается попытка записи в регистр
Структура микроконтроллеров AVR 69 данных SPI, что приводит к разрушению только что переданного байта данных. По этой причине текущая передача данных доводится до завершения, а новый байт не записывается в сдвиговый регистр интерфейса SPI. Флаг WCOL должен быть сброшен пользователем вручную посредством считывания регистра состо- яния и последующего обращения к регистру данных интерфейса SPL • Разряд 7 — флаг SPIF — указывает на завершение передачи и вызывает запрос на прерывание, как только в регистре управления SPCR будет установлен раз- ряд SPIE, а в регистре состояния SREG — разряд I. Когда линия /SS в режиме Master сконфигурирована как вход, то при низком уровне сигнала на выводе линии /SS также будет установлен флаг SP1F. Флаг SPIF сбрасывается автома- тически аппаратной частью при выполнении подпрограммы обработки преры- вания от интерфейса SPI. Альтернативно, сброс может быть выполнен вручную посредством считывания регистра состояния SPSR и последующего обращения к регистру данных интерфейса SPL Таблица 1.28. Частота импульсов в линии SCK в зависимости от разрядов SPR1, SPR0 SPI2X SPR1 SPR0 Частота импульсов в линии SCK 0 0 0 Частота системной синхронизации / 4 0 0 1 Частота системной синхронизации /16 0 1 0 Частота системной синхронизации / 64 0 1 1 Частота системной синхронизации /128 1 0 0 Частота системной синхронизации / 2 1 0 1 Частота системной синхронизации / 8 1 1 0 Частота системной синхронизации / 32 1 1 1 Частота системной синхронизации / 64 Работа приемопередатчика USART в режиме SPI Приемопередатчик USART новых микроконтроллеров AVR можно перевести в режим Master для обмена данными по интерфейсу SPI (так называемый режим MSP1M). Для этого необходимо установить в 1 разряды UMSEL1 и UMSEL0 в реги- стре UCSRC (см. рис. 1.32). В таком режиме все ресурсы USART (сдвиговые реги- стры приемника и передатчика, а также генератор частоты передачи) берет под свой контроль схема управления ведущего устройства SPL Схема контроля четности, схема восстановления данных и такта, а также схемы управления приемом и передачей через USART отключаются. Тем не менее, в режиме SP1 продолжают работать схема прерывания. В режиме MSPIM действуют следующие соглашения: • в регистре управления UCSRA доступны только разряды 5-7: UDRE, ТСХ и RXC; • в регистре управления UCSRB доступны только разряды 5-7: TXEN, RXEN, UDRIE, TXCIE, RXCIE; • регистр управления UCSRC претерпевает следующие изменения: ► разряд О (UCPOL) выполняет функцию разряда CPOL регистра SPCR; ► разряд 1 (UCPHA) заменяет разряд UCSZ0 и выполняет функцию разряда СРНА регистра SPCR; ► разряд 2 (UDORD) заменяет разряд UCSZ1 и выполняет функцию разряда DORD регистра SPCR; ► разряды 3-5 не используются;
70 ГлаваJ. Восьмиразрядные микроконтроллеры AVR ► разряды 6 (UMSEL0) и 7 (UMSEL1) выполняют прежнюю функцию пере- ключения в другой режим работы USART; • разряды WCOL, SPI2X регистра SPSR недоступны; • SPI-выводу MOSI соответствует USART-вывод TxD; • SPI-выводу MISO соответствует USART-вывод RxD; • SPI-выводу SCK соответствует USART-вывод ХСК; • линия /SS не поддерживается; • поддерживается только внутреннее формирования тактовых импульсов, а зна- чит для правильной работы USART в режиме MSPIM вывод ХСК должен быть определен как выход (лог. 1 в соответствующем разряде регистра DDR должна быть установлена до активизации режима MSPIM). Формирование тактового сигнала в режиме MSPIM организовано идентично синхронному Master-режиму работы USART. Разряды UCPHA и UCPOL определяют четыре комбинации для фазы и поляр- ности сигнала ХСК по отношению к последовательно передаваемым данным (табл. 1.29). Соответствующие временные диаграммы показаны на рис. 1.36. Таблица 1.29. Значение разрядов UCPHA и UCPOL в режиме MSPIM UCPOL UCPHA Передний фронт сигнала ХСК Задний фронт сигнала SCK 0 0 Чтение (нарастающий фронт) Выдача (ниспадающий фронт) 0 1 Выдача (нарастающий фронт) Чтение (ниспадающий фронт) 1 0 Чтение (ниспадающий фронт) Выдача (нарастающий фронт) 1 1 Выдача (ниспадающий фронт) Чтение (нарастающий фронт) Синхронная передача данных по интерфейсу l2C (TWI) Интерфейс I2C (Inter-integrated Circuit), состоящий только из двух линий (SDA и SCL), предназначен для низкоскоростного последовательного обмена данными с периферийными устройствами, подсоединенных к одной общей шине (рис. 1.37). В современных микроконтроллерах AVR этот интерфейс называется иначе: TW1 (Two-Wire Interface — двухпроводной интерфейс).
Структура микроконтроллеров AVR 71 SDA (линия последовательной передачи данных) SCL (линия последовательной передачи тактовых импульсов) Рис. 1.37. Подключение устройств к шине l2C (TWI) Характеристики шины 12С: • работа только с двумя линиями, благодаря чему требуется меньше мест соеди- нения и минимизируются затраты на проводку; • зона действия — до 3 м; • возможность работать в режиме с одним ведущим блоком (Single-Master) или с несколькими ведущими блоками (Multi-Master). Линия SCL используется для передачи синхроимпульсов. Если данные не пере- даются, она содержит высокий уровень сигнала. Линия SDA используется для по- битной передачи данных. Если данные не передаются, то она имеет высокий потен- циал. Передаваемые данные действительны в фазе высокого уровня такта и могут менять свое состояние только в фазе низкого уровня. Каждый блок, подсоединенный к шине, во время передачи данных может быть или приемником или передатчиком, а также ведущим (Master) или ведомым (Slave). Ведущее устройство инициирует передачу данных. В частности, Master занимает шину тем, что генерирует стартовый сигнал на линии SCL и начинает обмен с ведо- мым устройством. До тех пор, пока на шине работает ведущее устройство, не может быть активным никакой другой Master-блок. Тактовый сигнал на линии SCL может быть сформирован только ведущим устройством. Ведомым является устройство, по адресу которого обращается ведущее устрой- ство с требованием передачи данных. Теоретически Master может одновременно снабжать одними и теми же данными несколько ведомых устройств. В роли веду- щего устройства в большинстве случаев выступает микропроцессор, оборудован- ный или специальной аппаратной частью с шиной типа 12С, или контроллером ши- ны, работающим под управлением специального программного обеспечения. Протокол шины 12С Для того чтобы несколько блоков могли обмениваться данными, необходим не- который протокол, который описывает процесс передачи данных по шине и в любой момент времени не допускает ошибочной интерпретации состояния шины. В случае шины с несколькими ведущими устройствами (что относится и к 12С) необходимо также установить, когда и какое ведущее устройство имеет право занимать шину. Эти условия регулируются протоколом шины (рис. 1.38).
72 Глава 1. Восьмиразрядные микроконтроллеры AVR S: Условие начала D: Бит данных (не может быть изменен, когда SCL = выс ур ) Р: Условие завершения А: Подтверждение (от приемника о получении байта) MSB: Старший значащий бит LSB: Младший значащий бит Рис. 1.38. Протокол передачи байта данных через шину 12С Работа шины и, следовательно, ее занятость, определяется условием начала пе- редачи — изменение ведущим устройством состояние линии SDA с высокого уров- ня на низкий. После наступления условия начала передачи шина будет занята веду- щим устройством, создавшим это условие, вследствие чего все другие ведущие уст- ройства будут заблокированы. Условие начала является однозначным состоянием на шине, потому что смена уровня сигнала на линии SDA, как правило, допускается только тогда, когда тактовая линия SCL находится в состоянии низкого уровня. Все устройства, подключенные к шине, должны распознать условие начала пе- редачи и переключаются на прием (ведомое устройство/приемник). Условие начала передачи также учитывается и другим ведущим устройством, которое со своей сто- роны имело намерение занять шину. В результате оно немедленно отзывает свое требование. Устройство, создавшее условие начала передачи, в данный момент вре- мени является для шины ведущим (Master), а все остальные устройства — потенци-. альными ведомыми (Slave). Ведущее устройство теперь отвечает за тактовый сигнал и становится передатчиком. После создания условия начала ведущее устройство начинает передачу данных. Оно переводит тактовую шину в состояние низкого уровня и теперь может занять линию передачи данных затребованным информационным разрядом (высокий или низкий уровень в линии SDA). Затем тактовая шина опять переводится в состояние высокого уровня. ’ИМЕЧАНИЕ WnwtWrwvrfm Изменение в линии SDA может происходить только в фазе низкого уровня сигнала в линии SCL. Во время фазы высокого уровня в линии SCL линия SDA должна быть стабильной. Передача данных, как правило, выполняется побайтно, при этом первым пере- дается старший разряд. После передачи полного байта данных, состоящей из восьми тактовых циклов, следует бит подтверждения от приемника. Бит подтверждения (квитирования) — это реакция приемника на принятый байт данных. Он является для передатчика признаком того, что приемник физически присутствует и “прослушивает” линию. Одновременно с этим бит подтверждения можно рассматривать как сигнал синхронизации. Бит подтверждения, как правило, генерируется приемником. Если ведущее уст- ройство принимает от ведомого устройства несколько байтов данных, то оно квити- рует каждый отдельный байт битом подтверждения, за исключением последнего. Такое отрицательное квитирование сообщает ведомому устройству, что передача данных завершена, и далее последует условие завершения или новое условие начала передачи.
Структура микроконтроллеров AVR 73 Для передачи бита подтверждения ведущее устройство генерирует на линии SCL дополнительный тактовый импульс (рис. 1.39). Приемник выдает сигнал поло- жительного квитирования, переводя линию SDA в состояние низкого уровня, или отрицательного квитирования, переводя линию SDA в состояние высокого уровня. SCL (от ведущего устройства) SDA - выход ведущего устройства SDA - выход ведомого устройства SDA (монтажное “И") Шина занята ----------------------- D: Бит данный (не может быть изменен, когда SCL = выс. ур.) А: Подтверждение (от приемника о получении байта) MSB: Старший значащий бит LSB: Младший значащий бит S: Условие начала Р: Условие завершения Рис. 1.39. Выработка бита квитирования приемником, работающим в режиме ведомого устройства Таким образом, для передачи одного байта данных, как правило, требуется де- вять тактовых циклов. После передачи одного байта данных и приема бита под- тверждения передача данных может быть сразу же продолжена. Если приемник реа- гирует на передачу байта данных отрицательным квитированием, то ведущее уст- ройство должно завершить передачу данных, опять освободив шину. Шина после окончания передачи данных, которая может состоять из любого количества байтов, опять освобождается ведущим устройством. Освобождение ши- ны осуществляется с помощью условия завершения — изменение в линии SDA уровня сигнала с низкого на высокий в то время, когда по тактовой шине SCL пере- дается сигнал высокого уровня. После создания условия завершения передачи шина освобождается. Условие завершения передачи также представляет собой однозначное состояние на шине. Все блоки и устройства распознают его и подготавливаются к появлению нового условия начала передачи. В том случае, если ведущее устройство из-за промежу- точной занятости шины отзывает свое требование занять шину, то оно может пред- принять новую попытку создать условие начала передачи и тем самым получить шину для своих нужд. Н. .... Полная передача данных через шину 12С, в принципе, состоит из условия начала передачи, одного или нескольких байтов данных (за которыми, соответственно, следует бит квитирова- ния), и условия завершения передачи.
74 Глава 1. Восьмиразрядные микроконтроллеры AVR Адресация ведомых устройств Выбор ведомого устройства, с которым хотело бы обмениваться данными ве- дущее устройство, осуществляется посредством первого байта, который всегда оп- ределяется как адрес ведомого устройства — первый байт последовательности дан- ных. Он однозначно сопоставлен определенному устройству, подключенному к ши- не, и имеет длину 7 бит (разряды от 1 до 7). Теоретически, таким образом можно адресовать до 128 ведомых устройств, однако по определению некоторые адреса ве- домых устройств имеют особое значение. Адрес ведомого устройства состоит из двух частей: постоянной и переменной (рис. 1.40). Разряд направления передачи данных I Постоянная часть j Переменная часть ; ! адреса ведомого ! адреса ведомого I < устройства | устройства * I I Бит7 Битб Бит5 Бит4 БитЗ Бит2 Бит1 БитО R/W Рис. 1.40. Формат адреса шины 12С Постоянная часть адреса описывает требования к определенным группам уст- ройств и определяется изготовителем. Его длина определена в результате практиче- ского опыта и в большинстве случаев составляет четыре бита. Он будет тем короче, чем больше однотипных устройств в схеме. Постоянная часть адреса жестко “про- шита” в интегральной схеме и не может быть изменена пользователем. Переменная часть адреса ведомого устройства служит для выбора определенно- го устройства из группы однотипных кристаллов, среди которых все имеют посто- янную часть адреса ведомого устройства. Благодаря этому, к шине могут быть под- соединены несколько однотипных интегральных схем. Переменная часть в боль- шинстве случаев определяется пользователем с помощью внешних схем (через до- полнительные выводы). С помощью разрядов 1-7 адреса ведомого устройства однозначно идентифици- руется требуемый ведомый блок. Разряд 0 задает направление передачи данных. Он определяет, должны ли быть приняты или переданы данные. Если разряд направле- ния передачи данных содержит лог. 1 (чтение), то ведущее устройство находится в режиме приемника, а ведомое — в режиме передатчика. Если разряд направления передачи данных содержит лог. 0 (запись), то ведущее устройство будет работать как передатчик, а ведомое — как приемник. Адрес ведомого устройства также подтверждается этим устройством с помощью бита квитирования. Если ведущее устройство после адресации получает отрицательное квитирование, то оно может заключить, что ведомое устройство или вообще отсутствует, или в настоящий момент с ним невозможно установить связь (например, оно занято обработкой заданий, критическими с точки зрения времени). Арбитраж шины при работе с несколькими ведущими устройствами В связи с тем, что шина 12С занимается асинхронно (т.е. не в точно установлен- ный момент времени), может возникнуть случай, когда два или несколько ведущих устройств в один и тот же момент времени создают условие начала передачи. Каж- дое ведущее устройство на основании сигнала обратной связи через входной каскад создает впечатление, что именно оно является единственным передатчиком в дан- ный момент времени. В связи с тем, что для тактового сигнала выполняется синхро-
Структура микроконтроллеров AVR 75 низация, то это “впечатление” остается до тех пор, пока все передатчики передают в точности одну и ту же битовую комбинацию. Разногласие возникает только тогда, когда ведущее устройство, ожидающее появления на шине сигнала высокого уров- ня, вместо него обнаруживает сигнал низкого уровня. С этого момента данное ве- дущее устройство отзывает свою передачу данных, а другое или все остальные ве- дущие устройства по прежнему работают с шиной, поскольку не замечают возник- шей проблемы. Таким образом ведущие устройства одно за другим освобождают шину до тех пор, пока наконец останется единственное ведущее устройство, кото- рое “выиграло” процесс арбитража. Из-за открытого коллектора арбитраж всегда выигрывает то ведущее устройст- во, которое последовательно передает больше сигналов низкого уровня (т.е. нуле- вые биты). В связи с тем, что первый подлежащий передаче байт данных — это ад- рес ведомого устройства, решение в процессе арбитража принимается еще при ад- ресации, если к ведомому устройству хотят обратиться несколько ведущих уст- ройств. Для этого случая обращецие для записи (бит направления передачи данных = 0) опять имеет приоритет перед обращением для чтения. Таким образом, наивыс- шим приоритетом обладает адрес 0 ведомого устройства при обращении для записи (0000 0000b); обозначаемый понятием “общий вызов”. Также может возникнуть особый случай, когда два ведущих устройства одно- временно адресуют одно и то же ведомое устройство, Передают ему те же самые данные и совместно генерируют условие завершения передачи. При этом ни одно ведущее устройство “не замечает” каких-либо действий другого ведущего устрой- ства. Если ведущее устройство проигрывает арбитраж еще при выдаче .адреса ведо- мого устройства, то оно немедленно переключается в режим работы ведомого при- емника и считывает дальше данные с шины. Благодаря этому, устройство в состоянии отреагировать в том же цикле, когда оставшееся на шине ведущее уст- ройство обращается по его адресу. Задача пользователя — выбрать действия, необходимые после проигрыша ар- битража. Обычно после разблокирования шины повторяется весь процесс передачи данных, начиная с первого условия начала передачи. Синхронизация шины 12С В связи d тем, что в случае 12С речь идет о синхронной шине, к ее синхрониза- ции не предъявляется каких-либо особых требований, кроме одного: не должны быть превышены минимальные значения времени THlgll = 4 мкс для сигнала высоко- го уровня и Tlow = 4,7 мкс для сигнала низкого уровня для тактирующих сигналов в линии SCL. Универсальный последовательный интерфейс USI Некоторые современные микроконтроллеры AVR оснащены новым универ- сальным последовательным интерфейсом USI, объединяющим в себе функции трех- и двухпроводных последовательных интерфейсов (т.е. SPI и I2C/TWI). Упрощенная структурная схема модуля USI показана на рис. 1.41. Восьмиразрядный сдвиговой регистр USIDR доступен напрямую через шину данных и содержит принимаемые и выводимые данные. Для него не предусмотрено буферизации, поэтому во избежание информационных потерь данные должны счи- тываться максимально быстро. Старший разряд регистра USIDR выдается на один из двух выводов (DO или SDA) в зависимости от конфигурации модуля USI. При- нимаемые данные всегда считываются на входе DI независимо от конфигурации.
76 Глава 1. Восьмиразрядные микроконтроллеры AVR Рис. 1.41. Структурная схема модуля USI Четырехразрядный счетчик доступен как на чтение, так и на запись и может формировать прерывание по переполнению. Сдвиговой регистр и счетчик тактиру- ются одним и тем же тактовым сигналом. Это позволяет подсчитывать'количество принятых или переданных бит и формировать запрос на прерывание по окончанию передачи. Тактовый сигнал может поступать со входа USCK, от модуля сравнения тайме- ра/счетчика Т/СО или формировать программно. При этом следует учитывать, что при выборе внешнего источника тактирования счетчик USI будет инкрементиро- ваться как по нарастающему, так и по ниспадающему фронту' тактового сигнала. В таком случае он будет подсчитывать количество фронтов, а не количество пере- данных бит. Схема управления тактированием двухпроводного режима может формировать запрос на прерывание при обнаружении на шине условия начала передачи. Кроме того, она формирует состояние ожидания, удерживая низкий уровень сигнала в ли- нии тактирования после обнаружения условия начала передачи или переполнения счетчика. Режимы работы модуля USI: • трехпроводной ввод/вывод — аналог интерфейса SPI за исключением примене- ния линии SS для выбора ведомого устройства (в случае необходимости эту функцию можно реализовать программно); в этом режиме используются выво- ды DI, DO и USCK; • двухпроводной ввод/вывод — аналог интерфейса 12С или TWI; в этом режиме используются выводы SCL и SDA; • когда модуль USI не задействован для последовательного ввода/вывода, его можно сконфигурировать для выполнения альтернативных фунций:
Структура микроконтроллеров AVR 77 ► полудуплексный асинхронный обмен данными — задействовав сдвиговой режим в режиме трехпроводного ввода/вывода, можно эффективно реализо- вать приемопередатчик UART; ► четырехразрядный счетчик — формирование прерываний по переполнению; ► 12-разрядный таймер/счетчик — получается путем объединения четырехраз- рядного счетчика модуля USI и восьмиразрядного Т/СО. Регистры управления модулем USI В работе модуля USI задействованы следующие регистры: • USIDR (USI Data Register) — регистр данных; • USISR (USI Status Register) — регистр состояния, содержащий флаги прерыва- ний и статуса линии, а также значение четырехразрядного счетчика (рис. 1.42); • USICR (USI Control Register) — регистр управления, содержащий разряды раз- решения прерываний, установки режима работы модуля USI и выбора источни- ка тактирования (рис. 1.43). 7 6 5 4 3 21 О USISIF USIOIF USIPF USIDC USIGNT3 USICNT2 USICNT1 USICNTO Рис. 1.42. Регистр USISR Рассмотрим назначение разрядов регистра USISR. • USICNT0:USICNT3 — текущее состояние четырехразрядного счетчика модуля USI. • USIDC (Data Output Collision) — этот разряд,принимает значение лог. 1, когда старший разряд сдвигового регистра не соответствует физическому состоянию вывода. Этот флаг используется только в режиме двухпроводного ввода/ вывода и полезен при реализации арбитража шины. • USIPF (Stop Condition Flag) — этот флаг устанавливается в 1 в режиме двух- проводного ввода/вывода в случае обнаружения условия завершения передачи. Это может пригодиться при реализации арбитража шины. • USIOIF (Counter Overflow Interrupt Flag) — флаг, который устанавливается при переполнении четырехразрядного счетчика модуля USI (т.е. при переходе зна- чения полубайта USICNT3:0 от 15 к 0). Если прй этом установлены в 1 разряды USIOIE в регистре USICR и I в регистре SREG, то возникнет прерывание (среди прочего, выводит процессор из “спящего” режима). Флаг сбрасывается про- граммным обнулением разряда USIOIF. • USISIF (Start Condition Interrupt Flag) — этот флаг устанавливается в 1 в режи- ме двухпроводного ввода/вывода в случае обнаружения условия начала переда- чи. Если выбран режим отключенного выхода или трехпроводного ввода/ выво- да, то этот флаг устанавливается при инкрементировании четырехразрядного счетчика модуля USL Если при этом установлены в 1 разряды USISIE в регист- ре USICR и I в регистре SREG, то возникнет прерывание (среди прочего, выво- дит процессор из “спящего” режима). Флаг сбрасывается программным обнуле- нием разряда USISIF. 7 6 5 4 3 2 1______0 USISIE USIOIE USIWM1 USIWMO USICS1 USICSO USICLK USITC - Рис. 1.43. Регистр USICR
78 Глава 1. Восьмиразрядные микроконтроллеры AVR Рассмотрим назначение разрядов регистра USICR. • USITC (Toggle Clock Port Pin) — запись лог. 1 в этот разряд переключает зна- чение на выводе USCK/SCL на противоположное. Этот процесс не зависит от состояния соответствующего регистра DDR, однако, если с вывода необходимо считать значение, то он должен быть определен как выход. Возможность пере- ключения состояния линии позволяет легко организовать формирование такто- вого сигнала при реализации ведущих устройств. Если модуль USI тактируется от внешнего источника (USICS1 = 1), и USICLK = 1, то запись лог. 1 в разряд USITC будет напрямую выдавать тактовый импульс на четырехразрядный счет- чик. Это позволяет своевременно обнаруживать завершение передачи данных в режиме ведущего устройства. • tfSICLK (Clock Strobe) — запись лог. 1 в этот разряд приводит к сдвигу содер- жимого сдвигового регистра и инкрементированию содержимого четырехраз- рядного счетчика USI. Если модуль USI тактируется от внешнего источника (USICS1 = 1), то запись лог. 1 в разряд USICLK приведет к назначению строба USITC в качестве источника тактового сигнала для счетчика USI. • USICS1:USICSO (Clock Source Select) — выбор источника тактирования для сдвигового регистра и четырехразрядного счетчика модуля USI (табл. 1.30). Ес- ли оба разряда содержат 0, появляется возможность организовать программное тактирование сдвигового регистра и счетчика путем записи лог. 1 в разряд USICLK. При выборе внешнего источника тактового сигнала (USICS1=1) раз- ряд USICLK перестает использоваться в качестве строба, а определяет внешнее или программное тактирование через разряд USITC. • USIWM1 :USIWM0 (Wire Mode) — выбор режима работу модуля USI (табл. 1.31). Таблица 1.30. Выбор источника тактирования для модуля USI USICS1 USICS0 USICLK Источник тактового сигнала для сдвигового регистра Источник тактового сигна- ла для 4-хразряд. счетчика 0 0 0 Нет тактирования 0 0 1 Программный строб (USICLK) 0 1 X Сигнал от модуля сравнения таймера/счетчика Т/СО 1 0 0 Внешний, положительный фронт Внешний, оба фронта 1 1 0 Внешний, отрицательный фронт Внешний, оба фронта 1 0 1 Внешний, положительный фронт Программный строб (USITC) 1 1 1 Внешний, отрицательный фронт Программный строб (USITC) Таблица 1.31. Выбор режима работы модуля USI USIWM1 USIWM0 Описание 0 0 Выходы и схемы задержки тактирования и обнаружения условия на- чала передачи отключены. Выводы порта работаю, как обычно 0 1 Режим трехпроводного ввода/вывода. Используются выводы DO, DI и USCK. Функция DO Перекрывает обычную функцию порта, однако соответствующий регистр DDR по-прежнему контролирует направ- ление передачи данных. Функции DI и USCK не влияют на нормаль- ную работу портов. В режиме ведущего устройства тактовые им- пульсы формируются программно путем переключения разряда в регистре PORTx, когда вывод сконфигурирован как выход. Для этого цели можно использовать разряд USITC регистра USICR.
Структура микроконтроллеров AVR 79 Таблица 1.31. Окончание USIWM1 USIWM0 Описание 1 0 Режим двухпроводного ввода/вывода. Используются выводы SDA (DI) и SCL (USCK). В линии SCL удерживается сигнал низкого уровня, если обнаружено условие начала передачи при активном выходе. Линия освобождается путем обнуления флага USISIF в регистре USISR. 1 1 Режим двухпроводного ввода/вывода. Используются выводы SDA (DI) и SCL (USCK). Этот режим аналогичен представленному выше за тем исключением, что в линии SCL сигнал низкого уровня удержи- вается также при переполнении счетчика до момента обнуления флага USIOIF в регистре USISR. • USIOIE (Counter Overflow Interrupt Enable) — разрешение прерывания по пере- полнению четырехразрядного счетчика модуля USI; • USISIE (Start Condition Interrupt Enable) — разрешение прерывания при обна- ружении условия начала передачи. Модули последовательного ввода/вывода в семействах AT90S, ATtiny и ATmega Наличие того или иного модуля последовательного ввода/вывода в микрокон- троллерах AVR семейств AT90S, ATtiny и ATmega демонстрирует табл. 1.32. Таблица 1.32. Модули последовательного ввода/вывода в семействах AT90S, ATtiny и ATmega Микроконтроллер UART USART SPI TWI USI AT90S1200 — — — — — AT90S2313 s Есть — — — — AT90S2323 — — — — — AT90S2343 — — — — — AT90S4414 Есть — Есть — — AT90S4433 Есть — Есть — — AT90S8515 Есть — Есть — — AT90S8535 Есть — Есть — — ATtiny! 1 — — — — — ATtiny 12 — — — — — ATtiny 13А — — — — — ATtiny 15L — — — — — ATtiny2313 — . 1 — — Есть ATtiny24 — — — — Есть ATtiny25 — — — — Есть ATtiny26 — — — — Есть ATtiny261 — — — — Есть ATtiny28L — — — — — ATtiny44A — — — — Есть ATtiny45 — — — — Есть ATtiny461 — — — — Есть ATtiny48 — — Есть Есть —
80 Глава 1. Восьмиразрядные микроконтроллеры AVR Таблица 1.32. Окончание Микроконтроллер UART USART SPI TWI USI ATtiny84 — — — — Есть ATtiny85 — — — — Есть ATtiny861 — — — — Есть ATtiny88 — — Есть Есть — ATmega 128 — 2 Есть Есть — ATmega1280 — 4 Есть Есть — ATmega1281 — 2 Есть Есть — ATmega1284P — 2 Есть Есть — ATmega16 — 1 Есть Есть — ATmega16A — 1 Есть Есть — ATmega162 — 2 Есть — — ATmega164P — 2 Есть Есть — ATmega165P — 1 Есть — Есть ATmega168 — 1 Есть Есть — ATmega168P — 1 Есть Есть — ATmega169 — 1 Есть — Есть ATmega2560 — 4 Есть Есть — ATmega2561 — 2. Есть Есть — ATmega32A — 1 Есть Есть — ATmega324PA — 2 Есть Есть — ATmega325 — 1 Есть — Есть ATmega325P — 1 Есть — Есть ATmega3250 — 1 Есть — Есть ATmega3250P — 1 Есть — Есть 4 ATmega328P — 1 Есть Есть — ATmega48PA — 1 Есть Есть — ATmega64 — 2 Есть Есть — ATmega640 — 4 Есть Есть — ATmega644 — 1 Есть Есть — ATmega644P — 2 Есть Есть — ATmega645 — 1 Есть — Есть ATmega6450 — 1 Есть — Есть ATmega8 — 1 Есть Есть — ATmega8515 — 1 Есть — — ATmega8535 — 1 Есть Есть — ATmega88PA — 1 Есть Есть — Аналого-цифровое преобразование Число в цифровой форме определяется на основании отношения входного на- пряжения к полному номиналу напряжения аналого-цифрового преобразователя (АЦП). Например, если на вход АЦП с номинальным напряжением 5 В подать на- пряжение 1 В, то на цифровом выходе появится число, соответствующее 1/5 = 0,2 разрешающей способности преобразователя. Так, если используется АЦП с разре- шением 8 бит, то максимальное возможное значение на его выходе 28- 1 = 255. Та-
Структура микроконтроллеров AVR 81 ким образом, напряжению 1 В на аналоговом входе соответствует 0,2 • 255 = 51 на цифровом выходе. Встроенные АЦП микроконтроллеров AVR семейств AT90S, ATtiny и ATmega имеют разрешение 10 бит и позволяют считывать напряжение на одном из четырех, шести, восьми, 11 или 16 аналоговых входов (зачастую совмещены с выводами пор- та А). Для управления режимом АЦП используются два регистра: регистр управления ADCSR (в новых моделях микроконтроллеров AVR используется два регистра: ADCSRA и ADCSRB) и регистр мультиплексирования ADMUX (определяет, какие из входов микроконтроллера являются аналоговыми). Поскольку в различных моделях микроконтроллеров AVR набор разрядов в регистре ADCSR(A) может отличаться, рассмотрим его обобщенно: • ADPS0-ADPS2 — выбор коэффициента деления тактовой частоты (табл. 1.33); чем выше частота работы АЦП (производная от частоты системной синхрони- зации), тем ниже эффективное разрешение, поэтому следует устанавливать ко- эффициент деления; • ADIE — разряд маскирования прерывания от АЦП (1 — по окончанию преоб- разования разрешено прерывание); • ADIF — флаг прерывания от АЦП (устанавливается аппаратно по окончанию цикла преобразования); Таблица 1.33. Выбор коэффициента деления частоты системной синхронизации для тактирования АЦП микроконтроллеров AVR 0 ' 0 0 ---- 2 / — — 0 0 1 2 0 1 0 4 0 1 1 8 1 0 0 16 1 0 1 32 1 1 0 64 1 1 1 128 • ADFR (в старых микроконтроллерах) — лог. 1 в этом разряде переводит АЦП в несинхронизированный режим работы — обычно АЦП работает в режиме прерывания, чтобы процессор каждый раз не ожидал завершения медленно про- текающего преобразования, однако в несинхронизированном режиме АЦП вы- полняет преобразование постоянно, как можно быстрее (на период такого пре- образования должны быть запрещены все прерывания); • ADATE (в новых микроконтроллерах) — лог. 1 в этом разряде активизирует режим начала преобразования по нарастающему фронту сигнала, определенно- го с помощью разрядов ADTS регистра управления ADCSRB); • ADSC — установка этого разряда в лог. 1 начинает преобразование; • ADEN — установка этого разряда в лог. 1 разрешает использование АЦП, а установка в лог. 0 — отключает АЦП; Регистр управления ADCSRB (присутствует не во всех микроконтроллерах AVR) содержит разряды ADTS0:ADTS2, определяющие источник сигнала, по кото- рому начинается преобразование, если в регистре ADCSRA установлен в 1 разряд ADATE (табл. 1.34). Кроме того, этот регистр может содержать дополнительные
82 Глава 1. Восьмиразрядные микроконтроллеры AVR разряды MUXn, позволяющие расширить количество аналоговых входов (основная часть таких разрядов содержится в регистре ADMUX). Таблица 1.34. Выбор сигнала, инициирующего преобразование ADTS2 ADTS1 ADTS0 Источник инициирующего сигнала 0 0 0 Автономный режйм 0 0 1 Аналоговый компаратор 0 1 0 Внешний запрос на прерывание 0 0 1 1 Модуль сравнения А таймера/счетчика Т/СО 1 0 . 0 Переполнение таймера/счетчика Т/СО 1 0 1 Модуль сравнения В таймера/счетчика Т/С1 1 1 0 Переполнение таймера/счетчика Т/С1 1 1 1 Событие захвата по входу таймера/счетчика Т/С1 Как уже упоминалось выше, регистр ADMUX содержит разряды MUXn, за- дающие аналоговый вход для АЦП. Количество таких разрядов в разных моделях микроконтроллеров AVR может отличаться. В общем случае с помощью трех раз- рядов MUX можно выбрать один из восьми аналоговых входных каналов. Дополни- тельные разряды MUX (от одного до трех, причем в новых микроконтроллерах они могут быть и во втором регистре управления ADCSRB) служат для выбора допол- нительных режимов считывания входных сигналов. Рассмотрим две таблицы. Табл. 1.35 иллюстрирует выбор аналогового канала для микроконтроллеров AT90S8535 (три разряда MUX в регистре ADMUX), ATmega8 и ATtiny88 (по четы- ре разряда MUX), а табл. 1.36 — для ATmega640 (пять разрядов MUX в регистре ADCSRA и один — в регистре ADCSRB). Таблица 1.35. Выбор аналоговых каналов в различных микроконтроллерах AVR АД058535]АТтеда8^ ATtiny88 михз MUX2 MUX1 михо Аналоговый вход 0 0 0 0 ADC0 0 0 0 1 ADC1 0 0 1 0 ADC2 0 0 1 1 ADC3 0 1 0 0 ADC4 0 1 0 1 ADC5 0 1 1 0 ADC6 0 1 1 1 ADC7 1 0 0 0 ADC8 (датчик температуры) 1 1 1 0 VBG (1,3 или 1,1 В) 1 1 1 1 0 В (GND) Таблица 1.36. Выбор аналоговых каналов в микроконтроллере АТтеда640 -------------------------------------------------------L________ MUX5 MUX4 михз MUX2 MUX1 михо Аналоговый вход Дифференциальный вход Усиле- ние Положи- тельный Отрица- тельный 0 0 0 0 0 0 ADC0 — 0 0 0 0 0 1 ADC1 0 0 0 0 1 0 ADC2 0 0 0 0 1 1 ADC3 0 0 0 1 0 0 ADC4
Структура микроконтроллеров AVR 83 Таблица 1.36. Продолжение MUX5 MUX4 михз MUX2 MUX1 михо Аналоговый вход Дифференциальный вход Усиле- ние Положи- тельный Отрица- тельный 0 0 0 1 0 1 ADC5 — 0 0 0 1 1 0 ADC6 0 0 0 1 1 1 ADC7 0 0 1 0 0 0 — ADC0 ADCO 10х 0 0 1 0 0 1 ADC1 ADCO 10х 0 0 1 0 1 0 ADC0 ADCO 200х 0 0 1 0 1 1 ADC1 ADCO 200х 0 0 1 1 0 0 ADC2 ADC2 10х 0 0 1 1 0 1 ADC3 ADC2 10х 0 0 1 1 1 0 ADC2 ADC2 200х 0 0 1 1 1 1 ADC3 ADC2 200х 0 1 0 0 0 0 ADC0 ADC1 1х 0 1 0 0 0 1 ADC1 ADC1 1х 0 1 0 0 1 0 ADC2 ADC1 1х 0 1 0 0 1 1 ADC3 ADC1 1х 0 1 0 1 0 0 ADC4 ADC1 1х _9__ 1 0 1 0 1 ADC5 ADC1 1х 0 1 0 1 1 0 ADC6 ADC1 1х j) 1 0 1 1 1 ADC7 ADC1 1х _0_ 1 1 0 0 0 ADC0 ADC2 1х 1 1 0 0 1 ADC1 ADC2 1х 0 1 1 0 1 0 ADC2 ADC2 1х _9___ 1 1 0 1 1 ADC3 ADC2 1х 0 1 1 1 0 0 ADC4 ADC2 1х 0 1 1 1 0 1 ADC5 ADC2 1х 0 1 1 1 1 0 1,1 B(Vbg) — 0 _ 1 1 1 1 1 0 В (GND) 1 0 0 0 0 0 ADC8 _1 0 0 0 0 1 ADC9 _1 0 0 0 1 0 ADC10 _1 0 0 0 1 1 ADC11 _1 0 0 1 0 0 ADC12 J 0 0 1 0 1 ADC13 J 0 0 1 1 0 ADC14 J 0 0 1 1 1 ADC15 _1 0 1 0 0 0 — ADC8 ADC8 10х _1 0 1 0 0 1 ADC9 ADC8 10х 1 0 1 0 1 0 ADC8 ADC8 200х J 0 1 0 1 1 ADC9 ADC8 200х 1 0 1 1 0 0 ADC10 ADC10 10х 1 0 1 1 0 1 ADC11 ADC 10 10х 1 0 1 1 1 0 ADC10 ADC10 200х
84 Глава 1. Восьмиразрядные микроконтроллеры AVR Таблица 1.36. Окончание MUX5 MUX4 михз MUX2 MUX1 михо Аналоговый вход Дифференциальный вход Усиле- ние Положи- тельный Отрица- тельный 1 0 1 1 1 1 ADC11 ADC10 200х 1 1 0 0 0 0 ADC8 ADC9 1х 1 1 0 0 0 1 ADC9 ADC9 1х 1 1 0 0 1 0 ADC10 ADC9 1х 1 1 о • 0 1 1 ADC11 ADC9 1х 1 1 0 1 0 0 ADC12 ADC9 1х 1 1 0 1 0 1 ADC13 ADC9 1х 1 1 0 1 1 0 ADC14 ADC9 1х 1 1 0 1 1 1 ADC15 ADC9 1х 1 . 1 1 0 0 0 ADC8 ADC10 1х 1 1 1 0 0 1 ADC9 ADC10 tx 1 1 1 0 1 0 ADC10 ADC10 1х 1 1 1 0 1 1 ADC11 ADC10 1х 1 1 1 1 0 0 ADC12 ADC10 1х 1 1 1 1 0 1 ADC13 ADC10 1х Как видим, возможности зависят от конкретной модели микроконтроллера. Кроме разрядов MUXn, регистр ADMUX содержит один или два разряда REFS, отвечающих за выбор опорного напряжения для АЦП. Например, их значение для микроконтроллеров ATmega8 и ATmega640 сведено в табл. 1.37. Таблица 1.37. Выбор опорного напряжения для АЦП REFS1 REFS0 Опорное напряжение 0 0 С вывода AREF, внутренне Vref отключено 0 1 С вывода AVcc с внешним конденсатором на выводе AREF 1 0 Внутренне 1,1 В с внешним конденсатором на AREF (ATmega640) 1 1 Внутренне 2,56 В с внешним конденсатором на выводе AREF В то же время в таком микроконтроллере, как ATtiny88, присутствует только один разряд REFS0: • 0 — внутреннее опорное напряжение 1,1В; • 1 — опорное напряжение берется с вывода AVcc- Еще один важный разряд в регистре ADMUX — это ADLAR. Он определяет размещение результата преобразования в регистровой паре ADCH:ADCL: • 0 — результат сохраняется в ADCL и двух младших разрядах ADCH; • 1 — результат сохраняется в ADCH и двух старших разрядах ADCL. Другими словами, разряд ADLAR задает “выравнивание” по правому или по левому краю 16-разрядной регистровой пары ADCH:ADCL. Итак, подведом краткий итог... в общем случае процесс аналого-цифрового преобразования в микроконтроллерах AVR семейств AT90S, ATtiny и ATmega про- текает следующим образом.
Структура микроконтроллеров AVR 85 1. Установить в лог. 1 разряды регистра ADMUX, соответствующие выбору анало- гового или дифференциального входа. 2. Установить разряды ADPS2:ADPS0 регистра ADCSR для выбора коэффициента деления частоты системной синхронизации. 3. Установить в лог. 1 разряд ADIE для разрешения режима прерывания. 4. Установить в лог. 1 разряд ADEN, чтобы разрешить использование АЦП. 5. Установить в лог. 1 разряд ADSC, чтобы начать преобразование. 6. Результат преобразования сохраняется в регистровой паре ADCL, ADCH с вы- равниванием, заданным разрядом ADLAR. Возможности аналого-цифрового преобразования для различных микрокон- троллеров AVR сведены в табл. 1.38. Таблица 1.38. Возможности АЦП для различных микроконтроллеров AVR Микроконтроллер Аналоговых каналов Каскад аналогового усиления AT90S 1200/2313/ 2323 / 2343 / 4414/8515 — — AT90S4433 6 — AT90S8535 8 — ATtiny 11 /12/2313/28L — — ATtiny13A 4 — ATtiny 15L 4 — ATtiny24 8 Есть ATtiny25 4 Есть ATtiny26 11 Есть ATtiny 261 11 Есть ATtiny 44 A 8 Есть ATtiny45 4 Есть I ATtiny461 11 Есть i ATtiny48 8 — Г ATtiny84 8 Есть I ATtiny85 4 Есть ' ATtiny861 11 Есть ATtiny88 8 — ATmega162/8515 — — ATmega128 J Есть ATmega1280 16 Есть ATmega1281 8 Есть . ATmega1284P 8 Есть ATmega16 8 Есть , ATmega16A 8 Есть ATmega164P 8 Есть ATmega165P 8 — ATmega 168 6 или 8 — ATmega168P 8 — ATmega 169 8 — ATmega2560 16 Есть ATmega2561 8 Есть
86 Глава 1. Восьмиразрядные микроконтроллеры AV Таблица 1.38. Возможности АЦП для различных микроконтроллеров AVR М и кроконтрол л ер Аналоговых каналов Каскад аналогового усиления АТтеда32А 8 Есть АТтеда324РА 8 Есть АТтеда325 8 — АТтеда325Р 8 — АТтеда3250 8 — АТтеда3250Р 8 / АТтеда328Р 8 — АТтеда*48РА. 8 — АТтеда64 8 Есть АТтеда640 16 Есть АТтеда644 8 Есть АТтеда644Р 8 Есть АТтеда645 8 Есть АТтеда6450 8 — АТтедав 6 или 8 — АТтеда8535 8 Есть АТтеда88РА 8 — Встроенный аналоговый компаратор Почти во всех микроконтроллерах AVR семейств AT90S, ATtiny и ATmega ис пользуется встроенный аналоговый компаратор напряжения, сравнивающий вход ное напряжение на двух входах. Как только напряжение на неинвентирующем вход станет больше, чем на инвентирующем, на выходе компаратора устанавливаете; лог. 1. Часто аналоговый компаратор используют для сравнения некоторого входы о го напряжения с опорным (рис. 1.44). Рис. 1.44. Принцип работы аналогового компаратора напряжений Для активизации компаратора требуется предварительно перевести соответст вующие выводы микроконтроллера в режим входов. Время срабатывания компара торов — небольшое, поэтому с их помощью можно быстро формировать ответны реакции на изменение соотношений входных напряжений.
Программирование памяти 87 Входы компаратора, совмещенные с какими-либо двумя портами ввода/вывода, называются AINO и AIN1, для управления его работой используется регистр ACSR (рис. 1.45). 7_______6_______5 4_______3_______2_______1_______О ACD ACBG АСО ACI ACIE ACIC ACIS1 ACIS0 Рис. 1.45. Регистр ACSR микроконтроллеров AVR Назначение разрядов регистра ACSR: • ACD — если установлен в лог. I, то питание аналогового компаратора отклю- чено; • ACBG (в старых микроконтроллерах отсутствует) — если установлен в лог. I, то на вход AINO аналогового компаратора подается фиксированное опорное на- пряжение, являющееся пороговым при обнаружении провалов напряжения; • АСО — напрямую связан с выходом аналогового компаратора; • ACI — флаг прерываний от аналогового компаратора — устанавливается в лог. 1, когда наступает событие, определенное разрядами ACIS1 и AC1S0; • ACIE — разряд разрешения прерывания от аналогового компаратора; • ACIC — разряд разрешения захвата на входе аналогового компаратора; для того чтобы можно было вызвать прерывание по захвату, оно должно быть разрешено разрядом TICIE1 в регистре T1MSK; • ACIS1, ACIS0 — устанавливают вид события на выходе аналогового компара- тора, которое должно вызвать прерывание его работы (табл. 1.39). Таблица 1.39. Вид событий для вызова прерывания от аналогового компаратора ACIS1 ACIS0 Вид прерывания аналогового компаратора 0 0 Прерывание при изменении состояния выхода (разряда АСО) 0 1 Не используется 1 0 Прерывание по ниспадающему фронту на выходе аналогового компаратора (напряжение на AIN1 больше, чем на AIN0) 1 1 Прерывание по нарастающему фронту на выходе аналогового компаратора (напряжение на AIN0 больше, чем на AIN1) Современные микроконтроллеры AVR предоставляют и другие возможности при работе с аналоговым компаратором, но их изучение выходит за тематические рамки данной книги. При желании читатель может ознакомиться с ними самостоя- тельно, обратившись к соответствующим техническим описаниям. Программирование памяти Микроконтроллеры AVR предоставляют в распоряжение пользователя байт с разрядами блокировки (рис. 1.46). При этом следует учитывать, что в некоторых моделях используются только первые два разряда этого байта: LB1 и LB2. 7 6 5 4 3 2 1 0 — — BLB12 BLB11 BLB02 BLB01 [ LB2 LB1 Рис. 1.46. Байт разрядов блокировки В незапрограммированном состоянии (состояние по умолчанию) они содержат лог. I. Программирование разрядов блокировки подразумевает запись в них лог. 0.
88 Глава 1. Восьмиразрядные микроконтроллеры AVR Полученные в результате такого программирования возможности блокировки ото- бражены в табл. 1.40-1.42. Разряды BLBxx и рассмотренные ниже разряды предохранения всегда необходимо програм- мировать раньше разрядов LBx. Таблица 1.40. Программирование разрядов блокировки LBx LB2 LB1 Тип блокировки 1 1 Блокировка памяти не используется 1 0 Отключено дальнейшее программирование памяти Flash и EEPROM в по- следовательном и параллельном режиме. Разряды предохранения в обоих режимах заблокированы 0 0 Отключено дальнейшее программирование и проверка памяти Flash и EE- PROM в последовательном и параллельном режиме. Разряды блокировки BLBxx и разряды предохранения в обоих режимах заблокированы Таблица 1.41. Программирование разрядов блокировки BLBOx BLB02 BLB01 Тип блокировки 1 1 Ограничения на доступ команд spm и (е)1рш к разделу приложения па- мяти программ 1 0 Команда spm не может выполнять запись в раздел приложения памяти программ 0 0 Команда spm не может выполнять запись в раздел приложения памяти программ, а команда (e)lpm, выполняемая из раздела загрузчика, не может выполнять чтение раздела приложения. Если в раздел загрузчи- ка помещены векторы прерываний, то при выполнении команд из раз- дела приложения прерывания будут недоступны 0 1 Команда (e)lpm, выполняемая из раздела загрузчика, не может выпол- нять чтение раздела приложения. Если в раздел загрузчика помещены векторы прерываний, то при выполнении команд из раздела приложе- ния прерывания будут недоступны Таблица 1.42. Программирование разрядов блокировки BLB1x BLB12 BLB11 Тип блокировки 1 1 Ограничения на доступ команд spm и (е)1рш к разделу загрузчика па- мяти программ 1 0 Команда spm не может выполнять запись в раздел загрузчика памяти программ 0 0 Команда spm не может выполнять запись в раздел загрузчика памяти программ, а команда (е)1рт, выполняемая из раздела приложения, не может выполнять чтение раздела загрузчика. Если в раздел приложе- ния помещены векторы прерываний, то при выполнении команд из раз- дела загрузчика прерывания будут недоступны 0 1 Команда (е)1рш, выполняемая из раздела приложения, не может вы- полнять чтение раздела загрузчика. Если в раздел приложения поме- щены векторы прерываний, то при выполнении команд из раздела за- грузчика прерывания будут недоступны О программировании и чтении разрядов блокировки речь пойдет позже.
Программирование памяти 89 Разряды предохранения Микроконтроллеры AVR предоставляют два или три байта с разрядами предо- хранения, структура которых зависит от конкретной модели. Мы рассмотрим при- мер для микроконтроллера ATmega8, содержащего два таких байта (табл. 1.43 и табл. 1.44). Запрограммированному состоянию разряда предохранения соответст- вует лог. О, а незапрограммированному — лог. 1. Таблица 1.43. Младший байт с разрядами предохранения микроконтроллера АТтеда8 Разряд № Описание Значение по умолчанию BODLEVEL 7 Уровень срабатывания для схемы обнаружения прова- лов напряжения 1 BODEN 6 Разрешение обнаружения провалов напряжения 1 SUT1 5 Выбор времени запуска: 00 — шесть циклов; 01 — шесть циклов плюс 4,1 мс; 10 — шесть циклов + 65 мс 1 SUT0 0 CKSEL3 3 Выбор источника тактирования микроконтроллера: 0000 — внешний источник; 0001-0100 — калиброванный внутренней RC-осцил- лятор: 0001 — 1 МГц; 0010 — 2 МГц; 0011—4 МГц; 0100 —8 МГц; 0101-1000 — внешний RC-осциллятор: 0101 — 0,1..0,9 МГц; 0110 — 0,9..3 МГц; 0111 — 3..8 МГц; 1000 — 8.. 12 МГц; 1001 — внешний низкочастотный кварцевый резонатор; 1010-1111 — внешний кварцевый/керамический резо- натор; 0 CKSEL2 2 0 CKSEL1 1 0 CKSEL0 0 1 Таблица 1.44. Старший байт с разрядами предохранения микроконтроллера АТтеда8 Разряд № Описание Значение по умолчанию RSTDISBL 7 Функция вывода РС6: ввод-вывод или сигнал сброса 1 WDTON 6 Постоянная активность сторожевого таймера 1 SPIEN 5 Разрешение последовательного программирования и загрузки данных 0 СКОРТ 4 Настройка осциллятора 1 EESAVE 3 Защита памяти EEPROM при подаче сигнала очистки кристалла 1 BOOTSZ1 2 Выбор размера загрузчика: 11 — 128 слов; 10 — 256 слов; 01 — 512 слов; 00 — 1024 слова 0 BOOTSZO 1 0 BOOTRST 0 Выбор вектора сброса 1 При переходе микроконтроллера в режим программирования значения предо- хранителей фиксируются, и до выхода из этого режима коррекция данных разрядов (за исключением EESAVE) не будет иметь эффекта. Параллельное программирование Типичная схема сигналов при параллельном программировании восьмиразряд- ных микроконтроллеров AVR показана на рис. 1.47.
90 Глава 1. Восьмиразрядные микроконтроллеры AVR Рис. 1.47. Типичная схема сигналов при параллельном программировании восьмиразрядных микроконтроллеров AVR Смысл представленных здесь сигналов: • RDY/BSY — 0 — устройство находится в процессе программирования; I — устройство готово для получения новой команды; • /ОЕ — разрешение вывода; • /WR — сигнал записи; • BS1 — выбор байта 1:0 — младший байт; 1 — старший байт; • ХА1, ХАО — операция по импульсу XTAL: ► 00 — загрузка адреса памяти Flash или EEPROM (старший или младший байт, в зависимости от состояния сигнала BS1); ► 01 — загрузка данных (старший или младший байт, в зависимости от состоя- ния сигнала BS1); ► 10 — загрузка команды; ► 11 — отсутствие операции; • PAGEL — загрузка страницы памяти; • BS2 — выбор байта 2: 0 — младший байт; 1 — старший байт; • DATA — двунаправленная шина данных (вывод при низком уровне сигнала /ОЕ). Рассмотрим возможные команды (в двоичном представлении): • 10000000 — очистка кристалла; • 01000000 — запись в разряды предохранения; • 00100000 — запись в разряды блокировки; • 00010000 — запись в память Flash; • 00010001 — запись в память EEPROM; • 00001000 — чтение байтов сигнатуры и калибровки осциллятора;
Программирование памяти 91 • 00000100 — чтение разрядов блокировки и предохранения; • 00000010 — чтение памяти Flash; • 00000011 — чтение памяти EEPROM. В качестве примера различные аспекты параллельного программирования па- мяти рассмотрим применительно к микроконтроллеру ATmega8. Переход в режим параллельного программирования Для перехода в режим параллельного программирования необходимо выпол- нить следующую последовательность действий. 1. Подать между выводами VCC и GND напряжение 4,5..5,5 В и выждать по мень- шей мере 100 мкс. 2. Установить на выводе /RESET низкий уровень сигнала и по меньшей мере шесть раз переключить состояние входа XTAL1. 3. Установить на выводах PAGEL, ХА1, ХАО и BS1 низкий уровень сигнала и вы- ждать по меньшей мере 100 нс. 4. Подать на вход /RESET напряжение 11,5..12,5 В. Учтите, что после этого любая активность на выводах PAGEL, ХА1, ХАО и BS1 в течение 100 нс приведет к сбою перехода в режим программирования. В том случае, если вывод /RESET был отключен с помощью предохранителя RSTDISBL или в качестве источника тактирования выбран внешний резонатор или RC-осциллятор (т.е. занят вывод XTAL1), представленная выше процедура станет невозможной. В таком случае необходимо выполнить следующую последователь- ность действий. I. Установить на выводах PAGEL, ХА1, ХАО и BS1 низкий уровень сигнала. 2. Подать между выводами VCC и GND напряжение 4,5..5,5 В и одновременно — 11,5.. 12,5 В на вход /RESET. 3. Выждать 100 нс. 4. Перепрограммировать предохранители: CKSEL[3:0] = 0000; RSTDISBL = О'. Ес- ли запрограммированы разряды блокировки, то перед коррекцией предохрани- телей может потребоваться выполнить команду очистки кристалла. 5. Выйти из режима программирования, выключив питание микроконтроллера, или подав низкий уровень сигнала на вход /RESET. 6. Перейти в режим программирования по описанной выше процедуре. Очистка кристалла Команда очистки кристалла стирает содержимое памяти Flash и EEPROM (если только не запрограммирован предохранитель EESAVE), а также — разряды блоки- ровки. Байты с разрядами предохранения остаются неизменными. Очистку кристал- ла необходимо выполнять перед каждым повторным программированием памяти Flash или EEPROM. Для выполнения этой команды служит следующая процедура. 1. ХА[1:0] = 10 (загрузка команды). 2. BS1=O. 3. Подать в шину данных байт 10000000 (команда очистки кристалла).
92 Глава 1. Восьмиразрядные микроконтроллеры AVR 4. Подать импульс на вход XTAL1 для загрузки команды. 5. Подать сигнал низкого уровня на вход /WR, чтобы начать выполнение команды. 6. Дождаться, пока на выходе RDY/BSY появится сигнал высокого уровня, сигна- лизирующий об окончании выполнения команды. Программирование и чтение памяти программ Память программ микроконтроллеров AVR имеет страничную организацию. Размер страницы отличается в зависимости от устройства. Так, например, у микро- контроллера ATmega8 он составляет 32 слова, а у ATmega640 — 128 слов. При про- граммировании Flash-памяти программа фиксируется в буфере страницы, а затем все ячейки буфера одновременно записываются на кристалл. Рассмотрим процедуру программирования Flash-памяти. 1. Загрузить команду “Запись в памяти Flash” (ХА[1:0] = 10; BS1 = 0; DATA = = 00010000; XTAL1 = 1). 2. Загрузить младший байт адреса (ХА[1:0] = 00; BS1 = 0; BS2 = 0; DATA = млад- ший байт адреса; XTAL1 = 1). 3. Загрузить младший байт данных (ХА[ 1:0] = 01; DATA = младший байт данных; XTAL1 = 1). 4. Загрузить старший байт данных (BS1 = 1; ХА[1:0] = 01; DATA = старший байт данных; XTAL1 = 1). 5. Зафиксировать данные (BS1 = 1; PAGEL = 1). 6. Повторить пункты 2-5, пока не будет заполнен весь буфер или не будут загру- жены все данные внутри страницы. 7. Загрузить старший байт адреса (ХА[1:0] = 00; BS 1 = 1; BS2 = 0; DATA = стар- ший байт адреса; XTAL1 = 1). 8. Если допускается моделью микроконтроллера, загрузить дополнительный байт адреса (ХА[1:0] = 00; BS 1 =0; BS2 = 1; DATA = дополнительный байт адреса; XTAL1 = 1). 9. Запрограммировать страницу (BS 1 = 0; BS2 = 0; /WR = 0). 10. Дождаться; пока на выходе RDY/BSY не появится сигнал высокого уровня. 11. Повторить пункты 2-10, пока не будет записана вся программа или не будет за- полнена вся память Flash. 12. Завершить процесс программирования (ХА[1:0] = 10; DATA = 00000000; XTAL1 = 1). Для чтения слова из памяти программ необходимо выполнить следующую по- следовательность действий. 1. Загрузить команду “00000010”. 2. Загрузить старший байт адреса. 3. Загрузить младший байт адреса. 4. Установить на входах /ОЕ и BS 1 низкий уровень сигнала. 5. Загрузить младший байт данных. 6. Установить на входе BS 1 высокий уровень сигнала. 7. Загрузить старший байт данных. 8. Установить на входе /ОЕ высокий уровень сигнала.
Программирование памяти 93 Программирование разрядов блокировки и предохранения Рассмотрим процедуру программирования разрядов блокировки. 1. Загрузить команду “00100000”. 2. Загрузить байт с программируемыми (т.е. содержащими лог. 0) разрядами. 3. Подать сигнал низкого уровня на вход /WR. 4. Дождаться появления на выходе RDY/BSY сигнала высокого уровня. Очистить разряды блокировки можно только по команде очистки кристалла. Теперь рассмотрим процедуру программирования предохранителей. I. Загрузить команду “00100000”. 2. Загрузить байт данных с разрядами предохранения (0 — программирование предохранителя; 1— стирание предохранителя). 3. Установить значения разрядов BS2 и BS1: 00 — первый байт предохранителей; 01 — второй байт; 10 — третий байт. 4. Подать сигнал низкого уровня на вход /WR. 5. Дождаться появления на выходе RDY/BSY сигнала высокого уровня. 6. Установить значения BS2 = 0 и BS1 =0. Процедуры чтения байтов с разрядами блокировки и предохранения идентичны. 1. Загрузить команду “00000100”. 2. Подать сигнал низкого уровня на вход /ОЕ. 3. Подать требуемую комбинацию сигналов на входы BS2 и BS 1: 00 — первый байт предохранителей; 11 — второй байт предохранителей; 10 — третий байт предохранителей (если существует); 01 — байт с разрядами блокировки. 4. Считать байт с шины данных. 5. Подать на вход /ОЕ сигнал высокого уровня. Последовательное программирование Как память Flash, так и EEPROM можно программировать в последовательном режиме. В таком случае используются только три линии: SCK (тактовый сигнал), MOSI или PDI (линия ввода бита данных) и MISO или PDO (линия вывода бита данных) (рис. 1.48). Если микроконтроллер тактируется от внутреннего осциллятора, то к выводу X7AL1 подклю- чать источник тактовых импульсов не нужно. Запись данных в устройство осуществляется по нарастающему, а чтение — по ниспадающему фронту сигнала на входе SCK. Команды, используемые при последовательном программировании микрокон- троллеров AVR, перечислены в табл. 1.45. В табл. 1.45 приняты следующие условные обозначения: а — старший разряд адреса; b — младший разряд адреса; Н — 0 — младший байт; 1 — старший байт; о — вывод данных; i — ввод данных; х — не имеет значения.
94 Глава 1. Восьмиразрядные микроконтроллеры AVR Таблица 1.45. Команды последовательного программирования Команда Формат команды Байт 1 Байт 2 БайтЗ Байт 4 Операция Разрешение про- граммирования 1010 1100 0101 0011 хххх хххх xxxxxxxx Разрешение программи- рования Очистка кристал- ла 1010 1100 100х хххх хххх хххх xxxxxxxx Очистка памяти Flash и EEPROM Чтение из памя- ти программ 0010 нооо 0000 аааа bbbb bbbb OOOO 0000 Чтение байта данных из памяти программ по ад- ресу а:Ь Загрузка на стра- ницу памяти про- грамм 0100 нооо 0000 хххх xxxb bbbb iiii iiii Запись байта данных на страницу памяти про- грамм по адресу Ь. Пер- вым загружается млад- ший байт Запись страницы памяти программ 0100 1100 0000 аааа bbbb хххх xxxxxxxx Запись страницы памяти программ по адресу а:Ь Чтение из памя- ти EEPROM 1010 0000 ООххххха bbbb bbbb OOOO OOOO Чтение данных из ячейки памяти EEPROM по ад- ресу а:Ь Запись в память EEPROM 1100 0000 ООхх ххха bbbb bbbb iiii iiii Запись данных в ячейку памяти EEPROM по ад- ресу а:Ь Чтение разрядов блокировки 0101 1000 0000 0000 xxxxxxxx OOOO OOOO Чтение байта с разряда- ми блокировки Запись разрядов блокировки 1010 1100 111X хххх xxxxxxxx iiii iiii Запись байта с разряда- ми блокировки Чтение байта сигнатуры 0011 0000 ООхх хххх xxxx xxbb OOOO OOOO Чтение байта сигнатуры по адресу Ь. Запись предо- хранителей 1010 1100 1010 0000 xxxxxxxx iiii iiii Запись первого байта предохранителей Запись старших предохраните- лей 1010 1100 1010 1000 xxxxxxxx iiii iiii Запись второго байта предохранителей Запись дополни- тельных предо- хранителей 1010 1100 1010 0100 xxxxxxxx iiii iiii Запись третьего байта предохранителей (если он доступен) Чтение предо- хранителей 0101 0000 0000 0000 xxxxxxxx OOOO OOOO Чтение первого байта предохранителей Чтение старших предохраните- лей 0101 1000 0000 1000 xxxx xxxx OOOO OOOO Чтение второго байта п редохранител ей Чтение дополни- тельных предо- хранителей 0101 0000 0000 1000 xxxxxxxx OOOO OOOO Чтение третьего байта предохранителей (если он доступен)
Программирование памяти 95 Рис. 1.48. Схема для последовательного программирования (микроконтроллер ATmega8) Рассмотрим процедуру последовательного программирования. 1. Установить низкий уровень сигнала на входах /RESET и SCK. В некоторых сис- темах программатор не может гарантировать, что при подаче питания на входе SCK будет удержан низкий уровень. В таком случае после установки SCK = О необходимо подать на вход /RESET сигнал высокого уровня на протяжении по меньшей мере двух тактовых циклов процессора. 2. Подать напряжение между выводами VCC и GND. 3. Выждать по меньшей мере 20 мс и разрешить последовательное программиро- вание, передав побитно на вход MOST (PDI) соответствующую команду (см. табл. 1.45). Передаваться должны все четыре байта команды. 4. Если линии передачи верно синхронизированы, то в момент передачи третьего байта команды на выходе MISO (PDO) должен быть выдан второй байт (т.е. $53). Если этого не произошло, то возникло нарушение синхронизации, и необходимо подать на вход /RESET сигнал низкого уровня и повторно пере- дать команду разрешения программирования. 5. Память Flash программируется постранично, поэтому вначале побайтно загру- жается страница (для каждого слова первым идет младший байт). 6. Загруженная страница сохраняется, а до записи следующей страницы необхо- димо выждать не менее 4,5 мс. 7. Память EEPROM программируется побайтно. При этом перед записью новых данных ячейка EEPROM автоматически очищается. До записи следующего бай- та необходимо выждать не менее 9 мс. 8. Содержимое любой ячейки памяти можно проверить с помощью соответст- вующей команды чтения, которая побитно.выдаст на выход MISO (PDO) инте- ресующий байт данных. 9. В завершение процесса программирования необходимо установить высокий уровень сигнала на входе /RESET. После этого можно отключить питание.
96 Глава 1. Восьмиразрядные микроконтроллеры AVR Технология picoPower В завершение главы затронем такую инновацию Atmel как технология pico- Power, задействованную в ряде новых микроконтроллеров. Для того чтобы “идти в ногу” с требованиями, предъявляемыми к энергопотреблению современных мик- ропроцессорных систем, компания Atmel разработала технологию picoPower, кото- рая позволяет снизить потребляемое напряжение как в рабочем, так и в “спящем” режиме. Ее основные особенности: • работа устройства на напряжении 1,8 В; • потребление тока — 650 нА в рабочем режиме и 100 нА в “спящем” режиме; • малый уровень утечек; • обнаружение провалов напряжения в “спящем” режиме; • кварцевый генератор на 32 кГц с очень малым потреблением энергии; • использование регистра Power Reduction Register (PRR), содержащего управ- ляющие разряды для отключения тактирования неиспользуемых периферийных модулей; • опрос содержимого Flash-памяти в течение нескольких наносекунд с после- дующим ее отключением, что значительно снижает утечку тока. Технология picoPower реализована в микроконтроллерах ATtinylЗА, АТ- tiny44A, ATtiny48, ATtiny88, а также во всех представителях семейства ATmega, у которых в маркировке используется буква “Р” (например, ATmega328P и АТ- mega324PA).
Глава 2 Семейство AVR ATxmega Семейство микроконтроллеров ATxmega расширяет линейку устройств AVR как для совершенствования существующих встроенных систем, так и с прицелом на новые области применения. При этом поддерживаются не только восьми-, но и высокопроизводительные 16-разрядные процессоры, хотя сохраняется совмести- мость с микроконтроллерами ATtiny и ATmega. Основные преимущества семейства ATxmega: • реализация технологии picoPower, позволяющей значительно уменьшить энер- гопотребление; • рабочее напряжение 1,6 В при тактовой частоте 2 МГц; • система обработки событий; • контроллер прямого доступа к памяти; • высокопроизводительные 12-разрядные АЦП и ЦАП; • система шифрования данных; • точная, гибкая система синхронизации с возможностью динамического пере- ключения источника тактового сигнала. На момент издания книги семейство ATxmega представлено подсемействами А и D, однако моделей класса А значительно больше, поэтому мы рассмотрим некото- рые особенности архитектуры, характерные именно для них. Обзор возможностей микроконтроллеров ATxmega А Микроконтроллеры ATxmega А предоставляют в распоряжение программиста 115 команд и 32 рабочих регистра общего назначения. При этом, в отличие от клас- сической RISC-архитектуры, в одной команде можно обратиться сразу к двум рабо- чим регистрам, что значительно повышает производительность системы. Кроме наличия стандартных средств и интерфейсов (Flash, EEPROM, USART, TW1 и т.д.), семейство ATxmega А реализует некоторые возможности, отсутствую- щие в “классических” восьмиразрядных микроконтроллерах AVK: • четырехканальный контроллер прямого доступа к памяти (DMA); • восьмиканальная система обработки событий; • программируемый многоуровневый контроллер прерываний; • интерфейсы TWI, совместимые с протоколами шин 12С и SMBUS; • системы шифрования AES и DES; • восьмиканальные 12-разрядные ЦАП и АЦП с возможностью использования дифференциального входа с программируемым коэффициентом усиления; • до четырех аналоговых компараторов с режимом определения попадания изме- ряемого напряжения в заданный диапазон (режим “Window”);
98 Глава 2. Семейство AVR ATxmega для внутрисхемного программирования и отладки доступны интерфейсы PDI и JTAG. Структурная схема микроконтроллеров ATxmega А показана на рис. 2.1. Р0(0 7] M0SC1 isbH ” т71 PR(O.1) XTAL1 рвр.ту JTAG УСС 1 GND •POLD ►РМ|0,7| РК(О.7| PJJ0..7) РН(0.7] RESEP РО1„С1К PCJO..7] PD(0,7j pqO.TJ PF1O.7J Рис. 2.1. Структурная схема микроконтроллеров ATxmega А
Организация памяти семейства ATxmega 99 Организация памяти семейства ATxmega Кроме того, что касается наличия 32-х рабочих регистров, организация памяти в микроконтроллерах AVR нового семейства ATxmega отличается от “классиче- ской”. Прежде всего следует отметить, что рабочие регистры адресуются независи- мо от области данных, которая теперь включает в себя и область ввода/вывода (рис. 2.2). Память EEPROM по умолчанию адресуется- независимо, как в традицион- ной организации памяти микроконтроллеров AVR, однако может адресоваться и в пространстве памяти данных. В этом случае ей соответствует диапазон адресов $001000..$001FFF. $FFFFFF Внешнее ОЗУ (от Одо 16 Мбайт) RamEnd+1 RamEnd Внутреннее ОЗУ $002000 $001FFF Память EEPROM (до 4 Кбайт) $001000 $OOOFFF Область ввода/вывода (до 4 Кбайт) $000000 R31 $00001F Регистровый файл R0 $020000 Рис. 2.2. Организация памяти SRAM микроконтроллеров семейства ATxmega Микроконтроллеры семейства ATxmega оснащены внутренней памятью SRAM объемом 2, 4, 8, 16 или 32 Кбайт, а также памятью EEPROM объемом 1, 2 или 4 Кбайт (табл. 2.1). До четырех портов микроконтроллеров ATxmega предназначены для подклю- чения модулей внешней памяти типа SRAM (до 16 Мбайт) или SDRAM (до 128 Мбайт), а также — периферийных устройств с отображением в памяти данных (на- пример, ЖК-дисплеев).
100 Глава 2. Семейство AVR ATxmega Таблица 2.1. Объемы памяти данных в микроконтроллерах семейства ATxmega Микроконтроллер Внутренняя память SRAM, Кбайт Адрес “RamEnd” Память EEPROM, Кбайт АТхтеда128А1 8 $003FFF 2 ATxmega192A1 16 $005FFF 4 ATxmega256A1 16 $005FFF 4 ATxmega384A1 32 $009FFF 4 ATxmega64A1 4 $002FFF 2 ATxmega128A3 8' $003FFF 2 ATxmega192A3 • 16 $005FFF 4 ATxmega256A3B 16 $005FFF 1 4 ATxmega256A3 16 $005FFF 4 ATxmega64A3 4 $002FFF 2 ATxmega128A4 8 $003FFF 2 ATxmega16A4 2 $0017FF 1 ATxmega32A4 4 $002FFF 1 ATxmega64A4 4 $002FFF 2 ATxmega128D3 8 $003FFF 2 ATxmega192D3 16 $005FFF 2 ATxmega256D3 16 $005FFF 4 ATxmega64D3 4 $002FFF 2 ATxmega16D4 2 $0017FF 1 ATxmega32D4 4 $002FFF i Область ввода/вывода семейства ATxmega Как и в традиционном варианте, область ввода/вывода семейства ATxmega со- держит все регистры состояния и конфигурирования периферийных устройств и модулей микроконтроллера, включая процессор. Тем не менее, здесь присутствует ряд отличий: • младшие 16 адресов области ввода/вывода — это специальные регистры дан- ных, используемые для хранения информации, наподобие глобальных перемен- ных и флагов; • ассемблерные команды поразрядной обработки и различных проверок приме- нимы только к диапазону адресов $00..$lF, т.е. к 16 регистрам данных и 16 ре- гистрам, отвечающих за работу с виртуальными портами; • изменено размещение регистров в области ввода/вывода (пример для подсемей- ства ATxmega А представлен в приложении Д в конце книги). Арбитраж шины данных Поскольку память данных в микроконтроллерах ATxmega разбита на четыре модуля, к различным ее областям могут одновременно обращаться различные уст- ройства, которые являются ведущими по отношению к шине данных (рис. 2.3). На- пример, центральный процессор может обращаться к внешней памяти, в то время как контроллер прямого доступа (DMA) передает данные из внутренней памяти SRAM в область ввода/вывода (подробнее о контроллере DMA речь пойдет в сле- дующем разделе).
Организация памяти семейства ATxmega 101 Рис. 2.3. Доступ к шине данных в микроконтроллерах ATxmega Когда несколько ведущих устройств обращаются к одной и той же шине, ис- пользуется следующая приоритетность (вверху списка находятся устройства с более высоким приоритетом): • устройство, которое обращается к шине в данный момент; • устройство, которое работает с пакетом данных; • устройство, запрашивающее доступ к данным (процессор имеет приоритет); • устройство, запрашивающее доступ к шине (процессор имеет приоритет). Память программ Память программ в микроконтроллерах ATxmega традиционно выполнена по технологии Flash, и каждая ячейка в ней представляет собой 16-разрядное слово (все команды AYR — 16- или 32-разрядные). Основное отличие памяти программ ATx- mega от “классической” заключается в том, что она разбита на два раздела: прило- жения и загрузчика (рис. 2.4). FlashEnd Раздел загрузчика Раздел таблицы приложения Раздел приложения $000000 Рис. 2.4. Организация памяти программ микроконтроллеров семейства ATxmega Ассемблерная команда spin, которая служит для записи в Flash-память в ходе выполнения приложения, эффективна только в том случае, если она находится в разделе загрузчика. Эта команда может обращаться ко всей памяти программ,
102 Глава 2. Семейство AVR ATxmega включая сам раздел загрузчика. Если загрузчик не используется, то в данном разде- ле можно разместить код приложения. Раздел приложения содержит раздел таблицы, который можно использовать для хранения данных. Его размер совпадает с размером загрузчика. Суть таблицы за- ключается в том, что для нее может применять уровень защиты, отличный от уров- ня защиты приложения. Это позволяет безопасно сохранять в памяти программ дол- говременные данные (например, какие-нибудь важные параметры измерений). Если раздел таблицы не используется для хранения данных, в нем может размещаться программный код. Размер разделов фиксирован и зависит от типа микроконтролле- ра. Им соответствуют различные наборы разрядов блокировки, что обеспечивает не- зависимые настройки защиты. Объем памяти программ в различных микроконтроллерах ATxmega представ- лены в табл. 2.2. Таблица 2.2. Объемы памяти программ в микроконтроллерах семейства ATxmega Микроконтроллер Размер раздела приложения, Кбайт Размер раздела загрузчика, Кбайт Адрес “FlashEnd” АТхтеда128А1 128 8 $010FFF ATxmega192A1 192 8 $018FFF ATxmega256A1 256 8 $020FFF ATxmega384A1 384 8 S030FFF ATxmega64A1 64 4 $0087FF ATxmega 128A3 128 8 $010FFF ATxmega192A3 192 8 S018FFF ATxmega256A3B 256 8 $020FFF ATxmega256A3 256 8 S020FFF ATxmega64A3 64 4 $0087FF ATxmega128A4 128 4 $0107FF ATxmega16A4 16 4 $0027FF ATxmega32A4 32 4 $0047FF ATxmega64A4 64 4 $0087FF ATxmega128D3 128 8 $010FFF ATxmega192D3 192 8 $018FFF ATxmega256D3 256 8 $020FFF ATxmega64D3 64 4 S0087FF ATxmega16D4 16 4 S0027FF ATxmega32D4 32 4 • $0047FF Как видим, номер в маркировке микроконтроллеров ATxmega соответствует объему их памяти программ. Контроллер прямого доступа к памяти Контроллер прямого доступа к памяти (DMA — Direct Memory Access) семей- ства ATxmega организовывает передачу данных между различными модулями па- мяти, а также памятью и периферией с минимальным вмешательством центрального процессора. В нем реализована гибкая система выбора приоритетности каналов, не- сколько режимов адресации, возможность двойной буферизации и передачи данных большими блоками.
Контроллер прямого доступа к памяти 103 Контроллер DMA микроконтроллеров ATxmega А использует четыре канала, каждому из которых соответствует собственный источник данных, пункт назначе- ния и размер блоков, а также — настройки передачи и прерываний. Запросы на пре- рывание могут формироваться в момент завершения передачи данных или при об- наружении контроллером ошибки в одном из каналов. Когда некоторый канал DMA запрашивает передачу данных, арбитр ожидает освобождения шины центральным процессором, после чего разрешает начать процесс передачи, который протекает порциями по одному, два, четыре или восемь байт. Адресация может быть статиче- ской, с инкрементом или декрементом адреса. Передачу по каналу DMA может инициировать программа, периферийное устройство или система обработки собы- тий. Завершенная операция чтения или записи по каналу DMA называется транзак- цией. Количество байт, передаваемых в течение одной транзакции, устанавливается программно и определяется размерами блока и настройками счетчика повторений. Каждый блок передается меньшими порциями по одному, два, четыре или восемь байт. Для активизации контроллера прямого доступа к памяти служит регистр DMACTRL (в семействе ATxmega А ему соответствует адрес $0100 области вво- да/вывода) (рис. 2.5). 7 6 5 4 3 2 1 0 ENABLE RESET —Г — DBUFMODE1 DBUFMODEO PRIMODE1 PRIMODEO Рис. 2.5. Регистр DMACTRL Для активизации контроллера DMA необходимо установить в лог. 1 разряд ENABLE. Если контроллер активен, то обнуление этого разряда не будет выполнено до тех пор, пока не освободится внутренний буфер передачи, и не завершится тран- закция. Рассмотрим назначение остальных разрядов регистра DMACTRL. • RESET — установка этого разряда в лог. 1 разрешает программный сброс, что может быть осуществлено только при отключенном контроллере DMA (т.е. при ENABLE=0). После сброса разряд RESET автоматически обнуляется. • DBUFMODE[1:0] — определяют настройку двойной буферизации для различ- ных каналов (табл. 2.3). Под двойной буферизацией подразумевается связыва- ние двух каналов, в результате которого второй канал подхватывает передачу, когда первый ее заканчивает, и наоборот. Таблица 2.3. Значение разрядов DBUFMODE регистра DMACTRL DBUFMODE1 DBUFMODEO Значение * 0 . 0 Двойная буферизация не используется 0 1 Двойная буферизация для каналов 0 и 1 1 0 Двойная буферизация для каналов 2 и 3 1 1 Двойная буферизация для пар каналов 0/1 и 2/3 • PRIMODE[1:0] — эти разряды определяют внутреннюю приоритетность кана- лов (табл. 2.4). Схема приоритетности используется в тех случаях, когда в один и тот же момент времени запрос на передачу данных выдают сразу несколько каналов.
104 Глава 2. Семейство AVR ATxmega Таблица 2.4. Значение разрядов PRIMODE регистра DMACTRL PRIMODE1 PRIMODE0 Значение 0 0 Низший приоритет — у канала, передавшего данные последним 0 1 Канал 0 — наиболее приоритетный; среди остальных трех ка- налов низший приоритет — у канала, передавшего данные по- следним 1 1 0 Наивысший приоритет — у канала 0; далее — у канала 1; среди остальных двух каналов низший приоритет — у канала, пере- давшего данные последним 1 !• Наивысший приоритет — у канала 0, далее — у канала 1, за- тем — у канала 2. Самый низкий приоритет — у канала 3 Устройство, инициирующее передачу, определяется для каждого канала DMA отдельно с помощью соответствующего регистра TRIGSRC (в микроконтроллерах ATxmega А им соответствуют следующие адреса в области ввода/вывода: $0113 для канала 0; $0123 для канала 1; $0133 для канала 2 и $0143 для канала 3). Этот регистр содержит восьмиразрядный код инициатора, значение которого зависит от типа микроконтроллера и присутствующих в нем периферийных устройств и модулей. Данный код представляет собой сумму некоторого базового числа, соответствую- щего категории устройств, и смещения, задающего конкретное устройство или мо- дуль из выбранной категории. Значения регистра TRIGSRC для всех модулей мик- роконтроллеров ATxmega А перечислены в табл. 2.5. Таблица 2.5. Значения регистра TRIGSRC канала DMA Категория Смещение TRIGSRC Инициатор передачи Система обра- ботки событий $00 $01 (00000001) Канал событий 0 $01 $02 (00000010) Канал событий 1 $02 $03(00000011) Канал событий 2 АЦП на порту А $00 $10 (00010000) Канал 0 $01 $11 (00010001) Канал 1 $02 $12(00010010) Канал 2 $03 $13(00010011) Канал 3 $04 $14 (00010100) Объединение каналов 0..3 логиче- ской операцией “ИЛИ” ЦАП на порту А $00 $15(00010101) Канал 0 $01 $16(00010110) Канал 1 АЦП на порту В $00 $20 (00010000) Канал 0 $01 $21 (00010001) Канал 1 $02 $22 (00010010) Канал 2 $03 $23(00010011) Канал 3 $04 $24 (00010100) Объединение каналов 0..3 логиче- ской операцией “ИЛИ” ЦАП на порту В $00 $25 (00010101) Канал 0 $01 $26 (00010110) Канал 1 Таймер/счетчик, со $00 $40(01000000) Переполнение $01 $41 (01000001) Ошибка $02 $42 (01000010) Сравнение или захват, канал А $03 $43(01000011) Сравнение или захват, канал В $04 $44 (01000100) Сравнение или захват, канал С
Контроллер прямого доступа к памяти 105 Таблица 2.5. Продолжение Категория Смещение TRIGSRC Инициатор передачи Таймер/счетчик, СО $05 $45 (01000101) Сравнение или захват, канал D Таймер/счетчик, С1 $00 $46(01000110) Переполнение $01 $47 (01000111) Ошибка $02 $48 (01001000) Сравнение или захват, канал А $03 $49 (01001001) Сравнение или захват, канал В SPI на порту С " $00 $4А (01001010) Интерфейс SPI на порту С USART, СО $00 $4В (01001100) Прием по USART завершен $01 $4С (01001101) Регистр данных USART пуст USART, С1 $00 $4Е (01001110) Прием по USART завершен $01 $4F (01001111) Регистр данных USART пуст Таймер/счетчик, D0 $00 $60(01100000) Переполнение $01 $61 (01100001) Ошибка $02 $62(01100010) Сравнение или захват, канал А $03 $63(01100011) Сравнение или захват, канал В $04 $64(01100100) Сравнение или захват, канал С $05 $65(01100101) Сравнение или захват, канал D Таймер/счетчик, D1 $00 $66(01100110) Переполнение $01 $67(01100111) Ошибка $02 $68(01101000) Сравнение или захват, канал А $03 $69(01101001) Сравнение или захват, канал В SPI на порту D $00 $6А (01101010) Интерфейс SPI на порту С USART, DO $00 $6В (01101100) Прием по USART завершен $01 $6С (01101101) Регистр данных USART пуст USART, D1 $00 $6Е (01101110) Прием по USART завершен $01 $6F (01101111) Регистр данных USART пуст Таймер/счетчик, E0 $00 $80 (10000000) Переполнение $01 $81 (10000001) Ошибка $02 $82 (10000010) Сравнение или захват, канал А $03 $83(10000011) Сравнение или захват, канал В $04 $84 (10000100) Сравнение или захват, канал С $05 $85 (10000101) Сравнение или захват, канал D Таймер/счетчик, Е1 $00 $86 (10000110) Переполнение $01 $87 (10000111) Ошибка $02 $88 (10001000) Сравнение или захват, канал А $03 $89 (10001001) Сравнение или захват, канал В SPI на порту Е $00 $8А (10001010) Интерфейс SPI на порту С USART, Е0 $00 $8В (10001100) Прием по USART завершен $01 $8С (10001101) Регистр данных USART пуст USART, Е1 $00 $8Е (10001110) Прием по USART завершен $01 $8F (10001111) Регистр данных USART пуст Таймер/счетчик, F0 $00 $А0 (10100000) Переполнение $01 $А1 (10100001) Ошибка $02 $А2 (10100010) Сравнение или захват, канал А $03 $АЗ (10100011) Сравнение или захват, канал В
106 Глава 2. Семейство AVR ATxmega Таблица 2.5. Окончание Категория Смещение TRIGSRC Инициатор передачи $04 $А4 (10100100) Сравнение или захват, канал С $05 $А5 (10100101) Сравнение или захват, канал D Таймер/счетчик, F1 $00 $А6 (10100110) Переполнение $01 $А7 (10100111) Ошибка $02 $А8 (10101000) Сравнение или захват, канал А $03 $А9 (10101001) Сравнение или захват, канал В SPI на порту F $00 $АА (10101010) Интерфейс SPI на порту С USART, F0 $00 $АВ (10101100) Прием по USART завершен $01 $АС (10101101) Регистр данных USART пуст USART, F1 $00 $АЕ (10101110) Прием по USART завершен $01 $AF (10101111) Регистр данных USART пуст Стартовый адрес источника передачи для каждого канала DMA задают три ре- гистра SRCADDR0-SRCADDR2 (т.е. адрес — 24-разрядный), а соответствующий целевой адрес — регистры DESTADDR0-DESTADDR2. Режим адресации для каж- дого канала настраивается особо с помощью регистра ADDRCTRL (в микроконтро- ллерах ATxmega А ему соответствуют следующие адреса в области ввода/вывода: $0112 для канала 0; $0122 для канала 1; $0132 для канала 2 и $0142 для канала 3) (рис. 2.6). 7 6 5 4 3 2 1 0 SRCRELOAD SRCDIR DESTRELOAD DESTDIR Рис. 2.6. Регистр ADDRCTRL Рассмотрим назначение разрядов этого регистра. • SRCRELOAD[1:0] — определяют характер повторной загрузки адреса источ- ника в регистры SRCADDR (табл. 2.6). Если канал занят передачей, эти разряды изменить нельзя. • SRCDIR[l:0] — выбор режима адресации источника (табл. 2.7). Если канал за- нят передачей, эти разряды изменить нельзя. • DESTRELOAD[1:0] — определяют характер повторной загрузки целевого ад- реса в регистры DESTADDR (табл. 2.8). Если канал занят передачей, эти разря- ды изменить нельзя. • DESTDER[l:0] — выбор режима адресации целевого модуля (табл. 2.9). Если канал занят передачей, эти разряды изменить нельзя. Таблица 2.6. Значение разрядов SRCRELOAD SRCRELOAD1 SRCRELOAD0 Значение 0 0 Повторная загрузка не выполняется 0 1 Исходное значение загружается в регистры SRCADDR по завершении передачи каждого блока данных 1 0 Исходное значение загружается в регистры SRCADDR по завершении передачи каждой порции данных 1 1 Исходное значение загружается в регистры SRCADDR по завершении каждой транзакции
Контроллер прямого доступа к памяти 107 Таблица 2.7. Значение разрядов SRCDIR SRCDIR1 SRCDIR0 Значение 0 0 Фиксированный адрес 0 1 Инкремент адреса после каждого доступа 1 0 Декремент адреса после каждого доступа 1 1 Зарезервировано Таблица 2.8. Значение разрядов DESTRELOAD DESTRELOAD1 DESTRELOADO Значение 0 0 Повторная загрузка не выполняется 0 1 Исходное значение загружается в регистры DESTADDR по завершении передачи каждого блока данных 1 0 Исходное значение загружается в регистры DESTADDR по завершении передачи каждой порции данных 1 1 Исходное значение загружается в регистры DESTADDR по завершении каждой транзакции Таблица 2.9. Значение разрядов DESTDIR DESTDIR1 DESTDIR0 Значение 0 0 Фиксированный адрес 0 1 Инкремент адреса после каждого доступа 1 0 Декремент адреса после каждого доступа 1 1 Зарезервировано Количество байт в каждом передаваемом блоке задается регистровой парой TRFCNTH:TRFCNTL. После каждого считанного по каналу DMA байта данное 16- разрядное значение декрементируется. При достижении нуля в регистровую пару TRFCNTH:TRFCNTL повторно загружается значение, которое было записано в нее последним. Количество передач блока задается регистром REPCNT. После каждой переда- чи блока значение этого регистра декрементируется. Если с помощью регистра ADDRCTRL установлен режим повторов, то значение REPCNT определяет момент завершения транзакции. В таком случае при достижении регистром REPCNT нуля канал после передачи последнего блока отключается. Если REPCNT=0, то количе- ство передаваемых блоков не ограничено. Для управления каждым из каналов отве- дено по два регистра: CHxCTRLA и CHxCTRLB (рис. 2.7 и рис. 2.8). 7 6 5 4 3 2 * 1 0 CHEN CHRST REPEAT TRFREQ — SINGLE BURSTLEN Рис. 2.7. Регистр CHxCTRLA 7 6 5 4 3 2 1 0 CHBUSY CHPEND ERRIF TRNIF ERRINTLVL TRNINTLVL Рис. 2.8. Регистр CHxCTRLB Канал DMA активизируется установкой в лог. 1 разряда CHEN регистра CHxCTRLA. Это приводит к автоматической установке флага CHBUSY в регистре
108 Глава 2. Семейство AVR ATxmega CHxTRLB. По завершении транзакции разряды CHEN и CHBUSY автоматически обнуляются. Кроме того, флаг CHBUSY автоматически сбрасывается установкой флага TRNIF Или ERRIF в регистре CHxCTRLB. Рассмотрим назначение других разрядов регистров управления каналом DMA. • CHRST — установка этого разряда в лог. 1 вызывает сброс канала (обнуление всех его регистров), по завершении которого разряд автоматически обнуляется. Разряд CHRST можно изменить только в тот момент, когда канал неактивен (CHEN=0). • REPEAT — установка этого разряда в лог. 1 активизирует режим повторных передач. В момент начала передачи последнего блока он аппаратно обнуляется. Помните, что перед установкой разряда REPEAT необходимо инициализиро- вать соответствующий регистр REPCNT. • TRFREQ — установке этого разряда в лог. 1 соответствует запрос на передачу данных по каналу DMA. В момент начала передачи он автоматически обнуляет- ся. • SINGLE — установка этого разряда в лог. 1 активизирует режим однократной передачи. В нем канал по сигналу от инициатора, заданного регистром TRGSRC, передает посылку, длину которой определяют разряды BURSTLEN1 и BURSTLENO (см. ниже). Разряд SINGLE можно изменить только в тот мо- мент, когда канал неактивен (CHEN=0). • BURSTLEN[1:O] — определяют длину посылки данных (табл. 2.10). Эти разря- ды можно изменить только в тот момент, когда канал неактивен (CHEN=0). ' Таблица 2.10. Значение разрядов BURSTLEN BURSTLEN1 BURSTLENO Длина посылки 0 0 1 байт 0 1 2 байта 1 0 4 байта 1 1 8 байт • CHPEND — пока канал DMA ожидает начала передачи блока данных, этот разряд содержит лог. 1. Как только передача началась или прервана, флаг CHPEND автоматически сбрасывается. , • ERRIF — этот флаг устанавливается при обнаружении ошибки в канале DMA. Он сбрасывается вручную записью лог. 1 в данный разряд регистра CHxCTRLB. • TRNIF — этот флаг устанавливается в результате успешного завершения пере- дачи блока по каналу DMA. Он сбрасывается вручную записью лог. 1 в данный разряд регистра CHxCTRLB. Если установлен режим повторной передачи, дан- ный флаг устанавливается после передачи каждого блока. • ERRINTLVL[1:O] — эти разряды задают уровень прерывания при обнаруже- нии ошибки в канале DMA, т.е. когда установлен флаг ERRIF (табл. 2.11). За- просы на прерывание более высокого уровня прерывают работу процедуры об- работки любого прерывания более низкого уровня. По завершении обработки прерывания более высокого уровня прерванный обработчик низкого уровня продолжает свою работу. • TRNINTLVL[1:O] — задают уровень прерывания при завершении передачи по каналу DMA, т.е. когда установлен флаг TRNIF (см. табл. 2.11).
Система обработки событий 109 Таблица 2.11. Значение разрядов ERRINTLVL/TRNINTLVL ERRINTLVL1/TRNINTLVL1 ERRINTLVLO/TRNINTLVLO Уровень прерывания 0 0 Прерывание отключено 0 1 Прерывание низкого уровня 1 0 Прерывание среднего уровня 1 1 Прерывание высокого уровня Запросы на прерывание от каналов DMA определяют по флагам, устанавливае- мым в регистре INTFLAGS (адрес $0103 в области ввода/вывода микроконтролле- ров ATxmega А) (рис. 2.9). 7 6 5 4 3 2 1 0 CH3ERRIF CH2ERRIF CH1ERRIF CH0ERRIF CH3TRNFIF CH2TRNFIF CH1TRNFIF CHOTRNFIF Рис. 2.9. Регистр INTFLAGS Если в одном из каналов обнаружена ошибка, устанавливается соответствую- щий флаг CHxERRIF, а при успешном завершении передачи — соответствующий флаг CHxTRNFIF. Для сброса любого из флагов в регистре INTFLAGS необходимо записать лог. 1 в требуемый разряд. Последний управляющий регистр, определяющий состояние каналов DMA, на- зывается DMASTATUS (адрес $0104 в области ввода/вывода микроконтроллеров ATxmega А) (рис. 2.10). 7 6 5 4 3 2 1 0 CH3BUSY CH2BUSY CH1BUSY CH0BUSY CH3PEND CH2PEND CH1PEND CHOPEND Рис. 2.10. Регистр DMASTATUS Когда некоторый канал DMA начинает транзакцию, устанавливается соответст- вующий флаг CHxBUSY, который автоматически сбрасывается при отключении ка- нала, а также — при установке флага CHxERRIF или CHxTRFIF в регистре INTFLAGS. Когда в некотором канале DMA ожидается передача блока, в регистре DMASTATUS устанавливается соответствующий флаг CHxPEND, который автома- тически сбрасывается в момент начала или прекращения передачи. В завершение отметим, что в ходе транзакции большинство управляющих реги- стров контроллера прямого доступа к памяти и его каналов недоступны для измене- ния. Так, если установлен флаг CHxBUSY в регистре DMASTATUS, то для моди- фикации доступны только регистры DMACTRL и INTFLAGS (см. рис. 2.9), соответ- ствующий активному каналу регистр TRIGSRC (см. табл. 2.5), а также разряды CHEN, CHRST, TRFREQ и REPEAT регистра CHxCTRLA (см. рис. 2.7). Система обработки событий Система обработки событий, реализованная в микроконтроллерах ATxmega, по- зволяет автоматически активизировать некоторые действия в периферии в результа- те изменения состояния какого-либо периферийного устройства, что можно скон- фигурировать программно. Такой простой подход дает возможность автономно управлять периферией, не привлекая прерывания, центральный процессор и ресур- сы контроллера прямого доступа к памяти.
но Глава 2. Семейство AVR ATxmega Некоторое изменение состояния называется событием. События передаются между периферийными устройствами (порты, АЦП, ЦАП, таймеры/счетчики, кон- троллер прямого доступа к памяти, счетчик реального времени, аналоговые компа- раторы, модуль инфракрасной передачи) по специальной схеме маршрутизации (см. рис. 2.1). Для каждого периферийного устройства может быть определено несколь- ко разновидностей событий. Так, для таймеров/счетчиков это может быть перепол- нение или совпадение содержимого счетного регистра с регистром сравнения. При- мер взаимодействия счетчика и АЦП в рамках системы обработки событий показан на рис. 2.11. Рис. 2.11. Пример взаимодействия счетчика и АЦП в рамках системы обработки событий События бывают одного из двух типов: • сигнальные — только указывают на изменение состояния (большинство пери- ферийных устройств генерирует и использует только такие события); • данных — содержат дополнительную информацию об изменении состояния, которая может быть декодирована пользователем события дня определения не- обходимого действия. Схема маршрутизации состоит из восьмц мультиплексоров, на каждый из кото- рый поступают все события от всех источников. Мультиплексор выбирает, какое событие должно стать входным для пользователей. Его выход называют каналом события. Наличие восьми мультиплексоров подразумевает, что одновременно можно передавать до восьми событий. Кроме того, возможно маршрутизировать одно событие через все мультиплексоры. Каждому мультиплексору соответствует восьмиразрядный управляющий ре- гистр CHxMUX (диапазон адресов в области ввода/вывода микроконтроллеров ATxmega А — $0180..$0187). Его содержимое определяет источник события для данного канала (табл. 2.12). В табл. 2.12 показаны только комбинации разрядов регистра CHxMUX, для которых опреде- лены источники события. Остальные комбинации зарезервированы компанией Atmel для бу- дущего использования.
Система обработки событий 111 Таблица 2.12. Выбор источника событий по содержимому регистра CHxMUX CHxMUX Источник события 7 6 5 4 3 2 1 0 0 0 0 0 0 0 0 0 Отсутствует. События генерируются только вручную 0 0 0 0 1 0 0 0 Переполнение счетчика реального времени 0 0 0 0 1 0 0 1 Совпадение содержимого счетчика реального времени с регистром сравнения 0 0 0 1 0 0 0 0 Аналоговый компаратор на порту А, канал 0 0 0 0 1 0 0 0 1 Аналоговый компаратор на порту А, канал 1 0 0 0 1 0 0 1 0 Аналоговый компаратор на порту А, режим “Window” 0 0 0 1 0 0 1 1 Аналоговый компаратор на порту В, канал 0 0 0 0 1 0 1 0 0 Аналоговый компаратор на порту В, канал 1 0 0 0 1 0 1 0 1 Аналоговый компаратор на порту В, режим “Window” 0 0 1 0 0 0 0 0 АЦП на порту А, канал 0 0 0 1 0 0 0 0 1 АЦП на порту А, канал 1 0 0 1 0 0 0 1 0 АЦП на порту А, канал 2 0 0 1 0 0 0 1 1 АЦП на порту А, канал 3 0 0 1 0 0 1 0 0 АЦП на порту В, канал 0 0 0 1 0 0 1 0 1 АЦП на порту В, канал 1 0 0 1 0 0 1 1 0 АЦП на порту В, канал 2 0 0 1 0 0 1 1 1 АЦП на порту В, канал 3 0 1 0 1 0 0 0 0 Порт А, вывод 0 0 1 0 1 0 0 0 1 Порт А, вывод 1 0 1 0 1 0 0 1 0 Порт А, вывод 2 0 1 0 1 0 0 1 1 Порт А, вывод 3 0 1 0 1 0 1 0 0 Порт А, вывод 4 0 1 0 1 0 1 0 1 Порт А, вывод 5 0 1 0 1 0 1 1 0 Порт А, вывод 6 0 1 0 1 0 1 1 1 Порт А, вывод 7 0 1 0 1 1 0 0 0 Порт В, вывод 0 0 1 0 1 1 0 0 1 Порт В, вывод 1 0 1 0 1 1 0 1 0 Порт В, вывод 2 0 1 0 1 1 0 1 1 Порт В, вывод 3 0 1 0 1 1 1 0 0 Порт В, вывод 4 0 1 0 1 1 1 0 1 Порт В, вывод 5 0 1 0 1 1 1 1 0 Порт В, вывод 6 0 1 0 1 1 1 1 1 Порт В, вывод 7 0 1 1 0 0 0 0 0 Порт С, вывод 0 0 1 1 0 0 0 0 1 Порт С, вывод 1 0 1 1 0 0 0 1 0 Порт С, вывод 2 0 1 1 0 0 0 1 1 Порт С, вывод 3 0 1 1 0 0 1 0 0 Порт С, вывод 4 0 1 1 0 0 1 0 1 Порт С, вывод 5 0 1 1 0 0 1 1 0 Порт С, вывод 6 0 1 1 0 0 1 1 1 Порт С, вывод 7 0 1 1 0 1 0 0 0 Порт D, вывод 0 0' 1 1 0 1 0 0 1 Порт D, вывод 1
112 Глава 2. Семейство AVR ATxmega Таблица 2.12. Продолжение CHxMUX Источник события 7 6 5 4 3 2 1 0 0 1 1 0 1 0 1 0 Порт D, вывод 2 0 1 1 0 1 0 1 1 Порт D, вывод 3 0 1 1 0 1 1 0 0 Порт D, вывод 4 0 1 1 0 1 1 0 1 Порт D, вывод 5 ' 0 1 1 0 1 1 1 0 Порт D, вывод 6 0 1 1 0 1 1 1 1 Порт D, вывод 7 0 1 1 1 0 0 0 0 Порт Е, вывод 0 0 1 1 1 0 0 0 1 Порт Е, вывод 1 0 1 1 1 0 0 1 0 Порт Е, вывод 2 0 1 1 1 0 0 1 1 Порт Е, вывод 3 0 1 1 1 0 1 0 0 Порт Е, вывод 4 0 1 1 1 0 1 0 1 Порт Е, вывод 5 0 1 1 1 0 1 1 0 Порт Е, вывод 6 0 1 1 1 0 1 1 1 Порт Е, вывод 7 0 1 1 1 1 0 0 0 Порт F, вывод 0 0 1 1 1 1 0 0 1 Порт F, вывод 1 0 1 1 1 1 0 1 0 Порт F, вывод 2 0 1 1 1 1 0 1 1 Порт F, вывод 3 0 1 1 1 1 1 0 0 Порт F, вывод 4 0 1 1 1 1 1 0 1 Порт F, вывод 5 0 1 1 1 1 1 1 0 Порт F, вывод 6 0 1 1 1 1 1 1 1 Порт F, вывод 7 1 0 0 0 N Такт синхронизации периферии / N (N = 1..32768) 1 1 0 0 0 0 0 0 Переполнение таймера/счетчика, СО 1 1 0 0 0 0 0 1 Ошибка таймера/счетчика, СО 1 1 0 0 0 1 0 0 Захват или сравнение в канале А таймера/счетчика, СО 1 1 0 0 0 1 0 1 Захват или сравнение в канале В таймера/счетчика, СО 1 1 0 0 0 1 1 0 Захват или сравнение в канале С таймера/счетчика, СО 1 1 0 0 0 1 1 1 Захват или сравнение в канале D таймера/счетчика, СО 1 1 0 0 1 0 0 0 Переполнение таймера/счетчика, С1 1 1 0 0 1 0 0 1 Ошибка таймера/счетчика, С1 1 1 0 0 1 1 0 0 Захват или сравнение в канале А таймера/счетчика, С1 1 1 0 0 1 1 0 1 Захват или сравнение в канале В таймера/счетчика, С1 1 1 0 0 1 1 1 0 Захват или сравнение в канале С таймера/счетчика, С1 1 1 0 0 1 1 1 1 Захват или сравнение в канале D таймера/счетчика, С1 1 1 0 1 0 0 0 0 Переполнение таймера/счетчика, DO 1 1 0 1 0 0 0 1 Ошибка таймера/счетчика, DO 1 1 0 1 0 1 0 0 Захват или сравнение в канале А таймера/счетчика, DO 1 1 0 1 0 1 0 1 Захват или сравнение в канале В таймера/счетчика, DO 1 1 р 1 0 1 1 0 Захват или сравнение в канале С таймера/счетчика, DO 1 1 0 1 0 1 1 1 Захват или сравнение в канале D таймера/счетчика, DO 1 1 0 1 1 0 0 0 Переполнение таймера/счетчика, D1 1 1 0 1 1 0 0 1 Ошибка таймера/счетчика, D1 1 1 0 1 1 1 0 0 Захват или сравнение в канале А таймера/счетчика, D1
Система обработки событий 113 Таблица 2.12. Продолжение CHxMUX Источник события 7 6 5 4 3 2 1 0 1 1 0 1 1 1 0 1 Захват или сравнение в канале В таймера/счетчика, D1 1 1 0 1 1 1 1 0 Захват или сравнение в канале С таймера/счетчика, D1 1 1 0 1 1 1 1 1 Захват или сравнение в канале D таймера/счетчика, D1 1 1 1 0 0 0 0 0 Переполнение таймера/счетчика, Е0 1 1 1 0 0 0 0 1 Ошибка таймера/счетчика, Е0 1 1 1 0 0 1 0 0 Захват или сравнение в канале А таймера/счетчика, Е0 1 1 1 0 0 1 0 1 Захват или сравнение в канале В таймера/счетчика, Е0 1 1 1 0 0 1 1 0 Захват или сравнение в канале С таймера/счетчика, Е0 1 1 1 0 0 1 1 1 Захват или сравнение в канале D таймера/счетчика, Е0 1 1 1 0 1 0 0 0 Переполнение таймера/счетчика, Е1 1 1 1 0 1 0 0 1 Ошибка таймера/счетчика, Е1 1 1 1 0 1 1 0 0 Захват или сравнение в канале А таймера/счетчика, Е1 1 1 1 0 1 1 0 1 Захват или сравнение в канале В таймера/счетчика, Е1 1 1 1 0 1 1 1 0 Захват или сравнение в канале С таймера/счетчика, Е1 1 1 1 0 1 1 1 1 Захват или сравнение в канале D таймера/счетчика, Е1 1 1 1 1 0 0 0 0 Переполнение таймера/счетчика, F0 1 1 1 1 0 0 0 1 Ошибка таймера/счетчика, F0 1 1 1 1 0 1 0 0 Захват или сравнение в канале А таймера/счетчика, F0 1 1 1 1 0 1 0 1 Захват или сравнение в канале В таймера/счетчика, F0 1 1 1 1 0 1 1 0 Захват или сравнение в канале С таймера/счетчика, F0 1 1 1 1 0 1 1 1 Захват или сравнение в канале D таймера/счетчика, F0 1 1 1 1 1 0 0 0 Переполнение таймера/счетчика, F1 1 1 1 1 1 0 0 1 Ошибка таймера/счетчика, F1 1 1 1 1 1 1 0 0 Захват или сравнение в канале А таймера/счетчика, F1 1 1 1 1 1 1 0 1 Захват или сравнение в канале В таймера/счетчика, F1 1 1 1 1 1 1 1 0 Захват или сравнение в канале С таймера/счетчика, F1 1 1 1 1 1 1 1 1 Захват или сравнение в канале D таймера/счетчика, F1 Если выбрать источник, для которого в данной модели микроконтроллера от- сутствует соответствующее периферийное устройство, то система обработки собы- тий поведет себя так же, как при CHxMUX=0 (маршрутизация не выполняется, со- бытия генерируются только вручную, о чем речь пойдет чуть позже). Событие обычно длится один цикл синхронизации периферии (исключение со- ставляют, разве что, порты, генерирующие события постоянно), а от момента его формирования до момента выполнения пользователем некоторого действия прохо- дит не более двух циклов. Регистрация события системой маршрутизации происхо- дит по ближайшему нарастающему фронту такта, т.е. в течение одного цикла, а еще один цикл требуется для передачи события пользователю. Действия по обнаружению событий в каждом периферийном модуле реализо- ваны по-своему. Например, в 16-разрядном таймере/счетчике микроконтроллеров ATxmega А за это отвечает регистр управления CTRLD (адреса в области ввода/ вы- вода для различных счетчиков: $0803, $0843, $0903, $0943, $0А03, $0А43, $0В03,. $0В43)(рис. 2.12). Разряды EVACT определяют действие по событию, выполняемое таймером (табл. 2.13).
114 Глава 2. Семейство AVR ATxmega 7 6 5 4 3 2 1 0 EVACT EVDLY EVSEL Рис. 2.12. Регистр CTRLD управления 16-разрядным таймером/счетчиком Таблица 2.13. Значение разрядов EVACT EVACT2 EVACT1 EVACT0 Действие по событию 0 0 0 Отсутствует 0 0 1 Захват на входе 0 1 . 0 Счет в прямом или обратном направлении по внешнему сигналу 0 1 1 Квадратурная дешифрация (см. раздел ниже) 1 0 0 Начать заново период импульсов 1 0 1 Фиксация частоты 1 1 0 Фиксация ширины импульсов 1 1 1 Зарезервировано Выбор одного из действий приведет к изменению содержимого регистров ССх (управление захватом и сравнением), а также соответствующих разрядов состояния. В такой конфигурации флаг ошибки (ERRIF) свидетельствует о переполнении бу- фера. Генерирование событий вручную Если события для канала не генерируются автоматически (CHxMUX = 0), их можно генерировать вручную с помощью регистров STROBE (адрес $0190 в облас- ти ввода/вывода микроконтроллеров ATxmega) и DATA (адрес $0191 в области ввода/вывода микроконтроллеров ATxmega). Эти регистры содержат по одному разряду на каждый канал событий (разряду 0 соответствует канал 0, разряду 1 — канал 1 и т.д.). Запись лог. 1 в разряд регистра STROBE формирует событие в соот- ветствующем канале. Для того чтобы сформировать событие данных, перед уста- новкой разрядов в регистре STROBE должен быть инициализирован регистр DATA. Способ декодирования сгенерированных вручную событий иллюстрирует табл. 2.14. Таблица 2.14. Декодирование комбинаций соответствующих разрядов регистров STROBE и DATA STROBEn DATAn Событие данных Сигнальное событие 0 0 Отсутствует Отсутствует 0 1 Событие данных 1 Отсутствует 1 0 Событие данных 2 Есть 1 1 Событие данных 3 Есть Таким образом, в различных каналах можно одновременно генерировать разно- типные события. Они длятся один цикл синхронизации и “затирают” другие актив- ные события в соответствующих каналах. Фильтрация Каждый канал событий содержит цифровой фильтр, который активизируется и конфигурируется с помощью первых трех разрядов регистра CHxCTRL (диапазон
Система обработки событий 115 адресов в области ввода/вывода микроконтроллеров ATxmega А — $0188- $018F) (рис. 2.13). 7 6 5 4 3 2 1 0 — QDIRM QDIEN QDEN DIGFILT Рис. 2.13. Регистр CHxCTRL Разряды DIGFILT[2:0] определяют длину цифрового фильтра. Его суть заклю- чается в том, что событие пропускается в канал только в том случае, если оно опра- шивается на протяжении заданного числа циклов тактирования периферии (табл. 2.15). Таблица 2.15. Конфигурирование цифрового фильтра для канала событий DIGFILT2 DIGFILT1 DIGFILT0 Количество опросов 0 0 0 1 (фильтрация отсутствует) 0 0 1 2 0 1 0 3 0 1 1 4 1 0 0 5 1 0 1 6 1 1 0 7 1 1 1 8 Квадратурный дешифратор В состав системы обработки событий входят три так называемых квадратурных дешифратора (quadrature decoder, QDEC). Квадратурный сигнал характеризуется на- личием двух прямоугольных импульсов, смещенных относительно друг друга по фазе на 90 градусов. Это позволяет измерять параметры вращательного движения путем подсчета фронтов двух импульсов. Соотношение фаз этих импульсов опреде- ляет направление вращения. Типичный пример квадратурных сигналов от кругового датчика положения вала показан на рис. 2.14. Рис. 2.14. Квадратурные сигналы от кругового датчика положения вала
116 Глава 2. Семейство AVR ATxmega Сигналы QDPH0 и QDPH90 — квадратурные. Когда импульс QDPH0 предше- ствует импульсу QDPH90, то вращение происходит в прямом направлении, в про- тивном случае — в обратном направлении. Конкатенация этих двух сигналов назы- вается квадратурным или фазовым состоянием. Для определения абсолютного кру- гового смещения можно воспользоваться третьим импульсом, который появляется один раз на протяжении одного оборота (сигнал QDINDX на рис. 2.14). Наличие квадратурного дешифратора в составе схемы обработки событий по- зволяет декодировать квадратурные сигналы на входах портов и генерировать со- бытия данных, на основании которых таймер/счетчик может выполнять определен- ное действие (например, счет). Для активизации дешифратора необходимо устано- вить в лог. 1 разряд QDEN в регистре управления каналом событий CHxCTRL (см. рис. 2.13). ПРИМЕЧАНИЕ В семействе ATxmega А квадратурный дешифратор доступен только для каналов 0, 2 и 4. Если канал события необходимо использовать для передачи квадратурного со- стояния (например, для получения индекса счета), в регистре CHxCTRL следует ус- тановить разряд QDIEN. Состояние сигналов QDPH0 и QDPH90, при котором рас- познается индексный сигнал и формируется соответствующее событие для счетчика (см. рис. 2.13), определяется значением разрядов QDIRM[1:O] того же регистра CHxCTRL (табл. 2.16). Таблица 2.16. Значение разрядов QDIRM QDIRM1 QDIRM0 Состояние, при котором распознается индекс 0 0 QDPH0 = 0, QDPH90 = 0 0 1 QDPH0 = 0, QDPH90 = 1 1 0 QDPH0= 1,QDPH90 = 0 1 1 QDPHO = 2, QDPH90 = 1 Подводя итог, дадим полную процедуру настройки квадратурного дешифрато- ра. 1. Сконфигурировать два соседних вывода какого-либо порта в качестве входов для фазовых сигналов QDPH0 и QDPH90 (активный — низкий уровень). 2. Определить вывод QDPH0 как вход мультиплексора для канала событий N. 3. Активизировать в канале событий N квадратурный дешифратор и цифровую фильтрацию. 4. При желании можно сконфигурировать еще один вывод в качестве входа для индексного сигнала QINDX (считывание по обоим фронтам) и определить его как вход мультиплексора для канала событий Л/+1. Далее следует установить разряд QDIEN в регистре CH/v+iCTRL h выбрать режим распознавания индекса (см. табл. 2.16). 5. Назначить для таймера/счетчика квадратурную дешифрацию в качестве дейст- вия по событию (см. табл. 2ЛЗ). 6. Выбрать для таймера/счетчика в качестве источника события соответствующий канал события. 7. Инициализировать регистр периода таймера/счетчика значением “количество импульсов в линии кругового датчика положения вала” * 4 - 1. 8. Активизировать таймер/счетчик.
Система синхронизации 117 Значение угла поворота вала теперь можно считывать непосредственно из счет- ного регистра таймера/счетчика. Если в момент появления индексного сигнала со- держимое счетного регистра отличается от минимального значения “BOTTOM”, ус- танавливается флаг ошибки счетчика. Этот флаг также устанавливается, если значе- ние положения пересекает отметку “BOTTOM” при отсутствии индексного сигнала. Система синхронизации В микроконтроллерах ATxmega реализована гибкая система синхронизации с большим набором источников тактового сигнала, среди которых есть как точные встроенные осцилляторы, так и внешние кварцевые осцилляторы и резонаторы. Для получения большого диапазона тактовых частот можно использовать высокочас- тотную систему фазовой подстройки частоты (PLL — Phase Locked Loop) и предделители. Для автоматической калибровки внутренних осцилляторов доступ- ны две схемы цифровой автоподстройки частоты (DFLL — Digital Frequency Locked Loop). После сброса микроконтроллеры ATxmega А всегда тактируются от внутренне- го осциллятора на 2 МГц. Настройки источника тактового сигнала и коэффициент предделителя можно в любой момент изменить программно. Структурная схема системы синхронизации микроконтроллеров ATxmega А показана на рис. 2.15. Источники тактового сигнала в микроконтроллерах ATxmega можно разбить' на две категории: внутренние осцилляторы и внешние тактовые генераторы. Большин- ство из них можно напрямую включить или отключить программно, в то время как для некоторых других это происходит автоматически в зависимости от текущих на- строек периферии. Для работы внутренних осцилляторов никаких внешних компонентов не требу- ется. Рассмотрим их применительно к микроконтроллерам ATxmega А. • Низковольтный (ULP — Ultra Low Power) осциллятор на 32 кГц. Этот внутренний осциллятор потребляет очень мало энергии, однако не рассчитан на высокую точность работы. Он использует встроенный предделитель, обеспечи- вающий на выходе, кроме 32 кГц, также сигнал частотой 1 кГц. Данный осцил- лятор включается автоматически при его назначении в качестве источника так- тового сигнала для счетчика реального времени, сторожевого таймера или сис- темы обнаружения провалов напряжения. • Откалиброванный RC-осциллятор на 32,768 кГц. Его встроенный преддели- тель обеспечивает также выходную частоту 1,024 кГц. Калибровочное значение записывается при сбросе аппаратно в регистр R32KCAL (адрес в области вво- да/вывода микроконтроллеров ATxmega А — $0054). Его можно также изме- нить программно. • Откалиброванный RC-осциллятор на 32 МГц. Использует схему цифровой автоподстройки частоты, которую можно использовать для автоматической ка- либровки непосредственно во время выполнения программы. При сбросе 13- разрядное калибровочное значение записывается аппаратно в регистры CALA и CALB (адреса в области ввода/вывода микроконтроллеров ATxmega А — $0062 и $0063), однако может быть задано и программно. • Откалиброванный RC-осциллятор на 2 МГц. Использует схему цифровой автоподстройки частоты, которую можно использовать для автоматической ка- либровки непосредственно во время выполнения программы. При сбросе 13-
118 Глава 2. Семейство AVR ATxmega разрядное калибровочное значение записывается аппаратно в регистры CALA и CALB (адреса в области ввода/вывода микроконтроллеров ATxmega А — $0069 и $006А), однако может быть задано и программно. Рис. 2.15. Структурная схема системы синхронизации микроконтроллеров ATxmega А Для реализации внешних осцилляторов (кварцевых или керамических резона- торов) традиционно служат выводы XTAL1 и XTAL2, а вывод XTAL1 также может служить для подачи внешнего тактового сигнала. Выводы TOSC1 и TOSC2 предна- значены для подключения кварцевого осциллятора на 32 кГц. Типичная схема под- ключения кварцевого осциллятора или резонатора частотой 32 кГц или 0,4.. 16 МГц показана в предыдущей главе на рис. 1.4. Для актиЬизации того или иного осциллятора следует установить соответст- вующий разряд в регистре OSCCTRL (адрес в области ввода/вывода микроконтрол- леров ATxmega А — $0050):
Система синхронизации 119 • RC2MEN — внутренний RC-осциллятор на 2 МГц (этот разряд установлен по умолчанию); • RC32MEN — внутренний RC-осциллятор на 32 МГц; • RC32KEN — внутренний RC-осциллятор на 32 кГц; • XOSCEN — внешний осциллятор; • PLLEN — система фазовой автоподстройки частоты. При установке в лог. 1 разряда XOSCEN необходимо настроить параметры внешнего осциллятора с помощью регистра XOSCCTRL (адрес в области вво- да/вывода микроконтроллеров ATxmega А — $0052) (рис. 2.16). 7 6 5 4 3 2 1 О FRQRANGE X32KLPM — XOSCSEL Рис. 2.16. Регистр XOSCCTRL Первые четыре разряда этого регистра определяют тип и время стабилизации кварца или резонатора, подключенного к выводам XTAL или TOSC (табл. 2.17). Таблица 2.17. Выбор внешнего осциллятора XOSCSEL Источник тактового сигнала Время стабилизации 3 2 1 0 0 0 0 0 Внешний тактовый сигнал 6 циклов 0 0 1 0 32,768 кГц на TOSC 16К циклов 0 0 1 1 0,4..16МГцна XTAL 256 циклов 0 1 1 1 0,4.. 16 МГц на XTAL 1К циклов 1 0 1 1 0,4.. 16 МГц на XTAL 16К циклов Диапазон частот для кварцевого осциллятора на выводах XTAL определяют разряды FRQRANGE[1:O] (табл. 2.18). Таблица 2.18. Выбор диапазона частот для кварцевого осциллятора на выводах XTAL FRQRANGE1 FRQRANGE0 Диапазон частот Рекомендованная емкость конденсаторов С1 и С2 0 0 0.4..2 МГц 100 пФ 0 1 2..9 МГц 15 пФ 1 0 9..12 МГц 15 пФ 1 1 12..16 МГц 10 пФ Наконец, установка в 1 разряда X32KLPM регистра XOSCCTRL активизирует режим пониженного энергопотребления для кварцевого осциллятора на 32 кГц. Состояние того или иного осциллятора можно определить по содержимому раз- рядов регистра OSCSTATUS (адрес в области ввода/вывода микроконтроллеров ATxmega А — $0051). Если осциллятор стабилизирован и готов к использованию, то для него устанавливается соответствующий флаг: • RC2MRDY — готовность внутреннего RC-осциллятора на 2 МГц; • RC32MRDY — готовность внутреннего RC-осциллятора на 32 МГц; • RC32KRDY — готовность внутреннего RC-осциллятора на 32 кГц; • XOSCRDY — готовность внешнего источника тактового сигнала;
120 Глава 2. Семейство AVR ATxmega • PLLRDY — система фазовой автоподстройки частоты зафиксирована на выб- ранной частоте и готова к использованию в качестве источника тактового сиг- нала. Источник входного сигнала для системы фазовой автоподстройки частоты оп- ределяет регистр PLLCTRL (адрес в области ввода/вывода микроконтроллеров ATxmega А — $0055) (рис. 2.17). 7 6 5 4 3 2 1 0 PLLSRC — PLLFAC Рис. 2.17. Регистр PLLCTRL Значение разрядов PLLSRC дано в табл. 2.19. Таблица 2.19. Выбор источника входного сигнала для системы фазовой автоподстрой- ки частоты PLLSRC1 PLLSRC0 Источник 0 0 Внутренний RC-осциллятор на 2 МГц 0 1 Зарезервировано 1 0 Внутренний RC-осциллятор на 32 МГц 1 1 Внешний тактовый сигнал частотой минимум 0,4 МГц Разряды PLLFAC регистра PLLCTRL задают коэффициент умножения от 1 до 31. Частота на выходе системы PLL должна находиться в диапазоне 10..200 МГц. Выбор источника тактового сигнала системной синхронизации В качестве источника тактового сигнала системной синхронизации может быть выбран любой калиброванный внутренний осциллятор, внешние источники такто- вого сигнала и выход системы фазовой автоподстройки частоты (см. рис. 2.15). По- лученный сигнал поступает в блок предделителей, который может разделить такт до его поступления в процессор и периферию на коэффициент от 1 до 2048 (рис. 2.18). Первый предделитель (А) реализует деление на число от 1 до 512, а второй и третий (В и С) — на 1, 2 или 4. Выбор тактового сигнала Рис. 2.18. Схема выбора источника тактового сигнала системной синхронизации
Система синхронизации 121 Источник тактового сигнала системной синхронизации выбирают программно с помощью трех первых разрядов (SCLKSEL[2:0]) регистра CLKCTRL (адрес в об- ласти ввода/вывода микроконтроллеров ATxmega А — $0040) (табл. 2.20). Таблица 2.20. Выбор источника тактового сигнала системной синхронизации SCLKSEL2 SCLKSEL1 SCLKSEL0 Источник 0 0 0 Внутренний RC-осциллятор на 2 МГц 0 0 1 Внутренний RC-осциллятор на 32 МГц 0 1 0 Внутренний RC-осциллятор на 32 кГц 0 1 1 Внешний осциллятор или тактовый сигнал 1 0 0 Система фазовой автоподстройки частоты Остальные три комбинации разрядов SCLKSEL зарезервированы для использо- вания в будущем. ПРИМЕЧАНИЕ Смена источника тактового сигнала системной синхронизации займет четыре тактовых цикла: два на старом источнике и два на новом. Кроме того, аппаратные средства защиты не позво- лят выбрать нестабильный или отключенный осциллятор, а также — отключить осциллятор, задействованный в качестве источника тактового сигнала системной синхронизации. За конфигурирование блока предделителей отвечает регистр PSCTRL (адрес в области ввода/вывода микроконтроллеров ATxmega А — $0041) (рис. 2.19). 7 6 5 4 3 2 1 0 — PSADIV PSBCDIV Рис. 2.19. Регистр PSCTRL Пять разрядов PSADIV определяют коэффициент деления для предделителя А (табл. 2.21). Они доступны для записи во время выполнения программы. Таблица 2.21. Выбор коэффициента деления для предделителя А PSADIV Коэффициент деления 4 3 2 1 0 0 0 0 0 0 1 0 0 0 0 1 2 0 0 0 1 1 4 0 0 1 0 1 8 0 0 1 1 1 16 0 1 0 0 1 32 0 1 0 1 1 64 0 1 1 0 1 128 0 1 1 1 1 256 1 0 0 0 1 512 Разряды PSBCDIV определяют коэффициенты деления для предделителей В и С (табл. 2.22). Для запрета изменений в регистрах CLKCTRL и PSCTRL с целью защиты от случайной смены источника тактового сигнала системной синхронизации и коррек- ции настроек предделителей служит разряд 0 регистра LOCK (адрес в области вво-
122 Глава 2. Семейство AVR ATxmega да/вывода микроконтроллеров ATxmega А — $0042). Запись лог. 1 в этот разряд ак- тивизирует блокировку изменений. Таблица 2.22. Выбор коэффициентов деления для предделителей В и С PSBCDIV1 PSBCDIV0 Коэффициент для предделителя В Коэффициент для предделителя С 0 0 1 1 0 1 1 2 1 0 4 1 1 1 2 2 Счетчики реального времени Счетчики реального времени (RTC — Real Time Counter) обычно используют в различных режимах пониженного энергопотребления для отслеживания времени и “пробуждения” устройства через определенные периоды. В микроконтроллерах ATxmega А реализованы два таких счетчика: 16-разрядный RTC и 32-разрядный RTC32. Оба тактируются сигналом частотой 32 кГц или 1 кГц с последующим де- лением. Выбор источника тактирования и его активизацию определяет регистр RTCCTRL (адрес в области ввода/вывода микроконтроллеров ATxmega А — $0043) (рис. 2.20). 7 6 5 4 3 2 1 0 — — — — RTCSRC RTCEN Рис. 2.20. Регистр RTCCTRL Разряды RTCSRC определяют опорный тактовый сигнал для счетчиков реаль- ного времени (табл. 2.23). Таблица 2.23. Выбор тактового сигнала для счетчиков реального времени RTCSRC2 RTCSRC1 RTCSRC0 Источник 0 0 0 1 кГц от внутреннего ULP-осциллятора на 32 кГц 0 0 1 1 кГц от осциллятора на 32 кГц на выводе TOSC 0 1 0 1 кГц от внутреннего RC-осциллятора на 32 кГц 1 0 1 32 кГц от осциллятора на 32 кГц на выводах TOSC Источник тактирования для счетчиков реального времени активизируется уста- новкой в лог. 1 разряда RTCEN регистра RTCCTRL. Как RTC, так и RTC32 могут генерировать запросы на прерывание и события: • по совпадению значения счетчика со значением, записанным в соответствую- щие регистры сравнения (для RTC — регистровая пара COMPL и СОМРН; для RTC32 — регистры СОМРО..СОМРЗ); • по переполнению, т.е. по совпадению значения счетчика со значением, записан- ным в соответствующие регистры периода (для RTC — регистровая пара PERL и PERH; для RTC32 — регистры PER0..PER3). Момент прерывания определяется по установке соответствующего флага (COMPIF или OVFIF) в регистре INTFLAGS (адрес в области ввода/вывода микро- контроллеров ATxmega А для RTC — $0403, для RTC32 — $0423). Разрешение пре- рываний реализовано с прмощью регистра INTCTRL (адрес в области ввода/вывода
Модуль питания от батареи 123 микроконтроллеров ATxmega А для RTC — $0402, для RTC32 — $0422). Разряды OVFINTLVL[1:0] определяет уровень прерывания по переполнению, а разряды COMPINTLVLfl :0] — по совпадению с регистром сравнения. Счетчик RTC 16-разрядный счетчик RTC управляется регистром RTCCTRL (адрес в области ввода/вывода микроконтроллеров ATxmega А — $0400), в котором используются только первых три разряда, определяющих коэффициент деления тактового сигнала RTC (табл. 2.24). Таблица 2.24. Выбор коэффициента деления тактового сигнала для RTC PRESCALER2 PRESCALER1 PRESCALERO Коэффициент 0 0 0 0 (RTC остановлен) 0 0 1 1 0 1 0 2 0 1 1 8 1 0 0 16 1 0 1 64 1 1 0 256 1 1 1 1024 Счетчик RTC32 32-разрядный счетчик RTC32 тактируется сигналом частотой 1,024 кГц или 1 Гц, полученного от осциллятора на 32,768 кГц, подключенного между выводами TOSC1 и TOSC2. Для его активизации необходимо установить в лог. 1 разряд ENABLE в регистре RTC32CTRL (адрес в области ввода/вывода микроконтролле- ров ATxmega А — $0420). От момента записи значения в этот регистр и до момента активизации RTC32 требуется один тактовый цикл счетчика реального времени. Одна из основных сфер применения этого счетчика — работа от напряжения Vbat (батарея), когда возможна только малая частота тактирования. Выбор частоты осуществляют с помощью управляющего регистра VBATCTRL (адрес в области ввода/вывода микроконтроллеров ATxmega А — $00F0), который рассматривается в следующем разделе. Модуль питания от батареи В микроконтроллерах ATxmega А реализована возможность автоматического переключения с питания от рабочего напряжения Vcc на питание от батареи, под- ключенной к заданному выводу Vbat- Это обеспечивает работу счетчика реального времени RTC32, осциллятора на 32,768 кГц и двух управляющих регистров. Пере- ключение на батарею при пропадании рабочего напряжения (как и возврат к нормальному режиму питания) происходит автоматически. Для управления модулем питания от батареи служат два регистра: VBATCTRL и VBATSTATUS (адреса в области ввода/вывода микроконтроллеров ATxmega А — $00F0 и $00F 1) (рис. 2.21 и рис. 2.22). Разряд XOSCSEL регистра VBATCTRL определяет частоту входного тактового сигнала для счетчика реального времени RTC32. По умолчанию он содержит лог. 0, что соответствует тактовой частоте 1 Гц. Если его установить в лог. 1, то будет вы-
124 Глава 2. Семейство AVR ATxmega бран сигнал частотой 1,024 кГц. Тактирование начинается по установке в лог. 1 раз- ряда XOSCEN. Для отключения тактирования необходимо активизировать сброс модуля питания от батареи, установив в лог. 1 разряд RESET. 7 6 5 4 3 2 1 0 — — — XOSCSEL XOSCEN XOSCFDEN ACCEN RESET Рис. 2.21. Регистр VBATCTRL 7 6 5 4 3 2 1 0 BBPWR • — — XOSCRDY XOSCFAIL BBBODF BBPODF Рис. 2.22. Регистр VBATSTATUS Рассмотрим последовательность работы модуля, реализующего питание от ба- тареи, с использованием разрядов регистров VBATCTRL и VBATSTATUS. При по- даче питания или общем сбросе микроконтроллер проверяет наличие напряжения на выводе Vbat- Если требуемый уровень напряжения не обнаружен, то в регистре VBATSTATUS автоматически устанавливается флаг BBPWR. Если этот флаг уста- новлен, то далее программа должна проверить состояние флагов BBBODF и BBPODF регистра VBATSTATUS. Первый из них устанавливается, если обнаружен провал, а второй — повторная подача напряжения Vbat- Если флаги BBBODF и BBPODF сброшены, то это говорит о том, что питание от батареи стабильно и модуль можно активизировать. Для этого следует устано- вить в лог. 1 разряд ACCEN регистра VBACTRL и проверить, не было ли сбоя в ра- боте осцилляторов на выводах XOSC, опросив флаг XOSCFAIL. Если он установ- лен, то это говорит о некорректном значении счетчика реального времени RTC32. Если флаг BBBODF и/или BBPODF на предыдущем этапе оказался установлен- ным, то это говорит, что после отключения рабочего напряжения микроконтролле- ра, произошел сбой питания от батареи. В таком случае необходимо выполнить сле- дующую последовательность действий. 1. Установить в лог. 1 разряд ACCEN (разрешение доступа к модулю). 2. Установить в лог. 1 разряд RESET (сброс модуля). 3. Активизировать осциллятор на выводах XOSC. 4. Дождаться появления лог. 1 в разряде XOSCRDY регистра VBATSTATUS, что говорит о готовности осциллятора. 5. Активизировать режим обнаружения сбоев осциллятора, установив в лог. 1 раз- ряд XOSCFDEN регистра VBATCTRL. 6. Сконфигурировать и активизировать счетчик реального времени RTC32 (см. предыдущий раздел). В завершение отметим, что для сохранения данных в модуле питания от бата- реи перед потерей или провалом рабочего напряжения можно воспользоваться ре- гистровой парой BACKUP[O:1] (адреса в области ввода/вывода микроконтроллеров ATxmega А — $00F2 и $00F3). Обработка прерываний За обработку прерываний в микроконтроллерах ATxmega А отвечает програм- мируемый многоуровневый контроллер PMIC (Programmable Multi-level Interrupt
Обработка прерываний 125 Controller), который может определять приоритетность запросов и поддерживает немаскируемые прерывания. Каждому прерывания от периферийных устройств на- значен один из трех уровней приоритетности: низкий, средний или высокий. Пре- рывания более высокого уровня могут прерывать работу обработчиков прерываний более низкого уровня. В пределах каждого уровня приоритетности очередность об- работки прерываний определяется по старшинству адресов векторов прерывания (вектора с меньшими адресами имеют более высокий приоритет). Уровень того или иного прерывания определяется комбинацией двух разрядов в соответствующем управляющем регистре периферийного устройства: • 00 — прерывание запрещено; • 01 — прерывание низкого уровня; • 10 — прерывание высокого уровня; • 11 — прерывание среднего уровня. Например, уровень прерывания по переполнению одного из таймеров/счетчи- ков Микроконтроллера ATxmega А определяют разряды OVFINTLVL[1:0] соответ- ствующего регистра INTCTRLA. Так, если установлен уровень, отличной от “00”, и для микроконтроллера установлен флаг общего разрешения прерываний, то кон- троллер PMIC определяет возникновение переполнения по появлению лог. 1 в раз- ряде OVFIF соответствующего управляющего регистра INTFLAGS. Немаскируемые прерывания Немаскируемыми называются аппаратные прерывания, набор которых зависит от конкретной модели микроконтроллера. Подобные запросы обрабатываются неза- висимо от состояния флага общего разрешения прерываний и, в свою очередь, ни- когда не изменяют этот флаг. Никакие другие прерывания не могут прервать обра- ботчик немаскируемого прерывания. Если одновременно поступает несколько за- просов на обработку немаскируемого прерывания, то их приоритетность определя- ется по старшинству адресов векторов. Для того чтобы определить, обрабатывается ли в данный момент какое-либо немаскируемое прерывание, следует опросить разряд NMIEX управляющего реги- стра PMICSTATUS (адрес в области ввода/вывода микроконтроллеров ATxmega А — $00А0)(рис. 2.23). 7 6 5 4 3 2 1 0 NMIEX — — — — HILVLEX MEDLVLEX LOLVLEX Рис. 2.23. Регистр PMICSTATUS Первые три флага этого регистра определяют, активен ли в данный момент об- работчик прерывания высокого (HILVLEX), среднего (MEDLVLEX) или низкого (LOLVLEX) уровня. Если один из таких обработчиков был прерван немаскируемым прерыванием, то соответствующий флаг останется установленным до момента за- вершения прерванной процедуры. Регистр управления контроллером прерываний Для управления контроллером прерываний служит регистр PMICCTRL (адрес в области ввода/вывода микроконтроллеров ATxmega А — $00А2) (рис. 2.24).
126 Глава 2. Семейство AVR ATxmega 7 6 5 4 3 2 1 О RREN IVSEL — — — HILVLEN MEDLVLEN LOLVLEN Рис. 2.24. Регистр PMICCTRL Запись лог. 1 в один из первых трех разрядов этого регистра разрешает преры- вания нйзкого, среднего или высокого уровня. Разряд IVSEL определяет, куда помещаются вектора прерываний. Если он со- держит лог. 1, то векторы будут перемещены в начало раздела загрузчика памяти программ, в противном случае — в начало раздела приложения. При установке в лог. 1 разряда RREN активизируется циклическое планирова- ние прерываний низкого уровня, при котором адрес вектора последнего признанно- го прерывания низкого уровня получит самый низкий приоритет при следующем запросе на обработку одного или нескольких прерываний низкого уровня. Без при- менения такой схемы (т.е. при статическом определении приоритетности) может возникнуть ситуация, когда при наличии нескольких запросов низкого уровня до прерывания с самым низким приоритетом очередь так никогда и не дойдет. * При циклическом планировании адрес вектора последнего признанного преры- вания низкого уровня сохраняется в управляющем регистре INTPRI (адрес в облас- ти ввода/вывода микроконтроллеров ATxmega А — $00А1). Аналого-цифровое преобразование Аналого-цифровой преобразователь (АЦП) микроконтроллеров ATxmega А реализует 12гразрядное разрешение и допускает скорость преобразования до двух миллионов опросов в секунду. Его особенности: • измерения могут быть как на одиночном выводе, так и дифференциальными; в последнем случае для увеличения динамического диапазона возможно вклю- чение усилительного каскада; • доступны несколько внутренних сигнальных входов; • преобразование может быть начато или программно, или в качестве реакции на событие какого-либо периферийного устройства; • для получения опорных напряжений используются как очень точный внутрен- ний на 1 В, так и внешние источники; • доступен встроенный датчик температуры; • измерение может осуществляться одновременно по четырем каналам, каждому из которых соответствует собственный набор управляющих регистров (т.е. для АЦП можно создать четыре независимых конфигурации измерений, и затем ис- пользовать их по своему усмотрению в зависимости от потребностей приложе- ния); • в качестве аналоговых входов у микроконтроллеров ATxmega А используются выводы портов А и В. Для разрешения преобразований следует установить в лог. 1 разряд ENABLE управляющего регистра ADCxCTRLA (адрес в области ввода/вывода микрокон- троллеров ATxmega А — $0200 для АЦП на порту А и $0240 для АЦП на порту В). Одиночное преобразование по одному из четырех каналов начинается после уста- новки в лог. 1 соответствующего разряда CH[3:0]START в этом же регистре
Аналого-цифровое преобразование 127 ADCxCTRLA. По окончанию преобразования в одном из каналов соответствующий разряд аппаратно обнуляется. Конфигурирование АЦП \ До начала преобразования АЦП и канал необходимо сконфигурировать. Начнем с управляющего регистра ADCxCTRLB (адрес $0201 или $0241) (рис. 2.25). 7 6 5 4 3 2 10 — — — CONVMODE FREERUN RESOLUTION — Рис. 2.25. Регистр ADCxCTRLB управления АЦП Выбор разрешения преобразования Разрешение преобразования определяют разряды RESOLUTION регистра ADCxCTRLB (табл. 2.25). Таблица 2.25. Выбор разрешения аналого-цифрового преобразования RESOLUTION1 RESOLUTIONO Описание 0 0 1.2-разрядное разрешение, выравнивание результа- та по правому краю 1 0 8-разрядное разрешение, выравнивание результата по правому краю 1 1 12-разрядное разрешение, выравнивание результа- та по левому краю Выбор очередности преобразований в каналах Если с помощью разрядов CH[3:0]START регистра ADCxCTRLA задано преоб- разование одновременно для нескольких каналов, то они перебираются поочередно по направлению от нулевого к третьему. Микроконтроллеры ATxmega также позво- ляют задать циклический перебор всех или нескольких каналов. Для этого необхо- димо установить в лог. 1 разряд FREERUN регистра ADCxCTRLB и задать значения разрядов SWEEP[l:0] управляющего регистра ADCxEVCTRL (адрес $0203 или $0243): • 00 — только канал 0; • 01—каналы 0 и 1; • 10 — каналы 0, 1 и 2; • 11 — все четыре канала. Выбор режима измерения Если разряд CONVMODE регистра ADCxCTRLB содержит 0 (значение по умолчанию), то АЦП работает в режиме беззнакового измерения по одному каналу или опроса внутреннего сигнала. В противном случае используется знаковый ре- жим, в котором допустимо дифференциальное измерение. В случае беззнакового измерения на отрицательный вход АЦП подается половина опорного напряжения Vref минус некоторое фиксированное смещение AV, номинальное значение ко- торого составляет 0,05 • Vref- При беззнаковом режиме отрицательный вход соединен
128 Глава 2. Семейство AVR ATxmega с “землей” (в случае измерения внутреннего сигнала или сигнала на одиночном выводе) или же на него подается сигнал с одного из четырех аналоговых входов (ADC0-3 в случае диф- ференциального измерения без усиления или ADC4-7 в случае дифференциального измере- ния с усилением). Для каждого из четырех каналов АЦП тип измерения задается с помощью реги- стров с именами вида ADCxCHnCTRL (рис. 2.26) и ADCxCHnMUXCTRL (рис. 2.27), где “х” — “А” или “В”, а “п” — “0”..“3”. 7 6 5 4 3 2 1 0 START • — GAIN INPUTMODE Рис: 2.26. Регистр ADCxCHnCTRL управления каналом АЦП 7 6 5 4 3 2 1 0 — MUXPOS — MUXNEG Рис. 2.27. Регистр ADCxCHnMUXCTRL управления каналом АЦП Разряд START — это аналог соответствующего данному каналу разряда CHnSTART в регистре ADCxCTRLA. Разряды INPUTMODE[1:0] в комбинации с рассмотренным выше разрядом CONVMODE определяют источник входного измеряемого сигнала (табл. 2.26). Таблица 2.26. Определение входного измеряемого сигнала CONVMODE INPUTMODE1 INPUTMODEO Измеряемый сигнал 0 или 1 0 0 Внутренний на положительном входе АЦП 0 или 1 0 1 Одиночный аналоговый вход на положи- тельном входе АЦП 1 1 0 Дифференциальный входной сигнал 1 1 1 Дифференциальный входной сигнал с уси- лением Для последнего случая коэффициент усиления задают с помощью разрядов GAIN[2:0] регистра ADCxCHnCTRL: • 000—1; • 001—2; • 010 — 4; • 011—8; • 100 — 16; • 101—32; • 110 — 64. Разряды MUXPOS[2:0] в комбинации с рассмотренными выше разрядами INPUTMODE[1:0] определяют тип сигнала, подаваемого на положительный вход АЦП (табл. 2.27). ПРИМЕЧАНИЕ В микроконтроллерах с одним АЦП на положительный вход можно также подать сигнал из другого аналогового порта, отличного от основного. Для этого необходимо установить в лог. 1 разряд MUXPOS3.
Аналого-цифровое преобразование 129 Таблица 2.27. Выбор типа сигнала, подаваемого на положительный вход АЦП INPUTMODE[1:0] MUXPOS2 MUXPOS1 MUXPOS0 Тип сигнала 00 0 0 0 С датчика температуры 0 0 1 Внутреннее точное опорное напря- жение, базовое для других внутрен- них опорных напряжений 0 1 0 1/10 напряжения Vcc 0 1 1 С выхода ЦАП 01, 10,11 0 0 0 С входа ADC0 0 0 1 С входа ADC1 0 1 0 С входа ADC2 0 1 1 С входа ADC3 1 0 0 С входа ADC4 1 0 1 С входа ADC5 1 1 0 С входа ADC6 1 1 1 С входа ADC7 Разряды MUXNEG[1:O] определяют тип сигнала, подаваемого на отрицатель- ный вход АЦП в случае дифференциальных измерений (т.е. когда разряд INPUT- MODE^ 1) (табл. 2.28). Таблица 2.28. Выбор типа сигнала, подаваемого на отрицательный вход АЦП INPUTWIODEO MUXNEG1 MUXNEG0 Тип сигнала 0 0 0 С входа ADC0 0 1 С входа ADC1 1 0 С входа ADC2 1 1 С входа ADC3 1 0 0 С входа ADC4 0 1 С входа ADC5 1 0 С входа ADC6 1 1 С входа ADC7 Выбор опорного напряжения Опорное напряжение АЦП выбирают с помощью управляющего регистра AD- CxREFCTRL (адрес $0202 или $0242) (рис. 2.28). 765432 1 0 — — REFSEL BANDGAP TEMPREF Рис. 2.28. Регистр ADCxREFCTRL Разряды REFSEL[l:0] определяют источник опорного напряжения и диапазон преобразования: • 00 — внутреннее напряжение 1 В; • 01 — внутреннее напряжение Vcc/1.6; • 10 — внешнее напряжение на выводе AREF порта А (если такой вывод присут- ствует); • 11 — внешнее напряжение на выводе AREF порта В (если такой вывод присут- ствует).
130 Глава 2. Семейство AVR ATxmega Установка в лог. 1 разряда BANDGAP делает доступным для измерений с по- мощью АЦП внутренний точный источник опорного напряжения, определяемого шириной запрещенной зоны. Если какие-либо другие функции АЦП уже использу- ют это напряжение (например, в случае выбора внутреннего опорного напряжения 1 В), то разряд BANDGAP можно не устанавливать. Наконец, запись лог. 1 в разряд TEMPREF определяет в качестве опорного на- пряжение на выходе датчика температуры. Выбор коэффициента деления частоты тактирования АЦП микроконтроллеров ATxmega тактируется сигналом ClkpER, который слу- жит для обеспечения синхронизации периферийных устройств (см. рис. 2.15). Час- тоту этого сигнала для проведения измерений можно разделить, установив требуе- мое значение в первых трех разрядах управляющего регистра ADCxPRESCALER (адрес $0204 или $0244): • ООО — коэффициент деления 4; • 001 —коэффициент деления 8; • 010 — коэффициент деления 16; • 011 — коэффициент деления 32; • 100 — коэффициент деления 64; • 101—коэффициент деления 128; • 110 — коэффициент деления 256; • 111 — коэффициент деления 512. Результаты измерения При 12-разрядном разрешении и измерениях со знаком результат может нахо- диться в диапазоне -2048..2047 ($F800..$007FF). В беззнаковом режиме измерений результат находится в диапазоне 0..4095 (O..$OFFF). Полученное в результате преоб- разования значение записывается в регистровую пару RESH:RESL соответствующе- го канала. В режиме измерений с учетом знака результирующее значение вычисляется по формуле: 7? = (Г-У)/Kref-^-2047, где V* — напряжение на положительном входе АЦП; V — напряжение на отрица- тельном входе АЦП; Pref — опорное напряжение; К — коэффициент усиления (ес- ли не активен режим дифференциальных измерений с усилением, то он всегда равен 1). В случае беззнакового режима измерений функция преобразования имеет вид: R = (V - (-AV)) / Vref • 4095. С помощью разрядов RESOLUTION[1:0] управляющего регистра ADCxCTRLB (см. табл. 2.25) можно задать восьмиразряднре разрешение. В этом случае преобра- зование будет выполнено быстрее, однако сужается диапазон доступных значений. Прерывания от АЦП АЦП микроконтроллеров ATxmega А может формировать запросы на прерыва- ние двух видов:
Цифро-аналоговое преобразование 131 • по завершению преобразования в одном из каналов; • в том случае, если результат преобразования.выше или ниже заданного порого- вого значения. Управление прерываниями реализуется независимо для каждого канала с по- мощью регистра ADCxCHnINTCTRL (рис. 2.29). 7 6 5 4 3 2 1 О — — — — INTMODE INTLVL Рис. 2.29. Регистр ADCxCHnINTCTRL Разряды INTLVL[1:O] определяют уровень прерывания, а разряды INTMO- DE[1:O] — режим прерывания: • 00 — по завершению преобразования; • 01 — если результат меньше порогового значения; • 11 — если результат больше порогового значения. Для последних двух режимов пороговое значение сохраняют в регистровой napeADCxCMPH:ADCxCMPL (адреса $0218:$0219 или $0258:$0259). Момент возникновения прерывания в канале определяют по установке флага IF (нулевой разряд) в регистре ADCxCHnINTFLAG. При выполнении вектора преры- вания этот флаг автоматически сбрасывается. Кроме того, подобным же образом ус- танавливаются и автоматически обнуляются флаги CH[3:0]IF в управляющем реги- стре ADCxINTFLAGS (адрес $0206 или $0246). Цифро-аналоговое преобразование Цифро-аналоговый преобразователь (ЦАП) получает аналоговые напряжения из некоторых цифровых значений. В микроконтроллерах ATxmega А присутствует два ЦАП, которые реализуют 12-разрядное разрешение и могут выполнять до миллиона замеров в секунду. При этом в каждом ЦАП доступны два канала преобразований, а результирующее напряжение может выдаваться на один вывод или на два различ- ных вывода через схему выборки и хранения. Выходное напряжение определяется формулой: Рцап = CHnDATA / 4095 • Pref. Здесь CHnDATA — цифровые данные для преобразования, сохраняемые в ре- гистровой паре DACxCHnDATAH:DACxCHnDATAL Источник опорного напряже- ния Pref для ЦАП определяют разряды REFSEL[l:0] управляющего регистра DACxCTRLC (адрес $0302 или $0322): • 00 — внутренне напряжение 1 В; • 01—напряжение Усс, • 10 — напряжение на выводе AREF порта А; • 11 — напряжение на выводе AREF порта В. Режим преобразования задает управляющий регистр DACxCTRLB (адрес $0301 или $0321) (рис. 2.30).
132 Глава 2. Семейство AVR ATxmega 7 6 5 4 3 2 1 0 — CHSEL — — — CH1TRIG CH0TRIG Рис. 2.30. Регистр DACxCTRLB Выходные каналы ЦАП определяют разряды CHSEL[1:0]: • 00 — только по одному каналу 0; • 10 — по двум каналам через схему выборки и хранения. Напряжение на выходе ЦАП можно также использовать внутренне. Это опреде- ляется разрядами регистра DACxCTRLA (адрес $0300 или $0320) (рис. 2.31). 7 6 5 4 3 2 1 0 — — — IDOEN CH1EN CH0EN — ENABLE Рис. 2.31. Регистр DACxCTRLA Рассмотрим назначение разрядов этого регистра: • ENABLE — активизация или отключение ЦАП в целом; • CH0EN — если в этом разряде — лог. 1, то напряжение с выходного канала 0 подается на вывод микроконтроллера; в противном случае оно используется только внутренне; • CH1EN — если в этом разряде — лог. 1, то напряжение с выходного канала 1 подается на вывод микроконтроллера; в противном случае оно используется только внутренне; • IDOEN — установка в лог. 1 этого разряда подает напряжение с выхода ЦАП на входные мультиплексоры АЦП и аналогового компаратора. Начало преобразования Преобразование начинается автоматически по записи данных в регистровую пару DACxCHnDATAH:DACxCHnDATAL или по заданному входящему событию в выбранном канале событий, если в регистрах присутствуют данные, которые еще не были преобразованы. Последний режим работы определяют разряды CH1TRIG и CH0TRIG управляющего регистра DACxCTRLB (см. рис. 2.30). Если в один из них записать лог. 1, то преобразование в соответствующем канале начнется при на- личии данных в регистре DACxCHnDATAH по поступлению события, заданного тремя разрядами EVSEL регистра DACxEVCTRL (адрес $0303 или $0323): • 000 — канал событий 0; • 001 — канал событий 1; • 010 — канал событий 2; • 011 — канал событий 3; • 100 — канал событий 4; • 101 — канал событий 5; • 110 — канал событий 6; • 111 — канал событий 7.
Цифро-аналоговое преобразование 133 Завершение преобразования определяют по установке флагов CH0DRE и CH1DRE,сигнализирующих о том, что регистр данных в соответствующем канале пуст, и в него можно записать очередное значение. Ограничения на время преобразования Для того чтобы цифро-аналоговое преобразование давало корректные результа- ты, необходимо соблюдать некоторые ограничения по времени с привязкой к часто- те тактирования периферии CIRper: • интервал между двумя преобразованиями не должен быть меньше 1 мкс для од- ноканального режима и 1,5 мкс для двухканального; • время обновления в двухканальном режиме не должно превышать 30 мкс. Эти настройки определяет управляющий регистр DACxTIMCTRL (адрес $0304 или $0324) (рис. 2.32). 7 6 5 4,3 2 1 0 — CONINTVAL REFRESH Рис. 2.32. Регистр DACxTI MCTRL Разряды CONINTVAL[2:0] задают минимальный интервал между двумя после- довательными преобразованиями (табл. 2.29). Таблица 2.29. Настройка минимального интервала между двумя преобразованиями CONINTVAL2 CONINTVAL1 CONINTVALO Количество циклов CIKper Одноканальный режим Двухканальный режим 0 0 0 1 1 0 0 1 2 3 0 1 0 4 6 0 1 1 8 * 12 1 0 0 16 24 1 0 1 32 48 1 1 0 64 96 1 1 1 128 192 Разряды REFRESH[3:0] задают время обновления в двухканальном режиме: • 0000 — 16 циклов ClkpER; • 0001 — 32 цикла CIRper; • 0010 — 64 цикла С IRper; • 0011 — 128 циклов ClkpER; • 0100 — 256 циклов CIRper; • 0101 — 512 циклов CIRper; • 0110 — 1024 цикла CIRper; • 0111 — 2048 циклов CIRper; • 1000 — 4096 циклов CIRper; • 1001 — 8192 цикла CIRper; • 1010 — 16384 цикла CIRper;
134 Глава 2. Семейство AVR ATxmega • 1011 — 32768 циклов CIIcper; • 1100 — 65536 циклов ClkpER; • 1111 — отключение автоматического обновления. Аналоговый компаратор Аналоговые компараторы микроконтроллеров ATxmega А сгруппированы по два на каждый аналоговый порт (рис. 2.33). Со входа микроконтроллера От внутреннего источника Со входа микроконтроллера От внутреннего источника Отмасштабированное Усс Со входа микроконтроллера От внутреннего источника Выход 0 микроконтроллера Со входа микроконтроллера От внутреннего источника Отмасштабированное Усс Рис. 2.33. Два аналоговых компаратора на одном порту Входные сигналы для положительного и отрицательного входов каждого из двух компараторов определяют управляющие регистры ACxnMUXCTRL, где “х” обозначает порт А или В, а “п” — номер компаратора (для порта А такие два реги- стра имеют адреса $0382 и $0383, а для порта В — $0392 и $0393) (рис. 2.34). 7 6 5 4 3 2 1 0 MUXPOS MUXNEG Рис. 2.34. Регистр ACxnMUXCTRL Разряды MUXPOS[2:0] задают источник для положительного входа компарато- ра • 000 — аналоговый вход 0; • 001 — аналоговый вход 1; • 010 — аналоговый вход 2; • 011 — аналоговый вход 3; • 100 — аналоговый вход 4; • 101 — аналоговый вход 5; • 110 — аналоговый вход 6; • 111 — выход ЦАП.
Аналоговый компаратор 135 Разряды MUXNEG[2:0] задают источник для отрицательного входа компаратора: • ООО — аналоговый вход 0; • 001 — аналоговый вход 1; • 010 — аналоговый вход 3; • 011 — аналоговый вход 5; • 100 — аналоговый вход 7; • 101 — выход ЦАП; • 110 — внутренне точное опорное напряжение; • 111 — отмасштабированное напряжение Усс- Коэффициент масштабирования напряжения Усс записывают в младшие пять разрядов регистра ACxCTRLB. Отмасштабированное напряжение, подаваемое на отрицательный вход компаратора, имеет значение: KsCALE = Исс • (К + 1) / 64. Режимы работы компаратора Под режимами работы компаратора подразумеваются различные условия фор- мирования запросов на прерывание. За это отвечают управляющие регистры ACxnCTRL (рис. 2.35) и ACxWINCTRL (рис. 2.36). 7 6 5 4 3 2 1 0 INTMODE INTLVL HSMODE HYSMODE ENABLE Рис. 2.35. Регистр ACxnCTRL 7 6 5 4 3 2 1 0 — — — WEN WINTMODE WINTLVL Рис. 2.36. Регистр ACxWINCTRL Рассмотрим назначение разрядов регистра ACxnCTRL: • ENABLE — активизация компаратора; • HYSMODEfl :0] — выбор режима входного гистерезиса во избежание постоян- ного переключения на выходе компаратора, если входные напряжения близки по значению, и на них воздействую помехи: ► 00 — гистерезис отсутствует; ► 01 — малый гистерезис; ► 10 — большое гистерезис; • HSMODE — если в этот разряд записать лог. 1, то компаратор перейдет в ско- ростной режим работы с целью минимизации задержки на распространение сигнала (следует учитывать, что в таком режиме потребляется больше энергии); • INTLVL[1:0] — разряды, определяющие уровень прерывания от компаратора; • INTMODE[1:0] — эти разряды задают режим формирования прерываний от аналогового компаратора: ► 00 — по переключению уровня выходного сигнала; ► 10 — по ниспадающему фронту выходного сигнала; ► 11 — по нарастающему фронту выходного сигнала.
136 Глава 2. Семейство AVR ATxmega При записи лог. 1 в разряд WEN регистра ACxWINCTRL (см. рис. 2.36) два компаратора на одном порту переходят в режим “окна”, в котором можно опреде- лить, попадает ли входной сигнал в заданный диапазон напряжений. Схема сигна- лов в таком режиме показана на рис. 2.37. Рис. 2.37. Схема сигналов в режиме “окна” Разряды WINTLVL[1:O] задают уровень прерывания от компаратора в режиме “окна”, а разряды ^ВЧТМОПЕ[1:0] — режим прерывания: • 00 — если входной сигнал больше верхнего предела “окна”; • 01 — если входной сигнал попадает внутрь “окна”; • 10 — если входной сигнал меньше нижнего предела “окна”; • 11 — если входной сигнал лежит вне “окна”. Флаги состояния компаратора и прерываний содержатся в управляющем реги- стре ACxSTATUS (адрес $0387 или $0397) (рис. 2.38). 7 6 5 4 3 2 1 0 WSTATE АС1STATE AC0STATE — WIF AC1IF AC0IF Рис. 2.38. Регистр ACxSTATUS Разряды AC0IF и,АС 1 IF — флаги прерываний от компараторов 0 и 1 соответст- венно, а разряд W1F — флаг прерывания в режиме “окна”. Все три флага при вы- полнении соответствующего вектора прерывания автоматически сбрасываются. Разряды AC0STATE и АС 1 STATE показывают состояние входного сигнала компаратора 0 и 1 соответственно, а разряды WSTATE[l:0] — состояние в режиме “окна”: • 00 — сигнал больше верхнего предела “окна”; • 01 — сигнал — внутри “окна”; • 10 — сигнал меньше нижнего предела “окна”. Средства шифрования В микроконтроллерах ATxmega поддерживаются популярные стандарты шиф- рования AES (Advanced Encryption Standard) и DES (Data Encryption Standard), при- чем последний реализован на уровне процессорного ядра с помощью специальной команды des. Эта команда, занимающая один цикл, для шифрования или дешифро- вания блока из восьми байт (64 бит) данных должна быть выполнена подряд 16 раз.
Средства шифрования 137 Перед началом шифрования/дешифрования в регистровый файл должны быть за- гружены блоки данных (регистры R0-R7) и ключа (регистры R8-R15). Одно выполнение команды des выполняет один цикл алгоритма DES. Для по- лучения корректного зашифрованного текста требуется 16 повторов. Промежуточ- ные результаты после каждого шага сохраняются в тех же регистрах R0-R15. После 16 повторов ключ будет храниться в регистрах R8-R16, а зашифрованный/ дешиф- рованный текст — в регистрах R0-R7. В качестве операнда команде des передается порядковый номер повторения, а флаг Н в регистре состояния определяет характер операции: шифрование (Н=0) или дешифрование (Н=1). Модуль шифрования AES В состав микроконтроллеров ATxmega А входит модуль шифрова- ния/дешифрования по алгоритму AES. Дня шифрования в память ключа необходи- мо загрузить 128-битный ключ, а в память состояния — 128-битный блок данных. Для этого следует последовательно 16 раз выполнить запись в регистры KEY (адрес $00СЗ) и STATE (адрес $00С2). Зашифрованный/дешифрованный текст доступен в памяти состояния после 375 тактовых циклов. Перед загрузкой ключа и данных модуль AES необходимо настроить. Для этого служит управляющий регистр AESCTRL (адрес $00С0) (рис. 2.39). 7 6 5 4 3 2 1 0 START AUTO RESET DECRYPT — XOR — — Рис. 2.39. Регистр ACxSTATUS Характер работы модуля определяет разряд DECRYPT, Если он содержит лог. 0, то будет выполнено шифрование, в противном случае — дешифрование. Если .установить в лог. 1 разряд XOR, то данные, загружаемые в память состоя- ния, будут поразрядно объединяться с уже хранимыми там данными с помощью ло- гической операции “Исключающее ИЛИ”. В противном случае новые данные будут просто затирать старые. Установка в лог. 1 разряда RESET приведет к сбросу модуля шифрования AES по ближайшему нарастающему фронту сигнала тактирования периферии. Все реги- стры, указатели и блоки памяти модуля примут исходные значения. Разряд сохраня- ет состояние лог. 1 на протяжении одного тактового цикла, после чего автоматиче- ски обнуляется аппаратно. Для запуска процедуры шйфрования/дешифрования необходимо записать лог. 1 в разряд START. Запись в него лог. 0 прервет активный процесс. При обнаружении установленных флагов SRIF или ERROR в регистре AES STATUS (см. ниже) разряд START обнуляется автоматически. Запись лог. 1 в разряд AUTO активизирует режим автозапуска процесса шифро- вания/дешифрования. В таком режиме процесс начинается (т.е. автоматически уста- навливается в лог. 1 разряд START), если выполнены следующие условия: • разряд AUTO инициализирован до начала загрузки данных в память состояния; • указатели памяти ключа и памяти состояния — нулевые; • память состояния полностью загружена данными. В случае успешного завершения шифрования/дешифрования результат будет получен в памяти состояния, на что указывает установленный флаг SRIF в регистре
138 Глава 2. Семейство AVR ATxmega AESSTATUS (адрес $00С1). Для получения этих данных необходимо 16 раз после- довательно обратиться на чтение к регистру STATE. После первого же такого об- ращения флаг SRIF будет сброшен. Установка флага SRIF формирует запрос на прерывание от модуля шифрования AES. Уро- вень такого прерывания определяют первые два разряда (INTLVL[1:0]) управляющего регист- ра AESINTCTRL (адрес $0004). В случае возникновения ошибки при работе с модулем шифрования AES в ре- гистре AESSTATUS будет установлен флаг ERROR. Это может произойти в двух случаях: • запись лог. 1 в разряд START регистра AESCTRL в тот момент, когда память состояния или ключа еще не полностью загружена или прочитана; • доступ на чтение или запись к регистру AESCTRL в тот момент, когда разряд START содержит лог. 1. Для сброса флага ERROR в его позицию необходимо записать лог. 1. Модуль обмена данными по инфракрасному каналу Микроконтроллеры ATxmega оснащены модулем обмена данными по инфра- красному каналу (IRCOM), поддерживающий скорость передачи до 115,2 кбит/с. При этом реализованы три схемы модуляции: • 3/16 периода передачи данных; • фиксированная, программируемая длительность импульсов, основанная на сиг- нале тактирования периферии ClkPER; • отключенная импульсная модуляция. Схема модуляции устанавливается путем записи некоторого значения в уп- равляющий регистр TXPLCTRL (адрес $08F0). Если этот регистр содержит 0, то ис- пользуется 3/16 периода передачи данных. Запись в него значения от 1 до 254 дает фиксированную длину импульсов, а значение 255 отключает кодирование импуль- сов, в результате чего сигналы RX и ТХ проходят через модуль 1RCOM без измене- ний. Модуль IRCOM может быть подключен к любому приемопередатчику USART для кодирования/декодирования инфракрасных импульсов (рис. 2.40). Модуль IRCOM активизируется автоматически, когда какой-либо из модулей USART переходит в режим инфракрасной передачи. Для этого необходимо записать “10” в старшие два разряда управляющего регистра USARTxCTRLC. ... ...... ....................... .......--... . — ЦШшШ:. ..ЖМММВ. В каждый момент времени обмениваться данными с модулем IRCOM может только один приемопередатчик USART. Кроме того, в качестве входящего сигнала для приемника IRCOM может слу- жить какой-либо канал событий, который определяется записью битовой комбина- ции “1ххх” в младшие четыре разряда управляющего регистра IRCOMCTRL (адрес $08F2). Комбинации “1000” соответствует канал событий 0, а комбинации “1111” — канал событий 7.
Модуль обмена данными по инфракрасному каналу 139 Система обра- ботки событий EairJ События IRCOM Декодиро- вание им- пульсов RXD (код.) USARTxn USARTC1 USARTC0 Кодирова- ние импуль- сов RXD (цекод.) TXD (декод.) TXD (код.) g RXDnx 3 TXDnx .й TXD.,, RXD... RXDC1 TXDC1 RXDC0 TXDC0 Рис. 2.40. Подключение модуля IRCOM к USART
ЧАСТЬ 11 Компиляторы и средства разработки для микроконтроллеров AVR
Глава 3 Компилятор WinAVR WinAVR (http: //winavr. sourceforge. net) — это набор инструментальных средств, предназначенных для программирования RISC-микроконтроллеров семей- ства AVR на языке С. Он был создан трудом множества добровольцев, посвятивших свое свободное время тому, чтобы бескорыстно помогать другим. В комплект по- ставки входит компилятор GNU GCC для языков С и C++, а также — замечательная программа Programmers Notepad, которая будет использоваться в этой книге для разработки программ. Установочный файл WinAVR средств находятся на прилагаемом к книге компакт-диске в папке Software\AVR\WinAVR. Для запуска программы Programmers Notepad следует запустить на выполнение файл pn.exe, который находится в папке \WinAVR\pn. или воспользоваться коман- дой меню Пуск ► Все программы ► WinAVR ► Programmers Notepad. Интерфейс Programmers Notepad прост и интуитивно понятен: за исключением меню Tools, все остальные меню — обычные для любого приложения Windows (File, Edit, View, Window, Help), и потому на них мы останавливаться не будем. Окно Pro- grammers Notepad при первом запуске показано на рис. 3.1. Рис. 3.1. Окно Programmers Notepad при первом запуске
142 Глава 3. Компилятор WinAVR Внешние средства компиляции и синтаксического анализа активизируются че- рез меню Tools (если в среде разработки открыт какой-либо файл с исходным ко- дом). Для того чтобы добавить в это меню команду для создания файлов, исполь- зуемых при эмуляции в среде AVRStudio, необходимо выполнить команду Tools ► Options и в диалоговом окне Options выбрать категорию параметров Tools (рис. 3.2). Рис. 3.2. Внешние средства компиляции и синтаксического анализа Для того чтобы добавить новый элемент в список, нажмем кнопку Add и в диа- логовом окне Свойства: New Tool установим следующие параметры на вкладках Properties (Свойства) и Console I/O (Консольный ввод-вывод) (рис. 3.3): • Name—[WinAVR] Make Extcoff — имя средства; Рис. 3.3. Добавление средства создания файлов COFF для эмуляции программ в среде AVR Studio
Эмуляция 143 • Command — make. exe — компиляция и сборка программы осуществляется с помощью средства make. ехе, расположенного в папке \winAVR\utils\ bin, на основании параметров компиляции (формат выходного файла, тип мик- роконтроллера и др.), указанных в файле makefile (такой файл должен быть скопирован в ту же папку, что и исходный код программы — это будет показа- но чуть позже); • Folder,— %d — это означает, что выходные файлы размещаются в той же папке, что и исходные; • Parameters — extcof f — параметр, передаваемый файлу make. ехе; здесь воз- можны следующие варианты: ► all — на выходе получают файлы для загрузки в микроконтроллер; ► clean — удаление всех выходных файлов; ► cof f — преобразование файлов из формата ELF (Executable and Linkable For- mat) в AVR COFF (Common Object File Format) для использования в среде AVR Studio 3.x или VMLAB; ► extcof f — преобразование файлов из формата ELF в расширенный формат AVR COFF для использования в среде AVR Studio 4.x или выше) — нас ин- тересует именно этот вариант; ► program — загрузка НЕХ-файла в микроконтроллер с помощью специальной программы avrdude. ехе, входящей в пакет WinAVR; ► filename. s — просто компиляция файла filename. с в ассемблерный код; • Save — Current File — автоматическое сохранение при компиляции только те- кущего файла с исходным кодом; • выбор элемента Use the main output window на вкладке Console I/O означает, что для вывода сообщений о ходе и результатах компиляции будет использовано общее, а не индивидуальное окна Output (расположено вдоль нижнего края окна Programmers Notepad); • Clear output before running? — этот флажок лучше сбросить, чтобы содержимое окна Output не очищалось перед очередным вызовом средства. Нажимаем кнопку ОК вначале в окне Свойства: New Tool, а затем — в окне Options, чтобы сохранить изменения в списке подключаемых средств. Процесс компиляции в среде Programmers Notepad проиллюстрируем на приме- ре простой программы, создающей эффект сигнала “SOS” с помощью светодиодов, подключенных к микроконтроллеру AVR. Для создания исходного кода программы в среде Programmers Notepad можно воспользоваться одним из двух способов: • выполнить команду меню File ► New ► C/C++, чтобы создать новый файл исход- ного кода, а затем ввести в него текст из листинга 3.1; после этого следует вы- полнить команду меню File ► Save (комбинация клавиш <Ctrl+S>) и сохранить созданный файл в отдельной папке под именем SOS. с; • предварительно скопировать с прилагаемого к книге компакт-диска на жесткий диск папку Projects\WinAVR\SOS, а затем выполнить команду меню File ► Open (комбинация <Ctrl+O>) и открыть из скопированной папки файл sos. с. Листинг 3.1. Файл SOS. с для компилятора WinAVR #include <avr/io.h> #include cutil/delay.h>
144 Глава 3. Компилятор WinAVR Листинг 3.1. Окончание void Pause(int ms) { PORTD = OxFF; //Все светодиоды отключены _delay_ms(ms); //Задержка void P(void) { PORTD* *= 0; _delay_ms(500); Pause(500); void D(void) { PORTD = 0; _delay_ms(1000); Pause (500)1; } //Включаем все светодиоды //Короткая задержка //Пауза с погасшими светодиодами //Включаем все светодиоды //Длинная задержка //Пауза с погасшими светодиодами int main (void) { DDRD = OxFF; // Настройка порта D для вывода while(1) //Бесконечный цикл { Р(); Р(); Р();//.. . DO; D(); D(); //------- Р(); Р(); Р(); //. . . Pause(10000); } J______________________ ПРИМЕЧАНИЕ Программные элементы мы пока рассматривать не будем, поскольку это —• материал сле- дующих глав. Этот пример используется только для изучения среды программирования. Перед компиляцией заглянем в файл makefile. Скопируйте его в папку с файлом SOS. с из папки \Projects\WinAVR\SOS, если еще этого не сделали. При копировании этого файла из проекта в проект изменению подлежат, в основном, следующие поля: • мои — тип микроконтроллера, для которого создаются выходные файлы; • F_CPU — рабочая частота микроконтроллера в герцах; • FORMAT — формат загружаемого файла (используются значения srec, ihex, binary); • target — имя исходного файла (без расширения . с). Предположим, программа SOS должна компилироваться для микроконтроллера Atmegal69 в формате ihex (читатель может использовать необходимые ему значе-
Эмуляция 145 ния). В этом случае соответствующий фрагмент файла makefile будет выглядеть следующим образом: # MCU name MCU = atmegal69 # Output format, (can be srec, ihex, binary) FORMAT = ihex # Target file name (without extension). TARGET = SOS Теперь откомпилируем программу SOS. с. Для этого в среде Programmers Note- pad выполним команду меню Tools ► [WinAVR] Make АП. Если в окне Output в нижней части Programmers Notepad не было выдано сообщений об ошибках, значит компи- ляция прошла успешно и можно создать файл для эмулятора AVR Studio. Для этого выполним команду меню Tools ► [WinAVR] Make Extcoff. В результате в одной папке с файлом SOS. с будет создан файл SOS. cof. Обратите внимание на панель Text Clips (Фрагменты текста), расположенную вдоль левого края окна Programmers Notepad. Оно содержит список всех символов из таблицы ASCII с указанием их кода в десятичной и шестнадцатеричной форме. Для быстрой вставки того или иного символа в текст программы достаточно дважды щелкнуть мышью на требуемом элементе в этом списке. Кроме того, справа от вкладки Text Clips находится вкладка Tags (Метки), отображающая программу в виде иерархической структуры ее функций. Для быстрого перехода к той или иной функции достаточно просто дважды щелкнуть мышью на соответствующем элементе в панели Tags.
Глава 4 Среда разработки AVR Studio AVR Studio — среда, созданная компанией Atmel (распространяется бесплатно), которая используется для загрузки созданных программ в тот или иной программа- тор, а также эмуляции выполнения программ на том или ином микроконтроллере. • В этой книге рассматривается версия AVR Studio 4.13, установочный файл которой находится на прилагаемом к книге компакт-диске в папке Sof tware\AVR\AVRStudio4. AVR Studio — это интегрированная среда разработки (IDE — Integrated Devel- opment Environment), которая очень удобна для отладки AVR-приложений в операционной системе Windows. Эта среда предлагает интерфейс программного имитатора и Ьнутрисхемного эмулятора для микроконтроллеров AVR RISC. Кроме того, AVR Studio поддерживает набор разработчика STK500, позволяющий про- граммировать AVR-устройства, а также новый встроенный эмулятор JTAG. Поскольку описание эмуляторов, которые сами по себе не являются составной частью AVR Studio, а должны приобретаться у компании Atmel, выходит за темати- ческие рамки этой книги, то в дальнейшем ограничимся только рассмотрением ин- тегрированного' имитатора. Среду AVR Studio можно запустить по команде меню Пуск ► Все программы ► Atmel AVR Tools ► AVR Studio 4. При первом запуске AVR Studio на экране появится окно приветствия (рис. 4.1). Рис. 4.1. Окно приветствия AVR Studio 4 С помощью этого окна можно выполнить одну из трех операций: • создать новый проект “с нуля” — кнопка New Project; • открыть какой-либо файл . cof или . hex с диска — кнопка Open;
Эмуляция 147 • открыть один из проектов, которые использовались последними — для этого следует выбрать один из элементов в расположенном ниже списке. Для примера, загрузим для эмуляции созданную в предыдущей главе програм- му SOS.с. Для этого в окне приветствия нажмем кнопку Open и откроем файл SOS.cof. В результате будет предложено указать имя для проекта AVR Studio, со- храняемого в файле .aps. Назовите проект SOS cof.aps и нажмите кнопку Save (Сохранить). В результате откроется окно, в котором необходимо выбрать тип эму- лятора и микроконтроллера (рис. 4.2). Рис. 4.2. Выбор эмулятора и типа микроконтроллеров В данном случае нас интересует интегрированный имитатор AVR Simulator и микроконтроллер Atmega169 (читатель может использовать другой необходимый ему тип микроконтроллеров). Теперь можно нажать кнопку Finish (Готово), чтобы перейти к эмуляции и отладке программы. ПРИМЕЧАНИЕ Для того чтобы окно приветствия при последующих запусках AVR Studio не отображалось, в нем следует сбросить флажок Show dialog at startup. В таком случае все операции по соз- данию и загрузке проектов выполняются с помощью команд меню File и Project, а окно выбо- ра эмулятора и типа микроконтроллеров, соответствующее рис. 4.2, открывается по команде меню Debug ► Select Platform and Device Окно AVR Studio при открытии нового проекта показано на рис. 4.3. В данный момент в рабочем пространстве отображаются следующие панели: • Processor — текущее содержимое счетчика команд (Program Counter), указателя вершины стека (Stack Pointer), регистров двойной длины X, Y и Z, счетчика вы- полненных циклов (Cycle Counter), тактовой частоты процессора (Frequency), ре- гистра состояния SREG, 32-х рабочих регистров, а также — текущий момент времени в ходе выполнения программы (Stop Watch); • Disassembler — дизассемблированный код программы; • I/O View — содержимое регистров всех периферийный устройств и портов вы- бранного микроконтроллера; • Message — окно с сообщениями о ходе выполнения различных операций в среде AVR Studio.
148 Глава 4. Среда разработки AVR Studio Рис. 4.3. Проект AVR Studio Содержимое счетчика команд, регистров X, Y, Z и R00-R31, а также — разря- дов регистров периферии и SREG можно изменять вручную в ходе отладки про- грамм, щелкнув на них мышью. Измененные эмулятором или пользователем данные обозначаются в AVR Studio красным цветом (для числовых данных). Установлен- ным в лог. 1 разрядам в регистровых полях соответствуют серые, а обнуленным — белые прямоугольники. Строка, подлежащая исполнению первой, обозначена в окне Disassembler жел- той стрелкой. Для того чтобы увидеть исходный код программы, следует щелкнуть мышью на вкладке Project (Проект) в окне Processor, а затем — дважды щелкнуть на элементе SOS_cof ► Source ► SOS.c в иерархической структуре проекта (рис. 4.4). Следует учитывать, что исходный код извлечен из файла . cof или . hex, и по- тому редактированию не подлежит. Изменения следует вносить в среде Program- mers Notepad, а затем — по-новому выполнять компиляцию и создание объектного файла и переключиться в AVR Studio. Если в AVR Studio был открыт тот же файл, то внешние изменения будут распознаны и на экране появится предложение авто- матически обновить содержимое окна исходного кода. Эту же операцию можно вы- полнить и вручную с помощью кнопки панели инструментов Reload Object File. Эмуляция Как уже было отмечено ранее, окно I/O View позволяет контролировать работу устройств ввода-вывода микроконтроллера, выбранного для эмуляции. Например,
Эмуляция 149 с помощью элемента PORTD мы можем увидеть созданную ранее программу SOS. с в действии (рис. 4.5). Для этого достаточно запустить ее на выполнение командой 3 меню Debug ► Auto Step (комбинация клавиш <Alt+F5>) или соответствующей кнопкой панели инструментов Debug. Рис. 4.4. Просмотр исходного кода программы Рис. 4.5. Программа SOS включает все “светодиоды”, подключенные к выводам порта D
150 Глава 4. Среда разработки AVR Studio ПРИМЕЧАНИЕ Команда Auto Step отличается от команды Run (клавиша <F5>) тем, что в ходе выполнения программы после каждого шага обновляются окна AVR Studio (в случае команды Run — не обновляются). - ВНИМАНИЕ! Поскольку эмулятор выполняет программу в виртуальной среде, она работает значительно медленнее, чем в реальном микроконтроллере (особенно, выполнение функций задержки, наподобие _delay__ms из программы SOS.с). Если попытаться запустить программу SOS на эмуляцию в том виде» в каком она показана в листинге 3.1, то функции _delay_ms будут выполняться так долго, что может показаться, что программа “зависла”. Во избежание этого на этапе отладки в AVR Studio значения задержек следует выбирать в сотни или даже тысячи раз меньше. Например, в программе SOS короткой задержке может соответствовать значение 1 вместо 500, длинной — значение 2, а паузе — 10. Если даже такие задержки покажутся чи- тателю слишком долгими, то на этапе отладки можно заменить вызов функции _delay__ms вызовом функции delay us, которая реализует задержки в микросекундах. Для того чтобы приостановить выполнение программы, следует выполнить ко- манду меню D^bug ► Break (комбинация клавиш <Ctrl+F5>) или нажать соот- ветствующую кнопку панели инструментов Debug. Полному останову с воз- вратом к первой команде соответствует команда Debug ► Reset (комбинация клавиш <Shift+F5>). Ж В ходе выполнения программы можно наблюдать за изменением состояния ре- гистров процессора и периферии в окнах Processor и I/O View. По умолчанию значе- ния в окне Processor отображаются в шестйадцатеричной форме. Для того чтобы переключиться к десятичному формату отображения, следует щелкнуть внутри это- го окна правой кнопкой мыши и сбросить в контекстном меню флажок Hexadecimal Display (рис. 4.6). Progfam Counter Stack Pointer X pointer Y pointer Z pointer Cycle Counter Frequency Stop V/at ch SREG Registers R00 R01 R02 0x000088 1275 [256 1279 808 7546 4 0000 MHz 1886 50 us Г~! ГП F-] ГП ГЛ ПЛ СП ГП о о о Рис. 4.6. Переключение формата отображения значений регистров в окне Processor Для возврата к шестнадцатеричному представлению необходимо опять устано- вить флажок возле пункта Hexadecimal Display. Другие важные команды контекстного меню окна Processor: • Reset Stopwatch — обнуление значения “секундомера”; • Reset Cycle Counter — обнуление значения счетчика циклов; • Show Stopwatch as milliseconds — выбор в качестве единиц времени для “секун- домера” миллисекунд. В результате эта команда контекстного меню изменится на Show Stopwatch as microseconds, и ее выбор приведет к возврату к микросе- кундным отсчетам.
Окно Memory 151 Окно Memory Окно Memory позволяет пользователю при необходимости контролировать или изменять некоторую область памяти микроконтроллера AVR: память программ, па- мять EEPROM, память данных, память ввода/вывода, рабочие регистры процессора. Одновременно могут быть открыты сразу три окна Memory — для этого использу- ются соответствующие команды меню View (рис. 4.17), комбинация клавиш rzzi <Alt+4>, а также кнопка Toggle Memory Window панели инструментов. |ЛЦ Рис. 4.7. Два окна Memory AVR-Studio Тип области памяти выбирают с помощью раскрывающегося списка, располо- женного в верхнем левом углу окна Memory. В примере на рис. 4.7 для верхнего ок- на была выбрана память программ, а для нижнего — память данных. С помощью кнопки 8/16, расположенной справа от раскрывающегося списка, а также команд контекстного меню 1 Byte и 2 Byte пользователь может переклю- чаться между режимами разбивки дампа памяти на одно- и двухбайтные фрагменты, а с помощью кнопки abc — отобразить/скрыть дополнительную колонку с ASCII- значениями отображенной области памяти. Л Поле Address служит для отображения и ввода адреса ячейки памяти, на кото- рой в данный момент установлен курсор. Количество колонок со значениями ячеек памяти выбирается с помощью раскрывающегося списка Cols (если в этом списке выбран элемент Auto, то количество колонок выбирается автоматически в зависимо- сти от ширины окна Memory). Содержимое ячейки памяти в окне Memory можно легко изменить. Введенные значения расцениваются как шестнадцатеричные числа, при этом новое значение попадает в ячейку памяти сразу же после каждого нажатия клавиши. Если это неже- лательно (например, в случае применения эмулятора при доступе на запись к регистру UDR приемопередатчика USART инициируется новая передача, хотя в этом случае байт еще неполный), то новое значение можно альтернатив- но вводить в специальном диалоговом окне, которое откры- вается по двойному щелчку мыши на соответствующей ячейке памяти (рис. 4.8). В этом случае вводимое значение записывается в ячейку только тогда, когда в окне Edit будет нажата кнопка ОК (клавиша <Enter>). Значения, которые изменились с момента последней операции отладки, ото- бражаются красным шрифтом. Адреса восьмиразрядных ячеек памяти и ASCII- Рис. 4.8. Изменение значения ячейки памяти
152 Глава 4. Среда разработки AVR Studio символы выделены серым фоном, а адреса 16-разрядных ячеек памяти — голубым фоном. Окно Register Окно Register (рис. 4.9) показывает содержимое 32-х рабочих регистров микро- контроллера, которое обновляется после выполнения каждой команды. Оно откры- вается по соответствующей команде меню View, по нажатию комбинации клавиш <Alt+O> или с помощью кнопки Toggle Register Window панели инструментов. Рис. 4.9. Окно Register среды AVR Studio Значения, Изменившиеся в результате последней отладочной операции (напри- мер, при пошаговом проходе или в результате достижения точки останова) отобра- жаются красным шрифтом. Для того чтобы изменить содержимое регистра, следует остановить выполнение программы и сделать двойной щелчок мышью на выбранном регистре. Правила из- менений значений в регистрах аналогичны правилам изменения значений в окнах Memory. Окно Watch Рис. 4.10. Окно Watch среды AVR Studio Окно Watch (рис. 4.10) служит для ото- бражения типов, значений и адресов таких объектов как, например, переменные в про- грамме на С. Оно открывается по соответст- вующей команде меню View, по нажатию комбинации клавиш <Alt+l> или с помощью кнопки Toggle Watch Window панели ин- струментов. mU Это окно состоит из четырех колонок. В первой указано имя объекта, за кото- .рым ведется наблюдение, во второй — текущее значение, в третьей — тип объекта (Integer, unsigned Char ит.д.), а в четвертой —его адрес. Пользователь может добавлять новые объекты в окно Watch по команде контекстного меню Add Item или же по команде контекстного меню Add Watch в окне исходного кода. В последнем случае в список Watch будет добавлен элемент кода, на котором установлен курсор. Элементы окна Watch можно удалять по одному с помощью команды контекстного меню Remove Selected Item или все сразу по команде контекстного меню Remove All Items. Отладка программы Под отладкой подразумевают пошаговое выполнение программы с контролем содержимого регистров микроконтроллера (проверка на низком уровне) и перемен-
Настройка параметров имитатора 153 ных (проверка на программном уровне). Для отладки программ в AVR Studio ис- пользуют команды меню Debug и кнопки одноименной панели инструментов. Прежде, чем рассмотреть эти команды имеет смысл разъяснить такое понятие как “точка прерывания”, Точка прерывания (breakpoint) — это строка исходного кода, на которой работа программы приостанавливается. Таких точек (обозначаются коричневым кружком слева от строки) может быть установлено столько же, сколько эффективных строк в программе. Для установки/удаления точки прерывания в текущей строке служит команда меню Debug ► Toggle Breakpoint (клавиша <F9>) или соответствующая кнопка панели инструментов Debug. Для удале- ния всех расставленных в программе точек прерывания служит команда меню Debug ► Remove Breakpoints или кнопка Remove all program breakpoints панели инструментов Debug. Для последовательного перехода от одной точки прерывания к другой используется команда меню Debug ► Next Breakpoint или комбинация клавиш <Ctrl+F9>. Для перехода в режим отладки используются следующие команды меню Debug: • Run, Auto Step — переход в режим отладки происходит, если ветре- rg чается точка прерывания; • Step Into (клавиша <F11>) — выполняет текущую команду с заходом в подпрограммы (все окна обновляются); • Step Over (клавиша <F10>) — выполняет текущую команду без захода в подпрограммы (все окна обновляются); • Step Out (комбинация клавиш <Shift+F 11>) — запускает программу и вы- полняет ее до тех пор, пока не встретится окончание текущей подпрог- раммы; если ход выполнения находится в областй основной программы, то про- грамма будет выполняться до тех пор, пока не будет остановлена пользователем командой Break или не встретит точку прерывания; • Run То Cursor (комбинация клавиш <Ctrl+Fl 0>) — запускает программу, которая выполняется до тех пор, пока не будет достигнута позиция курсо- ра в окне исходного кода; если встречается точка останова, то выполнение про- граммы не останавливается; если позиция курсора не достигается никогда, то программа выполняется до тех пор, пока не будет остановлена командой Break. После выполнения команды все окна обновляются. Настройка параметров имитатора Для того чтобы выбрать имитацию работы конкретного микроконтроллера, а также его рабочую частоту, служит диалоговое окно Simulator Options (рис. 4.11), которое открывается по команде меню Debug ► AVR Simulator Options (комбинация клавиш <Alt+O>). Здесь допустимые параметры выбранного микроконтроллера ото- бражаются в текстовом поле, расположенном справа. Создание проекта и компиляция программы Среда AVR Studio позволяет не только загружать для имитации исполняемый код, созданный другими компиляторами, но и разрабатывать и компилировать про- граммы на ассемблере и С с помощью внутренних средств. Для этого необходимо нажать кнопку New Project в окне приветствия (см. рис. 4.1) или выбрать команду меню Project ► New Project непосредственно в интегрированной среде, чтобы создать
154 Глава 4. Среда разработки AVR Studio новый проект AVR Studio. В результате откроется диалоговое окно, показанное на рис. 4.12. Рис. 4.11. Диалоговое окно Simulator Options Рис. 4.12. Создание нового проекта AVR Studio Здесь в списке Project type (Тип проекта) необходимо выбрать С-компилятор AVR GCC, указать имя проекта в поле Project Name, имя главного файла .с — в по- ле Initial file, и, если требуется, — нажать кнопку справа от поля Location (Размеще- ние) и выбрать папку, в которой будут сохранены файлы проекта. Затем следует нажать кнопку Next, чтобы перейти к следующему окну мастера создания проекта, выбрать отладочную платформу и тип микроконтроллера (см. рис. 4.2) и нажать кнопку Finish. В результате в окне AVR Studio откроется панель AVR GCC, отображающая структуру проекта, и текстовый редактор, в котором мож- но ввести код программы (рис. 4.13). В проект AVR Studio можно также добавлять любые существующие файлы с исходным программным кодом. Для этого необходимо щелкнуть правой кнопкой мыши на элементе Source Files в панели AVR GCC и выбрать в контекстном меню команду Add Existing Source File(s) (рис. 4.14).
Создание проекта и компиляция программы 155 Рис. 4.13. Создание программы на С непосредственно в среде AVR-Studio Б v Hello (default)* Source :[gj Hell I Qj Header Ext erne Other F Add Existing Source File(s).,. Create New Source File Show File Paths Edit Configuration Options, Рис. 4.14. Добавление в проект уже существующих файлов с исходным программным кодом Например, в ветке Source Files можно выделить созданный по умолчанию пус- той файл . с, нажать клавишу <Delete>, чтобы удалить его, а затем добавить в про- ект уже знакомую нам программу SOS. с. Для того чтобы открыть текст программы в окне редактора, необходимо дважды щелкнуть мышью на соответствующем име- ни файла в панели AVR GCC. Если в контекстном меню, показанном на рис. 4.14 выбрать команду Edit Confi- guration Options, то откроется диалоговое окно с параметрами проекта (рис. 4.15). Его можно также открыть, выбрать команду меню Project ► Configuration Options или нажав кнопку Edit Current Configuration Options панели инструментов AVRGCC- PLUGIN. Основные параметры проекта находятся в разделе General. Здесь можно задать имя проектного файла .elf (поле Output File Name), указать папку для сохранения файлов (поле Output File Directory), выбрать тип микроконтроллера (раскрывающий- ся список Device) и задать частоту процессора в герцах (поле Frequency). В раскрывающемся списке Optimization можно задать уровень автоматической оптимизации программного кода: • -ОО — оптимизация не выполняется;
156 Глава 4. Среда разработки AVR Studio • -01 — уменьшение размера кода и времени выполнения без выполнения опти- мизации, что значительно увеличивает время компиляции; • -02 — средний уровень оптимизации; • -03 — уровень -02 плюс анализ имен регистров и подставляемых функций; • -Оз — оптимизация по размеру кода (рекомендованное значение). Рис. 4.15. Окно настройки параметров проекта Наконец, с помощью флажков, расположенных вдоль нижнего края раздела General, можно указать, какие файлы должны создаваться в результате компиляции. По умолчанию выбрано создание только файлов . hex. Еще один раздел окна Project Options, который имеет смысл рассмотреть, — это Custom Options (рис. 4.16). Здесь можно настроить параметры компиляции и компо- новки исходных файлов, а также указать внешний компилятор. Флажку Use WinAVR соответствует подключение рассмотренного в предыдущей главе компилятора Win- AVR и входящего в его состав средства обработки файлов makefile (программа make. ехе). Компиляция проекта После ввода или загрузки исходного кода программы, проект можно откомпи- лировать. Для этого можно выбрать команду меню Build ► Build, нажать клавишу <F7> или воспользоваться кнопкой Build Active Configuration панели инстру- Г^~| ментов AVRGCCPLUGIN. Если проект был откомпилирован успешно, то в конце Un отчета в окне Build в нижней части среды AVR Studio появится надпись “Build suc- ceeded”, а в папке, указанной в поле Output File Directory диалогового окна Project Op- tions (см. рис. 4.15) появятся файлы Makefile, . elf, . О и, возможно, — . hex, .map и .Iss (если были установлены соответствующие флажки в разделе General окна параметров проекта). Если в исходном коде программы были найдены ошибки, то в окне Build поя- вится сообщение “Build failed...”, и отобразится перечень ошибок, обозначенных красной окружностью. Двойной щелчок мышью на одной из ошибок установит кур- сор в соответствующей строке исходного кода (рис: 4.17).
Создание проекта и компиляция программы 157 Рис. 4.16. Параметры компиляции Б! *§Hello(default) Й Зойке Files _delay_ms( 1000); //Длинная задержка Pause(500); //Пауза с погасшими светодиодами Header Files IS External Dependencies Й <1 Other Files int main (void) DDD - OxFF, while(1) '/ Настройка порта D для вывода //Бесконечный цикл } } РО; DO; РО; ... . Pause(SOOO). Р(); D(); РО; Р(); DO; РО; 0^ E:\Work\Books\MKPress\CforMC2\CD\Projects\WinAVR\SOS\SOS.c \ 4 P Ш_____________________________ , ........ ................. ../Vark/Books/MKPress/CforMC2/CB/Projects/l?inAVR/S0S/50S. с: 26: error: ’DDB’ undeclared Цfirst us<jJ ../Work/Books/MKPress/CforHC2/CD/Projects/UinAVR/S0S/S0S.c:26: error: (Each undeclared identifiei ../../Work/Books/MKPress/CforMC2/CD/Projects/WinAVR/S0S/S0S.c:26: error: for each function it appeax make: *«* [SOS.o] Error 1 Build failed with 3 errors and 1 warnings... Ш Build [O Message \ Find in Flies ; ^Breakpoints and Tracepcints Рис. 4.17. В тексте программы была найдена ошибка После того как программа откомпилирована, ее можно отладить. Для этого не- обходимо перейти в соответствующий режим работы AVR Studio, выбрав команду меню Debug ► Start Debugging, нажав комбинацию клавиш <Ctrl+Shift+ Alt+5> ГТ-] или воспользовавшись кнопкой Start Debugging панели инструментов Debug. bfei Использование средств эмуляции и отладки уже было рассмотрено в начале этой главы. Преимущество работы с проектом, созданным непосредственно в AVR Studio, заключается в том, что ход выполнения программы можно отслеживать по коду С, а не по листингу дизассемблера, что гораздо удобнее. Для выхода из режима отладки следует выбрать команду меню Debug ► Stop Debugging, нажать комбинацию клавиш <Ctrl+Shift+F5> или воспользоваться Г”] кнопкой Stop Debugging панели инструментов Debug. IflU
Глава 5 Среда разработки CodeVisionAVR CodeVisionAVR — это еще одна популярная интегрированная среда разработки, компиляции и отладки программ для микроконтроллеров AVR, созданная компани- ей HP InfoTech. В ее состав также входит мастер создания программ CodeWizar- dAVR и встроенный терминал для тестирования систем, использующих последова- тельный обмен данными. В качестве отладчика в CodeVisionAVR служит рассмот- ренный в предыдущей главе AVR Studio от Atmel. еВ этой книге рассматривается оценочная версия CodeVisionAVR 1.25.7, установочный файл ко- торой находится на прилагаемом к книге компакт-диске в папке Software\AVR\ CodeV i s i onAVR. Для открытия среды разработки можно воспользоваться ярлыком CodeVision- AVR С Compiler, размещенным при установке пакета на Рабочем столе Windows, или же соответствующей командой меню Пуск ► Все программы ► CodeVisionAVR. Окно CodeVisionAVR при первом запуске имеет вид, показанный на рис. 5.1 Рис. 5.1. Окно CodeVisionAVR при первом запуске Для создания нового проекта необходимо выбрать ко- манду меню File ► New или нажать кнопку Create new file па- нели инструментов. В результате откроется диалоговое is| окно Create New File (рис. 5.2). МмИ Созданию проекта в этом окне соответствует переклю- чатель Project. Если его выбрать и нажать кнопку ОК, то поя- вится запрос на использование мастера CodeWizardAVR. Он будет рассмотрен позже, поэтому для начала можно создать Рис. 5.2. Диалоговое окно Create New File проект вручную, нажав в окне запроса кнопку No (Нет). В результате CodeVision-
Компиляция и построение проекта 159 AVR предложит указать имя и папку размещения файла проекта .prj. Когда про- ектный файл будет определен, отроется диалоговое окно Configure Project (Конфи- гурировать проект) (рис. 5.3). Рис. 5.3. Диалоговое окно Configure Project При создании нового проекта это окно на вкладке Files (Файл) будет содержать единственную ссылку на файл . prj. Для того чтобы добавить в проект файл с ис- ходным кодом . с, необходимо нажать кнопку Add. В качестве примера воспользу- емся файлом SOS. с, рассмотренным в главе 3. Скопируйте его в одну папку с но- вым проектным файлом SOS .prj, и добавьте в проект с помощью Цнопки Add диа- логового окна Configure Project. В результате у элемента, соответствующего проекту, на вкладке Files появится подчиненная ссылка, и будут активизированы кнопки Remove для удаления и Edit File Name для редактирования имени файла (рис. 5.4). Рис. 5.4. В проект добавлен файл с исходным кодом Компиляция и построение проекта Параметры компиляции проекта можно настроить непосредственно в процессе его создания на вкладке С Compiler диалогового'окна Configure Project (рис. 5.5).
160 Глава 5. Среда разработки CodeVisionAVR Рис. 5.5. Вкладка С Compiler диалогового окна Configure Project Эта вкладка содержит четыре вложенных вкладки: • Code Generation — собственно, параметры компиляции; • Messages — набор предупреждающих сообщений, которые могут выдаваться в ходе компиляции; • Globally #define — определение макроса #def ine, видимого во всех файлах про- екта (макросы рассматриваются в главе 16); • Paths — списки дополнительных путей к включаемым и библиотечным файлам. Рассмотрим подробнее некоторые параметры, настраиваемые на вкладке Code Generation: . • Chip — тип микроконтроллера; • Clock — тактовая частота процессора; • Memory Model — модель памяти; перечень элементов в этом списке зависит от выбранного типа микроконтроллера: ► Tiny — доступны только первые 256 байт памяти SRAM, а для хранения мас- сивов констант и строк доступны 64 Кбайт Flash-памяти; ► Small — доступны 64 Кбайт памяти SRAM, а для хранения массивов констант и строк доступны 64 Кбайт Flash-памяти; ► Medium (только для микроконтроллеров с не менее чем 128 Кбайт памяти программ) — модель, аналогичная Small, за тем исключением, что указатели на константы 32-разрядные, а указатели на функции — 16-разрядные, что достаточно для адресации 128 Кбайт Flash-памяти; ► Large (только для микроконтроллеров с не менее чем 256 Кбайт памяти про- грамм) — все указатели — 32-разрядные, что позволяет адресовать 256 Кбайт Flash-памяти;
Компиляция и построение проекта 161 • Optimize for — способ оптимизации исполняемого кода: по размеру (Size) или по скорости работы (Speed); • Optimization Level — уровень оптимизации; • Program Type — тип программы: приложение (Application) или загрузчик (Boot Loader); • Data Stack Size — размер стека данных; • Heap Size — размер “кучи” (области памяти, используемой для динамического размещения функций); • Internal SRAM size — объем внутренней памяти SRAM; • External SRAM size — объем внешней памяти SRAM; • File Output Formats — форматы файлов, создаваемых в папке проекта в результа- те компиляции. После настройки параметров компиляции в окне Configure Project можно нажать кнопку ОК, чтобы загрузить проектные файлы в рабочую область CodeVisionAVR (рис. 5.6). Рис. 5.6. Новый проект в рабочей области CodeVisionAVR Для открытия диалогового окна Configure Project после создания проекта можно воспользоваться командой меню Project ► Configure или кнопкой Configure the project панели инструментов.- ПРИМЕЧАНИЕ Обратите внимание на окно Notes, включенное в состав проекта. Оно позволяет создавать текстовые комментарии, которые после выбора команды меню File ► Save АП сохраняются в
162 Глава 5. Среда разработки CodeVisionAVR проектной папке в файле .txt. Для переключения между окном комментариев и редактором исходного кода необходимо щелкнуть мышью на соответствующем элементе в окне Navigator. Теперь можно попробовать откомпилировать проект. Для этого выберите ко- манду меню Project ► Compile, нажмите клавишу <F9> или воспользуйтесь кнопкой Compile the project панели инструментов. В результате откроется окно с информаци- ей о параметрах и результатах компиляции (рис. 5.7). Рис. 5.7. Диалоговое окно с информацией о параметрах и результатах компиляции Поскольку мы воспользовались исходным кодом, рассчитанным на компилятор WinAVR, то вполне логично, что он не будет откомпилирован в CodeVisionAVR без ошибок. Так, в окне Information показано, что в 34 обработанных строках было най- дено шесть ошибок. Их перечень с указанием соответствующих номеров программ- ных строк можно увидеть в окнах Navigator и Messages в рабочей области CodeVisi- onAVR (рис. 5.8). Для того чтобы перейти к строке с ошибкой можно щелкнуть мышью на соот- ветствующем элементе в ветке Errors окна Navigator или дважды щелкнуть на инте- ресующем элементе в окне Messages. В результате в окне редактора будет выделена ошибочная строка. Среда CodeVisionAVR позволяет выполнить поиск синтаксических ошибок в тексте файла, от- крытого в данный момент в окне редактора, еще до компиляции. Для этого следует выбрать команду меню Project ► Check Syntax или нажать кнопку Check Syntax for the currently edited file. Исправим ошибки. Во-первых, для компилятора CodeVisionAVR заголовочный файл io. h можно явно не включать. Вместо него следует указать файл . h, соответ-
Компиляция и построение проекта 163 ствующий выбранной модели микроконтроллера. Например, для ATmega 169 он на- зывается Меда 169.h. Все стандартные включаемые файлы компилятора CodeVisi- onAVR находятся в папке \<nanKa_CodeVisionAVR>\inc, которая определяется автоматически. Здесь же находится и файл delay.h, реализующий функции за- держки. Таким образом, вместо #include <util/delay.h> в данном примере не- обходимо указать просто #include <delay. h>. Рис. 5.8. Отображение ошибок, найденных в исходном тексте программы Вызов функций задержки для компилятора CodeVisionAVR практически анало- гичен вызовам для WinAVR за тем исключением, что не нужно указывать первого символа подчеркивания Таким образом, результирующий код программы SOS. с для CodeVisionAVR представлен в листинге 5.1. еЭту программу можно также найти на прилагаемом к книге компакт-диске в папке Pro j ects \ CodeVi s ionAVR\SOS. После успешной компиляции проекта в одной папке с файлом . prj будет соз- дан результирующий ассемблерный код . asm. Листинг5.1. Файл SOS.с для компилятора CodeVisionAVR #include <Megal69.h> linclude <delay.h> void Pause(int ms) { PORTD = OxFF; //Все светодиоды отключены
164 Глава 5. Среда разработки CodeVisionAVR Листинг 5.1. Окончание delay ms(ms); } //Задержка void P(void) { PORTD = 0; delay_ms(500); //Включаем все светодиоды //Короткая задержка Pause(500); } //Пауза с погасшими светодиодами void D(void) { PORTD = 0; delay_ms(1000); //Включаем все светодиоды //Длинная задержка Pause(500); } //Пауза с погасшими светодиодами int main (vo^Ld) { * DDRD = OxFF; // Настройка порта D для вывода while(1) //Бесконечный цикл { Р(); Р(); Р(); //. . . DO; D(); D(); РО; Р(); Р(); Pause(10000); // //. . . } Для того чтобы, кроме ассемблерного кода, получить файлы, заданные пара- метром компилятора File Output Formats (см. рис. 5.5) (т.е. .cof, .obj, .hex и т.д.) необходимо выполнить построение проекта. Этому процессу соответствует команда меню Project ► Make, комбинация клавиш <Shift+F9> и кнопка Make the project lj$g| панели инструментов. Создание проекта с помощью мастера CodeWizardAVR Если в диалоговом окне Create New File (см. рис. 5.2) выбрать переключатель Project, и затем в следующем окне с запросом выбрать Yes (Да), то будет запущен мастер создания проектов CodeWizardAVR (рис. 5.9). Его можно также запустить без использования окна Create New File. Для этого следует выбрать команду меню Tools ► CodeWizardAVR, нажать комбинацию клавиш <Shift+F2> или восполь- ПЕ1 зоваться кнопкой Run the CodeWizardAVR панели инструментов. ШВ Мастер CodeWizardAVR позволяет автоматически создать программный код для инициализации процессора, портов ввода-вывода, основных периферийных мо- дулей и ЖК-модуля. На любом этапе результирующий код можно предварительно посмотреть, выбрав в окне CodeWizardAVR команду меню File ► Program Preview (рис. 5.10).
Создание проекта с помощью мастера CodeWizardAVR 165 Рис. 5.9. Мастер CodeWizardAVR Рис. 5.10. Предварительный просмотр результирующего кода Для фактического создания файла . с следует выбрать команду меню File ► Ge- nerate, Save and Exit. Рассмотрим вкладки мастера CodeWizardAVR (их содержимое может разли- чаться в зависимости от выбранной модели микроконтроллера). Вкладка Chip (Кри- сталл) (см. рис. 5.9) определяет тип устройства, тактовую частоту процессора и вид программы: приложение или загрузчик. Если установить флажок Check Reset Source, то в программу будет добавлен код, позволяющий идентифицировать условия, вы- звавшие сброс микроконтроллера. Вкладка Chip может также содержать флажок Crystal Oscillator Divider Enabled, установка которого ак- тивизирует делитель частоты осциллятора. В этом слу- чае коэффициент деления указывают в поле Crystal Oscillator Divider. Вкладка External SRAM (на рис. 5.10 не показана) позволяет выбрать объем и параметры внешней памяти SRAM (для тех микроконтроллеров AVR, которые поддерживают подключение такой памяти). Вкладка Ports (рис. 5.11) определяет конфигура- цию портов ввода-вывода. Щелкая мышью на кнопках в столбце Data Direction, можно определить направле- ние передачи данных для соответствующих выводов порта: In — ввод; Out — вывод. Если вывод сконфигу- рирован как вход, то с помощью расположенной спра- ва, в столбце Pullup/Output Value кнопки его можно пе- ревести в третье состояние (Т) или активизировать внутренний подтягивающий резистор, подключенный к полюсу источника питания (Р). Если вывод сконфи- гурирован как вход, то его состояние можно сразу же установить в 0 или 1. Вкладка Bit-Banged (рис. 5.12) позволяет выбрать порт для подключения микросхемы часов реального Fde Hdp External IRQ j Timers | USARTO | USART1 Analog Comparator ] ADC j SPI | I2C IWie i 2Wue(!2C) ] LCD Bit-Banged | Pro|ect Inloimation Chip | External SRAM Purls В | Port £ | Port D | Pe l l > Dola Direction Pullup/Output Value B«0 .In Tj 8<i0 8П In T Bill B»2 In I BH2 £*3 In т B4 3 ♦ BMJnJ J.’BrU Bit 5 In I Bit 5 BitGJnJ jj'BitB EH 7 In I Bit 7 Рис. 5.11. Вкладка Ports мастера CodeWizardAVR
166 Глава 5. Среда разработки CodeVisionAVR времени DS1302 и определить, какие разряды порта будут использоваться для вво- да-вывода, для сигнала тактирования и сигнала сброса. Для активизации зарядки DS1302 малым током необходимо установить флажок Trickle Charge. Вкладка Project Information позволяет определить текстовую информацию, кото- рая будет помещена в заголовке комментариев в “шапке” результирующего файла . с: название, версия, дата, автор, организация, примечания. Вкладка 1 Wire (рис. 5.13) конфигурирует однопроводной интерфейс: • 1 Wire Port — порт, используемый для реализации линии передачи данных; • Data Bit — разряд порта, которому соответствует линия передачи данных; • если используются датчики температуры DS1820 или DS 18S20, то следует ус- тановить флажок Enabled; • если к шине подключено несколько датчиков, то необходимо установить фла- жок Multiple Devices. Вкладка 2 Wire (I2C) (рис. 5.14) позволяет настроить параметры двухпроводного интерфейса TWI (12С): • 2 Wire Enabled — акгивизация/отключение интерфейса; • Generate Acknowledge Pulse — формирование импульса квитирования; • Slave Address — адрес ведомого устройства (в шестнадцатеричном виде); • General Call Recognition — установка этого флажка соответствует активизации опознавания общего вызова, переданного по шине TWI; • Bit Rate — максимальная частота следования импульсов в линии SCL; • 2 Wire Interrupt — если установить этот флажок, то интерфейс TW1 будет фор- мировать запросы на прерывание. Рис. 5.12. Вкладка Bit-Banged Рис. 5.13. Вкладка 1 Wire Рис. 5.14. Вкладка 2 Wire (I2C) Вкладка External IRQ (рис. 5.15) конфигурирует внешние прерывания. Установка одного из флажков INTx Enabled разрешает соответствующее прерывание. Список
Создание проекта с помощью мастера CodeWizardAVR 167 Mode позволяет выбрать режим формирования запроса на прерывание: по низкому уровню сигнала на входе (Low level), по ниспадающему (Falling Edge) или по нарас- тающему (Rising Edge) фронту. Для каждого разрешенного прерывания по сигналу на входе мастер создаст пустую подпрограмму обработки прерывания. Вкладка Timers позволяет сконфигурировать таймеры/счетчики. Она содержит несколько вложенных вкладок, количество которых зависит от выбранного микро- контроллера. Набор параметров на каждой такой вкладке также зависит от типа устройства и номера таймера/счетчика (рис. 5.16). Рис. 5.15. Вкладка External IRQ Рис. 5.16. Параметры таймеров/счетчиков 0 и 1 Рассмотрим некоторые из них, общие для различных видов таймера: • Clock Source — источник тактирования; • Clock Value — частота тактирования, которая задается в килогерцах, если пара- метр Clock Source имеет значение System Clock, или определяется путем деления частоты на выбранном входе (если выбрать значение Timer х Stopped, то таймер/ счетчик будет отключен); • Mode — режим работы таймера/счетчика: обычный, ШИМ и т.п.; • Output или Out. X — действие на соответствующем выходе при совпадении со- держимого счетчика со значением, указанным в поле Compare или Comp. X: Dis- connected — выход отключен; Toggle — смена состояния на противоположное; Clear — обнуление; Set — установка в лог. 1; • флажки или списки флажков со словом “Interrupt” соответствуют разрешению или запрету соответствующих прерываний; • Timer Value или Value — исходное значение счетного регистра (в шестнадцате- ричной форме); • Inp. Capture — содержимое регистра захвата на входе. Еще одна вложенная вкладка: Watchdog — определяет параметры инициализа- ции сторожевого таймера (рис. 5.17). Для того чтобы активизировать этот таймер,
168 Глава 5. Среда разработки CodeVisionAVR необходимо установить флажок Watchdog Timer Enabled, а затем выбрать коэффици- ент деления частоты осциллятора с помощью группы переключателей Oscillator Prescaler. Если выбранный микроконтроллер предусматривает прерывания от сто- рожевого таймера, то вкладка Watchdog также будет содержать флажок Watchdog Timeout Interrupt для разрешения этого прерывания. Вкладки UARTx или USARTx задают конфигурацию приемо-передатчиков UART или USART (рис. 5.18): • установка флажков Receiver или Transmitter активизирует приемник и передат- чик соответственно, а флажков Rx Interrupt или Тх Interrupt разрешает преры- вание по окончании приема или передачи; • Baud Rate — скорость передачи данных в Кбит/с; • Communication Parameters — параметры обмена данными: количество битов данных и стоп-битов, а также наличие проверки на четность; • Mode — режим передачи: синхронный или асинхронный в режиме ведущего/ве- домого устройства. Вкладка LCD (рис. 5.19) позволяет определить параметры подключения ЖК- дисплея: порт и количество символов на строку дисплея. Рис. 5.17. Параметры сторожевого таймера Рис. 5.18. Вкладка USART0 Рис. 5.19. Вкладка LCD Если выбранный микроконтроллер содержит контроллер ЖК-дисплея, то в окне CodeWizardAVR будет вкладка LCD Controller с параметрами конфигурирования этого контроллера (рис. 5.20): • LCD Enabled — активизация/отключение ЖК-контролера; • LCD Low Power Waveform — при установке этого флажка на выводы ЖК-дисплея будет подаваться импульсное напряжение, что уменьшит его энергопотребле- ние;
Создание проекта с помощью мастера CodeWizardAVR 169 • LCD Frame Complete interrupt — установке этого флажка соответствует разреше- ние прерывания по заполнению кадра; • Duty Cycle — рабочий цикл: статический, 1/2,1/3 или 1/4; • Bias — смещение для нестатического рабочего цикла; • Clock Source — источник тактового сигнала: системный или внешний; • Frame Rate — частота обновления кадра в герцах; • Used Segments — вывод, используемый для управления сегментом ЖК-дисплея; • Contrast Control — напряжение между выводом управления сегментом ЖК-дис- плея и общим выводом. Оно определяет контрастность дисплея. Следующая вкладка, которая может присутствовать не для всех микроконтрол- леров AVR, — это SPI (рис. 5.21). Как следует из ее названия, она служит для кон- фигурирования последовательного интерфейса SPI: режим передачи (SPI Mode), по- зицию фронта строба SCK относительно бита данных (Clock Phase), полярность так- товых импульсов (Clock Polarity), частоту тактирования интерфейса (SPI Clock Rate), работу в режиме ведомого или ведущего устройства (SPI Туре) и порядок передачи данных: с младшего или старшего разряда (Data Order). Рис. 5.20. Вкладка LCD Controller Рис. 5.21. Вкладка.SPI Установке флажка SPI Interrupt соответствует разрешение прерывания от интер- фейса SPI, а флажка Clock Rate х2 — удвоение частоты тактирования. Для конфигурирования интерфейс^ 12С служит вкладка I2C (рис. 5.22). Здесь, выбрав в раскрывающемся списке I2C Port порт для реализации шины 12С, можно выбрать разряды этого порта, соответствующие линиям SDA и SCL. Ниже располо- жен набор вложенных вкладок, позволяющих активизировать (установка флажка Enabled) и сконфигурировать различные устройства, подключенные к интерфейсу 12С: датчик температуры LM75, термостат DS1621, часы реального времени PCF- 8563, PCF8583 или DS1307.
170 Глава 5. Среда разработки CodeVisionAVR Если выбранный микроконтроллер оснащен универсальным последовательным интерфейсом US.I, то окно CodeWizardAVR будет содержать соответствующую вкладку (рис. 5.23). й CodeWizardAVR - unMledxt Ede adp Bit-Banged | Pi eject Information | Chip j Ports j External IRQ | Timers I ICO Controller USI | USART | Analog Comparator j AOC SPI I2C j tWire | LCD I2C Port J PORTA 3 « SDA Bit [o " 3 SCI Bit |7“2 Рис. 5.23. Вкладка USI Рис. 5.22. Вкладка I2C Если в раскрывающемся списке Mode выбран элемент Disabled, то интерфейс USI отключен. В противном случае он определяет режим работы интерфейса: SPI по трем линиям или 12С по двум линиям. Параметр Clock определяет источник такти- рования для сдвигового регистра и счетчика USI, а установка флажков USI Counter Overflow Interrupt и USI Start Condition Interrupt разрешает прерывания по переполне- нию счетчика и возникновению условия начала передачи соответственно. Следующие две вкладки мастера CodeWizardAVR, которые имеет смысл затро- нуть, — это Analog Comparator (Аналоговый компаратор) (рис. 5.24) и ADC (АЦП) (рис. 5.25). Вкладка Analog Comparator содержит набор флажков, определяющих режим ра- боты устройства: • Bandgap Voltage Reference — подача внутреннего опорного напряжения на по- ложительный вход компаратора; • Negative Input Multiplexer — подключение аналогового мультиплексора АЦП к отрицательному входу компаратора; • Analog Comparator Input Capture — управление функцией захвата таймера/счет- чика 1 сигналом с выхода компаратора; • Analog Comparator Interrupt—разрешение прерывания от аналогового компара- тора (тип прерывания выбирают с помощью расположенной ниже группы пере- ключателей); • Disable Digital Input Buffer on AINx — запрет входа цифрового буфера на выводе AINx. Что касается вкладки ADC, то ее содержимое может различаться в зависимости от возможностей АЦП выбранного микроконтроллера.
Создание проекта с помощью мастера CodeWizardAVR 171 С CodeWizardAVR ~ urrttUedxwp FSe Help I2C | IWire | 2WM2CJ LCD | В it-Banged j Project Information Chip I Ports | External IRQ | Timers USART Analog Comparator |aDC j SPI (7 Analog Comparator Enabled Г Bandgap Voltage Reference Г Negative Input Multiplexer Г Analog Comparator Input Capture P Analog Coniparatw Irtetrup^ Analog Comparator Interrupt Mode \ f* Interrupt on Output loggia j : C interrupt on Failing Output Edge i C Interrupt on firing Output Edge < Г DisoUe DigUal Input Buller on AINQ Г Disable Digital Input Buller on AIN1 Рис. 5.24. Вкладка Analog Comparator Рис. 5.25. Два варианта вкладки ADC Рассмотрим только некоторые общие параметры: • Interrupt — разрешение прерывания по завершению преобразования; • Use 8 bite — использование только восьми младших разрядов результата преоб- разования; • Volt Ref — источник опорного напряжения; • Clock — частота тактирования АЦП; • Auto Trigger Source — источник автоматического запуска (аналоговый компара- тор, внешний запрос на прерывание и т.п.); • Disable Digital Input Buffers — запрет цифровых входов буферов, используемых АЦП. Окно CodeWizardAVR может содержать и другие вкладки, не рассмотренные выше (например, Voltage Reference с параметрами коррекции опорного напряжения), однако такие случаи довольно редки, поэтому мы их рассматривать здесь не будем. Сохранение и открытие проекта CodeWizardAVR Конфигурацию микроконтроллера, выполненную в окне CodeWizardAVR, можно сохранить для повторного использования. Для этого необходимо выбрать команду меню File ► Save или File ► Save as (для сохранения копии проекта под другим име- нем). Проект CodeWizardAVR сохраняет в файле с расширением .cwp, который представляет собой обычный текстовый документ с перечнем установок микрокон- троллера, который можно отредактировать в любом редакторе, наподобие Блокнота. ПРИМЕЧАНИЕ Мастер CodeWizardAVR также предлагает сохранить свой проект в момент генерирования ис- ходного кода программы и файла . prj по команде меню File ► Generate, Save and Exit.
172 Глава 5. Среда разработки CodeVisionAVR Сохраненный файл . cwp можно загрузить в окне CodeWizardAVR, выбрав ко- манду меню File ► Open. Создание новых файлов с исходным кодом Если после создания проекта файл . с должен быть не добавлен извне, а создан непосредственно в среде CodeVisionAVR, то -для этого необходимо выбрать коман- ду меню File ► New (или нажать соответствующую кнопку панели инструментов) и выбрать в диалоговом окне Create New File (см. рис. 5.2) переключатель Source. В результате после, нажатий кнопки ОК в проект будет добавлен пустой документ с именем по умолчанию untitled, с. При вводе кода программы различные конструкции языка С будут выделяться разными цветами и с помощью разных параметров шрифта. Эти и другие настройки редактора можно изменить в диалоговом окне Editor Settings (рис. 5.26), которое от- крывается по команде меню Settings ► Editor. Рис. 5.26. Диалоговое окно Editor Settings В частности, здесь можно задать размер отступа, создаваемого по нажатию кла- виши <ТаЬ>: параметр Tab Size. Например, для автора отступ в восемь символов ка- жется несколько завышенным. Удобнее использовать табуляторы по 3-4 символа. Кроме того, если читателю надоел стандартный для систем программирования шрифт Courier, то он может сменить его, нажав кнопку Font. Одно из очень удобных средств редактора CodeVisionAVR — набор шаблонов программных конструкций, реализующих ветвление и циклы. Он находится на вкладке Code Templates (по умолчанию расположена слева от окна редактора). Кро- ме всего прочего, набор шаблонов содержит заготовку для создания главной функ- ции программы: main (подробнее об этом — в главе 16). Для размещения той или иной конструкции в исходном коде ее необходимо перетащить мышью из вкладки Code Templates в окно редактора (рис. 5.27). ПРИМЕЧАНИЕ Обратите внимание на синюю полоску вдоль левого края программной конструкции. Она оп- ределяет длину данной конструкции. Если щелкнуть мышью на маленькой пиктограмме
Отладка программы 173 в виде знака расположенной на этой полосе, то конструкция будет свернута до одной первой строки. Для того чтобы развернуть ее, следует щелкнуть на пиктограмме Подоб- ное свертывание бывает удобным при анализе больших программ. Рис. 5.27. Размещение шаблона в коде программы: вверху — процесс; внизу — результат Отладка программы Для отладки программ в среде CodeVi- sionAVR по умолчанию предоставлен доступ к внешнему отладчику AVR Studio (см. пре- дыдущую главу) и встроенному терминалу. В первом случае пакет AVR Studio должен быть уже установлен в системе, а путь к не- му и версия — указаны в диалоговом окне Debugger Settings (рис. 5.28), которое откры- Рис. 5.28. Диалоговое окно Debugger Settings вается по команде меню Settings ► Debugger. Кроме того, для работы с внешним отладчиком проект необходимо построить с пра- вильной настройкой результирующих файлов. Для AVR Studio требуется формат . cof, поэтому обратите внимание на значение параметра File Output Formats на вкладке С Compiler диалогового окна Configure Project (см. рис. 5.5). Для вызова отладчика следует выбрать команду меню Tools ► Debugger, нажать комбинацию клавиш <Shift+F3> или воспользоваться кнопкой Run the debug- ger панели инструментов. В результате будет открыта среда AVR Studio и I2J появится окно приветствия (см. рис. 4.1). В нем необходимо нажать кнопку Open, выбрать интересующий файл . cof, задать имя проекта . aps, выбрать отладочную платформу (например, AVR Simulator) и тип микроконтроллера и нажать кнопку Finish (Готово). При этом AVR Studio может добавить некоторые дополнительные определения в текст программы. В таком случае в одной папке с исходным файлом . с будет создана копия с тем же именем, но с добавлением двух символов подчер- кивания, и в рабочую область AVR Studio загружена будет именно она. Методы отладки с помощью AVR Studio уже были рассмотрены в предыдущей главе, поэтому останавливаться на них мы не будем.
174 Глава 5. Среда разработки CodeVisionAVR Использование терминала Встроенный в CodeVisionAVR терминал служит для отладки систем, исполь- зующих последовательный обмен данными по протоколам RS232, RS422 и RS485. Его параметры настраивают в диалоговом окне Terminal Settings (рис. 5.29), которое открывают по команде меню Settings ► Terminal. Рис. 5.29. Диалоговое окно Terminal Settings Термина^ активизируют с помощью команды меню Tools ► Terminal, ком- бинации клавиш <Shift+F5> или кнопки Run the terminal панели инструментов. Isu Окно терминала содержит поле для отображения текста, передаваемого по по- следовательному интерфейсу, и типичный набор кнопок: Disconnect (Разъединить); Send (Передать) для передачи некоторого шестнадцатеричного кода, предваритель- но введенного в поле Hex Code; Rx File (Принять в файл) для сохранения полученных символов в файле; Тх File (Передать из файла); Hex для отображения символов в ви- де соответствующих им шестнадцатеричных кодов (для возврата в обычный режим необходимо нажать кнопку ASCII); Clear для очистка окна терминала и Reset Chip для сброса микроконтроллера, установленного на отладочной плате. После нажатия кнопки Disconnect все перечисленные кнопки исчезнут, и вместо них появится единственная кнопка Connect (Соединить).
Г ЛАВА 6 Программаторы для микроконтроллеров AVR Эмуляция эмуляцией, но любая программа, предназначенная для использования в микроконтроллерах, конечно же, должна быть каким-то образом записана в память программ целевого устройства. Какое бы средство программирования для этого ни использовалось, процесс всегда выглядит одинаково. 1. Подсоединить микроконтроллер к специальному адаптеру, который в свою оче- редь соединен с компьютером. 2. Перевести микроконтроллер в режим программирования. 3. Записать данные в память (Flash или EEPROM) с помощью специальных про- граммный средств. 4. Вывести микроконтроллер из режима программирования. Программаторы могут использоваться самые разнообразные. Обобщенно их можно разбить на три категории: • с параллельным интерфейсом; • с последовательным интерфейсом; • с интерфейсом USB. Один из вариантов адаптеров, совместимый с платами STK.200/300/500, для программирования микроконтроллеров AVR по параллельному интерфейсу пред- ставлен на рис. 6.1. Его принципиальная схема показана на рис. 6.2, а монтажная схема и разводка платы — на рис. 6.3. Рис. 6.1. Адаптер для программирования микроконтроллеров AVR по параллельному интерфейсу В схеме задействованы следующие компоненты: • ST1 — D-Sub штекер на 25 контактных выводов; • JP1 — разъем для подключения к печатной плате 2x5; • IC1 — микросхема SN74HC244;
176 Глава 6. Программаторы для микроконтроллеров AVR • D1 — диод Шотки ВАТ43 или ВАТ46; • R1 — резистор 100 кОм; • С1 — керамический конденсатор на 100 нФ. Рис. 6.2. Схема для программирования микроконтроллеров AVR по параллельному интерфейсу Рис. 6.3. Монтажная схема и разводка платы для адаптера Отладочные платы, наподобие STK500, подключаются к ПК по последователь- ному интерфейсу, а значит, разработчику доступно и последовательное программи- рование. Такой подход обрел широкую популярность и поддерживается, в том чис- ле, и средой AVR Studio. При последовательном программировании обычно используется интерфейс SPI. При этом программатор работает в режиме ведущего, а подлежащий программиро-
Отладка программы 177 ванию микроконтроллер — ведомого устройства. Последовательный интерфейс со- стоит из линий SCK, MOST (вход) и MISO (выход). По нарастающему фронту им- пульсов в линии SCK биты данных записываются в подлежащий программирова- нию микроконтроллер, а по ниспадающему фронту — считываются (рис. 6.4). Тактовый цикл | 1 | 2|3|4|5| 6| 7| 8| Рис. 6.4. Временная диаграмма передачи данных в режиме последовательного программирования Последовательное программирование доступно также и в микроконтроллерах AVR, в которых отсутствует интерфейс SPI. Для этого служит схема, показанная в обобщенном виде на рис. 6.5. Номиналы конденсаторов могут от- личаться в зависимости от типа програм- матора и микроконтроллера. Например, для модели AT90S2313 он в одном случае составляет 22 пФ, а в другом — 27 пФ. В качестве альтернативы схеме, пока- занной на рис. 6.5, на вход XTAL1 может быть подан внешний тактовый сигнал. Рис. 6.5. Монтаж микроконтроллера AVR для последовательного программирования Вход XTAL2 в этом случае остается от- крытым. В заключение скажем также несколько слов об адаптерах, рассчитанных на ра- боту с интерфейсом USB. В качестве примера можно рассмотреть программатор USBProg, информацию о котором (на немецком языке) можно найти на сайте www.embeddeci-projects.net (рис. 6.6). Рис. 6.6. USB-программатор USBProg Пример схемы его соединения с микроконтроллером AVR представлена на рис. 6.7.
178 Глава 6. Программаторы для микроконтроллеров AVR £ 8 I £ «-Ч U Рис. 6.7. Пример соединения адаптера USBProg с микроконтроллером ATmega32-A
Программные средства для программирования микроконтроллеров 179 Программные средства для программирования микроконтроллеров Кроме отладочной платы и/или аппаратного программатора (адаптера), для за- писи программ в память микроконтроллера требуется также специальное про- граммное обеспечение. В большинстве случаев оно совместимо с популярными средствами эмуляции и отладки, наподобие AVR Studio, что позволяет программи- ровать устройства непосредственно из интегрированной среды разработки. Кроме AVR Studio, можно использовать и другие популярные пакеты, предназначенные для программирования микроконтроллеров, например: PonyProg2000, AVRDUDE, USBProg Flashtool и др. ©Установочные пакеты РопуРгод2000 и USBProg Flashtool находятся на прилагаемом к книге ком- пакт-диске в папке Software\AVR. Основная тема данной книги — применение языка С для разработки встроен- ных приложений, поэтому подробно на процессе программирования мы останавли- ваться не будем. За дополнительной информацией по этому вопросу обращайтесь к специализированным изданиям. Кратко остановимся только на некоторых аспек- тах программирования микроконтроллеров в среде AVR Studio и CodeVisionAVR. Программирование устройства в среде AVR Studio 4 После того как микроконтроллер помещен в гнездо отладочной платы или про- грамматора, соединенного с ПК, и на него подано питание, в среде AVR Studio для настройки соединения следует выбрать команду меню Tools ► Program AVR ► Con- nect или нажать кнопку Display the Connect dialog панели инструментов STK500. В результате откроется диалоговое окно Select AVR Programmer, в котором не- = обходимо выбрать текущий программатор и порт, по которому он подключен к ПК (рис. 6.8). Рис. 6.8. Диалоговое окно Select AVR Programmer Программаторам, использующим интерфейсы USB, здесь в списке Platform по умолчанию соответствуют элементы JTAGICE mkll, AVRISP mkll и AVR Dragon. После того как программатор и порт выбраны, можно нажать кнопку rjjjZ Connect для установки соединения. Если при этом в списке Port был выбран Ьк элемент Auto, то AVR Studio выполнит поиск порта самостоятельно. Этому же дей- ствию соответствует выбор в главном меню команды Tools ► Program AVR ► Auto Connect или нажатие кнопки Connect to the Selected AVR Programmer панели инстру- ментов STK500.
180 Глава 6. Программаторы для микроконтроллеров AVR Если все аппаратные подключения были выполнены правильно, то на экране должно появиться диалоговое окно, соответствующее рис. 6.9. Рис. 6.9. Окно управления процессом программирования Здесь на вкладке Program необходимо выбрать целевое устройство (раскрыва- ющийся список Device), а также указать исполняемые НЕХ-файлы для памяти про- грамм (поле Flash - Input HEX File) и/или памяти EEPROM (поле EEPROM - Input HEX File). Перед программированием для контроля можно очистить память программ и данных микроконтроллера, нажав кнопку Erase Device. Собственно программиро- вание начинается по нажатию соответствующей кнопки Program. Рассмотрим другие элементы вкладки Program: • Programming mode — режимы программирования: ► ISP — внутрисхемное; ► PP/HVSP — высоковольтное параллельное или последовательное; ► JTAG — для программаторов AVR Dragon и JTAGICE mkll. • Erase Device Before Programming — если этот флажок установлен (рекомендует- ся), то память микроконтроллера перед записью будет очищена; • Verify Device After Programming — если этот флажок установлен (рекомендуется), то содержимое памяти микроконтроллера после записи будет проверено на кор- ректность; • Use Current Simulator/Emulator FLASH (EEPROM) Memory — этот переключатель можно выбрать для использования исполнимого кода не из внешнего файла . hex, а из открытого в данный момент проекта AVR Studio; • Verify — кнопка проверки записанных в память Flash или EEPROM данных; • Read — кнопка чтения записанных в память Flash или EEPROM данных. Показанное на рис. 6.9. окно позволяет также программировать разряды предо- хранения и блокировки. Для этого служат вкладки Fuses и LockBits соответственно. Вкладка Advanced служит для чтения из микроконтроллера байтов сигнатуры и ка- либровки осциллятора, а также для записи последнего по заданному пользователем
Программные средства для программирования микроконтроллеров 181 адресу памяти Flash или EEPROM. Вкладка Board позволяет изменить условия работы от- ладочной платы, а вкладка Auto — задать ав- томатически выполняемую последователь- ность операций. Для отладочных плат и программаторов, отличных от STK500/600, процесс програм- мирования может отличаться от описанного выше. Так, для плат myAVR все происходит по команду меню Tools ► AVR Prog. В резуль- тате откроется диалоговое окно, представлен- ное на рис. 6.10. В этом окне следует ввести имя объектного файла в поле Hex file (или най- ти его, нажав кнопку Browse), а затем нажать кнопку Program в разделе Flash или EEPROM. Программирование устройства в среде CodeVisionAVR Рис. 6.10. Окно, используемое при программировании р помощью плат myAVR Для выбора программатора, порта, по которому он подключен к ПК, и, возмож- но, — некоторых других параметров соединения в среде CodeVisionAVR необходи- мо выбрать команду меню Settings ► Programmer и указать соответствующие значе- ния в диалоговом окне Programmer Settings (рис. 6.11). Отметим, что CodeVi- sionAVR поддерживает следующие аппаратные средства: • Atmel STK200/300/500; • Atmel AVRISP Mkll (USB); • Atmel AVR Dragon; • Atmel JTAG-ICE Mkll (USB); • Atmel AVRProg (AVR910); • Dontronics DT006; • Vogel Elektronik VTEC-ISP; • Futurlec JRAVR; • MicroTronics ATCPU/Mega2000. Рис. 6.11. Диалоговое окно Programmer Settings Если используется самодельный программатор (например, показанный на рис. 6.1-6.3), то в диалоговом окне Programmer Settings в раскрывающемся списке AVR Chip Programmer Туре необходимо выбрать элемент Kanda Systems STK200+/300 и указать интересующий параллельный порт. После того как выбран аппаратный программатор, можно начать процесс запи- си исполняемого кода в целевое устройство. Для этого в среде CodeVisionAVR не- обходимо выбрать команду меню Tools ► Chip Programmer, нажать комбинацию кла- виш <Shift+F4> или воспользоваться кнопкой Run the chip programmer панели B| инструментов. Ifli В результате откроется диалоговое окно, показанное на рис. 6.12. Целевое уст- ройство выбирают в раскрывающемся списке Chip. По нажатию кнопки Program АП (Запрограммировать все) автоматически выполняется следующая последователь- ность операций. 1. В микроконтроллере очищается память программ и данных.
Глава 6. Программаторы для микроконтроллеров AVR 2. Выполняется проверка, корректно ли очищена память программ и данных. 3. Программируется и проверяется Flash-память. 4. Программируется и проверяется память EEPROM. 5. Программируются разряды блокировки. 6. Программируются разряды предохранения. Рис. 6.12. Диалоговое окно CodeVisionAVR Chip Programmer Нажатию кнопки Program All также соответствует выбор в окне CodeVisionAVR Chip Programmer команды меню Program ► АН. Другие команды меню Program по- зволяют выполнять перечисленные выше шесть операций по отдельности. Рассмотрим другие элементы диалогового окна CodeVisionAVR Chip Programmer: • Reset Chip — сброс микроконтроллера; • SCK Freq — тактовая частота в килогерцах; • FLASH — в этих полях отображается начальный и конечный адреса занятой об- ласти памяти программ, а также — контрольная сумма; • EEPROM — в этих полях отображается начальный и конечный адреса занятой области памяти EEPROM, а также — контрольная сумма; • FLASH Lock Bits — выбор степени защиты программы: ► No Protection — защита отсутствует; ► Programming disabled — запрещено программирование микроконтроллера; ► Programming and Verification disabled — запрещено программирование и чте- ние памяти микроконтроллера; • Program Fuse Bit(s) — если этот флажок установлен, то команде меню Program ► АН или Program ► Fuse Bits(s) будут запрограммированы разряды предохране- ния, отмеченные флажками в расположенном ниже списке; • Boot Lock Bit х — выбор значения для разрядов блокировки загрузчика;
Программные средства для программирования микроконтроллеров 183 • Check Signature — если этот флажок установлен, то перед любой операцией бу- дут проверяться байты сигнатуры; • Check Erasure — если этот флажок установлен, то после очистки памяти микро- контроллера будет проверено качество выполнения этой операции; • Preserve EEPROM — если этот флажок установлен, то при очистке памяти мик- роконтроллера по команде меню Program ► Erase Chip будет очищена только память программ (Flash); • Verify — если этот флажок установлен, то после программирования микрокон- троллера будет выполнена проверка на корректность записанных данных. Наконец, кратко рассмотрим назначение других пунктов меню диалогового ок- на CodeVisionAVR Chip Programmer: • File — команды, позволяющие загрузить (Load) содержимое файла . rom, . hex или .bin в буфер Flash-памяти или файла . еер, . hex или .bin в буфер памяти EEPROM, а также выполнить обратную операцию, т.е. сохранить (Save) содер- жимое буфера в указанном файле; • Edit — команды для вызова окна, позволяющего просмотреть и отредактировать буфер памяти Flash или EEPROM; • Read — команды для чтения в соответствующий буфер содержимого памяти Flash или EEPROM, а также — просмотра байтов сигнатуры, разрядов блоки- ровки и предохранения, байтов калибровки и версии программного обеспечения программатора; • Compare — команды для сравнения содержимого памяти Flash или EEPROM с соответствующим буфером.
ЧАСТЬ III Архитектура микроконтроллеров PIC
Г ЛАВА 7 Восьмиразрядные микроконтроллеры PIC В настоящее время микроконтроллеры PIC, производимые компанией Microchip Technology Inc., — одни из наиболее популярных в мире. Они основаны на модифи- цированной гарвардской RISC-архитектуре и поставляются в самых разнообразных аппаратных конфигурациях. Отличительной особенностью микроконтроллеров PIC является их совместимость “снизу вверх”, т.е. программы, написанные для более старых моделей, могут легко и во многих случаях — без каких-либо модификаций быть запущены в более новых устройствах. Базовый набор команд микроконтрол- леров PIC содержит всего лишь 33 инструкции, и большинство моделей (за исклю- чением самых современных) использует один и тот же набор команд. Все микроконтроллеры PIC реализуют следующие аппаратные возможности: • цифровые порты ввода-вывода; • встроенный таймер с восьмиразрядным предделителем частоты; • сброс по включению электропитания; • сторожевой таймер; • “спящий” режим, позволяющий экономить электроэнергию; • интерфейс со внешним тактовым генератором; • память данных; • память программ типа EEPROM или Flash. Некоторые модели реализуют следующие дополнительные функции: • аналоговые входные каналы; • аналоговые компараторы; • дополнительные таймеры; • память данных БЕРНОМ; • внешние и внутренние прерывания; • внутренний осциллятор; • выходной сигнал с широтно-импульсной модуляцией (ШИМ); • интерфейс USART для последовательного обмена данными. Некоторые из более сложных микроконтроллеров PIC предлагают следующие дополнительные возможности: • шинный интерфейс CAN; • шинный интерфейс 12С; • шинный интерфейс SPI; • прямой интерфейс с модулем ЖК-дисплея;
186 Глава 7. Восьмиразрядные микроконтроллеры PIC • интерфейс USB; • схема управления электродвигателем. Для начала мы рассмотрим “традиционные” семейства микроконтроллеров PIC, работающие с восьмиразрядным данными. Все они разбиты на три основных под- семейства: • микроконтроллеры с 12-разрядным командным словом (например, PIC 12С5ХХ и PIC 16С5Х); • микроконтроллеры с 14-разрядным командным словом (например, PIC 16F8X); • микроконтроллеры с 16-разрядным командным словом (например, PIC 17С7ХХ иР1С 18С2ХХ). Все три подсемейства используют одну и ту же RISC-архитектуру и одинако- вый набор команд при наличии нескольких дополнительных инструкций в моделях с 14-разрядным и 16-разрядным командным словом. В этой главе мы остановимся подробнее на микроконтроллерах семейств Р1С16 и Р1С12, а в следующей — на более современных устройствах семейства PIC18F. Также, мы не могли обойти вниманием новые разработки компании Microchip: 16- разрядную архитектуру PIC24 и 32-разрядную — PIC32. Изучению их особенностей посвящены главы 9 и 10 соответственно. Общие аспекты архитектуры восьмиразрядных микроконтроллеров РЮ Несмотря на большое разнообразие восьмиразрядных микроконтроллеров PIC, все они обладают некоторыми общими особенностями: наличие памяти программ и памяти данных; портов ввода-вывода, таймеров и т.д. Таким образом, имеет смысл рассмотреть эти аспекты архитектуры, общие для разных подсемейств, чтобы не повторяться в последствии. Организация памяти Память микроконтроллеров PIC состоит из трех основных компонентов: реги- стровый файл; память данных; память программ. Регистровый файл содержит все регистры, доступные в микроконтроллере PIC. Он разделен на две части: регистры специального назначения (SFR — Special Function Registers) и регистры общего назначения (GPR — General Purpose Registers) (рис. 7.1). Так, например, в микроконтроллере PIC16F84 присутствует 68 регистров общего назначения, используемых для хранения временных данных. Регистры специального назначения служат для управления внутренними про- цессами микроконтроллера PIC. Их набор варьируется в зависимости от конкретной модели. Среди важных регистров специального назначения можно назвать OPTION и INTCON, регистры ввода-вывода, таймеров, АЦП и др. Память данных используется для того, чтобы хранить все программных пере- менных. Она — энергозависимая. Это означает, что при отключении питания все содержащиеся в ней данные будут потеряны. В “традиционных” микроконтролле- рах PIC разрядность каждой ячейки памяти составляет восемь бит. По этой причине такие микроконтроллеры PIC называются восьмиразрядными. В настоящее время также доступны 16- и 32-разрядные архитектуры PIC, о которых речь пойдет в гла- вах 9 и 10.
Общие аспекты архитектуры восьмиразрядных микроконтроллеров PIC 187 Важно помнить, что, в отличие от рассмотренных в части I микроконтроллеров AVR, память данных микроконтроллеров PIC разбита на банки. В некоторых моделях таких банков два, в других — четыре или более. Требуемый банк памяти выбирается программно. Память программ служит для хранения пользовательской программы. В более старых микроконтроллерах PIC память программ была выполнена по технологии EPROM. Это означало, что ее содержимое перед программированием стиралось с помощью ультрафиолетового излучения. В современных микроконтроллерах PIC память программ реализована по технологии Flash, при которой стирание и повтор- ное программирование осуществляют с помощью программаторов. Большинство микроконтроллеров PIC может также программироваться без удаления их из схемы. Этот процесс, называемый внутрисхемным последовательным программированием ISP), ускоряет разработку проектов и снижает затраты на разработку. Хотя память программ главным образом используется для хранения программы, никто не пре- пятствует задействовать ее для хранения постоянных данных. Первым словом (ширина командного слова — 12, 14 или 16 разрядов) памяти программ микроконтроллеров PIC является адрес вектора сброса, по которому про- исходит переход при включении питания или подаче сигнала низкого уровня на вход MCLR. Таким образом, первая команда, выполняемая после сброса, размещена по адресу 0 памяти программ. Объемы памяти данных и памяти программ в различных моделях восьмираз- рядных микроконтроллеров PIC перечислены в табл. 7.1. Таблица 7.1. Параметры памяти данных и памяти программ в различных восьмираз- рядных микроконтроллерах PIC Модель Разрядность командного слова, бит Объем памяти данных, байт Объем памяти программ, слов 12С508 12 25 512 16С505 12 41 1 024 16С54 12 25 384 16С554 14 80 512 16С57 12 72 2 048 16С58А 12 73 2 048 16С64 14 128 2 048 16F627 14 224 1 024 16F628 14 224 2 048 16F676 14 64 1 024 16F73 14 192 4 096 16F84 14 36 1 024 16F876 14 368 8 192 16F877 14 368 8 192 17С43 16 454 4 096 17С752 16 678 8 192 18С242 16 512 8 192 18С252 16 1 536 16 384 18F4520 16 1 536 32 768
188 Глава 7. Восьмиразрядные микроконтроллеры PIC Организация тактирования Микроконтроллеры PIC оснащены встроенным осциллятором, который может работать в одном из пяти режимов: • LP — маломощный кварц; • XT — кварц/резонатор; • HS — высокоскоростной кварц/резонатор; • RC — цепочка резистор-конденсатор; • без внешних компонентов (только в некоторых микроконтроллерах РТС). В режимах LP, XT и HS внешний осциллятор может быть подключен ко входу OSC1 (рис. 7.1). При использовании внешнего кварца ко входам OSC1 и OSC2 мик- роконтроллера подключают два конденсатора (рис. 7.2), номинал которых выбира- ют в соответствии с табл. 7.2. Например, при частоте кварца 4 МГц можно исполь- зовать два конденсатора на 22 пФ. PIC 16F84 Внешний тактовый сцгнал Рис. 7.1. Использование внешнего осциллятора OSC1 OSC2 22pF 4MHz 22 pF Рис. 7.2. Схема с кварцевым осциллятором Таблица 7.2. Выбор конденсатора для работы кварцевого осциллятора Режим Частота С1,С2 LP 32 кГц 68-100 пФ LP 200 кГц 15-33 пФ XT 100 кГц 100-150 пФ XT 2 МГц 15-33 пФ XT 4 МГц 15-33 пФ HS 4 МГц 15-33 пФ HS 10 МГц 15-33 пФ Что касается резонаторов, то они работают в диапазоне частот от 4 МГц до поч- ти 8 МГц. Они не столь точны, как кварцевые осцилляторы, и обычно представляют собой устройства с тремя выводами, два из которых связаны со входами OSC1 и OSC2 микроконтроллера, а третий — с “землей” (рис. 7.3). Для приложений, в которых точность синхронизации неважна, ко входу OSC1 микроконтроллера можно подключить внешний резистор и конденсатор (рис. 7.4).
Общие аспекты архитектуры восьмиразрядных микроконтроллеров PIC 189 Частота такого осциллятора зависит от номиналов резистора и конденсатора (см. табл. 7.3), напряжения питания и температуры. Для большинства случаев примене- ния резистор на 5 кОм с конденсатором на 20 пФ дает приблизительно 4 МГц, что приемлемо для систем, некритичных к временным характеристикам. Рис. 7.3. Схема резонаторного осциллятора Таблица 7.3. Выбор компонентов RC-осциллятора С R Частота 20 пФ 5 кОм 4,61 МГц 10 кОм 2,66 МГц 100 кОм 311 кГц 100 пФ 5 кОм 1,34 МГц 10 кОм 756 кГц 100 кОм 82,8 кГц 300 пФ 5 кОм 428 кГц 10 кОм 243 кГц 100 кОм 26,2 кГц В завершение этой темы отметим, что некоторые микроконтроллеры PIC оснащены встроенным осцилля- тором, не требующим никаких внешних компонентов. Он обычно работает с частотой 4 МГц и выбирается в ходе программирования устройства. Например, микро- контроллеры PIC 16F62X могут работать от внутреннего RC-осциллятора на 4 МГц, а для обеспечения перемен- ной частоты к выводу RA7 может быть дополнительно подключен резистор (рис. 7.5). В зависимости от номи- нала этого резистора частота осциллятора составляет от 200 кГц до 10,4 МГц. В этом режиме вывод RA7 недос- тупен для цифрового ввода-вывода. Значение резистора для настройки частоты внутрен- него осциллятора: • 0—10,4 МГц; • 1 кОм — 10,0 МГц; Рис. 7.5. Изменение частоты внутреннего осциллятора
190 Глава 7. Восьмиразрядные микроконтроллеры PIC • 10 кОм —7,4 МГц; • 20 кОм — 5,3 МГц; • 47 кОм — 3 МГц; • 100 кОм—1,6 МГц; • 220 кОм — 800 кГ ц; • 470 кОм — 300 кГц; • 1 МОм — 200 кГц. Частота внутреннего осциллятора некоторых микроконтроллеров (например, PIC 16F630) может быть откалибрована для получения более точных импульсов синхронизации в критических ко времени приложениях (например, при последова- тельном обмене данными). Для этого служит специальный регистр OSCCAL, в который загружается калибровочная константа, по умолчанию хранимая в послед- ней ячейке памяти. Кроме того, можно самостоятельно корректировать значение ре- гистра OSCCAL для подстройки частоты осциллятора. Порты Для управления вводом-выводом через каждый параллельный порт служит со- ответствующая пара регистров: • регистр данных — PORTx; • регистр управления направлением передачи — TRISx. 0 0 0 0 0 0 1 1 PORTB 7 6 5 4 3 2 1 _°J Рис. 7.6. Регистры TRISB и PORTB Количество таких пар регистров соответствует количеству портов. С их помо- щью через любой порт может быть одновременно выдано или принято от одного до восьми бит данных. Порты в микроконтроллерах PIC — двуна- правленные. Это означает, что любой вывод порта может использоваться и как вход, и как выход. Это задает соответствующий управляющий регистр TRISx. Запись в некоторый разряд регистра TRISx лог. 1 делает соответствующий вывод порта вхо- дом, а лог. 0 — выходом. Например, для того что- бы разряды 0 и 1 порта В были входами, а все ос- тальные — выходами, в регистр TRISB необходи- мо записать значение 00000011 (рис. 7.6). В некоторых микроконтроллерах PIC (например, 18Сх) порт D может работать в режиме управляемого параллельного порта PSP (Parallel Slave Port). Это означает, что он действует как регистр, который может быть подключен к шине другого мик- роконтроллера, обмениваясь с ним данными. В режиме PSP, как и в случае обмена данными с любым периферийным устройством, используются сигналы RD (чтение), WR (запись) и CS (выбор кристалла) — разряды 0-2 порта Е (пример — рис. 7.7). Для управления режимом PSP используется регистр TRISE (рис. 7.8). Режим PSP активизируется путем установки в лог. 1 разряда PSPMODE. Прерывания раз- решаются установкой в лог. 1 разряда PSPIE (разряд 7) регистра PIE1, а запросы формируются в разряде PSPIF (разряд 7) регистра PIR1. С помощью разрядов 0-2 регистра TRISE осуществляется выбор режима для соответствующих разрядов пор- та Е.
Общие аспекты архитектуры восьмиразрядных микроконтроллеров PIC 191 Микроконтроллер в режиме PSP Внешний микроконтроллер Рис. 7.7. Пример подключения внешнего микроконтроллера PIC в режиме PSP 7 6 5 4 3 2 1 О IBF OBF IBOV PSPMODE — TRISE2 TRISE1 TRISE0 Рис. 7.8. Регистр TRISE Когда на линиях CS и RD (выводы Е2 и ЕО) одновременно появляется низкий уровень сигнала, содержимое регистра OUTREG выводится через порт D. При запи- си в регистр OUTREG устанавливается в лог. 1 разряд OBF регистра TRISE. Это оз- начает, что выходной буфер заполнен данными. После передачи данных разряд OBF автоматически обнуляется. Когда на линиях CS и WR (выводы Е2 и Е1) одновременно появляется низкий уровень сигнала, осуществляется прием данных через порт D. Принятая величина сохраняется в регистре INREG, при этом автоматически устанавливается в лог. 1 разряд IBF регистра TRISE. После программного считывания содержимого регистра INREG этот разряд автоматически обнуляется. Если ранее принятый байт не считывается до поступления следующего байта в регистр INREG, то устанавливается в лог. 1 разряд IBOV регистра TRISE, указы- вающий на переполнение входного буфера. Вывод порта микроконтроллера может выдавать и принимать ток силой до 25 мА. Когда вывод выдает ток, схема нагрузкй одним концом связана с этим выво- дом, а другим — с “землей” (рис. 7.9 слева). Энергия поступает в нагрузку, когда вывод порта переходит в состояние лог. 1. Если вывод принимает ток, то схема нагрузки одним концом подключена к на- пряжению питания, а другим связана с выводом (рис. 7.9 справа). Энергия поступа- ет в нагрузку, когда вывод порта переходит в состояние лог. 0. Нагрузка Рис. 7.9. Подключение нагрузки к выводу порта: слева — выдача тока; справа — получение тока
192 Глава 7. Восьмиразрядные микроконтроллеры PIC Таймеры Некоторые восьмиразрядные микроконтроллеры PIC (например, 16F84) осна- щены только одним таймером, в то время как другие могут предоставлять до трех таймеров. В этом случае они нумеруются, начиная с нуля: TMRO, TMR1 и TMR2. Кроме того, практически все микроконтроллеры PIC оснащены так называемым сторожевым таймером. Поскольку TMR0 и сторожевой таймер присутствуют почти в любой модели PIC, мы начнем именно с нйх. TMR0 и сторожевой таймер Таймер TMR0 представляет собой восьмиразрядный регистр (адрес $01) и мо- жет работать в режиме таймера или счетчика. В последнем случае его содержимое увеличивается на единицу всякий раз при поступлении тактового импульса на вы- вод Т0СК1 микроконтроллера. В режиме таймера прирост содержимого, происходит с частотой, определяемой частотой системной синхронизации и коэффициентом предварительного деления, задаваемой регистром OPTION (рис. 7.10). 7 б 5 4 3 2 1 0 RBPU INTEDG TOCS TOSE PSA PS2 PS1 PSO Рис. 7.10. Регистр OPTION Коэффициент деления выбирают с помощью разрядов PS2:PS0 регистра OPTION в диапазоне от 2 до 256 (табл. 7.4). Например, при использовании тактовой частоты 4 МГц, базовый командный цикл составляет 1 мкс (частота тактирования внутренне делится на четыре). Таким образом, если, например, выбрать коэффици- ент деления 16, то содержимое счетчика будет увеличиваться на единицу через ка- ждые 16 мкс. Таблица 7.4. Выбор коэффициента деления с помощью регистра OPTION PS2 PS1 PSO Коэффициент деления 0 0 0 2 0 0 1 4 0 1 0 8 0 1 1 16 1 0 0 32 1 0 1 64 1 1 0 128 1 1 1 256 При переполнении (т.е. переходе от 255 к 0) счетного регистра формируется прерывание от таймера (если оно разрешено). Например, если необходимо выдавать запрос на прерывание с интервалом в 200 мкс при тактовой частоте 4 МГц, то мы можем задать коэффициент деления 4 и разрешить прерывания от таймера. В ре- зультате мы получим период следования импульсов тактирования таймера 4 мкс. Для получения 200 мкс на таймер необходимо подать 50 тактовых импульсов, а зна- чит в регистр TMR0 должно быть предварительно загружено значение 256 - 50 = = 206, т.е. до переполнения должно быть отсчитано 50 единиц. Что касается сторожевого таймера, то его осциллятор независим от сигнала сис- темной синхронизации, а период его срабатывания составляет 18 мс. Во избежание сброса от сторожевого таймера, его следует периодически программно обнулять.
Общие аспекты архитектуры восьмиразрядных микроконтроллеров PIC 193 Для увеличения периода срабатывания можно использовать предделитель. При этом доступны коэффициенты деления частоты 1, 2, 4, 8, 16, 32, 64 и 128. Например, ко- гда установлен коэффициент 128, то период срабатывания сторожевого таймера со- ставит около 2 с (18 х 128 = 2 304 мс). Если сторожевой таймер не используется, то его при программировании микроконтроллера можно отключить. Функциональная схема включения TMR0 и сторожевого таймера показана на рис. 7.11. Рис. 7.11. Схема включения TMR0 и.сторожевого таймера Источник входного сигнала для TMR0 выбирают с помощью разряда TOCS ре- гистра OPTION (см. рис. 7.10): • 0 — внутренний осциллятор микроконтроллера с делением частоты fosc на 4; • 1 — внешний тактовый сигнал на входе RA4/T0CK1. Мы затронем лишь вариант , с внутренним осциллятором. При использовании кварца на 4 МГц частота внутреннего осциллятор составит fosc/4 = 1 МГц, что соот- ветствует периоду Т = l(f = IO-6 или 1 мкс. Таймер TMR0 выбирают в качестве ис- точника для предделителя путем обнуления разряда PSA в регистре OPTION (см. рис. 7.10). Требуемое значение коэффициента деления выбирают с помощью разря- дов PS2:PS0 того же регистра (см. табл. 7.4). Разряд PSA затем должен быть обну- лен для назначения предделителя таймеру. Теперь содержимое регистра TMR0 бу- дет увеличиваться на единицу по каждому импульсу от внутреннего осциллятора. Когда TMR0 переходит от 255 к 0, формируется запрос на прерывание от тай- мера (если оно разрешено). Загружая некоторое значение в регистр TMR0, можно управлять количеством отсчетов до получения переполнения. *Для вычисления вре- мени до момента переполнения таймера при заданном периоде следования тактовых импульсов, исходном значении и коэффициенте деления частоты можно воспользо- ваться следующей формулой: Tovf = 4 х Tqsc х К х (256 - TMR0), (7.1) где Tqvf — время до момента переполнения (мкс), lose — период следования им- пульсов от осциллятора (мкс); К — коэффициент делителя частоты, выбранный с помощью регистра OPTION; TMR0 — значение, загруженное в регистр TMR0.
194 Глава 7. Восьмиразрядные микроконтроллеры PIC Предположим, мы используем кварц на 4 МГц, а коэффициент деления равен 8 (PS2:PS0.= 010). Также примем, что в регистр TMR0 загружено десятичное число 100. В таком случае время до переполнения составляет: Tovf = 4 х (1 / 4 МГц ) х 8 х (256 - 100) = 4 х 0,25 мкс х 8 х 156 = 1248 мкс. На практике нам необходимо знать на время до переполнения, как таковое, а значение, которое должно быть загружено в регистр TMR0. Его можно вычислить по формуле, полученной из уравнения (hl): TMR0 = 256 -(2ovf)/(4 х Tqsc х К) . (1.2) Предположим, мы хотим, чтобы прерывание возникло через 500 мкс. При этом тактовая частота и коэффициент деления — такие же, как и в предыдущем примере. В таком случае, значение, которое должно быть загружено в регистр TMR0, равно: TMR0 = 256 - 500/(4 х 0,25 х 8) = 193,5. Таким образом, в регистр TMR0 необходимо загрузить число 193. Значения, ко- торые должны быть записаны в регистр TMR0 для получения различных периодов до переполнения, показаны в табл. 7.5 (принимается, что используется кварц на 4 МГц). TMR1 Хотя TMR0 — базовый таймер, присутствующий почти во всех микроконтрол- лерах PIC, некоторые модели предоставляют несколько таймеров, например: TMR0, TMR1 и TMR2. Дополнительные таймеры расширяют функциональные возможно- сти устройства. Так, TMR1 — это 16-разрядный таймер, состоящий из двух восьми- разрядных регистров TMR1H и TMR1L. Как показано на рис. 7.12, с TMR1 исполь- зуется предделитель частоты. При этом доступны коэффициенты деления 1, 2, 4, и 8. Таблица 7.5. Значения TMR0 для получения различных периодов до переполнения Время до пере- полнения, мкс Коэффициент деления 2 4 8 16 32 64 128 256 100 206 231 243 250 253 254 — — 200 156 206 231 243 250 253 254 — 300 106 181 218 237 246 251 253 255 400 56 156 206 231 243 250 253 254 * 500 6 131 193 224 240 248 252 254 600 — 106 181 218 237 16 251 253 700 — 81 168 212 234 245 250 253 800 — 56 156 206 231 243 250 253 1 000 — 6 131 193 225 240 248 252 5 000 — — — — 100 178 77 236 10 000 — — — — — 100 178 217 20 000 — — — — — — 100 178 30 000 — — — — — — — 139 40 000 — — — — — — — 100 50 000 — — — — — — — 60 60 000 — — — — — — — 21
Общие аспекты архитектуры восьмиразрядных микроконтроллеров PIC 195 Рис. 7.12. Структура TMR1 Работой TMR1 управляет регистр T1CON (рис. 7.13). 7 6 5 4 3 2 1 О — — T1CKPS1 TICKP5O T1OSCEN TISYNC TMR1CS TMR1ON Рис. 7.13. Регистр T1CON TMR1 может работать в режиме таймера и счетчика; что определяется состоя- нием разряда TMR1CS. В режиме таймера содержимое регистра TMR1 увеличива- ется на единицу по каждому импульсу в сигнале с частотой /bsc/4. Для включения или выключения TMR1 служит разряд TMR1ON. Счет выполняется от 0 до 65 535. При переходе от 65 535 к 0 возникает прерывание по переполнению (если оно раз- решено). Когда TMR1 работает в режиме счетчика, его содержимое увеличивается на единицу по каждому нарастающему фронту сигнала на входе TIOSO. Коэффициент деления частоты тактового сигнала для TMR1 задают разряды TICKPS[1:0] регистра T1CON (табл. 7.6). Таблица 7.6. Выбор коэффициента деления с помощью регистра T1CON TICKPS1 TICKPS0 Коэффициент деления 0 0 1 0 1 2 1 0 4 1 1 8 Счетный регистр таймера TMR1 представляет собой регистровую пару TMR1H:TMR1L, а управление прерываниями осуществляется с помощью разрядов регистров PIR1 и PIE1: • регистр PIR1: ► разряд 0 — TMR1IF — флаг переполнения TMR1; ► разряд 2 — ССР 1 IF — флаг прерывания при возникновении захвата по входу; • регистр PIE 1: ► разряд 0 — TMR1IE — флаг разрешения прерывания при переполнении TMR1; ► разряд 2 — ССР НЕ — флаг разрешения прерывания при возникновении за- хвата по входу. TMR2 TMR2 — это восьмиразрядный таймер с предделителем и постделителем часто- ты, содержащий восьмиразрядный регистр периода PR2 (рис. 7.14). Его назначение
196 Глава 7. Восьмиразрядные микроконтроллеры PIC — измерение временных интервалов для реализации ШИМ, обеспечения опреде- ленной скорости обмена по последовательному порту и т.п. В этом смысле он подо- бен таймеру TMR0. Рис. 7.14. Схема таймера TMR2 Таймер TMR2 тактируется импульсами, следующими с частотой такта систем- ной синхронизации, деленной на четыре. Каждый раз, когда содержимое счетного регистра TMR2 совпадает с содержимым регистра PR2, таймер автоматически сбра- сывается в исходное (нулевое) состояние. При каждом совпадении TMR2 и PR2 генерируется запрос на прерывание, час- тоту возникновения которого можно также масштабировать с помощью выходного делителя частоты. Для управления таймером TMR2 используется регистр T2CON (рис. 7.15). 7 6 5 4 3 2 1 О — TOUTPS3 TOUTPS2 TOUTPS1 TOUTPSO TMR2ON T2CKPS1 T2CKPS0 Рис. 7.15. Регистр T2CON микроконтроллеров PIC Назначение отдельных разрядов регистра T2CON: • T2CKPS[l: 0] — управление предделителем частоты (табл. 7.7); • TMR2ON — подключение таймера (0 — отключен, 1 — включен); • TOUTPS[3:0] — выбор коэффициента деления частоты запросов на прерывание при TMR2 = PR2 (табл. 7.8). Таблица 7.7. Назначение разрядов T2CKPS[1:0] регистра T2CON T1CKPS1 T1CKPS0 Коэффициент деления частоты тактового сигнала 0 0 1 0 1 4 1 X 16 Таблица 7.8. Назначение разрядов TOUTPS[3:0] регистра T2CON TOUTPS3 TOUTPS2 TOUTPS1 TOUTPSO Коэффициент деления частоты запросов 0 0 0 0 1 0 0 0 1 2
Общие аспекты архитектуры восьмиразрядных микроконтроллеров PIC 197 Таблица 7.8. Окончание TOUTPS3 TOUTPS2 TOUTPS1 TOUTPSO Коэффициент деления частоты запросов 0 0 1 0 3 0 0 1 1 4 0 1 0 0 5 0 1 0 1 6 0 1 1 0 7 0 1 1 1 8 1 0 0 0 9 1 . 0 0 1 10 1 0 1 0 11 1 0 1 1 12 1 1 0 0 13 1 1 0 1 14 1 1 1 0 15 1 1 1 1 16 _ _ . __J Для организации прерываний используются разряды TMR2IE (флаг разреше- ния) и TMR2IF (флаг прерывания) регистров PIE1 и PIR1 соответственно. Для того чтобы эффективно использовать таймер TMR2, используются сле- дующие формулы: Г=(4х^1 х К2 х PR2) //; PR2 = T*fl(4 х к\ Х/Г2), где Т — требуемая временная задержка, К\ — коэффициент предварительного де- ления частоты;. К2 — коэффициент деления частоты запросов на прерывание; PR2 — содержимое регистра PR2;/— частота системной синхронизации. Модуль ССР Таймеры TMR1 и TMR2 микроконтроллеров PIC применяются в составе модуля сравнения/захвата/ШИМ — ССР (Compare-Capture-PWM). Таких модулей может быть два: ССР1 и ССР2, — управление которыми реализовано с помощью регист- ров CCPxCON (рис. 7.16). 7 6 5 4 3 2 1 О — — DC1BX1 DC1BX0 ССР1МЗ ССР1М2 ССР1М1 ССР1М0 Рис. 7.16. Регистр CCPxCON микроконтроллеров PIC Назначение отдельных разрядов регистра CCPxCON: • ССР1М[3:0] — выбор режима захвата/сравнения (табл. 7.9); • DC 1 ВХ[ 1:0] — два младших разряда 10-разрядной ШИМ. Таблица 7.9. Назначение разрядов ССР1М[3:0] регистра CCPxCON ССР1МЗ ССР1М2 ССР1М1 ССР1М0 Значение 0 0 X X Модуль ССР отключен 0 1 0 0 Захват по каждому ниспадающему фронту 0 1 0 1 Захват по каждому нарастающему фронту 0 1 1 0 Захват по каждому 4-му нарастающему фронту 0 1 1 1 Захват по каждому 16-му нарастающему фронту
198 Глава 7. Восьмиразрядные микроконтроллеры PIC Таблица 7.9. Окончание ССР1МЗ ССР1М2 ССР1М1 ССР1М0 Значение 1 0 0 0 В случае совпадения на выходе — высокий уро- вень 1 0 0 1 В случае совпадения на выходе — низкий уровень 1 0 1 0 В случае совпадения — запрос на прерывание 1 0 1 1 Особый случай режима сравнения 1 1 X X Режим ШИМ В режиме захвата (т.е. фиксации значения таймера в момент появления опреде- ленного условия) используются регистры CCPR1H, CCPR1L (в случае TMR1) или CCPR2H, CCPRL (в случае TMR2). В таком режиме таймер выполняет функции счетчика тактовых импульсов, и при наступлении условия захвата его содержимое переписывается в регистровую пару CCPRx. В режиме сравнения модуль ССР формирует сигнал на выходе ССРх в том слу- чае, когда содержимое счетного регистра становится равным значению, записанно- му в регистровой паре CCPRxH:CCPRxL. Этот режим обычно используется для вы- дачи сигналов на внешние устройства по истечении некоторого временного интер- вала. В режиме ШИМ таймер работает как делитель частоты,, формирующий период ШИМ-сигнала. Его значение постоянно сравнивается с содержимым регистра PR2, и при совпадении компаратор сбрасывает таймер в исходное состояние, после чего цикл повторяется. Параллельно организован контур сравнения, включающий в себя таймер, второй компаратор и регистр CCPRxH. Выходы обоих компараторов управ- ляют RS-триггером, выход которого соединен с выводом ССРх. Вначале триггер устанавливается в “1” по сигналу сброса таймера, а по сигналу компаратора контура сравнения — сбрасывается в “0”. Таким образом, на выходе RS-триггера формируется сигнал с периодом, определяемым содержимым регист- ров PR2 и CCPRxH. Обработка прерываний Прерывания — это вызовы определенных функций, генерируемые, главным образом, аппаратной частью микроконтроллера. В результате прерывания выполне- ние программы останавливается, и происходит переход к соответствующей подпро- грамме обработки прерывания. Прерывания бывают внутренними и внешними. Ис- точниками внутреннего прерывания являются встроенные модули микроконтролле- ра (например, таймер/счетчик или сторожевой таймер). Внешние прерывания вызы- ваются сбросом (сигнал на выводе RESET) или сигналами предустановленного уровня на выводах 1NT. В ряде восьмиразрядных микроконтроллербв PIC выбор фронта для активиза- ции прерывания по входу INT определяется состоянием разряда INTEDG регистра OPTION (см. рис. 7.10). Лог. 1 в этом разряде соответствует прерывание по нарас- тающему, а лог. 0 — по ниспадающему фронту сигнала. В микроконтроллерах PIC источники прерывания, кроме RESET, не рассматри- ваются в отдельности, им обычно соответствует один вектор, а в некоторых моде- лях — два вектора для прерываний с различной приоритетностью. Определять, ка- кое именно прерывание требует обслуживания, — задача программиста, и многие компиляторы с языка С предоставляют для этой цели готовые функции, освобож- дающйе от необходимости самому “вычислять” источник прерывания.
Общие аспекты архитектуры восьмиразрядных микроконтроллеров PIC 199 В момент возникновения прерывания в стек помещается адрес возврата — ад- рес команды, которая должна быть выполнена первой после выхода из подпрограм- мы обработки прерывания. В результате выполнения последней ассемблерной ко- манды подпрограммы обработки прерывания (для микроконтроллеров PIC это ко- манда ret fie) адрес возврата извлекается из стека в счетчик команд, и выполнение программы продолжается. В микроконтроллерах PIC управление прерываниями реализовано с помощью регистров специальных функций, и отличается от устройства к устройству. Напри- мер, в моделях 12С6х, 14000, 16х для этой цели используются регистры INTCON (рис. 7.17), PIE и PIR, а программы обработки прерываний всегда начинают испол- няться с адреса $004. 7 6 5 4 3 2 1 О GIE PEIE TOIE INTE RBIE TOIF INTF RBIF Рис. 7.17. Регистр INTCON микроконтроллеров PIC12C6x, PIC14000, Р1С16х Разряд GIE — это флаг общего разрешения прерываний. Если он установлен в лог. 1, то все немаскированные прерывания разрешены, если же он сброшен в лог. 0, то все прерывания запрещены. Разряд PEIE регистра INTCON может использоваться в качестве флага разре- шения всех прерываний от периферии, определяемых с помощью регистров PIE и PIR. Флаг TOIE разрешает (лог. 1) или запрещает (лог. 0) прерывания при перепол- нении таймера TMR0), а флаг TOIF определяет запрос на соответствующее преры- вание. Разряд INTE — флаг разрешения внешнего прерывания по входу INT, а разряд INTF — флаг запроса на прерывания по этому входу. Аналогичное значение, но для порта В имеют разряды RBIE и RBIF. Регистр PIE содержит флаги разрешения прерываний от периферийных уст- ройств, а регистр PIR — соответствующие флаги запросов на прерывание. Позиции разрядов в этих регистрах для различных микроконтроллеров отличаются. Микроконтроллеры серии Р1С17Сх В микроконтроллерах серии Р1С17Сх используется четыре вектора прерываний: • $00008 — внешнее прерывание по входу INT (приоритет — высокий); • $00010 — прерывание от таймера TMR0 (приоритет — высокий); • $00018 — внешнее прерывание по входу ТОСК1 (приоритет — высокий); • $00020 — прерывание от периферийных устройств (приоритет — низкий). Для управления прерываниями в этой серии микроконтроллеров используется регистр INTSTA (рис. 7.18). 7_______6_______5 4________3______2_______1_______0 PEIF TOCKIF TOIF INTF PEIE TOCKIE TOIE INTE Рис. 7.18. Регистр INTSTA микроконтроллеров PIC17CX Рассмотрим назначение разрядов этого регистра: • PEIF — устанавливается в лог. 1 в случае задержки прерывания, инициирован- ного периферийным устройством;
200 Глава 7. Восьмиразрядные микроконтроллеры PIC • TOCKIF — флаг разрешения внешнего прерывания по входу TOCKI (при пере- ходе к вектору $00018 аппаратно сбрасывается в лог. 0); • TOIF — флаг переполнения счетчика TMR0 (при переходе к вектору $00010 ап- паратно сбрасывается в лог. 0); • INTF — флаг разрешения внешнего прерывания по входу INT (при переходе к вектору $00008 аппаратно сбрасывается в лог. 0); • PEIE — флаг разрешения прерываний от периферийных устройств; • TOCKIE — флаг разрешения внешних прерываний по входу ТОСК1; • TOIE — флаг разрешения прерываний от таймера TMR0; • INTE — флаг разрешения прерываний по входу INT. Флаги разрешений и запросов на прерывания от внешних устройств находятся в регистрах PIE и PIR. При этом их разряды имеют следующую взаимосвязь с пери- ферией микроконтроллера: • 0 (RCIE/RCIF) — прием данных приемопередатчиком UASRT; • 1 (TXIE/TXIF) — передача данных приемопередатчиком UASRT; • 2 (С А1 IE/С А1 IF) — модуль ССР 1; • 3 (CA2IE/CA2IF) — модуль ССР2; • 4 (TMR1IE/TMR1 IF) — таймер TMR1; • 5 (TMR2IE/TMR2IF) — таймер TMR2; • 6 (TMR3IE/TMR3IF) — таймер TMR3; • 7 (RBIE/RB1F) — порт В. Микроконтроллеры серии Р1С18Сх В этой серии микроконтроллеров PIC применяется схема управления прерыват ниями, немного напоминающая задействованную в сериях 12С6х, 14000 и 16х, од- нако есть четыре важных отличия: • каждому источнику прерываний задается собственный уровень приоритета; • вместо одного регистра INTCON используется три (INTCON, INTCON2, INTCON3); • вместо одного регистра PIE и PIR используется по два (PIE1/PIE2; PIR1/PIR2); • присутствует регистры IPR1 и IPR2, задающие приоритеты прерываний от пе- риферийных устройств. Рассмотрим вначале регистры INTCON (рис. 7.19). 7 6 5 4 3 2 1 0 INTCON GIE PEIE TMR0IE INTOIE RBIE TMR0IF INTOIF RBIF 7 6 5 4 3 2 • 1 0 INTCON2 _RBPU INTEDG0 INTEDG1 INTEDG2 — TMR0IP — RBIP 7 6 5 4 3 2 1 0 INTCON3 INT2IP INT1IP — INT2IE INT1IE — INT2IF INT1IF Рис. 7.19. Регистры INTCON микроконтроллеров PIC18CX
Общие аспекты архитектуры восьмиразрядных микроконтроллеров PIC 201 Назначение разрядов регистров INTCON: • INTCON: ► GIE — флаг общего разрешения прерываний; ► PEIE — флаг разрешения всех запросов на прерывание с низким приорите- том; ► TMR0IE — флаг разрешения прерываний от таймера TMR0; ► INT0IE — флаг разрешения прерываний по входу INTO; ► RBIE — флаг разрешения прерывания по изменению состояния порта В; ► TMR0IF — запрос на прерывание от таймера TMR0; ► INT0IF — запрос на прерывание по входу INTO; ► RBIF — запрос на прерывание по изменению состояния порта В; • INTCON2: ► INTEDG0 — выбор фронта для внешнего прерывания по входу INTO (лог. 1 — по нарастающему фронту); ► INTEDG1 — выбор фронта для внешнего прерывания по входу 1NT1 (лог. 1 — по нарастающему фронту); ► INTEDG2 — выбор фронта для внешнего прерывания по входу INT2 (лог. 1 — по нарастающему фронту); ► TMR0IP — задает высокий приоритет для прерывания от таймера TMR0; ► RBIP — задает высокий приоритет для прерывания по изменению состояния порта В; • INTCON3: ► INT2IP — задает высокий приоритет для внешних прерываний по входу INT2; ► INTI IP — задает высокий приоритет для внешних прерываний по входу INT1; ► INT2IE — флаг разрешения внешних прерываний по входу INT2; ► INTI IE — флаг разрешения внешних прерываний по входу INT1; ► INT2IF — запрос на прерывание до входу INT2; ► INTI IF — запрос на прерывание по входу INT1. Структура регистров PIE показана на рис. 7.20. 2 1 0 7 6 5 4 3 PIE1 PSPIE ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE 7 6 5 4 3 2 1 0 PIE2 — — — '— BCLIE LVDIE TMR3IE CCP2IE Рис. 7.20. Регистры PIE микроконтроллеров Р1С18Сх Назначение разрядов регистров PIE: • PSPIE — флаг разрешения прерывания от PSP при выполнении операций чте- ния/записи; • ADIE — флаг разрешения прерывания по завершению аналого-цифрового пре- образования; • RCIE — флаг разрешения прерывания от USART при приеме данных; • TXIE — флаг разрешения прерывания от USART при передаче данных; • SSPIE — флаг разрешения прерывания от MSSP;
202 Глава 7. Восьмиразрядные микроконтроллеры PI • ССРПЕ — флаг разрешения прерывания от модуля ССР1; • TMR2IE — флаг разрешения прерывания при совпадении содержимого таймер; TMR2 и регистра PR2; • TMR1 ТЕ — флаг разрешения прерывания при переполнении таймера TMR1; • BCLIE — флаг разрешения прерывания при конфликте на шине; • LVDIE — флаг разрешения прерывания при обнаружении низкого уровня пи- тающего напряжения; • TMR3IE — флаг разрешения прерывания при переполнении таймера TMR3; • CCP2IE — флаг разрешения прерывания от модуля ССР2. Регистры PIR и IPR имеют сходную структуру и взаимосвязь разрядов с раз личными устройствами и модулями. Сброс Сброс используется для того, чтобы привести микроконтроллер в заранее из вестное состояние. В случае с восьмиразрядными микроконтроллерами PIC управ ление при сбросе обычно передается на адрес 0 памяти программ (первая исполняв мая команда программы пользователя). Операция сброса также приводит в исход ное состояние различные регистры специального назначения. Сброс возникает по одной из следующих причин: • при включении питания; • при появлении сигнала низкого уровня на входе MCLR; • по переполнению сторожевого таймера. Наиболее распространенные виды сброса — при подаче питания, когда вхо MCLR подключен к напряжению питания через резистор (например, на 4,7 кОм (рис. 7.21). Кроме того, во многих системах необходимо предусмотреть сброс мик роконтроллера по нажатию внешней кнопки. Простейшая схема обеспечения внеш него сброса показана на рис. 7.22. В этой схеме вход MCLR в ходе работы микро контроллера находится в состоянии лог. 1. При нажатии кнопки он переходит в со- стояние лог. 0, что приводит к сбросу. Когда кнопка сброса отпущена, микрокон- троллер начинает выполнять команды, начиная с адреса 0 памяти программ. +Vdd 4.7 К MCLR PIC Рис. 7.22. Использование для сброса внешней кнопки Рис. 7.21. Сброс при подаче питания Последовательный обмен данными В случае последовательного обмена данными используется только одна инфор- мационная линия. При этом передача бывает асинхронной и синхронной. При сии-
Общие аспекты архитектуры восьмиразрядных микроконтроллеров PIC 203 хронном последовательном вводе-выводе синхронизируется передача отдельных битов данных с помощью одновременно передаваемого тактового сигнала. Син- хронная последовательная передача данных применяется, главным образом, на уровне печатных плат, в том числе — для обмена данными между различными ин- тегрированными блоками в составе схемы микроконтроллера и различными пери- ферийными схемами (например, для обработки видеосигнала). В противоположность этому, при асинхронной передаче данных передается не тактовый сигнал, а старт-бит и стоп-бит, определяющие начало и завершение пе- редачи слова данных. Главной областью применения асинхронной передачи дан- ных, как правило, является не обмен данными в составе схемы, а коммуникация ме- жду блоками, разделенными пространственно и обладающими признаками собст- венного интеллекта. В качестве примера можно назвать связь между персональным компьютером и принтером, модемом, программирующим устройством или регист- ратором данных. В микроконтроллерах PIC асинхронная передача данных осуществляется с помощью приемопередатчика USART или по шине CAN, а для синхронного вво- да-вывода используется особый режим приемопередатчика USART, а также интер- фейсы SPI и 12С (или с помощью порта MSSP). Рассмотрим перечисленные средства подробнее. Приемопередатчик USART В восьмиразрядных микроконтроллерах PIC скорость обмена данными через приемопередатчик USART задается восьмиразрядным счетчиком во взаимодейст- вии с регистром SPBRG. Когда содержимое счетчика и регистра SPBRG совпадает, счетчик сбрасывается в нуль. На значение скорости передачи через USART также влияет состояние разряда BRGH регистра управления TXSTA (рис. 7.23). Этот раз- ряд определяет, какая требуется скорость для передачи данных: высокая (BRGH = 1) или низкая (BRGH = 0). 7_______6______5 4_______3 2_______1_______0 CSRC ТХ9 TXEN SYNC — BRGH TRMT TX9D Рис. 7.23. Регистр TXSTA микроконтроллеров PIC Значение для записи в регистр SPBRG вычисляется по следующей формуле: SPBRG = (/osc х 4brgh) / (64 х скорость передачи) - 1. Например, для того чтобы получить скорость передачи 9 600 бод для микрокон- троллера с рабочей частотой fosc = Ю МГц в регистр SPBRG должно быть записано значение (10 х 106 х 4) / (64 х 9 600) - 1 = 64,1 (округляем до 64). Управление приемопередатчиком USART осуществляется с помощью регист- ров TXSTA (см. рис. 1.32) и RCSTA (управление процессом приема) (рис. 7.24). 7 6 5 4 3 2 1 0 SREN RX9 SREN CREN ADDEN FERR OERR RX9D Рис. 7.24. Регистр RCSTA микроконтроллеров PIC Приемопередатчик USART может обмениваться данными не только в асин- хронном, но и в синхронном режиме. В этом случае поразрядный сдвиг данных из сдвигового регистра в линию передачи (или наоборот) осуществляется по синхро- импульсам самого приемопередатчика USART или внешнего устройства. Выбор
204 Глава 7. Восьмиразрядные микроконтроллеры PIC режима работы USART осуществляется с помощью разряда SYNC регистра TXSTA (1 — синхронный режим; 0— асинхронный режим), а выбор источника тактовых импульсов в синхронном режиме — с помощью разряда CSRC (1 — внутренний ис- точник; 0 — внешний источник). Назначение остальных разрядов регистра TXSTA: '• TX9D — девятый бит передаваемых данных, если ТХ9 = 1; • TRMT — флаг, сигнализирующий о завершении передачи байта; • TXEN — флаг разрешения передачи данных; • ТХ9 — разрешение (лог. 1) передачи данных в девятиразрядном формате. Назначение разрядов регистра RCSTA: • RX9D — девятый бит принимаемых данных, если RX9 = 1; • OERR — флаг, указывающий на переполнение буфера приема; • FERR — флаг, указывающий на обнаружение ошибки в формате принимаемых данных; • ADDEN — разрешение обнаружения адреса в асинхронном режиме передачи девяти бит данных — в некоторых микроконтроллерах PIC приемник USART может использоваться для приема сразу двух байтов в формате “данные:адрес”, где адрес предназначен для идентификации устройства, связанного с шиной данных (в таком случае подпрограмма обработки прерывания вначале проверит адрес запрошенного устройства и только потом обработает байт данных); • CREN — разрешение режима непрерывного приема; • SREN — флаг разрешения однократного приема в синхронном режиме (после приема данных автоматически сбрасывается в лог. 0); • RX9 — флаг разрешения приема девяти бит данных; • SREN — флаг активизации USART (для передачи битов данных используется вывод 6 порта С, а для приема — вывод 7 того же порта). Флаги запросов (TXIF и RCIF) и разрешения (TXIE и RCIE) прерываний от USART находятся в регистрах PIR и PIE. Синхронная передача данных по интерфейсу SPI Интерфейс SPI (Serial Peripheral Interface) служит для обмена данными с пери- ферийными устройствами. В качестве таких устройств могут выступать простые сдвиговые регистры или буквенно-цифровые модули индикации, а также сложные микропроцессорные системы или системы регистрации данных. Многие компании- изготовители предлагают большой выбор устройств с интерфейсом SPI. В случае обмена данными по интерфейсу SPI микроконтроллер работает в режиме ведущего устройства (Master), взаимодействуя с одним или несколькими ведомыми блоками (Slave). Схема передачи данных по интерфейсу SP1 микрокон- троллеров PIC показана на рис. 7.25 (MSB — старший разряд, a LSB — младший разряд передаваемого байта). Ведущее устройство берет на себя активную часть обмена данными, вызывая передачу и управляя-процессом. Ведомое устройство не может само быть активным. Оно принимает и передает данные только тогда, когда происходит его активизация со стороны ведущего устройства по линии /SS. Ведущее устройство также генери- рует такт для передачи по выходной линии SCK. Для ведомого блока вывод SCK
Общие аспекты архитектуры восьмиразрядных микроконтроллеров PIC 205 является входом, через который он получает от Master-устройства тактирующие сигналы. Сдвиговой регистр MASTER Рис. 7.25. Схема передачи данных по интерфейсу SPI микроконтроллеров PIC Если ведомое устройство активизируется ведущим по линии /SS, то начинается обмен данными: Master записывает подлежащий передаче байт в свой сдвиговой ре- гистр данных SSPBUF. С помощью каждого выработанного тактового импульса Master перемещает < один бит данных на выход SDO, a Slave одновременно в обратном направлении передает один бит на вход SDI ведущего блока. Таким об- разом, в течение цикла SPI, состоящего из восьми тактовых импульсов, Master и Slave обмениваются байтом данных. По окончании передачи данных в регистре состояния интерфейса SPI устанав- ливается флаг соответствующего запроса на прерывание. Этот флаг указывает на окончание передачи и вызывает запрос на прерывание после того как в регистре уп- равления SPI будет установлен разряд разрешения на прерывание от интерфейса SPI. В режиме “Master” текущая передача данных может быть преждевременно за- вершена выдачей в линию /SS сигнала лог. 1. В микроконтроллерах PIC для последовательной синхронной передачи данных используется порт MSSP, работающий в режиме интерфейса SPI или 12С. Линиям - SPI соответствуют выводы порта А и С: • /SS — зависит от модели (например, разряд 5 порта А); • SDO — разряд 5 порта С; • SDI — разряд 4 порта С; • SCK — разряд 3 порта С. Для управления интерфейсом SPI в восьмиразрядных микроконтроллерах PIC используются регистры SSPSTAT (рис. 7.26) и SSPCON1 (рис. 7.27). 7 6 5 4 3 2 1 0 SMP СКЕ D/A Р S R/W UA BF Рис. 7.26. Регистр SSPSTAT микроконтроллеров PIC 7 6 5 4 3 2 1 0 WCOL SSPOV SSPEN СКР SSPM3 SSPM2 SSPM1 SSPM0 Рис. 7.27. Регистр SSPCON1 микроконтроллеров PIC
206 Глава 7. Восьмиразрядные микроконтроллеры PIC Назначение разрядов регистра SSPSTAT: • BF — флаг заполнения буфера данных; • UA, R/W, S, Р, D/A — имеют отношение к рассмотренному ниже последова- тельному интерфейсу 12С; • СКЕ — выбор активного фронта импульсов SCK для передачи данных (исполь- зуется совместно с разрядом СКР регистра SSPCON1); • SMP — точка стробирования данных в режиме Master (1 — стробирование в конце битового интервала; 0 — стробирование в середине интервала). В режиме Slave этот разряд всегда содержит лог. 0. Назначение разрядов регистра SSPCON1: • SSPM[3:0] — выбор режима работы порта MSSP (значения для интерфейса SPI представлены в табл. 7.10); • СКР — выбор фронта для передачи (если СКР = 0, то передача осуществляется по нарастающему фронту тактового сигнала); • SSPEN — флаг разрешения работы интерфейса SPI; • SSPOV — флаг переполнения приемного буфера; • WCOL — флаг коллизий при записи (1 — запись новых данных в буферный ре- гистр была произведена в момент передачи). Таблица 7.10. Выбор режима работы порта MSSP для интерфейса SPI SSPM3 SSPM2 SSPM1 SSPM0 Режим .0 0 0 0 Режим Master, частота = Fosc / 4 0 0 0 1 Режим Master, частота = Fosc /16 0 0 1 0 Режим Master, частота = Fosc / 64 0 0 1 1 Режим Master, частота = выход TMR2 / 2 0 1 0 0 Режим Slave, вывод SS разрешен 0 1 0 1 Режим Slave, вывод SS не используется Синхронная передача данных по интерфейсу 12С Протокол шины 12С и процесс адресации подключенных к ней устройств был подробно рассмотрен в главе 1, “Восьмиразрядные микроконтроллеры AVR”, по- этому повторно останавливаться на этих вопросах мы не будем. В микроконтроллерах PIC обмену данными по интерфейсу 12С соответствует особый режим работы порта MSSP. Линии SCL соответствует вывод 3 порта С, а линии SDA — вывод 4 того же порта. Для управления передачей в режиме 12С используются три регистра: уже рас- смотренные выше SSPSTAT (см. рис. 7.26) и SSPCON1 (см. рис. 7.27), а также SSPCON2 (рис. 7.28). Назначение разрядов регистра SSPSTAT, имеющих отношение к 12С: • BF — флаг заполнения буфера данных; • UA — устанавливается в лог. 1 в том случае, если необходимо модифицировать адрес устройства (содержимое регистра SSPADD); • R/W — указывает на тип операции: 0 — запись, 1 — чтение; • S — устанавливается в лог. 1 при обнаружении условия начала передачи; • Р — устанавливается в лог. 1 при обнаружении условия завершения передачи;
бщие аспекты архитектуры восьмиразрядных микроконтроллеров PIC 207 • D/A — признак переданного байта: 0 — байт адреса, 1 — байт данных. Назначение разрядов регистра SSPCON1, имеющих отношение к 12С: • SSPM[3:0] — выбор режима работы порта MSSP (значения для интерфейса 12С представлены в табл. 7.11); • СКР — установка этого разряда в лог. 1 разрешает тактирование; • SSPEN — флаг разрешения работы интерфейса; • SSPOV — флаг переполнения приемного буфера; • WCOL — флаг коллизий при записи (1 — запись новых данных в буферный ре- гистр была произведена в момент передачи). аблица 7.11. Выбор режима работы порта MSSP для интерфейса 12С SSPM3 SSPM2 SSPM1 SSPM0 Режим 0 1 1 0 Режим Slave, используется 7-разрядный адрес 0 1 1 1 Режим Slave, используется 10-разрядный адрес 1 0 0 0 Режим Master, частота = Fosc / (4 (SSPADD + 1)) J 0 1 1 Режим Master с программным управлением 1 1 1 0 Режим Slave, используется 7-разрядный адрес J 1 1 1 Режим Slave, используется 10-разрядный адрес 7________6_______5 4________3_______2________1________0 GCEN ACKSTAT ACKDT ACKEN RCEN PEN RSEN SEN Рис. 7.28. Регистр SSPCON2 микроконтроллеров PIC Назначение разрядов регистра SSPCON2: • SEN — устанавливается в лог. 1 для создания условия начала передачи; • RSEN — устанавливается в лог. 1 для создания повторных условий начала пе- редачи; • PEN — сбрасывается в лог. 0 для создания условия окончания передачи; • RCEN — устанавливается в лог. 1 для разрешения режима приема; • ACK.EN — инициирует последовательность битов квитирования; • ACKDT — устанавливается в лог. 1 для отправки подтверждения при приеме байта; • ACKSTAT — устанавливается в лог. 1 при получении подтверждения приема от ведомого устройства. Аналого-цифровое преобразование АЦП преобразовывает аналоговые сигналы (например, напряжение) в цифро- вую форму. В большинстве микроконтроллеров PIC, оснащенных АЦП, для анало- гового ввода используются выводы порта А, совмещающие цифровые и аналоговые функции. Количество АЦП отличается в зависимости от модели микроконтроллера PIC. Так, в состав устройства 16F876 входит пять, a 16F877 — восемь АЦП. При этом, фактически, в них присутствует только один АЦП, а входы мультиплексируется, совместно используя один и тот же преобразователь (рис. 7.29). Разрядность АЦП может составлять 8 или 10 разрядов. Так, в состав PIC 16F876 и PIC 16F877 входят 10-разрядные преобразователи, а в состав PIC 16F73 — восьмиразрядные.
208 Глава 7. Восьмиразрядные микроконтроллеры PIC АЦП требует некоторого .опорного напряжения (обычно 5 В). Таким образом, если мы используем 10-разрядный преобразователь (1 024 уровней дискретности), то разрешающая способность преобразователя составит 5 / 1024 = 0,00488 В или 4,88 мВ, т.е. мы можем измерять аналоговые напряжения с разрешением 4,88 мВ. Например, если измеряемое аналоговое входное напряжение равно 4,88 мВ, то мы получим 10-разрядное цифровое значение 0000000001. Если аналоговое входное напряжение равно 2 х 4,88 = 9,76 мВ, то получится 10-разрядное цифровое значение 0000000010. Если же входное напряжение равно 3 х 4,88 = 14,64 мВ, то 10-разряд- ное цифровое значение составит 0000000011 и т.д. АЦП Преобразованный цифровой сигнал Мультиплексор Рис. 7.29. Мультиплексная структура АЦП Подобным же образом, если опорное напряжение равно 5 В, и мы используем восьмиразрядный преобразователь (256 уровней дискретности), то разрешающая способность составит 5 / 256 = 19,53 мВ. Например, если измеряемое входное на- пряжение равно 19,53 мВ, то мы получим восьмиразрядное цифровое значение 00000001. Если входное напряжение равно 2 х 19,53 = 39,06 мВ, то мы получим восьми разрядное цифровое значение 00000010 и т.д. Для управления АЦП в микроконтроллерах PIC служат регистры ADCONO (рис. 7.30} и ADCON1 (рис. 7.31). 7 6 5 4 3 2 1 0 ADCS1 ADCS0 CHS2 CHS1 CHS0 GO/DONE ADIF ADON Рис. 7.30. Регистр ADCONO микроконтроллеров PIC Назначение разрядов регистра ADCONO: • ADON — флаг разрешения использования АЦП; • ADIF — разряд запроса на прерывание по окончанию преобразования; • GO/DONE — установка этого разряда в лог. 1 активизирует АЦП; по оконча- нию преобразования автоматически сбрасывается в лог. 0; • CHS[2:0] — выбор аналогового входа порта А (назначение этих разрядов зави- сит от типа микроконтроллера); • ADCS[ 1:0] — выбор рабочей частоты АЦП (табл. 7.12). Таблица 7.12. Выбор рабочей частоты АЦП микроконтроллеров PIC ADCS1 ADCS0 Частота 0 0 Частота системной синхронизации / 2 0 1 Частота системной синхронизации / 8 1 0 Частота системной синхронизации / 32 1 1 Тактирование от встроенного RC-осциллятора АЦП (250 кГц)
Общие аспекты архитектуры восьмиразрядных микроконтроллеров PIC 209 Максимальная допустимая рабочая частота АЦП микроконтроллеров PIC — 625 кГц. Это следует учитывать при выборе коэффициента деления частоты сис- темной синхронизации. Использование внутреннего RC-осциллятора АЦП не рекомендуется для микроконтроллеров с частотой системной синхронизации выше 1 МГц. 7 6 5 4 3 2 1 О ADFM — — — PCFG3 PCFG2 PCFG1 PCFG0 Рис. 7.31. Регистр ADCON1 микроконтроллеров PIC Назначение разрядов регистра ADCON1: • ADFM — выбор разрешения преобразования: 1 — 10 бит; 0 — 8 бит; • PCFG[3:0] — разряды конфигурации, которые определяют, какие выводы порта АЦП являются аналоговыми входами, а какие используются для подачи опор- ных напряжений Vref+ и Vref_. Наиболее распространенная конфигурация — 0000, которая определяет все восемь выводов как аналоговые входы, а в качестве опорных напряжений устанавливает Vdd и Vss- Другие значения разрядов PCFG[3:0] варьируются в зависимости от типа микроконтроллера (пример — в табл. 7.13). Таблица 7.13. Пример использования разрядов конфигурации АЦП PCFG[3:0] AN7 AN6 AN5 AN4 AN3 AN2 AN1 ANO Vref+ Vref- 0000 А А А А А A A A Vdd Vss 0001 А А А А Vref+ A A A RA3 Vss 0010 D D D А А A A A Vdd Vss 0011 D D D А Vref+ A A A RA3 Vss 0100 D D D D А D A A Vdd Vss 0101 D D D D Vref+ D A A RA3 Vss 0110 D D D D D D D D Vdd Vss 0111 D D D D D D D D Vdd Vss 1000 А А А А Vref+ Vref- A A RA3. RA2 1001 D D А А А A A A Vdd Vss 1010 D D А А Vref+ A A A RA3 Vss 1011 D D А А Vref+ Vref- A A RA3 RA2 1100 D D D А Vref+ Vref- A A RA3 RA2 1101 D D D D Vref+ Vref- A A RA3 RA2 1110 D D D D D D D A Vdd Vss 1111 D D D D Vref+ Vref- D A RA3 RA2 Встроенный аналоговый компаратор В ряде моделей микроконтроллеров PIC используется встроенный аналоговый компаратор напряжения, сравнивающий входное напряжение на двух входах. Как только напряжение на неинвентирующем входе станет больше, чем на инвенти- рующем, на выходе компаратора устанавливается лог. 1. Часто аналоговый компа- ратор используют для сравнения некоторого входного напряжения с опорным.
210 Глава 7. Восьмиразрядные микроконтроллеры PIC Для активизации компаратора требуется предварительно перевести соответст- вующие выводы микроконтроллера в режим входов. Время срабатывания компара- торов небольшое, поэтому с их помощью можно быстро формировать ответные ре- акции на изменение соотношений входных напряжений. В микроконтроллерах PIC конфигурация входов компаратора (вывода порта А) настраивается с помощью разрядов регистра CMCON (рис. 7.32). В некоторых мо- делях используются два аналоговых компаратора (например, в серии 16С62х). В этом случае для управления их работой также служит регистр CMCON. 7 6 5 4 3 2 1 0 C2OUT сюит — — CIS СМ2 СМ1 смо Рис. 7.32. Регистр CMCON микроконтроллеров серии Р1С16С62х Назначение разрядов регистра CMCON: • СМ[2:0] — выбор режима работы компаратора (табл. 7.14); • CIS — разряд управления входным коммутатором компаратора (табл. 7.14); • ’* С1 OUT — выходной сигнал компаратора 1; • C2OUT — выходной сигнал компаратора 2. Таблица 7.14. Конфигурация входов компараторов напряжения в серии Р1С1вСв2х CIS СМ2 СМ1 смо Компаратор 1 Компаратор 2 Вход + Вход- Вход + Вход- X 0 0 0 RA0 RA3 RA2 RA1 0 0 0 1 RA2 RAO RA2 RA1 1 0 0 1 RA2 RA3 RA2 RA1 0 0 1 0 Vref RAO Vref RA1 1 0 1 0 Vref RA3 Vref RA2 X 0 1 1 RA2 RAO RA2 RA1 X 1 0 0 RA3 RAO RA2 RA1 X 1 0 1 — — RA2 RA1 X 1 1 0 RA2 RAO RA2 RA1 X 1 1 1 — — — — Семейство микроконтроллеров PIC16 Семейство микроконтроллеров PIC 16 растет очень обширно, однако все его представители имеют идентичное ядро и набор команд. Различия составляют только периферийные устройства, некоторые другие средства, а также размеры корпусов. Данные о некоторых представителях семейства PIC16 представлены в табл. 7.15. Даже такая небольшая сводка явно показывает все разнообразие доступных моде- лей. Первым в списке идет микроконтроллер 16F84A, особенности которого мы и рассмотрим в качестве примера. Он имеет “родственника”: микроконтроллер 16LF84A, расширенный диапазон питания которого позволяет работать при пони- женных напряжениях. Эти устройства доступны в разных корпусах, могут работать в разных диапазонах температур и с разной частотой тактового генератора. Напри- мер, микроконтроллер 16F84A существует в версиях на 4 и 20 МГц.
Семейство микроконтроллеров PIC16 211 Табл. 7.15. Некоторые представители семейства PIC16 Модель Число вы- водов (кор- пус DIP) Тактовая частота, МГц Память Периферия 16F84A 18 До 20 1 Кбайт памяти про- грамм 68 байт ОЗУ 64 байт EEPROM 1 восьмиразрядный таймер 1 пятиразрядный порт 1 восьмиразрядный порт 16F873A 28 До 20 4 Кбайт памяти про- грамм 192 байт ОЗУ 128 байт EEPROM 3 восьмиразрядных порта 3 счетчика/таймера 2 модуля ССР 2 модуля последовательного обмена данными 5 10-раз рядных каналов АЦП 2 аналоговых компаратора 16F874A 40 До 20 4 Кбайт памяти про- грамм 192 байт ОЗУ 128 байт EEPROM 5 восьмиразрядных портов 3 счетчика/таймера 2 модуля ССР 2 модуля последовательного обмена данными 8 10-раз рядных каналов АЦП 2 аналоговых компаратора 16F876A 28 До 20 8 Кбайт памяти про- грамм 368 байт ОЗУ 256 байт EEPROM 3 восьмиразрядных порта 3 счетчика/таймера 2 модуля ССР 2 модуля последовательного обмена данными 5 10-раз рядных каналов АЦП 2 аналоговых компаратора 16F877A 40 До 20 8 Кбайт памяти про- грамм 368 байт ОЗУ 256 байт EEPROM 5 восьмиразрядных портов . 3 счетчика/таймера 2 модуля ССР 2 модуля последовательного обмена данными 8 10-разрядных каналов АЦП 2 аналоговых компаратора. е Технические описания перечисленных здесь микроконтроллеров (на английском языке) можно найти на прилагаемом к книге компакт-диске в папке Datasheets\Р1С. Микроконтроллер 16F84A Микроконтроллер 16F84A (вначале назывался 16С84) — один из самых успеш- ных микроконтроллеров PIC. Появился он в то время, когда большинство произво- дителей микроконтроллеров пытались сделать свои модели большими, совершен- ными и сложными. Однако компания Microchip приняла смелое решение и оставила свои модели маленькими, простыми и простыми в использовании. Хотя в то время большинство микроконтроллеров имели встроенную в кристалл память программ типа EPROM с длительным циклом стирания, микроконтроллер 16С84 было решено
212 Глава 7. Восьмиразрядные микроконтроллеры PIC снарядить памятью типа EEPROM, что ускорило и упростило его программирова- ние и привело к более частой модернизации систем. Затем появилась версия с тех- нологией Flash, и название микроконтроллера было изменено с “С84” на “F84’’. Структурная схема микроконтроллера PIC 16F84A показана на рис. 7.33. Счетчик команд Флэш память программ 1 Их 14 Шина / команд7 1 14 [ Регистр команд ~| Инструкция декодирования и управления Тактовый генератор Шина данных в EEPROM память данных Адрес RAM Прямой адрес 8 8-ми уровневый стек (13-ти разрядный) EEPROM память данных RAM Регистры файлов Таймер включения питании Таймер запуска генератора Сброс по включению питания Сторожевой таймер RA4/TOCKI | РегистрW | Порт ввода/вывода адрес | PemcTpFSR Рис. 7.33. Структурная схема микроконтроллера PIC 16F84A EEADR OSC2/CLKOUT MCLR Vdo, Vss Ч^Мультиплексор/ RBWWT 5^ Регистр состояния Результат любой операции, выполняемой центральным процессором, сохраня- ется в рабочем регистре W, однако в нем не всегда присутствуют все необходимые данные о только что выполненной операции. Например, что произойдет, если в ре- зультате выполнения команды сложения будет превышен восьмиразрядный диапа- зон? Рабочий регистр не умеет распознавать подобные ситуации, и потому сохранит некорректный результат. Учитывая это, в любой центральный процессор компьютера встроен набор ло- гических разрядов, которые иногда называют флагами условий. Они предназначены для передачи дополнительной информации о результате выполнения последней ко- манды, например, является ли он нулевым, отрицательным или положительным. В микроконтроллере 16F84A эти флаги хранятся в регистре состояния (рис. 7.34). По сути, к категории флагов условий можно отнести только три разряда этого реги- стра: с 0 по 2, т.е. С, DC и Z. Им соответствует флаг переноса, знак переноса и флаг нулевого результата. 7 6 5 4 3 2 1 0 — — RP0 то PD Z DC С Рис. 7.34. Регистр состояния микроконтроллера PIC 16F84A
Семейство микроконтроллеров PIC16 213 Разряд RP0 отвечает за выбор банка памяти: 0 — банк 0 (диапазон адресов $00..$7F; 1 — банк 1 (диапазон адресов $80..$FF). Флаг ТО устанавливается после подачи питания, сброса сторожевого таймера и перехода микроконтроллера в “спящий” режим, и сбрасывается при переполнении сторожевого таймера. Флаг PD устанавливается после подачи питания или сброса сторожевого тайме- ра, и сбрасывается при переходе микроконтроллера в “спящий” режим. Организация памяти Структура памяти программ и стека микроконтроллера PIC 16F84A показана на рис. 7.35, а структура ОЗУ — на рис. 7.36. Рис. 7.35. Структура памяти программ и стека микроконтроллера PIC 16F84A Схема, показанная на рис. 7.35, содержит счетчик команд, стек и собственно память программ. Все три элемента не могут работать друг без друга. В память про- грамм загружается программный код, выполняемый микроконтроллером, который представляет собой список команд. Адрес следующей команды, которую должен выполнить микроконтроллер, хранится в счетчике команд. Таким образом, он вы- полняет функцию указателя. Значение счетчика команд можно также поместить в стек. Это происходит в случае перехода к подпрограмме или при возникновении прерывания. ПРИМЕЧАНИЕ Ассемблерные команды, обозначенные на схеме как CALL, RETURN, RETFIE и RETLW, от- носятся к подпрограммам и прерываниям. Поскольку книга посвящена программированию на языке С, подробно останавливаться на них бы не будем.
214 Глава 7. Восьмиразрядные микроконтроллеры PIC Как видим, диапазон адресов памяти программ составляет $0000..$03FF. Имея 13-разрядный счетчик команд, микроконтроллер теоретически может адресовать область $0000..$ 1FFF. Дополнительное адресное пространство окрашено в серый цвет, так как оно фактически не используется. Первая ячейка памяти программ называется вектором сброса. При запуске про- граммы на выполнение (например, при подаче питания), счетчик команд устанавли- вается в 0, поэтому первая ячейка памяти, на которую он указывает, — это вектор сброса. Таким образом, программист должен поместить первую команду именно в этой ячейке. Вектор прерывания от периферии, для подпрограмм обслуживания этих прерываний, действует аналогичным образом. Адрес в файле OOh 0th 02h 03П (Mh 05h 07h 09h OAh OBh OCh 4Fh 50h Косвенный ддриР} Косвмиьйвдрк^^ TMR0 OPTION JO PCL PCX STATUS STATUS F8R FSR PORTA TRISA PORTS EEADR еесонгго PCLATH PCLATH INTCON INTCON 68 регистров общего назначения (SRAM) Отображена в банке 0 BOh 81h 82h 83h 84h 85h 86h «Th 88h «Ah 8Bh 8Ch Адрес в файле CFh ООП 7Fh Банк 1 FFh БанкО О Неиспользуемая область памяти данных, считывается как к0п Примечание 1: Не физические регистры Рис. 7.36. Структура ОЗУ микроконтроллера PIC 16F84A Область ОЗУ (см. рис. 7.36) распределена по банкам и разбита на две важные области. Нижняя из них — память данных общего назначения, занимающая ячейки с адресами от $0С до $4F. Над ней размещены регистры специального назначения. Проблема, которая присуща любой памяти, заключается в том, что чем больше памяти, тем шире должна быть ее шина адреса. Одним из методов уменьшения ад- ресной шины является разбиение памяти на несколько меньших блоков одинакового размера, называемых банками. В каждый момент времени в качестве целевого мо- жет быть выбран только один банк.
Семейство микроконтроллеров PIC 16 215 Микроконтроллер PIC 16F84A содержит два таких банка. Адрес каждого из них — семиразрядный адрес RAM. Активный банк выбирают с помощью разряда RP0 регист- ра состояния (см. рис. 7.34). Перед получением любого доступа к памяти программист должен удостовериться, что этот разряд содержит корректное значение. На рис. 7.33 показано, что существует два возможных источника адреса ОЗУ, один из которых выбирается с помощью мультиплексора адресов. Если адрес явля- ется частью команды и поступает на мультиплексор из регистра команд, то он на- зывается прямым. Кроме того, адрес можно получить из регистра выбора файла FSR (File Select Register), относящегося к регистрам специального назначения (см. рис. 7.36). Если пользователь загружает в регистр FSR адрес, который может быть использован в качестве адреса ячейки в памяти данных, то такая методика называ- ется косвенной адресацией. Фактические адреса памяти изображены на рис. 7.36 в столбце “Адрес в файле”. Они — восьмиразрядные, однако из рис. 733 видно, что разрядность адресной шины ОЗУ составляет только семь бит, а при прямой адресации доступны только пять разрядов адреса. Важно понимать, что эти адреса состоят из семиразрядного адреса ОЗУ и разряда выбора банка из регистра состояния, подставляемого вместо старше- го, восьмого разряда. Во время программирования важно разделять эти источники, удостоверившись, что старший разряд задействован для выбора банка. Слово конфигурации Особым элементом памяти программ микроконтроллера 16F84A является слово конфигурации (рис. 7.37). 13 12 11 10 9 8 7 6 5 4 3 2 1 0 СР СР СР СР СР СР СР СР СР СР PWRTE WDTE F0SC1 F0SC0 Рис. 7.37. Слово конфигурации микроконтроллера PIC 16F84A Назначение разрядов слова конфигурации: • СР — разряды конфигурации защиты кода; • PWRTE: 0 — таймер включения питания активен; 1 — таймер включения пита- ния отключен; • WDTE: 0 — сторожевой таймер отключен; 1 — сторожевой таймер включен; • FOSC[1:O] — выбор типа осциллятора: 00 — LP; 01 — XT; 10 — HS; 11 — RC. С помощью слова конфигурации пользователь может, во время загрузки про- граммы, определить некоторые свойства конфигурации микроконтроллера. Впо- следствии они остаются фиксированными до следующего программирования. Этот подход отличается от других возможностей, наподобие записи в регистры специ- ального назначения. Хотя слово конфигурации является частью памяти программ, к нему нельзя по- лучить доступ из программы или любым другим способом во время работы про- граммы. Память EEPROM Память EEPROM — энергонезависимая и особенно удобна для хранения пере- менных данных, которые, скорее всего, потребуется хранить длительный период времени. В микроконтроллере 16F84A она адресуется с помощью специального ре- гистра EEADR, а данные передаются через регистр EEDATA (см. рис. 7.36).
216 Глава 7 Восьмиразрядные микроконтроллеры PIC Считать данные из памяти EEPROM просто, а вот записать — нет. По меркам электрических процессов, процесс записи в данном случае занимает много времени (миллисекунды), и поэтому следует по возможности избегать случайной записи в память EEPROM. Таким образом, необходим набор средств управления для ини- циализации процесса записи и определения момента его окончания. Эти функции выполняет регистр EECON1 (рис. 7.38). 7 6 5 4 3 2 1 0 — — — EEIF WRERR WREN WR RD Рис. 7.38. Регистр EECON1 микроконтроллера PIC 16F84A Для того чтобы считать данные из ячейки памяти EEPROM, необходимый адрес требуется поместить в регистр EEADR и установить в лог. 1 разряд RD регистра EECON1. Данные из соответствующей ячейки памяти будут сразу же скопированы в регистр EEDATA. Для записи в ячейку памяти EEPROM соответствующие данные и адрес следует поместить в регистры EEDATA и EEADR соответственно. Процесс записи разреша- ется путем установки в лог. 1 разряда WREN регистра EECON1, после чего необхо- димо передать последовательно байты $55 и $АА в регистр EECON2. Эти коды по- зволяют обезопаситься от случайной записи (например, при включении питания или при его исчезновении). Далее устанавливается в лог. 1 разряд WR регистра EE- CON 1, чем фактически и начинается процесс записи. О завершении этого процесса сигнализирует установка флага EEIF. Микроконтроллеры серии 12F50x При производстве некоторых микроконтроллеров PIC компания Microchip су- мела втиснуть большое количество функций в крошечный корпус с восемью выво- дами. К ним относится и серия PIC 12F50x, представители которой (12F508 и 12F509) в значительной степени напоминают модель PIC 16F54. Для них не тре- буется никакого внешнего осциллятора (кварцевого или RC), поскольку микросхема оснащена внутренним осциллятором на 4 МГц. Она даже позволяет внешним сигна- лам выводить себя из “спящего” состояния. Для любого приложения, в котором не- большой размер является преимуществом, и достаточно шести выводов микрокон- троллеры серий PIC 12F50x просто неоценимы. Основные отличительные особенности этой серии устройств связаны с регист- ровым файлом (рис. 7.39). Первое» отличие связано с регистром состояния STATUS. Серия PIC 12F50x предлагает возможность выхода из “спящего” режима при изменении состояния од- ного из трех выводов: GPO, GP1 или GP3. Для контроля за этим используется ранее незадействованный седьмой разряд регистра STATUS. Кроме того, данная функция разрешена только в том случае, если обнулен седьмой разряд регистра OPTION. ПРИМЕЧАНИЕ Вывод GP3 работает только как вход и не может быть сконфигурирован как выход. Шестой разряд регистра OPTION также выполняет особую роль. Если он обну- лен, то микроконтроллер на выводах GPO, GP1 и GP3, когда они ни к чему не под- ключены, установит состояние лог. 1. Эта функция известна под названием “слабые подтягивающие сопротивления” (weak pull-ups). Она полезна, когда выводы исполь-
Микроконтроллеры серии 12F50x 217 зуются как входы, которые переводится в состояние логического нуля, если что то происходит (например, если между выводом и О В подключить кнопку, то ее нажа- тие переводит вход в состояние лог. 0). Если активизированы слабые подтягиваю- щие сопротивления, то отпадает необходимость во внешнем подтягивающем рези- сторе. Если данная функция не нужна, то шестой разряд регистра OPTION должен быть установлен в лог. 1. Рис. 7.39. Регистровый файл микроконтроллеров PIC 12F50X Еще одна отличительная особенность микроконтроллеров PIC 12F50x — нали- чие по адресу $05 в регистровом файле регистра OSCCAL. Он служит для калиб- ровки осциллятора. Для обеспечения более высокой точности работы внутреннего осциллятора на 4 МГц в регистр OSCCAL должно быть занесено специальное чи- словое значение. Как и в случае с серией PIC 16F5x, процессор вначале выполнит команду, хранимую в последней ячейке памяти программ. В процессе изготовления микроконтроллера в эту ячейку записывается особая ассемблерная команда, которая переносит калибровочное значение в рабочий регистр: movlw хх ; перемещает калибровочное значение в регистр w После выполнения данной команды ход выполнения программы автоматически возвращается к адресу $000. При стирании памяти нового микроконтроллера PIC вначале следует считать содержимое памяти программ и записать числовое значение, запрограммированное изготовителем, чтобы впоследствии записать его по требуемому адресу самостоятельно. Для того чтобы сделать внутренний осциллятор более точным, по адресу $000 следует записать следующую команду:
218 Глава 7. Восьмиразрядные микроконтроллеры PIC movwf OSCCAL ; используется предустановленное значение Если точность осциллятора значения не имеет, то эту команду можно пропус- тить и просто разместить по адресу $000 с помощью команды org команду goto start. В завершение отметим, что в микроконтроллерах PIC 12F50x реализовано две особые ог/ции конфигурирования: • возможность отключить сброс по сигналу на выводе MCLR; • возможность использования внутреннего осциллятора.
Глава 8 Семейство PIC18F Семейство микроконтроллеров PIC18F было разработано компанией Microchip для реализации комплексных проектов с применением операционной системы ре- ального времени (RTOS — Real-Time Operating System) и сложных протоколов об- мена данными, таких как TCP/IP, CAN, USB и ZigBee. Перечислим основные характеристики микроконтроллеров семейства PIC18F: • восьмиразрядная шина данных; • 77 16-разрядных команд; • допускается использование программного кода, предназначенного для микро- контроллеров PIC16; • память программ до 2 Мбайт; • ОЗУ до 4 Кбайт; • частота процессора до 40 МГц; • аппаратный умножитель 8><8; • возможность назначать прерываниям уровни приоритетности; • до двух восьми- и до трех 16-разрядных таймеров/счетчиков; • до четырех внешних источников прерывания; • возможность приема и выдачи тока до 25 мА; • до пяти модулей ССР; • порт MSSP (режимы SPI и 12С); • один или два модуля USART; • порт PSP; • высокоскоростной 10-разрядный АЦП; • программируемый модуль обнаружения провалов напряжения; • сторожевой таймер со встроенным RC-осциллятором; • возможность внутрисхемного программирования. Кроме того, некоторые представители семейства PIC18F предоставляют сле- дующие интерфейсы: • CAN 2.0; • USB 2.0; • интерфейс прямого управления ЖК-дисплеем; • TCP/IP; • ZigBee; • интерфейс прямого управления двигателем.
220 Глава 8. Семейство PIC18F На рис. 8.1 показана структурная схема микроконтроллеров PIC18F4x2. 21 .21 Схема инкремен- та/декре мента Шина данных Фиксация данных □ЗУ (до 4 Кбайт) Фиксация адреса Память программ (до 2 Мбайт) Фиксация данных 16 I Фиксация [ I таблицы I Регистр команды |pCLATu|pCLATb| | PCU| РСН| PCL| Счетчик команд £ |31-уровн стек | OSC2AXKO OSC1/CLKI Дешифрация команды и управление жг T1OSCI T1OSCO MCLR VOD,VSS Схема управ- ления такти- < рованием Тошыйисточ- нис опорного =i напряжения Таймыр запуска Таймер пуска осциллятора Сброс по подаче -Лианна..... Сторожевой таймер Сброс по провалу напряжения Низковольт- ное програм- мирование Внутрисхем- ный отпад- чик Фиксация адреса Адрес 4N 12 FSRO FSR1 FSR2 Схема »| Декодир инкДО/ |де*рем TV |БанкО, F| 12 | PROOH PRODLl 3 | Умножитель 8x81 ♦ Л ,8 |В1ТОР| IWREGkr RA0/AN0 RA1/AN1 RA2/AN2/VREF- RA3/AN3A/REF* RA4/TOCK[ RA5AN4SS4VDIN RA6 । ПортЕ RDQ/PSPO | RD1/PSP1 . RD2/PSP2 ' RD3ZPSP3 I RD4/PSP4 RD5/PSP5 I RD6/PSP6 । RD7/PSP7 . 1 -—-И REVANWR ’—И RE2.'AN7/CS RE0/AN5/RD т 21 8 8 8 8 8 Рис. 8.1. Структурная схема микроконтроллеров PIC18F4x2 Сравнение характеристик некоторых популярных моделей семейства PIC18F дано в табл. 8.1. В этой главе мы рассмотрим микроконтроллеры PIC18Fxx2. Архи- тектура остальных представителей семейства PIC 18F подобна.
Организация памяти 221 Таблица 8.1. Некоторые представители подсемейства PIC18Fxx2 Свойство PIC18F242 PIC18F252 PIC18F442 PIC18F452 Память программ, Мбайт 16 32 16 32 ОЗУ, байт 768 1536 768 1536 Память EEPROM, байт 256 Параллельные порты 3 I I 5 _ Таймеры/счетчики 4 Источники прерывания 17 | 18 Модули ССР 2 Каналы АЦП 5 I I § В качестве примера сравним характеристики микроконтроллеров семейств PIC 16F и PIC 18F. Их сходства: • схема расположения выводов; • имена и функции регистров специального назначения; • набор периферийных устройств. Отличия микроконтроллеров PIC18F: • удвоено число команд; • 16-разрядное командное слово; • аппаратный умножитель 8x8; • больше внешних источников прерывания; • система прерываний допускает назначение приоритетности; • расширенный регистр состояния; • увеличен объем памяти программ и данных; • увеличен стек; • тактовый генератор с системой фазовой автоподстройки частоты (PLL); • усовершенствованная архитектура портов ввода-вывода; • присутствует набор конфигурационных регистров; • уменьшено энергопотребление. Организация памяти В качестве примера рассмотрим микроконтроллер PIC18F452. Начнем с органи- зации ОЗУ, которое состоит из 16 банков по 256 байт в каждом, хотя из нйх исполь- зуются только шесть (рис. 8.2). Эти шесть банков (1536 байт) занимают нижнюю область ОЗУ. В случае использования компилятора с языка С переключение банков происходит автоматически, т.е. пользователю не нужно думать о том, в каком месте программы выбрать тот или иной банк. ПРИМЕЧАНИЕ На рис. 8.2 используются следующие обозначения: “РОН” — регистры общего назначения; ’РСН" — регистры специального назначения. Организация памяти программ микроконтроллера PIC18F452 показана на рис. 8.3. Область, доступная для пользователя, занимает пространство адресов от $0000 до $7FFF. Доступ по адресу в диапазоне $8000..$lFFFFF приведет к считыва-
222 Глава 8. Семейство PIC18F нию нулевых значений. Память программ адресуется побайтно, а команды хранятся по два или четыре байта. Старший байт командного слова всегда записывается в ячейки с четными адресами. BSR<3:0> = 0101 = 0110 = 0000 --------► = 0001 = 0010 --------► = 0011 --------► = 0100 = 1110 --------► Рис. 8.2. Организация ОЗУ микроконтроллера PIC18F452 Конфигурационные регистры Микроконтроллер PIC18F452 предоставляет набор конфигурационных регист- ров, которые программируются с помощью программатора. Доступные разряды та- ких регистров в незапрограммированном состоянии содержат “I”. Рассмотрим основные из этих регистров подробнее. Первый конфигурационный регистр находится по адресу $300001 и называется CONFIG Ш (рис. 8.4).
Организация памяти 223 | Счетчик команд CALL t RCALb. RETUREfft 2 V RETFIE,RETLW ' 1-й уровень стека 31-й уровень стека Вектор сброса Вектор прерывания с высоким приоритетом ooooh Вектор прерывания с низким приоритетом Встроенная в кристалл память программ OOOBh 0018h 7FFFh BOOOh iFFFFFh 200000b- Рис. 8.3. Организация памяти программ микроконтроллера PIC18F452 7 6 5 4 3 2 1 0 — — OSCSEN — — FOSC2 FOSC1 FOSC0 Рис. 8.4. Конфигурационный регистр CONFIG1H Этот регистр служит для выбора источников тактирования микроконтроллера. Назначение его разрядов: • OSCSEN — активизация переключения источников системной синхронизации: 1 — в качестве источника системной синхронизации используется главный ос- циллятор; 0 — активно переключение осцилляторов; • FOSC[2:0] — выбор осциллятора: ► 111 — RC, вывод OSC2 сконфигурирован как RA6; ► 110 — HS, активизирована фазовая автоподстройка частоты, тактовая частота равна 4 х fosc-9 ► 101 — ЕС, вывод OSC2 сконфигурирован как RA6; ► 100 — ЕС, вывод OSC2 сконфигурирован как выход с делением частоты на четыре; ► ОН—RC; ► 010 —HS; ► 001 — XT; ► 000 —LP. Второй конфигурационный регистр находится по адресу $300002 и называется CONFIG2L (рис. 8.5). 7 6 5 4 3 2 1 0 — — — — BORV1 BORVO BOREN PWRTEN Рис. 8.5. Конфигурационный регистр CONFIG2L
224 Глава 8. Семейство PIC18F Этот регистр служит для настройки схемы обнаружения провалов напряжения. Назначение его разрядов: • BORV[1:0] — выбор порогового напряжения, ниже которого происходит сброс микроконтроллера: 11 — 2,5 В; 10 — 2,7 В; 01 — 4,2 В; 00 — 4,5 В; • BOREN — активизация слежения за провалами напряжения: 1 — активно; 0 — отключено; • PWRTEN — активизация таймера включения: 1 — отключен; 0 — активен. Следующий конфигурационный регистр находится по адресу $300003 и назы- вается CONFIG2H (рис. 8.6). 7 6 5 4 3 2 1 0 — — — — WDTPS2 WDTPS1 WDTPS0 WDTEN Рис. 8.6. Конфигурационный регистр CONFIG2H Этот регистр служит для конфигурирования сторожевого таймера. Назначение его разрядов: • WDTPS[2:0] — выбор коэффициента деления частоты тактирования сторожево- го таймера: 111 — 128; 110 — 64; 101 — 32; 100 — 16; 011 — 8; 010 — 4; 001 — 2; 000 — деление отсутствует; • WDTEN — активизация сторожевого таймера: 1 — активен; 0 — выключен. Конфигурационный регистр CONFIG3H, расположенный по адресу $300005, содержит единственный разряд ССР2МХ. Его назначение — мультиплексирование входа/выхода модуля ССР2: 1 — с выводом RC1; 0 — с выводом RB3. Следующий конфигурационный регистр, который мы рассмотрим, находится по адресу $300008 и называется CONFIG5L (рис. 8.7). 7 6 5 4 3 2 1 0 — — — — СРЗ СР2 СР1 СРО Рис. 8.7. Конфигурационный регистр CONFIG5L Этот регистр определяет защиту блоков памяти программ. Обнуление того или иного разряда этого регистра соответствует защите определенного диапазона адре- сов: • СРО —$0200..$lFFF; • CPI — $2000..$3FFF; • СР2 — $4000..$5FFF; • СРЗ — $6000..$7FFF. Еще один “защитный” конфигурационный регистр — CONFIG5H (рис. 8.8). 7 6 5 4 3 2 1 0 CPD СРВ — — — — — — Рис. 8.8. Конфигурационный регистр CONFIG5H Этот регистр, расположенный по адресу $300009, отвечает за защиту памяти EEPROM (разряд CPD) и кода загрузчика (СРВ). Обнуление разряда соответствует активизации защиты.
Организация тактирования 225 Для защиты от записи памяти программ, памяти EEPROM и кода загрузчика служит пара регистров CONFIG6L, расположенный по адресу $30000А (рис. 8.9), и CONFIGH, расположенный по адресу $30000В (рис. 8.10). 7 6 5 4 3 2 1 0 — — — — WRT3 WRT2 WRT1 WRT0 Рис. 8.9. Конфигурационный регистр CONFIG6L 7 6 5 4 3 2 1 0 WRTD WRTB WRTC — — — — — Рис. 8.10. Конфигурационный регистр CONFIG6H Соответствие разрядов WRT[3:0] различным блокам памяти программ анало- гично сказанному выше для разрядов СР[2:0] регистра CONFIG5L. То же самое от- носится и к разрядам WRTD и WRTB: они защищают от записи память EEPROM и код загрузчика. Разряд WRTC отвечает за защиту от записи блока конфигураци- онных регистров. Защиту от табличного чтения памяти программ и области загрузчика реализуют конфигурационные регистры CONFIG7L (рис. 8.11) и CONFIG7H (рис. 8.12), распо- ложенные по адресам $30000С и $30000D соответственно. 7 6 5 4 3 2 1 0 — — — — EBTR3 EBTR2 EBTR1 EBTR0 Рис. 8.11. Конфигурационный регистр CONFIG7L 7 6 5 4 3 2 1 0 — EBTRB . — — — — — — Рис. 8.12. Конфигурационный регистр CONFIG7H Организация тактирования Организация тактирования микроконтроллеров семейства PIC18F во многом подобна той, которая была рассмотрена в предыдущей главе. Затронем лишь неко- торые отличительные особенности, характерные, в частности, для PIC18F452. Пре- жде всего отметим, что за выбор источника тактового сигнала отвечает рассмотрен- ный выше конфигурационный регистр CONFIGШ (см. рис. 8.4). В случае использования кварцевого осциллятора между выводами OSC1 и OSC2 (см. рис. 7.2) номиналы конденсатором следует выбирать по табл. 8.2. Таблица 8.2. Выбор конденсаторов для кварцевого осциллятора PIC18F452 Режим Частота С1,С2 LP 32 кГц 33 пФ LP 200 кГц 15 пФ хт 200 кГц 22-68 пФ XT 1 МГц 15 пФ XT 4 МГц 15 пФ HS 4 МГц 15 пФ HS 8 МГц 15-33 пФ
226 Глава 8. Семейство PIC18F Таблица 8.2. Выбор конденсаторов для кварцевого осциллятора PIC18F452 Режим Частота С1, С2 HS 20 МГц 15-33 пФ HS 25 МГц 15-33 пФ В случае использования внешнего тактового сигнала на входе OSC1 микрокон- rpojpiep перевести в такой режим, чтобы на выходе OSC2 был получен импульсный сигнал с частотой в четыре раза меньше частоты сигнала на OSC1. Этому режиму соответствует запись двоичного значения “110” или “100” в разряды FOSC[2:0] конфигурационного регистра CONFIG 1Н (см. рис. 8.4). Также доступны два режи- ма, когда вывод OSC2 выполняет роль обычного порта ввода-вывода RA6. При подключении к выводу OSC1 RC-осциллятора номиналы конденсатора и резистора для микроконтроллеров PIC18Fxx2 выбирают по табл. 8.3. Таблица 8.3. Выбор компонентов RC-осциллятора С R Частота 22 пФ 3,3 кОм 3,3 МГц 4,7 кОм 2,3 МГц 10 кОм 1,08 МГц 30 пФ 3,3 кОм 2,4 МГц 3,9 кОм 2 МГц 4,7 кОм 1,7 МГц 10 кОм 793 кГц Внутренний осциллятор Некоторые микроконтроллеры семейства PIC18F оснащены встроенным осцил- лятором (в подсемействе PIC18Fxx2 он отсутствует). При его использовании выво- ды OSC1 и OSC2 могут выполнять роль обычных портов RA6 и RA7. Для управле- ния внутренним осциллятором служит регистр OSCCON (рис. 8.13). 7 6 5 4 3 2 1 0 IDLEN IRCF2 IRCF1 IRCF0 OSTS IOFS SCSI scso Рис. 8.13. Регистр OSCCON Рассмотрим назначение разрядов этого регистра: • IDLEN — выбор режима работы осциллятора: 1 — в “спящем” режиме; 0 — в активном режиме; • IRCF[2:0] — выбор частоты: 111 —8МГц; 110 —4МГц; 101 — 2 МГц; 100 — 1 МГц; 011 — 500 кГц; 010 — 250 кГц; 001 — 125 кГц; 000 — 31 кГц; • OSTS — флаг, указывающий на срабатывание таймера запуска внутреннего ос- циллятора; _ • IOFS — флаг стабильности работы внутреннего осциллятора (1 — стабилен). Переключение источника тактирования Разряды SCS[1:0] регистра OSCCON отвечают за переключение источника так- тирования с основного осциллятора на низкочастотный тактовый сигнал и обратно: • 00 — внешний осциллятор на выводах OSC1/OSC2; '
Таймеры 227 • 01 — осциллятор таймера 1; • 1 х — внутренний осциллятор. Для разрешения такого режима должен быть предварительно обнулен разряд OSCSEN конфигурационного регистра CONFIG 1Н (см. рис. 8.4). Если микроконтроллер не оснащен внутренним осциллятором (как, например, PIC18F452), то регистр OSCCON содержит единственный (нулевой) разряд SCS. В таком случае лог. 1 в данном разряде соответствует работе от осциллятора тайме- ра 1, а лог. 0 — основному осциллятору на выводах OSC1/OSC2. Таймеры Многие представители семейства PIC18F предоставляют в распоряжение поль- зователя четыре таймера. Рассмотрим их применительно к микроконтроллеру PIC18F452. Поскольку таймер 2 в семействе PIC18F реализован типичным для восьмиразрядных микро- контроллеров образом, он здесь рассмотрен не будет (см. предыдущую главу). То же самое относится и к двум модулям ССР, для управления которыми предназначены регистры ccpiconhcx^ TMR0 Таймер 0 микроконтроллера PIC18F452 подобен таймеру 0 семейства PIC16 за тем исключением, что может работать не только в восьми-, но и в 16-разрядном ре- жиме. Кроме того, для управления TMR0 вместо традиционного регистра OPTION (см. рис. 7.10) служит регистр TOCON (рис. 8.14). 7 6 5 4 3 2 1 0 TMROON T08BIT TOCS TOSE PSA T0PS2 T0PS1 TOPSO Рис. 8.14. Регистр TOCON Функция младших шести разрядов этого регистра аналогична функциям соот- ветствующих разрядов регистра OPTION, Разряд T08BIT определяет работу в вось- ми- (I) или 16-тиразрядном (0) режиме, а разряд TMROON включает (1) или оста- навливает (0) таймер. В 16-разрядном режиме вместо одного счетного регистра используется регист- ровая пара TMR0L:TMR0 (рис. 8.15). Младший байт (TMR0L) загружается непо- средственно с шины данных, а старший (TMR0) — через буфер TMR0H. Во время чтения из регистра TMR0L старший байт результата также загружается в регистр TMR0H. Таким образом, результат считывается двумя командами: вначале — младший байт, затем — старший. Аналогичным образом, при записи данных в регистр TMR0L регистр TMR0 об- новляется содержимым буфера TMR0H. Таким образом, перед инициализацией таймера должно быть предварительно записан старший байт в регистр TMR0H. Этот байт будет перенесен в регистр TMR0 автоматически при записи в регистр TMR0L.
228 Глава 8. Семейство PIC18F Рис. 8.15. Счетные регистры TMR0 в 16-разрядном режиме TMR1 Схема этого таймера и управление им реализовано в представителях семейства PIC18F так же, как и во всех остальных восьмиразрядных микроконтроллерах PIC. Отличие заключается только в наличии разряда RD 16 в регистре T1CON. Если этот разряд обнулен, то запись и чтение счетного регистра TMR1 представляет собой две восьмиразрядные операции. В том случае, если RD 16 = 1, работа с регистровой па- рой TMR1L:TMR1 реализована так же, как при работе TMR0 в 16-разрядном режи- ме, т.е. через буфер TMR1H (см. рис. 8.15). TMR3 Структура таймера 3 подобна структуре таймера 1, поэтому останавливаться на нем подробно мы не будем. Рассмотрим только соответствующий ему управляющий регистр T3CON (рис. 8.16). 7 6 5 4 3 2 1 О RD16 ТЗССР2 T3CKPS1 T3CKPS0 ТЗССР1 T3SYNC TMR3CS TMR3ON Рис. 8.16. Регистр T3CON Назначение разрядов этого регистра: • TMR3ON — активизация/отключение таймера 3; • TMR3CS — выбор источника тактирования: 1 — внешний осциллятор или сиг- нал на выводе T1CKI; 0 — внутренний тактовый сигнал частотойybsc/4; • T3SYNC — управление синхронизацией с внешним тактовым сигналом: 1 — синхронизация отсутствует; 0 — синхронизация активна; • ТЗССР1 — выбор таймера 1 в качестве источника тактирования для модулей ССР: 1 — TMR1 тактирует модуль ССР1, a TMR3 — ССР2; 0 — TMR1 тактиру- ет оба модуля ССР; • T3CKPS[1:0] — выбор коэффициент деления частоты: 11 — 8; 10 — 4; 01 — 2; 11 — деление отсутствует; • ТЗССР2 — если этот разряд установлен в лог. 1, то TMR3 тактирует оба модуля ССР;
ацп 229 • RD16 -н если этот разряд обнулен, то запись и чтение счетного регистра TMR3 представляет собой две восьмиразрядные операции. В том случае, если RD 16 = = 1, работа с регистровой парой TMR3L:TMR3 реализована так же, как при ра- боте TMR0 в 16-разрядном режиме, т.е. чер^з буфер TMR3H (см. рис. 8.15). АЦП Аналого-цифровое преобразование у представителей семейства PIC18F реали- зовано практически так же, как было показано в предыдущей главе. Единственное отличие заключается в появлении нового разряда ADCS2 в управляющем регистре ADCON1 (см. рис. 7.31). Его назначение — удвоить количество возможных коэф- фициентов деления частоты осциллятора для тактирования АЦП (табл. 8.4). Таблица 8.4. Выбор рабочей частоты АЦП микроконтроллеров PIC18F ADCS2 ADCS1 ADCS0 Частота 0 0 0 Частота системной синхронизации / 2 0 0 1 Частота системной синхронизации / 8 0 1 0 Частота системной синхронизации / 32 0 1 1 Тактирование от встроенного RC-осциллятора АЦП 1 0 0 Частота системной синхронизации / 4 1 0 1 Частота системной синхронизации /16 1 1 0 Частота системной синхронизации / 64 1 1 1 Тактирование от встроенного RC-осциллятора АЦП Напомним, что разряды ADCS[1:O], указанные в табл. 8.4, находятся в уп- равляющем регистре ADCONO (см. рис. 7.30). Обработка прерываний Обработка прерываний у представителей семейства PIC18F реализована прак- тически так же, как было показано в предыдущей главе для микроконтроллеров се- рии PIC18C. Основное отличие заключается в появлении нового управляющего ре- гистра RCON (рис. 8.17). IPEN — — RI то PD POR BOR Рис. 8.17. Регистр RCON Старший разряд этого регистра (IPEN) отвечает за активизацию схемы назначе- ния прерываниями уровней приоритетности. Если IPEN = 0, то приоритетность не учитывается, и при возникновении любого прерывания происходит переход по ад- ресу памяти программ $00008. В этом режиме разряд PEIE регистра INTCON (см. рис. 7.19) разрешает/запрещает все прерывания от периферии, а разряд GIE отвечает за общее разрешение прерываний. Если IPEN = 1, то все прерывания разбиваются на две группы: с высоким и с низким приоритетом. Вектор высокоприоритетных прерываний находится в памяти программ по адресу $00008, а низкоприоритетных — по адресу $00018 (см. рис. 8.3). Теперь, если для того или иного прерывания установить соответствующий разряд приоритетности (находятся в регистрах INTCON2, INTCON3, IPR1 и IPR2), то оно станет высокоприоритетным, а в противном случае — низкоприоритетным.
230 Глава 8. Семейство PIC18F Установка в лог. 1 разряда GIEH в регистре INTCON разрешает все высокоприори- тетные прерывания, а установка разряда GIEL — все низкоприоритетные. Остальные разряды регистра RCON — это флаги, позволяющие определить причину сброса микроконтроллера: у • RI — если этот разряд обнулен, то это указывает на выполнение команды reset; • ТО — если этот разряд обнулен, то это указывает на сброс от сторожевого тай- мера; он устанавливается в лог. 1 при включении питания, а также — по коман- де clrwdt или sleep; • PD — если этот разряд обнулен, то это указывает на выполнение команды sleep; он устанавливается в лог. 1 при включении питания или по команде clrwdt; • POR — если этот разряд обнулен, то это указывает на сброс при подаче пита- ния; • BOR — если этот разряд обнулен, то это указывает на сброс при обнаружении провала напряжений.
Глава 9 Семейство PIC24 В 2007 году компания Microchip дала миру новое семейство микроконтролле- ров, оперирующих уже не восьми-, а 16-разрядными данными. Эта технология по- лучила название PIC24. Номер “24” в ее названии объясняется использованием 24- разрядных команд и 24-разрядной адресации. В остальном многие архитектурные характеристики микроконтроллеров PIC24 пересекаются с их восьмиразрядными предшественниками, однако есть и ряд существенных отличий. Поскольку рассмот- реть подробно технологию PIC24 в рамках этой книги не представляется возмож- ным, мы затронем лишь основные ее особенности. Кроме того, в главе 22 будут да- ны примеры программ для микроконтроллера PIC24FJ128GA010. Все микроконтроллеры PIC24 делятся на несколько подсемейств: • PIC24F04KА20х — самые простые представители семейства с 14 и 20 вывода- ми, минимальным составом периферии, небольшим объемом ОЗУ (512 байт), поддержкой последовательной передачи данных по инфракрасному каналу и новым модулем аналоговых измерений CTMU; • PIC24FxxKA 1 Ох — расширенная версия предыдущего подсемейства: 20 выво- дов, 1,5 Кбайт ОЗУ, 512 байт памяти EEPROM, часы реального времени; • PIC24FJxGA — более сложные микроконтроллеры с ОЗУ объемом 8 Кбайт, портами РМР и PSP и интерфейсом JTAG' однако без поддержки CTMU; • PIC24FJxGB — устройства с ОЗУ объемом 16 Кбайт, возможностью переназна- чения 44 цифровых линий ввода-вывода различным периферийным устройст- вам непосредственно во время выполнения программы (технология PPS), пор- тами РМР и PSP, интерфейсами USB и JTAG, модулем CTMU и возможностью беспроводной последовательной передачи данных; • PIC24HJ — микроконтроллеры с модулем прямого доступа к памяти (DMA), контроллером прерываний, девятью 16-разрядными таймерами, 18/32-каналь- ными АЦП и интерфейсом CAN. Максимальная частота — 200 МГц! Базовые характеристики микроконтроллеров PIC24 сведены в табл. 9.1, набор периферийных модулей — в табл. 9.2, а наличие интерфейсов передачи данных — в табл. 9.3. Таблица 9.1. Базовые характеристики микроконтроллеров PIC24 Устройство Выво- дов ОЗУ, Кбайт Память про- грамм, Кбайт Память EEPROM, байт Порты (линий) 24F04KA200 14 0,5 4 — А(7), В(5) 24F04KA201 20 0,5 4 — А(7), В(10) 24F08KA101 20 1,5 8 512 А(7), В(11) 24F08KA102 28 1,5 8 512 А(8), В(16) 24F16KA101 20 1,5 16 512 А(7), В(11) 24F16KA102 28 1,5 16 512 А(8), В(16)
232 Глава 9. Семейство PIC24 Таблица 9.1. Продолжение Устройство Вы- во- дов ОЗУ, Кбайт Память программ, Кбайт Память EEPROM, байт Порты (линий) 24FJ128GA006 64 8 128 — В(16), С(4), D(12), Е(8), F(7), G(6) 24FJ128GA008 80 8 128 — А(4), В(16), 0(6), D(16), Е(10), F(9), G(8) 24FJ128GA010 100 8 128 — , А(12), В(16), С(8), D(16), Е(10), F(11), G(12) 24FJ64GA006 64 8 64 — В(16), 0(4), D(12), Е(8), F(7), G(6) 24FJ64GA008 80 8 64 — А(4), В(16), С(6), D(16), Е(10), F(9), G(8) 24FJ64GA010 100 8 64 — А(12), В(16), С(8). D(16), Е(10), F(11), G(12) 24FJ96GA006 64 8 96 — В(16), 0(4), D(12), Е(8), F(7), G(6) 24FJ96GA008 80 8 96 — А(4), В(16), С(6), D(16), Е(10), F(9), G(8) 24FJ96GA010 100 8 96 — А(12), В(16), С(8), D(16), Е(10), F(11), G(12) 24FJ128GB106 64 16 128 — В(16), 0(4), D(12), Е(8), F(5), G(6) 24FJ128GB108 80 16 128 — А(4), В(16), С(6), D(16), Е(10), F(7), G(8) 24FJ128GB110 100 16 128 — А(<2), В(16), С(8). D(16), Е(10), F(9), G(12) 24FJ192GB106 64 16 192 — В(16), 0(4), D(12), Е(8), F(5), G(6) 24FJ192GB108 80 16 192 — А(4), В(16), С(6), D(16), Е(10), F(7). G(8) 24FJ192GB110 100 16 192 — А(12), В(16), С(8), D(16), Е(10), F(9), G(12) 24FJ256GB106 64 16 256 — В(16), 0(4), D(12), Е(8), F(5), G(6) 24FJ256GB108 80 16 256 — А(4), В(16), С(6), D(16), Е(10), F(7), G(8) 24FJ256GB110 100 16 256 — А(12), В(16), 0(8), D(16), Е(10), F(9), G(12) 24FJ64GB106 64 16 64 — В(16), 0(4), D(12), Е(8), F(5), G(6) 24FJ64GB108 80 16 64 4 А(4), В(16), С(6), D(16), Е(10), F(7), G(8) 24FJ64GB110 100 16 64 — А(12), В(16), С(8), D(16), Е(10), F(9), G(12) 24HJ128GP206 64 8 128 — А(14), В(16), 0(8), D(16), Е(8), F(11), G(12) 24HJ128GP210 100 8 128 — А(14), В(16), 0(8), D(16), Е(8), F(11), G(12) 24HJ128GP306 64 16 128 — А(14), В(16)> 0(8), D(16), Е(8), F(11), G(12) 24HJ128GP310 100 16 128 — А(14), В(16), С(8), D(16), Е(8), F(11), G(12)
Обработка прерываний 233 Таблица 9.1. Окончание Устройство Вы- во- дов ОЗУ, Кбайт Память программ, Кбайт Память EEPROM, байт Порты (линий) 24HJ128GP506 64 8 128 — А(14), В(16), С(8), D(16), Е(8). F(11), G(12) 24HJ128GP510 100 8 128 — А(14), В(16), С(8), 0(16), Е(8), F(11), G(12) 24HJ256GP206 64 16 256 — А(14), В(16), 0(8), 0(16), Е(8), , F(11). G(12) 24HJ256GP210 100 16 256 — А(14), В(16), С(8), D(16), Е(8), F(11),G(12) 24HJ256GP610 100 16 256 — А(14), В(16), 0(8), D(16), Е(8), F(11). G(12) 24HJ64GP206 64 8 64 — А(14), В(16), С(8), D(16), Е(8), F(11), G(12) 24HJ64GP210 64 8 64 — А(14), В(16), 0(8), D(16), Е(8), F(11), G(12) 24HJ64GP506 64 8 64 — А(14), В(16), 0(8), D(16), Е(8), F(11), G(12) 24HJ64GP510 64 8 64 — А(14), В(16), С(8), D(16), Е(8), F(11), G(12) Таблица 9.2. Периферийные модули микроконтроллеров PIC24 Устройство Тай- ме- ры Часы ре- ального времени Захват на вхо- де Сравнение на выходе / ШИМ UART АЦП (кана- лов) Ком- пара- торы CTMU 24F04KA200 3 — 1 1 1 1(7) 2 Есть 24F04KA201 3 — 1 1 1 1 О) 2 Есть 24FxxKA10x 3 Есть 1 1 2 1 О) 2 Есть 24FJxGA 5 Есть 5 5 2 1 (16) 2 — 24FJxGB 5 Есть 9 9 4 1 (16) 3 Есть 24HJ128GP206 9 Есть 8 8 2 1 (18) — — 24HJ128GP210 9 Есть 8 8 2 1(32) — — 24HJ128GP306 9 Есть 8 8 2 1 (18) — — 24HJ128GP310 9 Есть 8 8 2 1 (32) — — 24HJ128GP506 9 Есть 8 8 2 1 (18) — — 24HJ128GP510 9 Есть 8 8 2 1 (32) — — 24HJ256GP206 9 Есть 8 8 2 1 (18) — — 24HJ256GP210 9 Есть 8 8 2 1 (32) — — 24HJ256GP610 9 Есть 8 8 2 2(32) — — 24HJ64GP206 9 Есть 8 8 2 1 (18) — — 24HJ64GP210 9 Есть 8 8 2 1 (32) — — 24HJ64GP506 9 Есть 8 8 2 1 (18) — — 24HJ64GP510 9 Есть 8 8 2 1 (32) — —
234 Глава 9. Семейство PIC24 Таблица 9.3. Интерфейсы микроконтроллеров PIC24 Устройство IrDA SPI l2C РМР PSP JTAG USB CAN 24F04KA20X Есть 1 1 — — — — — 24FxxKA10x Есть 1 1 — — — — — 24FJxGA Есть 2 2 Есть Есть Есть — — 24FJXGB Есть 3 3 Есть Есть Есть Есть — 24HJ128GP206 Есть 2 2 — — — — — 24HJ128GP210 Есть 2 2 — — — — — 24HJ128GP306 Есть 2 2 — — — — — 24HJ128GP310 Есть 2 2 — — — — — 24HJ128GP506 Есть 2 2 — — — — 1 24HJ128GP510 Есть 2 2 — — — — 1 24HJ256GP206 Есть 2 2 — — — — — 24HJ256GP210 Есть 2 2 — — — — — 24HJ256GP610 Есть 2 2 — — — — 2 24HJ64GP206 Есть 2 1 — — — — — 24HJ64GP210 Есть 2 2 — — — — — 24HJ64GP506 Есть 2 2 — — — — 1 24HJ64GP510 Есть 2 2 — — — — 1 Структура микроконтроллера PIC24 показана на примере подсемейства PIC24FJxGA (рис. 9.1). Поскольку подробное изучение технологии PIC24 выходит за тематические рамки этой книги, мы затронем только некоторые отличительные особенности данного семейства устройств. Порты Попытка программно сконфигурировать выводы порта В, как входы, путем за- писи нулей в соответствующие разряды регистра TRISB может завершиться ничем. Причина в том, что большинство выводов порта В мультиплексированы с аналого- выми входами АЦП. Другими словами, в 16-разрядной архитектуре PIC порты А и В поменялись ролями. В восьмиразрядных микроконтроллерах PIC только пользователь мог опреде- лить направление передачи данных через тот или иной вывод, даже если его ис- пользования требовал какой-либо периферийный модуль. В архитектуре PIC24 ре- жим работы вывода всецело зависит от входного/выходного сигнала некоторого пе- риферийного модуля, мультиплексированного на этот вывод, независимо от содер- жимого регистра TRISx. По умолчанию выводы, мультиплексированные с “аналоговыми” входами, от- соединены от своих “цифровых” входов. При подаче питания все выводы порта В по умолчанию выполняют функцию аналоговых входов. Как следствие, чтение пор- та В даст все нули. Тем не менее, в отличие от регистра PORTB, выходной фиксатор порта В (регистр LATB) содержит корректное значение. Для соединения входов порта В с цифровыми входами необходимо оперировать настройками модуля АЦП. За цифро-аналоговое распределение каждого вывода от- вечает регистр специального назначения AD1PCFG (рис. 9.2). Таким образом, для реализации задачи цифрового вывода через порт В необходимо записан лог. 1 в со- ответствующие разряды регистра ADI PCGF. Если же разряд содержит лог. О, то со-
Порты 235 ответствующий вывод сконфигурирован в аналоговом режиме, чтение порта запре- щено, и АЦП опрашивает напряжение на выводе. Рис. 9.1. Структурная схема микроконтроллеров PIC24FJxGA
236 Глава 9. Семейство PIC24 15 14 13 12 11 10 9 8 PCFG15 PCFG14 PCFG13 PCFG12 PCFG11 PCFG10 PCFG9 PCFG8 7 6 5 4 3 2 1 0 PCFG7 PCFG6 PCFG5 PCFG4 PCFG3 PCFG2 PCFG1 PCFG0 Рис. 9.2. AD1PCFG, регистр конфигурирования порта АЦП ПРИМЕЧАНИЕ Как видно из рис. 9.2, большинство управляющих регистров PIC24, включая регистры пор- тов, — 16-разрядные. Таймеры В архитектуре Р1С24 отсутствует таймер 0. Все остальные таймеры, которых может быть от трех до девяти, — 16-разрядные. Имена всех регистров специального назначения, отвечающих за управление таймерами, совпадают с именами, исполь- зованными в восьмиразрядных микроконтроллерах PIC. По структуре они также во многом сходны, но все же не забывайте сверяться со спецификациями. Новые возможности таймеров PIC24: • наличие 16-разрядного регистра периода, предназначенного для организации периодического сброса таймера; • для таймеров 2/3,4/5, 6/7 и 8/9 доступен новый механизм одновременного ис- пользования в паре, обеспечивающий 32-разрядный режим счета; • к таймеру 1 была добавлена новая возможность стробирования внешнего такто- вого сигнала. Прерывания Архитектура PIC24 предоставляет гибкую систему прерываний, поддерживаю- щая до П8 различных источников прерывания. Для обеспечения оперативного от- клика на событие и быстрого возврата в главную программу крайне важно миними- зировать время отклика (период между возникновением события и выполнением первой команды подпрограммы обслуживания прерывания). В архитектуре PIC24 это время не только очень мало, но и фиксировано для каждого источника прерыва- ния: всего лишь три командных цикла для внутренних событий и четыре для внеш- них. Благодаря этой важной особенности системы управления прерываниями, мик- роконтроллеры PIC24 получают явное преимущество перед многими конкурентами. Кроме того, важно отметить, что микроконтроллеры PIC24 хранят все векторы прерываний в одной большой таблице, называемой IVT (Interrupt Vector Table). Компиляторы с языка С, рассчитанные на работу с 16-разрядными устройствами (в частности, рассматриваемый в главе 14 компилятор СЗО), автоматически связы- вают эти векторы со специальными, определенными пользователем функциями. В качестве примера рассмотрим систему прерываний микроконтроллера PIC 24FJ128GA010. Внешние источники прерываний для этого микроконтроллера: • пять — для внешних выводов с обнаружением по изменению уровня;
Прерывания 237 • 22 — для внешних выводов, соединенных с модулем уведомления об изменени- ях (Change Notification); • пять — для модулей захвата на входе (Input Capture); • пять — для модулей сравнения на выходе (Output Compare); • два — для модулей UART; • четыре — для синхронных последовательных интерфейсов (SPI и 12С); • один — для ведущего параллельного порта (РМР). Внутренние источники прерываний микроконтроллера PIC24FJ128GA010: • пять — для таймеров; • один — для АЦП; • один — для модуля аналоговых компараторов; • один — для часов и календаря реального времени; • один — для средств контроля циклическим Избыточным кодом (CRC). Каждому источнику прерываний соответствует пять управляющих разрядов в различных регистрах специального назначения (табл. 9.4): • разряд разрешения прерывания (обычно обозначен с помощью суффикса IE): О — соответствующее событие не вызывает прерывания; 1 — прерывание раз- решено; • флаг прерывания (обычно ^Обозначен с помощью суффикса IF) — устанавлива- ется каждый раз при возникновении соответствующего события независимо от состояния разряда разрешения; ПРИМЕЧАНИЕ Однажды установленный флаг прерывания должен быть сброшен вручную. Другими словами, его необходимо обнулить до выхода из подпрограммы обслуживания прерывания, иначе эта же подпрограмма будет сразу же вызвана еще раз. • уровень приоритетности (обычно обозначен с помощью суффикса IF). Преры- ванию можно назначить один из семи уровней приоритетности. Если одновре- менно возникает два различных запроса на прерывание, то первым будет об- служен тот из них, для которого определен более высокий приоритет. Для ко- дирования приоритетности каждого источника прерываний отведены три раз- ряда. В каждый момент времени уровень приоритетности для задач процессора PIC24 хранится в регистре SR в разрядах IPL0..IPL2. Прерывания, у которых приоритет ниже текущего значения IPL, игнорируются. При подаче питания всем источникам прерываний по умолчанию назначается уровень приоритетно- сти 4, а процессору — уровень 0. Таблица 9.4. Векторы прерываний микроконтроллера PIC24FJ128GA010 Источник прерывания Номер вектора Адрес в IVT Адрес BAIVT Размещение разрядов прерывания Флаг Разрешение Приоритет АЦП1 — преобразование завершено 13 $00002Е $00012Е IFS0<13> IEC0<13> IPC3<6:4> Внешнее прерывание 0 0 $000014 $000114 IFS0<0> IEC0<0> IPC0<2:0> Внешнее прерывание 1 20 $00003С $000130 IFS1<4> IEC1<4> IPC5<2:0> Внешнее прерывание 2 29 $00004Е $00014Е IFS1<13> IEC1<13> IPC7<6:4> Внешнее прерывание 3 53 $00007Е $00017Е IFS3<5> IEC3<5> IPC13<6:4>
238 Глава 9. Семейство PIC24 Таблица 9.4. Окончание Источник прерывания Номер вектора Адрес в IVT Адрес bAIVT Размещение разрядов прерывания Флаг Разрешение Приоритет Внешнее прерывание 4 54 $000080 $000180 IFS3<6> IEC3<6> IPC13<10:8> Генератор CRC 67 $00009А $00019А IFS4<3> IEC4<3> IPC16<14:12> Захват на входе 1 1 $000016 $000116 IFS0<1> IEC0<1> IPC0<6:4> Захват на входе 2 5 $00001Е $00011Е IFS0<5> IEC0<5> IPC1<6:4> Захват на входе 3 37 $00005Е $00015Е IFS2<5> IEC2<5> IPC9<6:4> Захват на входе 4 38 $000060 $000160 IFS2<6> IEC2<6> IPC9<10:8> Захват на входе 5 39 $000062 $000162 IFS2<7> IEC2<7> IPC9<14:12> « Компаратор 18 $000038 $000138 IFS1<2> IEC1<2> IPC4<10:8> Уведомление об изменениях 19 $00003А $0001ЗА IFS1<3> IEC1<3> IPC4<14:12> Сравнение на выходе 1 2 $000018 $000118 IFS0<2> IEC0<2> IPC0<10:8> Сравнение на выходе 2 6 $000020 $000120 IFS0<6> IEC0<6> IPC1<10:8> Сравнение на выходе 3 25 $000046 $000146 IFS1<9> IEC1<9> IPC6<6:4> Сравнение на выходе 4 26 $000048 $000148 IFS1<10> IEC1<10> IPC6<10:8> Сравнение на выходе 5 41 $000066 $000166 IFS2<9> IEC2<9> IPC10<6:4> Таймер 1 3 $00001А $00011А IFS0<3> IEC0<3> IPC0<14:12> Таймер 2 7 $000022 $000122 IFS0<7> IEC0<7> IPC1<14:12> Таймер 3 8 $000024 $000124 IFS0<8> IEC0<8> IPC2<2:0> Таймер 4 27 $00004А $00014А IFS1<11> IEC1<11> IPC6<14:12> Таймер 5 28 $00004С $00014С IFS1<12> IEC1<12> IPC7<2:0> Часы/календарь реального времени 62 $000090 $000190 IFS3<14> IEC3<14> IPC15<10:8> 12С 1 — событие ведомого блока 16 $000034 $000134 IFS1<0> IEC1<0> IPC4<2:0> 12С 1 — событие ведущего блока 17 $000036 $000136 IFS1<1> IEC1<1> IPC4<6:4> 12С 2 — событие ведомого блока 49 $000076 $000176 IFS3<1> IEC3<1> IPC12<6:4> 12С 2 — событие ведущего блока 50 $000078 $000178 IFS3<2> IEC3<2> IPC12<10:8> РМР (ведущий параллельный порт) 45 $00006Е $00016Е IFS2<13> IEC2<13> IPC11<6:4> SPI 1 — ошибка 9 $000026 $000126 IFS0<9> IEC0<9> IPC2<6:4> SPI 1 — событие 10 $000028 $000128 IFS0<10> IEC0<10> IPC2<10:8> SPI 2 — ошибка 32 $000054 $000154 IFS2<0> IEC2<0> IPC8<2:0> SPI 2 — событие 33 $000056 $000156 IFS2<1> IEC2<1> iPC8<6:4> UART 1 — ошибка 65 $000096 $000196 IFS4<1> IEC4<1> IPC16<6:4> UART 1 — передатчик 12 $00002С $00012С IFS0<12> IEC0<12> IPC3<2:0> UART 1 — приемник 11 $00002А $00012А IFS0<11> IEC0<11> IPC2<14:12> UART 2 — ошибка 66 $000098 $000198 IFS4<2> IEC4<2> IPC16<10:8> UART 2 — передатчик 31 $000052 $000152 IFS1<15> IEC1<15> IPC7<10:8> UART 2 — приемник 30 $000050 $000150 IFS1<14> IEC1<14> IPC7<10:8> При подаче питания все источники прерываний по умолчанию неактивны. На- ряду с назначенным уровнем приоритетности, также существует относительный (установленный по умолчанию) приоритет среди различных источников прерыва- ний в соответствии с фиксированным порядком их следования в таблице IVT. Вложение прерываний Прерывания можно вкладывать одно в другое, прерывая менее приоритетные подпрограммы обслуживания прерываний более приоритетными. Этот механизм контролируется разрядом NSTDIS регистра INTCON1. Если этот разряд содержит
Окно Program Space Visibility 239 лог. 1, то при поступлении запроса на прерывание процессору присваиваемся мак- симальный уровень приоритетности (IPL = 7) независимо от уровня приоритетно- сти, определенного для данного события. Это гарантирует, что новые прерывания не будут обслужены до тех пор, пока обслуживается текущее. Другими словами, при установке NSTDIS = 1 уровень приоритетности каждого прерывания использу- ется только для разрешения конфликтов при одновременном поступлении разных запросов, в результате чего все прерывания обслуживаются последовательно. Системные прерывания Первые восемь позиции в таблице IVT занимают дополнительные векторы, предназначенные для обнаружения особых ошибочных состояний, наподобие сбоя выбранного осциллятора, обращения по некорректному адресу, переполнения стека или деления на ноль (математическая ошибка) (табл. 9.5). Таблица 9.5. Векторы системных прерываний Номер вектора Адрес в IVT Источник системного прерывания 0 000004h Зарезервировано 1 000006h Ошибка тактового генератора 2 000008h Ошибочный адрес 3 OOOOOAh Ошибка стека 4 OOOOOCh Математическая ошибка 5 OOOOOEh Зарезервировано 6 00001Oh Зарезервировано 7 000012h Зарезервировано Поскольку такие ошибки обычно приводят к фатальным последствиям для ра- ботающего Приложения, им назначены фиксированные уровни приоритетности вы- ше семи базовых уровней, доступных для всех остальных прерываний. Это также означает, что их невозможно случайно маскировать (или задержать с помощью раз- ряда NSTDIS), благодаря чему мы получаем дополнительный уровень надежности. В архитектуре PIC24 отсутствует отдельный управляющий разряд, запрещающий все преры- вания, зато присутствует специальная команда disi, запрещающая прерывания на ограни- ченное число циклов. ................................... ..................................Й......Й.................................................. ............................... Окно Program Space Visibility Архитектура PIC24 предоставляет два метода чтения памяти программ: • с помощью специальной команды табличного чтения third; • с помощью окна Program Space Visibility (PSV), которое можёт занимать до 32 Кбайт памяти программ, доступной для шины. Другими словами, PSV — это своеобразный мост между шинами памяти про- грамм и данных (рис. 9.3). Обратите внимание на тот факт, что микроконтроллеры PIC24 используют 24- разрядную шину памяти программ при 16-разрядной шине данных. Ввиду этого не- соответствия разрядности двух шин использование “моста” PSV становится еще бо- лее интересным. В действительности PSV связывает с шиной памяти данных только младшие 16 разрядов шины памяти программ. Старшая часть (восемь разрядов) ка-
240 Глава 9. Семейство PIC24 ждого слова памяти программ для окна PSV недоступна. В то же время, при исполь- зовании команд табличного чтения память программ доступна полностью, но — це- ной необходимости проводить различие между работой с данными в ОЗУ (прямая адресация) и с данными в памяти программ (через специальные команды таблично- го доступа). Пространство памяти программ (Flash) Пространство памяти данных (ОЗУ) 24 разряда 16 разрядов 0x0000 0x0800 0x2800 0X7FFF OxFFFF Таким образом, программисту микроконтроллеров PIC24 предоставляется вы- бор: более удобный, однако менее эффективный с точки зрения использования па- мяти метод пересылки данных между двумя шинами с помощью окна PSV, или же более эффективное и менее “прозрачное” решение в виде команд табличного досту- па. Интерфейс SPI В дополнение к возможностям SPI, реализованным в большинстве микрокон- троллеров PIC в модулях SSP и MSSP, модуль SPI-интерфейса микроконтроллеров PIC24 предоставляет ряд новых возможностей: • режим 16-битной передачи; • выбор фазы опроса входных данных; • режим покадровой передачи; • управление синхроимпульсами передачи кадров (выбор полярности и активного фронта); • расширенный режим (восьмиуровневые FIFO-буферы приема/передачи). В частности, в ходе операции последовательного чтения и/или страничной за- писи для повышения производительности и увеличения (вдвое) числа циклов, дос- тупных центральному процессору в промежутках между обращениями к буферам SPI, можно использовать режим 16-битной передачи. Однако по-настоящему раз- грузить процессор позволяет расширенный режим (Enhanced Mode) с его восьми- уровневыми FIFO-буферами. До восьми слов (16 байт) можно записывать в буферы SPI или извлекать их оттуда небольшими фрагментами, оставляя в промежутках го- раздо больше времени центральному процессору на обработку данных.
Порт РМР 241 Порт РМР Разработчики PIC24 создали новый адресуемый параллельный порт РМР для автоматизации и ускорения доступа к большому спектру внешних устройств общего назначения, включая аналого-цифровые преобразователи, буферы оперативной па- мяти, совместимые с шиной ISA интерфейсы, модули ЖК-дисплеев и даже жесткие диски и карты CompactFlash. Можно сказать, что РМР — это гибкая шина ввода-вывода, добавленная в архи- тектуру PIC24, которая не мешает ни 24-разрядной шине памяти программ, ни 16- разрядной шине памяти данных (и не замедляет их работу). Порт РМР предлагает: • восьми- или 16-разрядный двунаправленный тракт данных; • до 64 Кбайт адресного пространства (16 адресных линий); • шесть дополнительных линий стробирования/управления: ► разрешения; ► фиксации адреса; ► чтения; ► записи; ► две линии выбора кристалла. Порт РМР также можно сконфигурировать для работы в режиме ведомого, что- бы подключиться в качестве адресуемого периферийного устройства к более круп- ной микропроцессорной или микроконтроллерной системе. Командные последовательности чтения из шины и записи в нее — полностью программируемые, поэтому можно не только сконфигурировать под целевую шину полярность и набор управляющих сигналов, но и точно настроить временные харак- теристики в соответствии с быстродействием периферийных устройств. Как и в случае со всеми остальными периферийными модулями микроконтрол- лера PIC24, за конфигурирование порта РМР отвечает ряд управляющих регистров. Первый из них — PMCON, содержащий знакомый набор разрядов, типичный для всех регистров xxCON (рис. 9.4). 15 14 13 12 11 10 9 8 PMPEN — PSIDL ADRMUX1 ADRMUX0 PTBEEN PTWREN PTRDEN 7 6 5 4 3 2 1 0 CSF1 CSFO ALP CS2P CS1P ВЕР WRSP RDSP Рис. 9.4. Регистр PMCON Другие регистры управления модулем РМР: PMMODE, PMADDR, PMSTAT, PMPEN и PADCFG1. Они предоставляют множество разнообразных возможностей, однако подробно останавливаться на них мы сейчас не будем. Это лучше сделать на примере взаимодействия микроконтроллера PIC24 с ЖК-модулем, рассмотренного в главе 22. АЦП Структура модуля АЦП микроконтроллеров PIC24 показана на рис. 9.5
242 Глава 9. Семейство PIC24 Управление конфигурацией вывода Рис. 9.5. Структурная схема модуля АЦП микроконтроллеров PIC24 Эта схема предлагает множество интересных возможностей: • под аналоговые входы можно задействовать до 16 выводов; • для выбора различных входных аналоговых каналов и источников опорного на- пряжения служат два входных мультиплексора; • результат, полученный на выходе 10-разрядного преобразователя, можно от- форматировать под 16-разрядную целочисленную или вещественную арифме- тику (со знаком или без); • схема управления предусматривает различные последовательности автоматиче- ского преобразования с синхронизацией с работой других модулей и входов, задействованных в данном процессе; • результат преобразования сохраняется в 16-разрядном буфере глубиной 16 слов, который можно сконфигурировать для последовательного считывания или простой FIFO-буферизации.
ацп 243 Регистры конфигурирования АЦП: • ADIPCFG — маска выбора аналоговых входных каналов (0 в некотором разря- де обозначает аналоговый, а 1 — цифровой вход); • AD1CON1 — определяет автоматическое начало преобразования по заверше- нию этапа выборки; результат будет отформатирован как обычное беззнаковое целое с выравниванием по правому разряду; • AD1CSSL — конфигурирование функции опроса; • ADI CON2 — определяет использование мультиплексора MUXA и соединяет входы опорного сигнала АЦП с аналоговыми входами AVdd и AVss; • ADI CON3 — выбирает источник тактирования и коэффициент деления для преобразования. По сути аналого-цифровое преобразование — это двухэтапный процесс. Преж- де всего необходимо снять сигнал входного напряжения, после чего вход можно от- ключить и выполнить собственно преобразование считанного напряжения в число- вое значение. Эти два этапа контролируются двумя управляющими разрядами в ре- гистре AD1CON1: SAMP и DONE. Для обеспечения необходимой точности измерений важную роль играет хроно- метраж этих двух этапов. • На этапе выборки внешний сигнал подается на внутренний конденсатор, кото- рый необходимо зарядить до уровня входного напряжения. Для этого требуется выделить достаточно времени, которое обычно пропорционально импедансу источника входного сигнала, а также емкости конденсатора* В общем случае, чем больше время выборки, тем лучше результат, согласующийся с частотой входного сигнала. • Длительность этапа преобразования зависит от выбранного источника тактиро- вания АЦП. Тактовый сигнал обычно получают из синхросигнала центрального процессора после пропускания через делитель или с помощью независимого RC-осциллятора. Последний вариант, хотя и привлекает своей простотой, хо- рошо подходит в тех случаях, когда преобразование выполняется в “спящем” режиме при отключенном тактовом генераторе центрального процессора. В ос- тальном, предпочтительный способ формирования тактового сигнала — с по- мощью делителя, поскольку он обеспечивает синхронизацию с центральным процессором и, как следствие, — более надежное подавление внутреннего шу- ма. Частота тактового сигнала должна быть максимально большой согласно спецификациям модуля АЦП. Согласно базовому методу программист сам отвечает за обеспечение точных временных характеристик этапа выборки с помощью двух циклов ожидания. Одна- ко микроконтроллеры PIC24 позволяют отчасти автоматизировать данный процесс. Длительность этапа выборки определяется без нашего участия при условии, что им- педанс входного источника достаточно мал для того, чтобы обеспечить максималь- ную продолжительность дискретизации 32 х Tad. Этого можно достичь, записав в разряды SSRC регистра AD1CON1 двоичное значение 111, чтобы активизировать автоматическое начало преобразования по завершении периода дискретизации. Сам период выбирают с помощью разрядов SAM регистра AD1CON3.
244 Глава 9. Семейство PIC24 Автоматическое начало преобразования по завершении этапа выборки дает два преимущества: , • гарантированно корректное время выборки без необходимости использовать какие-либо циклы задержки и/или другие ресурсы; • для выполнения всей процедуры дискретизации и преобразования достаточно одной команды (начала этапа выборки). Когда АЦП сконфигурирован подобным образом, активизация преобразования и считывание результата становится совсем простой задачей. 1. Разряд AD1CHS выбирает входной канал для мультиплексора. 2. Запись лог. 1 в разряд SAMP регистра ADI CON1 начинает этап выборки с ав- томатическим выбором длительности, после которого сразу же следует преоб- разование. 3. Как только будет выполнена вся процедура, и результат готов к использованию, в регистре AD1CON1 устанавливается флаг DONE. 4. Чтение регистра ADC 1BUF0 сразу же дает требуемый результат преобразова- ния. Модуль CTMU В микроконтроллерах PIC24 появился новый аналоговый модуль, позволяющий измерять уровень заряда конденсаторов, точно определять различия временных ха- рактеристик импульсных сигналов и формировать асинхронные последовательности импульсов. Его название — CTMU (Charge Time Measurement Unit). Этот модуль — идеальный вариант для организации взаимодействия с емкостными тактильными датчиками. Управление модулем CTMU осуществляют с помощью двух регистров: CTMUCON (рис. 9.6) и CTMUICON (рис. 9.7). 15 14 13 12 11 10 9 8 CTMUEN — CTMUSIDL TGEN EDGEN EDGSEQEN IDISSEN CTTRIG 7 6 5 4 3 2 1 0 EDG2POL EDG2SEL1 EDG2SEL0 EDG1POL EDG1SEL1 EDG1SEL0 I EDG2STAT EDG1STAT Рис. 9.6. Регистр CTMUCON Назначение разрядов регистра CTMUCON: • CTMUEN — включение (1) и отключение (0) модуля CTMU; • CTMUSIDL-— прекращение (1) или продолжение (0) работы модуля при пере- ходе микроконтроллера в “спящий” режим; • TGEN — разрешение (1) или запрет (0) формирования задержки фронта; • EDGEN — разблокирование (1) или блокирование (0) фронтов; • EDGSEQEN — разрешение последовательности фронтов: 1 — для возникнове- ния фронта 2 должен появиться фронт 1; 0 — последовательность фронтов не отслеживается; • IDISSEN — аналоговый выход выдачи тока заземлен (1) или не заземлен (0); • CTTRIG — разрешение (1) или запрет (0) выхода срабатывания;
Модуль CTMU 245 • EDGxPOL — выбор полярности фронта “х”: 1 — реакция на нарастающий фронт; 0 — реакция на ниспадающий фронт; • EDGxSEL[l :0] — выбор источника для фронта “х”: 11 — вывод CTED1; 10 — CTED2; 01 — модуль сравнения на выходе 1; 00 — модуль таймера 1; • EDGxSTAT — состояние фронта “х”: 1 — событие произошло; 0 — событие не произошло. 12 11 10 9 8 15 14 13 ITRIM5 ITRIM4 ITRIM3 ITRIM2 ITRIM1 ITRIM0 IRNG1 IRNG0 7 6 5 4 3 2 1 0 — — — — — — — —- Рис. 9.7. Регистр CTMUICON Назначение разрядов регистра CTMUICON: • ITRIM[5:0] — выбор источника тока: ► 000000 — номинальный ток, заданный разрядами IRNG[1:0]; ► 000001 — минимальное положительное отклонение от номинального тока; ► 011111 — максимальное положительное отклонение от номинального тока; ► 100000 — максимальное отрицательное отклонение от номинального тока; ► 111111 — минимальное отрицательное отклонение от номинального тока; • IRNG[1:0] — выбор пределов источника тока: 11 — 100 х базовый ток; 10 — 10 х базовый ток; 01 — уровень базового тока (номинал — 0,55 мкА); 00 — источ- ник тока отключен. Измерение заряда конденсатора Модуль CTMU измеряет заряд путем формирования выходного импульса, дли- тельность которого равна времени между моментами появления фронтов на двух входных каналах, задаваемых с помощью разрядов EDG1SEL и EDG2SEL регистра CTMUCON. Емкость конденсатора рассчитывается по формуле: C = I*dV/dT. Схема подключений для измерения заряда показана на рис. 9.8. Для измерения заряда АЦП опрашивает конденсатор Сарр, соединенный с одним из его входных каналов, после получения импульса от CTMU. Резистор Rpr обеспечивает калибров- ку источника тока на втором входном канале АЦП. По завершении импульса АЦП определяет напряжение на конденсаторе, а фактическое вычисление емкости возла- гается на программу. В примере на рис. 9.8 показано, что события на входы EDG1 и EDG2 модуля CTMU поступают от таймера 1, однако его роль могут выполнять и внешние источ- ники импульсного сигнала. Измерение времени Схема подключений для измерения времени по длительности импульса с при- менением внутреннего конденсатора Сдо модуля АЦП показана на рис. 9.9.
246 Глава 9. Семейство PIC24 FIC24F Таймер 1 i CTMU *-l EDG1 Источник I Рис. 9.8. Схема подключений для измерения заряда конденсатора с помощью модуля CTMU PIC24F ! CTMU | *“| EDG1 ИСТОЧНИК । тока > EDG2 АЦП “Выходной импульс Cad Рис. 9.9. Схема подключений для измерения времени с помощью модуля CTMU Формирование импульсных последовательностей и задержек Модуль CTMU также может формировать на выходе импульсный сигнал, фрон- ты которого являются асинхронными по отношению к сигналу системной синхро- низации. Точнее сказать, он выдает импульсы с запрограммированндй задержкой. Когда модуль путем записи лог. 1 в разряд TGEN регистра CTMUCON (см. рис. 9.6) конфигурируется на формирование импульсных задержек, внутренний источ- ник тока соединяется со входом В компаратора 2. С этим же входом через вывод C2INB соединен конденсатор Cdelay, а ко входу А компаратора подключен источ- ник опорного напряжения компаратора (рис. 9.10). При обнаружении фронта на входе EDG1 модуль CTMU начинает заряжать конденсатор Cdelay- Когда уровень заряда превышает некоторый порог, заданный источником опорного напряжения, на вывод CTPLS выдается импульс. Длитель- ность задержки определяется номиналом Cdelay и напряжением СVref-
Модуль CTMU 247 Рис. 9.10. Схема подключений для формирования импульсных задержек с помощью модуля CTMU
Глава 10 Семейство PIC32 В 2008 году компания Microchip выпустила новое семейство микроконтролле- ров, оперирующих 32-разрядными данными. Эта технология получила название PIC32. Многие архитектурные характеристики микроконтроллеров PIC32 пересе- каются с их восьми- и 16-разрядными предшественниками, однако есть и ряд суще- ственных отличий. Поскольку рассмотреть подробно технологию PIC32 в рамках этой книги не представляется возможным, мы затронем лишь основные ее особен- ности. Кроме того, в главе 23 будут даны примеры программ для микроконтроллера PIC32MX360F512L. На момент издания этой книги существовала только серия микроконтроллеров PIC32MX. Общие особенности устройств этой серии: • 32-разрядное ядро с пятиуровневым конвейером; • максимальная.тактовая частота — 80 МГц (кроме моделей PIC32MX320F032H и PIC32MX420F032H, у которых тактовая частота не превышает 40 МГц); • наличие модуля, реализующего операции умножения и деления за один такто- вый цикл; • два регистровых файла; • модуль предварительной выборки, ускоряющий работу с памятью Flash; • низкие рабочие напряжения в диапазоне 2,3..3,6 В; • совместимость функций выводов с большинством представителей семейства PIC24; • до восьми модулей прямого доступа к памяти (DMA) с автоматическим опреде- лением разрядности данных; • интерфейс USB 2.0 с выделенными каналами DMA; • 16-канальный 10-разрядный АЦП; • два аналоговых компаратора; • 12 Кбайт Flash-загрузчика; • раздельные системы фазовой автоподстройки частоты (PLL) для центрального процессора и интерфейса USB; • аппаратные часы реального времени (RTCC); • модули UART с аппаратным шифратором/дешифратором IrDA и поддержкой интерфейсов RS-232, RS-485 и UN 1.2; • встроенный регулятор напряжения; • по пять таймеров, модулей захвата на входе и модулей сравнения на выходе; • наличие портов PMP/PSP и интерфейса JTAG. Базовые характеристики микроконтроллеров PIC32 сведены в табл. 10.1, а на- личие каналов DMA и интерфейсов передачи данных — в табл. 10.2.
Модуль CTMU 249 Таблица 10.1. Базовые характеристики микроконтроллеров PIC24 Устройство Выво- дов ОЗУ, Кбайт Память программ, Кбайт Порты (линий) 32MX320F032H 64 8 32 В(16), 0(4), 0(12), Е(8), F(7), G(6) 32MX320F064H 64 16 64 В(16), С(4), D(12), Е(8), F(7), G(6) 32MX320F128H 64 16 128 В(16), С(4), D(12), Е(8), F(7), G(6) 32MX320F128L 100/121 16 128 A(12), B(16), C(8), D(16), E(10), F(11), G(12) 32MX340F128H 64 32 128 B(16), C(4), D(12), E(8), F(7), G(6) 32MX340F128L 100/121 32 128 A(12), B(16), 0(8), D(16), E(10), F(11), G(12) 32MX340F256H 64 32 256 B(16), 0(4), D(12), E(8), F(7), G(6) 32MX340F512H 64 32 512 B(16), 0(4), D(12), E(8), F(7), G(6) 32MX360F256L 100/121 32 256 A(12), B(16), C(8), D(16), E(10), F(11), G(12) 32MX360F512L 100/121 32 512 A(12), B(16), 0(8), D(16), E(10), F(11), G(12) 32MX420F032H 64 8 32 B(16), 0(4), D(12), E(8), F(7), G(6) 32MX440F128H 64 32 128 B(16), 0(4), D(12), E(8), F(7), G(6) 32MX440F128L 100/121 32 128 A(12), B(16), C(8), D(16), E(10), F(11), G(12) 32MX440F256H 64 32 256 B(16), 0(4), D(12), E(8), F(7), G(6) 32MX440F512H 64 32 512 B(16), C(4), D(12), E(8), F(7), G(6) 32MX460F256L 100/121 32 256 A(12), B(16), C(8), D(16), E(10), F(11). G(12) 32MX460F512L 100/121 32 512 A(12), B(16), 0(8), D(16), E(10), F(11), G(12) 32MX575F256H 64 64 256 B(16), 0(4), D(12), E(8), F(5), G(6) 32MX575F256L 100 64 256 A(12), B(16), 0(8), D(16), E(10), F(9), G(12) 32MX575F512H 64 64 512 B(16), 0(4), D(12), E(8), F(5), G(6) 32MX575F512L 100 64 512 A(12), B(16), 0(8), D(16), E(10), F(9), G(12) 32MX675F256H 64 64 256 B(16), 0(4), D(12), E(8), F(5), G(6) 32MX675F256L 100 64 256 A(12), B(16), C(8), D(16), E(10), F(9), G(12) 32MX675F512H 64 64 512 B(16), 0(4), D(12), E(8), F(5), G(6) 32MX675F512L 10СГ 64 512 A(12), B(16), 0(8), D(16), E(10), F(9), G(12) 32MX695F512H 64 128 512 B(16), 0(4), D(12), E(8), F(5), G(6) 32MX695F512L 100 128 512 A(12), B(16), C(8), D(16), E(10), F(9), G(12) 32MX775F256H 64 64 256 B(16), 0(4), D(12), E(8), F(5), G(6) 32MX775F256L 100 64 256 A(12), B(16), 0(8), D(16), E(10), F(9), G(12) 32MX775F512H 64 64 512 B(16), 0(4), D(12), E(8), F(5), G(6) 32MX775F512L 100 64 512 A(12), B(16), 0(8), D(16), E(10), F(9), G(12) 32MX795F512H 64 128 512 B(16), 0(4), D(12), E(8), F(5), G(6) 32MX795F512L 100 128 512 A(12), B(16), C(8), D(16), E(10), F(9), G(12) Таблица 10.2. Каналы DMA и интерфейсы в микроконтроллерах PIC32 Устройство Каналы DMA UART SPI l2C Ethernet CAN Программируемые Выделенные 32MX320F032H 0 0 2 2_ 2 — — 32MX320F064H 0 0 2 2 2 — — 32MX320F128H 0 0 2 2 2 — — 32MX320F128L 0 0 2 2 2 — — 32MX340F128H 4 0 2 2 2 — — 32MX340F128L 4 0 2 2 2 — — 32MX340F256H 4 0 2 2 2 — —
250 Глава 10. Семейство PIC32 Таблица 10.2. Окончание Устройство Каналы DMA UART SPI 12С Ethernet CAN Программируемые Выделенные 32MX340F512H 4 0 2 2 2 — — 32MX360F256L 4 0 2 2 2 — — 32MX360F512L 4 0 2 2 2 — — 32MX420F032H 0 2 2 1 2 — — 32MX440F128H 4 2 2 1 2 — — 32MX440F128L 4 2 2 2 2 — — 32MX440F256H 4 2 2 1 2 — — 32MX440F512H 4 2 2 1 2 — — 32MX460F256L 4 2 2 2 2 — — 32MX460F512L 4 2 2 2 2 — — 32MX575F256H 8 4 6 3 4 — 1 32MX575F256L 8 4 6 4 5 — 1 32MX575F512H 8 4 6 ч 3 4 — 1 32MX575F512L 8 4 6 4 5 — 1 32MX675F256H 8 4 6 3 4 1 — 32MX675F256L 8 4 6 4 5 1 — 32MX675F512H 8 4 6 3 4 1 — 32MX675F512L 8 4 6 4 5 1 — 32MX695F512H 8 4 6 3 4 1 — 32MX695F512L 8 4 6 4 5 1 - — 32MX775F256H 8 8 6 3 4 1 2 32MX775F256L 8 8 6 4 5 1 2 32MX775F512H 8 8 6 3 4 1 2 32MX775F512L 8 8 6 4 5 1 2 32MX795F512H 8 8 6 3 4 1 2 32MX795F512L 8 8 6 4 5 1 2 Структура микроконтроллера PIC32 показана на рис. 10.1 ан примере подсе- мейств Р1С32МХЗх/4х. Поскольку подробное изучение технологии PIC32 выходит за тематические рамки этой книги, мы затронем только некоторые отличительные особенности данного семейства устройств. Порты ‘ Работа с параллельными портами в микроконтроллерах PIC32 реализована ана- логично тому, как это сделано у представителей в семейства PIC24 (см. предыду- щую главу). Кроме того, следует отметить, что вместо двухпроводного подключения к внут- рисхемному программатору и (или) отладчику (интерфейс ICSP/ICD) в устройствах PIC32 предлагается дополнительный интерфейс JTAG, поддерживающий функции не только отладки, как это было в PIC24, но и программирования. Выводы JTAG мультиплексированы с линиями RAO, RAI, RA4 и RA5 порта А. Отметим так же, что все управляющие регистры портов в микроконтроллерах PIC32 — 32-разрядные, однако порты не масштабируются. Например, модуль порта А по-прежнему группирует менее 16 выводов, хотя регистры PORTA и TRISA — 32-разрядные. Это упрощает перенос в PIC32 кода из более старых архитектур.
Таймеры 251 Шина периферии, тактируемая сигналом SYSCLK <--13 Vbo.Vss <—3 мая iijietjis п сдач-; JWUHHH CN1-22 ЯО 'Г)н,'фр Н,И(Ъ ПрчЧЛГМ напряжений Рис. 10.1. Структурная схема микроконтроллеров PIC32MX3x/4x йсцшпчно; j Таймеры Внутренне в PIC32MX таймеры реализованы практически так же, как в серии PIC24H (в принципе, то же самое можно сказать и обо всех остальных периферий- ных модулях). Основное различие между этими двумя архитектурами — разделение сигнала тактирования шины ядра и шины периферии (см. рис. 10.1). Для микрокон- троллеров PIC такое решение — совершенное новое. Оно освобождает процессор- ное ядро от скоростных ограничений Flash-памяти и периферийных модулей, что позволяет достичь нового уровня производительности, не жертвуя совместимостью со старыми приложениями. Системная шина Архитектура PIC32 отличается от всех своих предшественников тем, что в ней вместо классической для микроконтроллеров PIC гарвардской модели используется более традиционная модель фон Неймана. Теперь две раздельные, полностью неза-
252 Глава 10. Семейство PIC32 висимые шины заменены одной 32-разрядной системной шиной, по которой осуще- ствляется доступ как к памяти программ, так и к памяти данных. Такой подход дает три преимущества: • более простая, унифицированная модель программирования; • отпадает необходимость прибегать к различным уловкам для получения досту- па к таблицам данных, размещенным в памяти программ; • процессоры PIC впервые получают возможность выполнять код, размещенный в ОЗУ. Для повышения производительности работы с одной системной шиной в мик- роконтроллерах PIC32 реализована пятиуровневая конвейеризация, а также — ме- ханизм предварительной выборки (кэширование). Все это позволяет выполнять лю- бую команду за один тактовый цикл. Организация памяти Память микроконтроллеров PIC32MX разбита на виртуальную и физическую. Всем аппаратным ресурсам (память программ, ОЗУ и периферия) соответствуют адреса в физическом пространстве. Виртуальные адреса используются исключи- тельно центральным процессором для извлечения и выполнения команд, а также — для доступа к периферии. К физическому пространству адресов также обращаются контроллеры DMA и Flash, получающие доступ к памяти независимо от процессора. Пример распределения адресного пространства в микроконтроллерах PIC32MX показан на рис. 10.2. Следует отметить, что для управления доступа к памяти в PIC32 были реализо- ваны два новых механизма: FMT (Fixed Mapping Translation — фиксированное пре- образование адресов памяти) и ВМХ (Bus Matrix — шинная матрица). Так, фикси- рованная схема FMT упрощает разработку приложений и перенос кода в микрокон- троллеры PIC32, в то же время значительно уменьшая размеры устройств. Модуль ВМХ предоставляет гибкость в разбиении основной памяти на разделы, а также помогает осуществлять арбитраж доступа со стороны процессора, запросов на выборку команд, запросов от DMA и логики внутрисхемного программирования. Разработчики PIC32 обеспечили возможность накладывать определенные “пра- вила” на использование памяти для защиты от распространенных программных ошибок. Например, при работе операционной системы (ОС) может потребоваться запретить доступ приложения к определенным участкам ОЗУ. Другими словами, пользовательский код не должен касаться кода ядра. Для реализации этого необхо- димо вначале обратиться к модулю ВМХ. С помощью управляющих регистров шинной матрицы мы можем разбить ос- новную'физическую память на фрагменты различной величины (рис. 10.3). Напри- мер, регистр BMXPUPBA позволяет разделить часть память программ таким обра- зом, чтобы пользователю были доступны только адреса от $BD000000 и выше. Аналогичным образом данные пользователя могут быть отделены от данных ядра путем разбиения ОЗУ с помощью регистров BMXDKPBA и BMXXDUDBA. Они также позволяют разместить в определенных участках ОЗУ программный код, что значительно повышает производительность приложения. На следующем этапе система FMT преобразовывает все физические адреса в вир- туальные, т.е. создаются два совершенно независимых адресных пространства, в ко- торых могут работать программы: одно — для пользовательских приложений (адре-
Организация памяти 253 са ниже $80000000), а другое — для ядра (адреса выше $80006000). Полученное распределение виртуальной памяти, видимой приложению, которое работает в по- льзовательском режиме, иллюстрирует рис. 10.4. Обратите внимание, что область загрузчика л пользовательском режиме вообще не отображается. Такого адреса, который позволил бы приложению затронуть за- щищенную область, просто не существует. Благодаря этому, каким бы некоррект- ным ни был пользовательский код, он не повредит операционную систему. Виртуальная память Физическая память OxFFFFFFFF OxBFCO3OOO 0XBFC02FFF 0XBFC02FF0 0xBFC02F£F OxBFCOOOOO OxSFOOOOOO OxBFSFFFFF OxBFSOOOOO OxBDDOSOOO 0xBD007FFF OxBDOGOOOD OxA0002000 OxAOOOIFFF OxAOOOOOOO Qx9FC03000 0X9FCD2FFF 0x9FC02FEF 0x9FC02FEF OxSFCOOOOO OxSDOOSOOD 0x9D007FFF OxSDOOOOOO 0x80002000 OxSOOOIFFF 0x80000000 0x00000000 Зарезервировано ОЗУ ОЗУ Зарезервировано Регистры конфигурирования устройств Flash-загрузчик Зарезервировано Регистры специального назначения Зарезервировано Память программ Зарезервировано Зарезервировано Регистры конфигурирования устройств Flash-загрузчик Зарезервировано Память программ Зарезервировано * Зарезервировано Регистры конфигурирования устройств Flash-загрузчик Зарезервировано Регистры специального назначения Зарезервировано Память программ Зарезервировано ОЗУ OxFFFFFFFF 0X.1FC03D00 0X1FCO2FFF 0X1FCO2FF0 QX1FC02FEF QxlFCOOOOO Ox1F9COOOO 0X1F8FFFFF OX1F800000 0x10008000 Gx1D007FFF 0x10000000 0x00002000 0x00001FFF 0x00000000 Рис. 10.2. Организация памяти микроконтроллеров PIC32MX
254 Глава 10. Семейство PIC32 ОЗУ пользо- вателя (данные) ОЗУ пользо- вателя (прог- рамма) $00000000 BMXDKDBA BMXDUDBA $BFOOOOOO+ $BFOOOOOO+ $FFFFFFFF BMXDUDBA BMXOUPBA Ptfc. 10.3. Разбиение ОЗУ на фрагменты с помощью модуля ВМХ $70000000 $FFFFFFFF $7F000000+ $7FOOOOOO+ BMXDUDBA BMXDUPBA Рис. 10.4. Распределение виртуальной памятке пользовательском режиме Аналогичным образом, обратите внимание, что в пользовательском виртуаль- ном адресном пространстве не отображаются регистры специального назначения. Другими словами, какой бы некачественной ни была программа, она не сможет по- лучить доступ к аппаратным средствам и изменить конфигурацию устройств. Описанный сложный механизм распределения памяти имеет смысл только при создании операционных систем реального времени (RTOS). Во всех остальных слу- чаях программа работает обычным образом в адресном сегменте KSEG0 или KSEGI (см. рис. 10.2). Разница между этими двумя сегментами заключается в том, что код в K.SEG0 доступен для механизма кэширования, а код в KSEG1 — нет. Прерывания и исключения Для процессорного ядра PIC32 все прерывания относятся к более общей катего- рии исключений (exception) — событий, нарушающих нормальную работу про- граммы, например: сигнал сброса, ошибка деления на ноль, обращение к отсутст- вующему адресу памяти и т.д. В действительности, прерывания — наиболее “бла- гоприятный” тип исключений. При обработке всех возможных исключений процессорное ядро опирается на несколько векторов, которые размещаются в ОЗУ или (и) в памяти программ со- гласно табл. 10.3. Как всегда, подобные векторы размещаются в секции программы, выполняемой после включения микроконтроллера.
Прерывания и исключения 255 Таблица 10.3. Векторы исключений Источник исключения Область памяти Описание Сброс и немаскируемые прерывания Память программ Обычный сброс и запрос на немаскируемое прерывание Внутрисхемная отладка Память программ Используется интерфейсами ICD и JTAG при внутрисхемной отладке Ошибка кэша ОЗУ или память программ Ошибочное состояние, специфическое для механизма кэширования Общее исключение ОЗУ или память программ Все остальные типы исключений Прерывание ОЗУ или память программ Обычный вектор прерывания Как видим, обычным прерываниям в таблице векторов исключений соответст- вует единственный элемент, а значит всем возможным событиям,/вызывающим прерывания, ставится в соответствие одна подпрограмма обработки. Как только возникает запрос на прерывание, всю информацию о нем (источник события и наиболее подходящую реакцию) внутри подпрограммы обслуживания прерывания можно извлечь из специального регистра CAUSE. । В качестве примера рассмотрим систему прерываний микроконтроллера PIC 32MX360F512L. Внешние источники прерываний для этого микроконтроллера: • пять — для внешних выводов с обнаружением по изменению уровня; • 22 — для внешних выводов, соединенных с модулем уведомления об изменени- ях (Change Notification); • пять — для модулей захвата на входе (Input Capture); • пять — для модулей сравнения на выходе (Output Compare); • два — для модулей UART; • четыре — для синхронных последовательных интерфейсов (SPI и 12С); • один — для ведущего параллельного порта (РМР). Как видим, перечень внешних источников для микроконтроллеров PIC32MX идентичен аналогичному перечню для семейства PIC24 (см. предыдущую главу) Теперь рассмотрим внутренние источники прерываний микроконтроллера PIC 32MX360F512L: • один — для внутреннего 32-разрядного таймера процессорного ядра; • пять — для 16-разрядных таймеров/счетчиков; • один — для АЦП; • один — для модуля аналоговых компараторов; • один — для часов и календаря реального времени; • один — для контроллера Flash-памяти; • один — для монитора работы системы тактирования; • два — программные прерывания; • четыре — для каналов DMA. Как видим, здесь, по сравнению с архитектурой PIC24, есть ряд существенных отличий.
256 Глава 10. Семейство PIC32 ПРИМЕЧАНИЕ Модуль управления прерываниями микроконтроллеров PIC32 способен обрабатывать до 96 независимых событий, чего более чем достаточно для любых приложений. Каждому источнику прерываний соответствует семь управляющих разрядов в различных регистрах специального назначения. • Разряд разрешения прерывания (обычно обозначен с помощью суффикса IE): 0 — соответствующее событие не вызывает прерывания; 1 — прерывание раз- решено. Примечание................................. При включении питания все источники прерываний по умолчанию запрещены. • Флаг прерывания (обычно обозначен с помощью суффикса IF) — устанавлива- ется каждый раз при возникновении соответствующего события независимо от состояния разряда разрешения. ПРИМЕЧАНИЕ Однажды установленный флаг прерывания должен быть сброшен вручную. Другими словами, его необходимо обнулить до выхода из подпрограммы обслуживания прерывания, иначе эта же подпрограмма будет сразу же вызвана еще раз. • Уровень приоритетности группы (обычно обозначен с помощью суффикса IP). Прерыванию можно назначить один из семи уровней приоритетности. Если од- новременно возникает два различных запроса на прерывание, то первым будет обслужен тот из них, для которого определен более высокий приоритет. Для кодирования приоритетности каждого источника прерываний отведены три раз- ряда. В каждый момент времени уровень приоритетности для задач процессора PIC32 хранится в регистре статуса в разрядах IPL0..IPL2. Прерывания, у которых приоритет ниже текущего значения IPL, игнорируются. • Еще два разряда (новшество PIC32) определяют четыре дополнительных уровня приоритетности внутри данной группы. Если одновременно возникает два со- бытия с одинаковым приоритетом, то первым будет обработано то, у которого выше субприоритет. Все запросы на прерывания с тем же уровнем приоритет- ности, что и активное, будут игнорироваться до тех пор, пока не обнулится со- ответствующий флаг. Внутри любой группы задана относительная приоритетность различных источ- ников по умолчанию, которая может отличаться в зависимости от конкретной моде- ли микроконтроллера. Например, для PIC32MX360F512L она выглядит следующим образом (источники с более высоким приоритетом находятся ближе к вершине спи- ска): • таймер процессорного ядра; • программное прерывание 0 от процессорного ядра; • программное прерывание 1 от процессорного ядра; • внешнее прерывание 0; • прерывание от таймера 1; • прерывание от модуля захвата на входе 1; • прерывание от модуля сравнения на выходе 1;
Прерывания и исключения 257 • внешнее прерывание 1; • прерывание от таймера 2; • прерывание от модуля захвата на входе 2; • прерывание от модуля сравнения на выходе 2; • внешнее прерывание 2; • прерывание от таймера 3; • прерывание от модуля захвата на входе 3; • прерывание от модуля сравнения на выходе 3; • внешнее прерывание 3; • прерывание от таймера 4; • прерывание от модуля захвата на входе 4; • прерывание от модуля сравнения на выходе 4; • внешнее прерывание 4; • прерывание от таймера 5; • прерывание от модуля захвата на входе 5; • прерывание от модуля сравнения на выходе 5; • ошибка SPI 1; • передача данных по SPI 1 завершена; • прием данных по SPI 1 завершен; • ошибка UART 1; • прием данных через UART 1 завершен; • передача данных через UART 1 завершена; • конфликт в шине I2C 1; • событие ведомого устройства на шине I2C 1; • событие ведущего устройства на шине I2C 1; • прерывание по изменению состояния входа; • завершено аналого-цифровое преобразование; • прерывание от порта РМР; • прерывание от аналогового компаратора 1; • прерывание от аналогового компаратора 2; • ошибка SPI 2; • передача данных по SPI2 завершена; • прием данных по SPI2 завершен; • ошибка UART 2; • прием данных через UART 2 завершен; • передача данных через UART 2 завершена; • конфликт в шине 12С 2; • событие ведомого устройства на шине 12С 2; • событие ведущего устройства на шине 12С 2; • прерывание от монитора системы тактирования;
258 Глава 10. Семейство PIC32 • прерывание от RTCC; • прерывание от DMA-канала 0; • прерывание от DMA-канала 1; • прерывание от DMA-канала 2; • прерывание от DMA-канала 3; • прерывание от контроллера Flash-памяти. Система тактирования Микроконтроллеры PIC32MX могут тактироваться от одного из пяти источни- ков: • внутренний осциллятор FRC, предназначенный для высокопроизводительных задач при малом энергопотреблении, — не требует внешних компонентов и по- сле калибровки обеспечивает относительно точный (±2%) тактовый сигнал час- тотой 8 МГц; • внутренний низкочастотный и маломощный осциллятор LPRC — не требует внешних компонентов и обеспечивает базовый (неточный) такт 32 кГц; • главный внешний осциллятор POSC, предназначенный для высокопроизводи- тельных задач с большой точностью тактирования, — кварц XT или HS часто- той до 20 МГц на выводах OSCI и OSCO; • вторичный, низкочастотный и маломощный внешний осциллятор SOSC — кварц на 32768 Гц на выводах SOSCI и SOSCO (может использоваться как для тактирования всего микроконтроллера, так и — таймера 1 и RTCC); • внешний тактовый сигнал ЕС. Интерфейс SPI По сравнению с микроконтроллерами PIC24 семейство PIC32 реализует сле- дующие дополнительные возможности при работе с интерфейсом SPI: • размещение разрядов в регистре SPIxCON теперь более соответствует размеще- нию разрядов в управляющих регистрах других периферийных модулей (на- пример, разряды ON, FRZ и IDL теперь находятся в стандартных позициях 15, 14 и 13, а раньше были в регистре SPIxSTAT); • разряды управления режимом покадровой передачи (FRMEN, SPIFSD и др.) были перемещены из регистра SPIxCON2 в регистр SPIxSTAT; • новый разряд MODE32 выбирает режим 32-разрядной передачи; • предделитель модуля SPI расширен до полного девятиразрядного генератора частоты, управляемого регистром SPIxBRG. Порт РМР Порт РМР микроконтроллеров PIC32 во многом аналогичен этому же интер- фейсу в семействе PIC24, однако присутствует и ряд существенных отличий: • размещение разрядов в регистре PMCON теперь более соответствует размеще- нию разрядов в управляющих регистрах других периферийных модулей (разря- ды ON, FRZ и IDL находятся в стандартных позициях 15, 14 и 13);
АЦП 259 • убран выходной сигнал РМВБ; • разряд PMPTTL для выбора триггера Шмитта или входных уровней ТТЛ из ре- гистра PADCFG1 перенесен в регистр PMCON; • в регистре PMMODE были изменены битовые комбинации IRQM =11 и IRQM = 10; • регистр PMPEN переименован в PMAEN; • одновременный доступ ко всем буферам данных обеспечивают 32-разрядные регистры PMDIN и PMDOUT. АЦП Модуль АЦП микроконтроллеров PIC32 во многом реализован аналогично это- му же модулю в семействе PIC24, однако присутствует и ряд существенных отли- чий: • в регистре AD1CON1 задается еще один вариант формата преобразования: 32- разрядное дробное слово; • в регистр ADI CON1 был добавлен разряд CLRASAM, позволяющий остановить последовательность преобразования после первого прерывания; • регистр ADI CON2 реализует новый режим автокалибровки для уменьшения ошибки преобразования (для перехода в этот режим служит разряд OFFCAL); • разряды управляющего регистра AD1CHS смещены в верхнюю половину 32- разрядного регистра. Кроме того, появился разряд CH0NB0 для выбора отрица- тельного входа второго входного мультиплексора. Модуль сравнения на выходе Модуль сравнения на выходе микроконтроллеров PIC32 во многом аналогичен этому же модулю в семействе PIC24, однако присутствует и два существенных от- личия: • размещение разрядов в регистре OCxCON теперь более соответствует размеще- нию разрядов в управляющих регистрах других периферийных модулей (для удобства управления в режимах малого энергопотребления теперь доступны разряды ON, FRZ и IDL); • был добавлен разряд ОС32 для активизации 32-разрядного режима работы, ко- гда модуль связан с парой таймеров.
ЧАСТЬ IV Компиляторы и средства разработки для микроконтроллеров PIC
Глава 11 Компилятор CCS-PICC Компилятор CCS-PICC разработан для запуска в среде Windows 95/98/Me/NT4/ 2000/ХР. Прилагаемый к книге компакт-диск содержит демонстрационную 30-днев- ную версию компилятора PCW 4.102, который накладывает ограничения на размер исходного компилируемого файла до 2 Кбайт и работает только с семью микрокон- троллерами PIC. • Установочный файл компилятора CCS-PICC demoupd. ехе можно также найти на прилагае- мом к книге компакт-диске в папке Sof tware\PIC\CCS-PICC. Компилятор CCS-PICC доступен через его интегрированную среду разработки (IDE), позволяющую пользователю создавать проекты из одного или нескольких файлов исходного кода, настраивать опции компилятора, а также компилировать исходный код в исполняемые файлы, предназначенные для загрузки в целевой мик- роконтроллер. По умолчанию, после установки CCS-PICC на Рабочем столе Windows будет размещен ярлык PIC С Compiler, который и используется для запуска среды разра- ботки. В любом случае, IDE CCS-PICC можно запустить по команде меню Пуск ► Все программы ► PIC-C ► PIC С Compiler. Окно среды разработки CCS-PICC при первом запуске показано на рис. 11.1. Рис. 11.1. Окно IDE CCS-PICC при первом запуске Создание проектов CCS-PICC вручную В среде разработки CCS-PICC в большинстве случаев речь идет не просто о фай- ле с кодом на языке С, а о проекте, состоящем из одного или более файлов с исход- ным кодом программы (главный файл проекта имеет расширение .pjt). Новый
262 Глава 11. Компилятор CCS-PICC проект можно создавать вручную с помощью команды меню Project ► Create или сгенерировать его автоматически с помощью мастера PIC Wizard, который вызыва- ется по команде меню Project ► PIC Wizard или Project ► 24 Bit Wizard. Оба метода создания нового проекта запрашивают у пользователя имя главного исходного фай- ла для проекта и целевое устройство. Если было выбрано создание проекта вручную, то вначале появится стандарт- ное диалоговое окно, предлагающее выбрать имя главного исходного файла проекта (с расширением . с). После выбора такого файла откроется диалоговое окно, пред- лагающее указать целевой микроконтроллер (рис. 11.2). ПРИМЕЧАНИЕ Это же диалоговое окно можно открыть в любой момент и после создания проекта по коман- де меню Options ► Options ► Project Options. Если готового исходного кода нет, и необходимо начать создание проекта “с нуля”, то можно выбрать любой файл . с (например, из папки \Program Files\ PlCC\Examples), а затем выделить его в списке диалогового окна Project Options и нажать кнопку Remove (Удалить). В дальнейшем файл исходного кода будет соз- дан автоматически. В таком случае понадобится также изменить папку размещения и имя проектного файла. Для этого следует нажать кнопку ... справа от поля Project Name и задать новое расположение и имя файла . р j t. Рис. 11.2. Диалоговое окно Project Options ПРИМЕЧАНИЕ В версии компилятора CCS-PICC, поставляемого с этой книгой, в качестве целевого устрой- ства можно использовать только микроконтроллеры PIC16C554, PIC16F877, PIC16F877A, PIC18C452, PIC18F452, PIC18F458 и PIC24FJ128GA006. Заголовочные файлы для устройств по умолчанию устанавливаются в папку \Program Files\PICC\Devices. Для того чтобы задать размещение файлов с описанием поддерживаемых ком- пилятором микроконтроллеров, отличное от выбранного по умолчанию, в окне Proj- ect Options следует нажать кнопку Include Files. В результате откроется соответст- вующий раздел параметров проекта (рис. Г1.3). ПРИМЕЧАНИЕ Суть заголовочных файлов с расширением . h подробно рассматривается в следующей части книги. Сейчас только отметим, что это — внешние файлы описаний, подключаемые к про- граммному модулю с помощью директивы #include.
Создание проектов CCS-PICC вручную 263 Рис. 11.3. Раздел Include Files диалогового окна Project Options Для того чтобы добавить новый путь в список, следует ввести его в располо- женном внизу поле (или найти с помощью диалогового окна поиска, нажав кнопку с изображением папки) и нажать кнопку Add. Для удаления текущего элемента из списка предназначена кнопка Delete. После того как список путей поиска сформиро- ван, можно нажать кнопку Apply (Применить), чтобы завершить создание проекта. Если проект создается на основе существующего файла . с, то в одной с ним папке будет создан проектный файл с тем же именем, но с расширением .pjt. В противном случае появится запрос на создание файла noname. с. После утверди- тельного ответа на этот запрос будет создан проект с именем, заданным в диалого- вом окне Project Options. В любом случае в рабочей среде CCS-PICC откроется ис- ходный код главного файла . с (рис. 11.4). Рис. 11.4. Создана заготовка для разработки программы на языке С На рис. 11.4 показан случай создания проекта “с нуля”. К видим, к проекту под- ключен внешний файл описаний для микроконтроллера PIC18F458, выбранного ра- нее в диалоговом окне Project Options.
264 Глава 11. Компилятор CCS-PICC Что касается мастера создания проектов PIC Wizard, то при работе с ним поль- зователь должны знать, как будет применяться микроконтроллер, а также иметь ба- зовые знания об архитектуре целевого устройства. Этот мастер мы рассмотрим чуть позже, а сейчас создайте в качестве примера в отдельной папке новый исходный файл SOS. с для микроконтроллера PIC18F458. Введите в него код, представленный в листинге 11.1. Этот пример — аналог рассмотренного в главе 3 для микрокон- троллеров AVR. Листинг 11.1. Файл SOS. а для микроконтроллера PIC18F458 #include <18F458.h> #use delay(clock=20000000) ♦fuses HS, NOWDT void Pause(int ms) { output_D(OxFF); //Все светодиоды отключены delay_ms(ms); } //Задержка void P(void) t output_D(0); //Включаем все светодиоды delay_ms(5); //Короткая задержка Pause (5); } //Пауза с погасшими светодиодами void D(void) { output_D(0); delay__ms (20) ; //Включаем все * светодиоды //Длинная задержка Pause (5); } //Пауза с погасшими светодиодами int main (void) t set_tris_D(OxFF); // Настройка порта D для вывода while(1) //Бесконечный цикл Р(); Р(); Р(); //. . . DO; D(); D(); Р(); Р(); Р(); // //. . . Pause(100) ; ) } ПРИМЕЧАНИЕ Программные элементы мы пока рассматривать не будем, поскольку это — материал сле- дующих глав. Этот пример используется только для изучения среды программирования. Файл SOS. с можно также скопировать с прилагаемого к книге компакт-диска из папки Pro- ject s\CCS-PICC\SOS.
Создание проектов CCS-PICC с помощью PIC Wizard 265 Создание проектов CCS-PICC с помощью PIC Wizard Для запуска мастера PIC Wizard следует выполнить соответствующую команду меню Project, а затем указать размещение и имя главного файла проекта. В резуль- тате откроется окно мастера, состоящее из семнадцати разделов с параметрами про- екта (рис. 11.5). Рис. 11.5. Раздел General мастера PIC Wizard Внешний вид окна мастера может отличаться в зависимости от версии компилятора CCS- PICC и выбранного типа микроконтроллера. В разделе General выбирается целевой микроконтроллер (раскрывающийся спи- сок Device), его рабочая частота (поле Oscillator Frequency), а также настраиваются общие параметры, наподобие разрядов предохранения, типа источника системной синхронизации, порогового напряжения для сброса и др. Для просмотра программного кода, который будет сгенерирован и добавлен в исходный файл в соответствии с параметрами на текущей вкладке, следует вы- брать вкладку Code (рис. 11.6). В разделе Communications (рис. 11.7) настраиваются параметры ввода/вывода для интерфейсов RS232 и 12С (скорость обмена данными, соответствующие линии портов ввода/вывода, проверка ошибок, режим Master/Slave и т.д.), а также активи- зируется/отключается аппаратный порт PSP. В разделе SPI and LCD (рис. 11.8) пользователь может активизировать аппарат- ный интерфейс SPI и настроить соответствующие параметры обмена данными (ре- жим Master/Slave, активный фронт тактового импульса, коэффициент деления час-
266 Глава 11. Компилятор CCS-PICC тоты системной синхронизации, использование вывода /SS), а также использование жидкокристаллического дисплея (LCD), если он доступен. Рис. 11.6. Предварительный просмотр кода, генерируемого мастером PIC Wizard для текущего раздела Рис. 11.7. Раздел Communications мастера PIC Wizard
Создание проектов CCS-PICC с помощью PIC Wizard 267 Рис. 11.8. Раздел SPI and LCD мастера PIC Wizard В разделе Timers (рис. 11.9) настраиваются параметры таймеров, включая сто- рожевой. Значение некоторых параметров: • Not used — для включения сторожевого таймера этот флажок следует сбросить; • WDT Reset — период между сигналами сброса от сторожевого таймера; • Source — выбор источника тактирования таймера TMR0: внутренний или вйешний (по нарастающему или ниспадающему фронту сигнала); • Frequency — установка частоты в случае выбора внешнего источника тактиро- вания таймера TMR0; • Resolution — разрешение таймера, влияющее на период между переполнениями счетного регистра (для таймеров TMR0 и TMR1 вычисляется автоматически и отображается в поле Overflow); • Interrupt Period — период между запросами на прерывание от таймера TMR2. ПРИМЕЧАНИЕ Если выбранный микроконтроллер предоставляет дополнительные таймеры, их параметры настраиваются в разделе PCH Timers мастера PIC Wizard. Раздел Analog (рис. 11.10) служит для настройки встроенного АЦП (конфигура- ция аналоговых входов, частота и разрядность преобразования). В разделе Other (рис. 11.11) активизируется модуль ССР и настраивается режим его работы, а также выбирается конфигурация входов компараторов напряжений. Раздел Interrupts (рис. 11.12) позволяет с помощью набора флажков разрешить или запретить то или иное прерывание, доступное для выбранного устройства.
268 Глава 11. Компилятор CCS-PICC Рис. 11.9. Раздел Timers мастера PIC Wizard Рис. 11.10. Раздел Analog мастера PIC Wizard
Создание проектов CCS-PICC с помощью PIC Wizard 269 Рис. 11.11. Раздел Other мастера PIC Wizard Рис. 11.12. Раздел Interrupts мастера PIC Wizard
270 Глава 11. Компилятор CCS-PICC Для каждого выбранного прерывания в глав- ную процедуру программы main() добавляется вызов соответствующей подпрограммы обработки прерывания enable_interrupts (), а тело самой подпрограммы размещается выше main() (при- мер— рис. 11.13). В разделе Drivers содержится список програм- мных драйверов, доступных для выбранного мик- роконтроллера в компиляторе CCS-PICC. Выбор конкретного драйвера приводит к тому, что в про- ект включается соответствующий заголовочный файл, и вызывается подпрограмма для инициали- зации этого драйвера (по умолчанию размещены в папке \Program Files\PICC\Drivers). Конфигурация выводов портов микроконтрол- лера настраивается в разделе I/O Pins (рис. 11.14). При этом для каждого вывода возможны значения Options Code | Inserted into .c file before main(): #int_RTCC void RTCC isr(void) { } Inserted into .c file in main(): enable_interrupts(l N T_R T CC); enable_interrupts(G L0 BAL); Рис. 11.13. Пример программного кода, сгенерированного PIC Wizard в разделе Interrupts Input (вход), Output (выход), Input/Output (вход/выход), Analog (аналоговый) и Not used (не используется). Каждому выводу в программе будут соответствовать иден- тификаторы, указанные через запятую в столбце Identifiers. Если установить флажбк Enable Pullups on port В, то выводы порта В будут сконфигурированы с подтягиваю- щим сопротивлением. Рис. 11.14. Раздел I/O Pins мастера PIC Wizard В разделе мастера PIC Wizard Header Files — с помощью флажков можно вклю- чить в проект дополнительные заголовочные файлы, используемые, например, для работы со сроками или с числами с плавающей запятой.
Создание проектов CCS-PICC с помощью PIC24 Wizard 271 Остальные разделы мастера служат для настройки различных аппаратных функций и интерфейсов, которые во многих микроконтроллерах PIC отсутствуют: • High/Low Voltage — обнаружение повышений и падений уровня рабочего напря- жения; • Intr Oscillator Configuration — конфигурация внутреннего осциллятора; • CAN BUS — параметры шины CAN; • LCD options — параметры интерфейса для подключения ЖК-дисплея; • MOD BUS — параметры шины Mod; • BOOT LOADER — активизация и параметры размещения загрузчика. После настройки всех необходимых параметров, в окне мастера можно нажать кнопку ОК, и в одной папке с изначально заданным проектным файлом будет создан файл . с с тем же именем, а также — все необходимые включаемые файлы . h. Создание проектов CCS-PICC с помощью PIC24 Wizard В состав среды CCS-PICC PCW 4.102 входит мастер создания проектов для 16- разрядных микроконтроллеров PIC24 (см. главу 9). Для его вызова служит команда меню Project ► 24 bit Wizard. Внешне данный мастер напоминает обычный PIC Wiz- ard (рис. 11.15). Отличие заключается лишь в наборе разделов и параметров конфи- гурирования аппаратных средств. Рис. 11.15. Мастер PIC24 Wizard Поскольку правила работы с этим мастером аналогичны рассмотренным ранее для PIC Wizard, останавливаться на них подробно мы не будем.
272 Глава 11. Компилятор CCS-PICC Открытие и добавление в проект файлов с исходным кодом В качестве примера создайте новый проект на ос- нове файла sos.с (см. листинг 11.1). По умолчанию в окне PCW открывается только главный исходный файл .с. Для того чтобы увидеть структуру проекта, разместите указатель мыши над кнопкой Files, распо- ложенной у левого края рабочей области. В результате отобразится панель Files (рис. 11.16), в которой видно, что проект SOS состоит из файлов SOS. с и 18F458. h. sosx 1 1Ш31ШИИВ' ПРИМЕЧАНИЕ k sos.c 18F458.h 3 Output =- Documentation B Q? Source j Й SOI J Если кнопка отображения панели Files отсутствует, выберите пункт меню View и установите флажок Projfect Files в подме- ню Windows. Рис. 11.16. Панель Files СОВЕТ Как только указатель мыши выйдет за пределы панели Files (или любой другой панели, для отображения которой служат кнопки, расположенные у левого края окна PCW), она автомати- чески свернется. Для того чтобы зафиксировать такую панель, в ней необходимо щелкнуть мышью на маленькой пиктограмме с изображением канцелярской кнопки. В результате заго- ловок панели примет вид, позволяющий перетаскивать ее мышью в любую позицию экрана. Для того чтобы открыть тот или иной файл с исходным кодом, уже сущест- вующим в проекте, следует дважды щелкнуть мышью на соответствующем элемен- те в разделе Source. Можно также быстро открыть все файлы, перечисленные в этом разделе, выбрав команду меню Project ► Open All Files. Для добавления в проект нового файла с исходным кодом служит кнопка Q Add Unit панели Files, а для удаления выбранного в разделе Sources файла (кро- на ме главного) — кнопка Remove Unit ' “ Каждому файлу в окне среды разработки соответствует отдельная вкладка. Для того чтобы закрыть текущую вкладку, на ней следует щелкнуть правой кнопкой мыши и выбрать в контекстном меню команду Close или нажать комбинацию кла- виш <Ctrl+F4>. Для того чтобы полностью закрыть проект, следует выполнить ко- манду меню Project ► Close Project. Компиляция проекта Для компиляции текущего проекта можно выполнить команду меню Compile ► Compile или нажать клавишу <F9>. ПРИМЕЧАНИЕ Перед компиляцией следует выбрать корректное значение серии микроконтроллеров PIC в раскрывающемся списке, расположенном в подменю Compile ► Compile слева от кнопки Clean. Для того чтобы точно выяснить, к какой серии относится то или иное устройство (РСМ, РСН или PCD) следует нажать расположенную ниже кнопку Lookup Part (Проверить модель), и выбрать целевое устройство в диалоговом окне Select Target Chip. Корректное обозначе- ние серии микроконтроллеров отобразится в поле Compiler. В результате компиляции в папке размещения исходных файлов будут созданы еще несколько файлов с тем же именем, но другими расширениями:
Компиляция проекта 273 • .cof — файл, используемый в среде отладки; • . err — файл с перечнем ошибок (если были обнаружены); кроме того, первая обнаруженная ошибка будет выделена в исходном тексте программы, а ее опи- сание — отображено на красном фоне в строке состояния; • . hex — объектный файл для загрузки в микроконтроллер; • .1st — файл листинга, в котором отображены соответствия между оператора- ми на языке С и ассемблерными наборами команд; • . sta — файл статистики по результатам последней компиляции; • . sym — файл символов, содержащий адреса переменных в памяти RAM; • .tre — дерево вызовов подпрограмм. Для просмотра содержимого одного из этих файлов можно дважды щелкнуть мышью на соответствующем элементе в разделе Output панели Files или выбрать одну из команд в подменю Compile ► View Output Files. Формат некоторых из выходных файлов можно выбрать в разделе Output Files уже знакомого нам диалогового окна Project Options, которое открывается по коман- де меню Options ► Project Options (рис. 11.17). Рис. 11.17. Настройка формата выходных файлов Формат отладочного файла выбирают с помощью группы переключателей De- bug File; объектного файла — Object File (восьми- или 16-тибитный .hex или двоич- ный); файла с перечнем ошибок — Error File, файла листинга — List File. С помощью флажков в группе Other Files можно отменить создание файлов . sta и . tre. "7"Т” .. • ...... Для отладки программ в среде MPLAB, которая рассматривается в следующей главе, в груп- пе Debug File до компиляции необходимо выбрать переключатель Standard .COD или Expan- ded .COD. В группе Compile Window Up настраиваются параметры отображения окна с ре- зультатами компиляции (рис. 11.18). В раскрывающемся списке No Errors устанав- ливается значение задержки окна результатов на экране (в секундах) в случае отсут- ствия ошибок компиляции. Варианту Hold Up соответствует постоянное отображе- ние, пока пользователь сам не закроет окно результатов. Список On Error имеет тот же смысл, но для случая, когда были обнаружены ошибки: No — окно результатов
274 Глава 11. Компилятор CCS-PICC компиляции не отображается; As above — задержка отображения как в случае от- сутствия ошибок. Меню Tools Меню Tools содержит команды доступа к различным полезным утилитам. Рас- смотрим назначение некоторых из них: • Device Editor — доступ к базе данных свойств каждого под держиваемого микро- контроллера PIC; • Device Selector — выбор целевого микроконтроллера и его свойств; • File Compare — утилита сравнения файлов (исходных кодов или листингов) — если выбрано сравнение исходных файлов, то выполняется обычное построчное сравнение, если же выбрано сравнение листингов, то его можно настроить та- ким образом, чтобы адреса памяти не учитывались; • Numeric Converter — средство преобразования целых и вещественных чисел в десятичном представлении в шестнадцатеричное и наоборот; • Serial Port Monitor — монитор последовательного порта для отладки встроенных систем, предназначенных для обмена через интерфейс RS-232, RS-442, RS-485; • MPLAB — отладчик MPLAB. Рис. 11.18. Результаты работы компилятора CCS-PICC
Глава 12 Эмуляция и отладка программ в среде MPLAB Рассмотренный в предыдущей главе компилятор CCS-PICC спроектирован для работы совместно с отладчиком Microchip MPLAB, представляющий собой про- граммный имитатор микроконтроллеров PIC. Средство MPLAB можно бесплатно загрузить с Web-сайта компании Microchip (www. mi crochip. com). e Установочный пакет MPLAB версии 8.50 также можно найти на прилагаемом к книге компакт- диске в папке Software\PIC\MPLAB. В среде MPLAB используются файлы .cod, которое создаются, в том числе, и компилятором CCS-PICC (см. предыдущую главу). Для сопряжения среды CCS- PICC с MPLAB требуется установить два дополнения, которые можно загрузить с Web-сайта www. ccsinfо. com. • Соответствующие файлы setup_mplab_plugin. ехе и setup_mctools . ехе так- же находятся на прилагаемом к книге компакт-диске в папке Sof tware\PIC\CCS-PICC. Среда CCS-PICC позволяет выполнять внутрисхемную отладку, не переходя в MPLAB. Для этого необходимо выбрать команду меню Debug, щелкнуть мышью на направленной вниз стрелки справа от пиктограммы Enable Debugger и выбрать требуемый отладчик (рис. 12.1). Если к компьютеру по соответствующему последовательному интерфейсу подключены аппаратные отла- дочные средства с микроконтроллером, то активизируется ре- жим отладки. В этом режиме открыта панель Debug, позволяю- щая просматривать состояние памяти и регистров целевого уст- ройства, а управление процессом отладки осуществляется с по- мощью команд подменю Debug ► Debugger Control (рис. 12.2). Теперь для выхода из режима отладки следует выбрать команду Debug ► Disable. Рис. 12.1. Переход в режим внутрисхемной отладки Рис. 12.2. Команды для управления режимом отладки в среде CCS-PICC Если говорить о рассмотренной ранее среде CCS-PICC, то для запуска MPLAB достаточно выполнить команду меню Tools ► MPLAB. В любом случае, MPLAB за- пускается с помощью соответствующего ярлыка на Рабочем столе Windows или по команде меню Пуск ► Все программы ► Microchip ► MPLAB IDE v8.50 ► MPLAB IDE.
276 Глава 12. Эмуляция и отладка программ в среде MPLAB Рабочая область и проект MPLAB Для того чтобы перейти в режим имитации или отладки программы в среде MPLAB, для нее необходимо создать рабочую область и проект. Для этого лучше всего воспользоваться специальным мастером, который запускается в среде MPLAB по команде меню Project ► Project Wizard. В первом окне мастера следует только на- жать кнопку Далее, после чего откроется окно выбора типа микроконтроллера для имитации. На следующем этапе (рис. 12.3) выбирают программную среду, используемую для разработки отлаживаемых программ. Для случая с CCS-PICC в раскрывающем- ся списке Active Toolsuite следует выбрать элемент CCS С Compiler for Р1С10/12/14/16/ 18/24ldsPIC30/dsPIC33, и удостовериться, что в поле Location указан корректный путь к файлу ccsc. ехе. Рис. 12.3. Выбор средства разработки программ На следующем шаге указывается имя MPLAB-проекта и выбирается каталог его размещения, а в следующем окне мастера необходимо добавить в проект сущест- вующие файлы с исходным кодом С-проекта (рис. 12.4). Для этого требуемые фай- лы следует выделить в списке, расположенном слева, и нажать кнопку Add. Доба- вим, к примеру, созданный ранее файл sos. с. Рис. 12.4. Выбор файла с исходным кодом программы
Компиляция под управлением MPLAB 277 В последнем окне мастера достаточно нажать кнопку Готово. Окно MPLAB с загруженным для отладки файлом SOS. с показано на рис. 12.5. Рис. 12.5. Окно MPLAB 8.50 Для сохранения проекта используют команду меню Project ► Save Project или Project ► Save Project As, а для сохранения рабочей области — команду File ► Save Workspace и File ► Save Workspace As. Компиляция под управлением MPLAB Проект можно откомпилировать с помощью подключенного компилятора (на- пример, CCS-P1CC) непосредственно в среде MPLAB. Для этого служит команда меню Projects Make (клавиша <F10>). Окно состояния компилятора откроется на период компиляции, а затем исчезнет. Для сбора данных, необходимых при эмуля- ции и отладке MPLAB требуется файл .cod или .cof. При вызове компилятора CCS-PICC из MPLAB для него, по умолчанию, выходной файл — .cof, однако при подобном вызове он не создается. Вместо этого должен генерироваться файл . cod. Для того чтобы выбрать этот формат, следует в среде MPLAB выполнить ко- манду меню Project ► Build Options ► Project, в диалоговом окне Build Options перей- ти на вкладку CCS С Compiler, в группе параметров Debug выбрать переключатель Expanded COD Format (рис. 12.6) и нажать кнопку ОК. Теперь по завершению компиляции эмулятор MPLAB будет автоматически за- гружать файл . cod, созданный компилятором. Настройка режима отладки/эмуляции , Микроконтроллер для программной эмуляции выбирается на этапе создания проекта MPLAB, но этот выбор можно изменить позже, выполнив команду меню Configure ► Select Device и указав требуемое значение в поле Device диалогового ок- на Select Device (рис. 12.7). Для перевода MPLAB в режим программной эмуляции, необходимо выполнить пункт меню Debugger ► Select Tool ► MPLAB SIM. В результате отобразится панель инструментов Debug с кнопками, используемыми для отладки.
278 Глава 12. Эмуляция и отладка программ в среде MPLAB Рис. 12.6. Диалоговое окно Build Options Рис. 12.7. Выбор микроконтроллера для программной эмуляции Для настройки параметров эмуляции следует выполнить команду меню Debug- ger ► Settings. В открывшемся диалоговом окне Simulator Settings особый интерес представляют вкладки Osc/Trace и Animation / Realtime Updates (рис. 12.8). На вкладке Osc/Trace можно выбрать частоту осциллятора, а на вкладке Animati- on/Realtime Updates задать период анимационного прохода (выполнение программы с обновлением окон отладчика через строго определенные промежутки времени) и период обновления окон при выполнении в реальном режиме времени. Если тре- буется, чтобы обновления окон происходили таким образом, чтобы отражать ин- формацию реалистично, значения этих периодов не следует выбирать большими.
Работа в режиме отладки/эмуляции 279 Рис. 12.8. Параметры эмуляции Если не установить флажок Enable Realtime watch updates, то при запуске программы в ре- жиме реального времени окна отладчика вообще не будут обновляться. ПРИМЕЧАНИЕ Как и в случае с AVR Studio (см. главу 4), при эмуляции программ в среде MPLAB следует учитывать, что задержки при работе с реальным микроконтроллером намного меньше. С помощью параметров, расположенных в диалоговом окне Simulator Settings на вкладке Break Options можно управлять моментами останова эмуляции, включая ос- танов по сигналу от сторожевого таймера (WDT) и останов по переполнению стека. Работа в режиме отладки/эмуляции Команды, используемые в режиме отладки, находятся в меню Debugger. Как и в AVR Studio, в MPLAB используются точки прерывания, обозначаемые красным кружком с символом “В” слева от строки исходного кода, в которых они установле- ны. Для установки/удаления точки прерывания следует дважды щелкнуть мышью на сером поле слева от сроки или выполнить команду контекстного меню Set Break- point. Для отключения/активизации и удаления точек прерывания используется диа- логовое окно Breakpoints, которое открывается по команде меню Debugger ► Break- points (клавиша <F2>), или же команды Disable Breakpoint (отключение), Enable Breakpoint (активизация) и Remove Breakpoint (удаление) контекстного меню. Для отключения, активизации или удаления всех расставленных точек прерывания мож- но воспользоваться тем же диалоговым окном Breakpoints или командами подменю Breakpoints контекстного меню. Для перехода в режим отладки используются команды меню Debugger или соот- ветствующие кнопки панели инструментов Debug: • Run (клавиша <F9>) — выполнение программы в режиме реального вре- м мени; переход в режим отладки происходит, если встречается точка пре- пн рывания; • Animate — выполнение программы с периодическим обновлением окон МД отладчика; • Step Into (клавиша <F7>) — выполняет текущую команду с заходом рд в подпрограммы (все окна обновляются); ИВ
280 Глава 12. Эмуляция и отладка программ в среде MPLAB • Step Over (клавиша <F8>) — выполняет текущую команду без захода в подпрограммы (все окна обновляются); • Step Out — запускает программу и выполняет ее до тех пор, пока не ветре- CS тится окончание текущей подпрограммы; если ход выполнения находится - в области основной программы, то программа будет выполняться до тех пор, пока не будет остановлена пользователем командой Halt или не встретит точку прерывания; • Halt (клавиша <F5>) — принудительный останов работы программы. | ВВ Для эмуляции сброса используются команды подменю Debugger ► Reset, а также кнопка Reset панели инструментов Debug (клавиша <F6>). —- Еще одна возможность — выполнение программы до строки, в которой в дан- ный момент установлен курсор. Для этого используется команда контекстного ме- ню Run to Cursor. Окна отладчика Вызов окон отладчика реализован с помощью команд меню View. Прежде всего, интерес представляют окна Watch, File Registers и Special Function Registers. Типич- ное для отладчиков окно Watch (рис. 12.9) позволяет просматривать значения пере- менных и содержимое регистров управления во время выполнения программы. Рис. 12.9. Окно Watch С помощью кнопки Add SFR и расположенного справа от нее раскрывающегося списка можно создать элемент для просмотра содержимого какого-либо регистра управления (в примере на рис. 12.9 — регистра данных порта D). Аналогичное на- значение, но для переменных, имеет кнопка Add Symbol и расположенное справа по- ле. Для того чтобы изменить формат отображения значения некоторого элемента просмотра, на нем следует щелкнуть правой кнопкой мыши, выбрать в контекстном меню команду Properties и задать требуемый формат на вкладке Watch Properties. Для удаления текущего элемента просмотра достаточно нажать клавишу <De- lete> или же воспользоваться командой Delete контекстного меню. Следующее окно отладчика, представляющее интерес, — File Registers. Оно отображает содержимое регистрового файла. Содержимое этого вида памяти можно просмотреть в виде шестнадцатеричного дампа (вкладка Hex) или же последова- тельного списка ячеек с отображением их содержимого в различных форматах (вкладка Symbolic) (рис. 12.10). Значения, измененные в процессе выполнения про- граммы, выделяются в окне File Registers красным цветом. Окно File Registers позволяет редактировать расположенные в памяти перемен- ные непосредственно или с помощью специального окна, которое открывается по команде контекстного меню Fill Registers (рис. 12.11). В окне Fill Registers можно указать начальный и конечный адрес области памяти, занимаемой переменной,
Окна отладчика 281 в поле Data вести требуемые данные в шестнадцатеричной или десятичной форме (это определяется с помощью переключателей Data Radix) и нажать кнопку Write. Для выхода без выполнения записи используется кнопка Close. Рис. 12.10. Вкладки Hex и Symbolic окна File Registers Наконец, последнее окно отладчика, которое мы рас- смотрим, — это Special Function Registers (рис. 12.12). Как понятно из его названия, оно используется для просмотра и модификации содержимого регистров управления различ- ными устройствами микроконтроллера (таймеры, порты ввода/вывода, последовательные интерфейсы и т.д.). К при- меру, рассмотренная выше программа SOS. с изменяет со- держимое регистров PORTD (адрес $0F83), LATD (адрес $0F8C) и TRISD (адрес S0F95). Значения, измененные в процессе выполнения про- граммы, выделяются в окне Special Function Registers крас- ным цветом. Так же как и в окне File Registers, в этом окне можно изменять содержимое регистров прямо в процессе выполне- ния программы (в режиме отладки). Еддавс: ж; *1 SlartAdduJM: |охООО1| EndAd-1 ем: |oxOFFF Da»a |oxO5 Da1 a Radix Hex Decsnal : Use Dale Ar C «Value Sequence Start C Randoms e Data Г~ Rdati Address Range Wntft | Clote | Рис. 12.11. Диалоговое окно Fill Registers Рис. 12.12. Окно Special Function Registers
Глава 13 Компилятор mikroC Компилятор mikroC, разработанный компанией MikroElektronica, как и рас- смотренные ранее средства программирования, предоставляет интегрированную среду разработки (IDE) и возможность выполнять эмуляцию программ. Бесплатную версию этого компилятора, поддерживающую программы размером до 2 Кбайт, можно загрузить с сайта www.mikroe.com. Для получения полнофункциональной версии без каких-либо ограничений следует приобрести соответствующую лицен- зию. • Установочный файл ограниченной версии компилятора mikroC версии 7.0.0.3 можно также най- ти на прилагаемом к книге компакт-диске в папке Sof tware\PIC\mikroC. По умолчанию, после установки mikroC на Рабочем столе Windows будет раз- мещен ярлык mikroC, который и используется для запуска среды разработки. В лю- бом случае, IDE mikroC можно запустить по команде меню Пуск ► Все программы ► Mikroelektronika ► mikroC ► mikroC. Окно среды разработки mikroC при первом запуске показано на рис. 13.1. Рис. 13.1. Окно среды разработки mikroC при первом запуске
Создание проекта mikroC 283 Как видим, рабочая среда разделена на четыре части: • редактор исходного кода, в котором по умолчанию открывается пример про- граммы, реализующей мигание светодиодов, подключенных к порту С (подоб- ные примеры устанавливаются вместе с компилятором в папку \Program Files\Mikroelektronika\Examples); • панель Code Explorer, отображающая иерархию всех структурных элементов программы (переменные, функции); ПРИМЕЧАНИЕ С панелью Code Explorer совмещены еще две полезные панели: QHelp — перечень всех встроенных и библиотечных функций, позволяющий быстро открыть соответствующую стра- ницу интерактивной справки; Keyboard — перечень всех клавиатурных эквивалентов команд, используемых в интегрированной среде разработки mikroC. • панель Project Setup, позволяющая установить для проекта тип микроконтрол- лера, его тактовую частоту и способ отладки (программный имитатор или внут- рисхемный отладчик mikroICD); • панель, содержащая вкладки Messages (сообщения среды разработки об ошиб- ках и предупреждения), Find (сведения о строках в файлах проекта, в которых найдена интересующая информация с помощью команды меню Edit ► Find in Files) и QConverter (средство преобразования чисел из одной системы счисления в другую). Создание проекта mikroC По умолчанию имя проектного файла mikroC имеет расширение .ррс. Он со- держит информацию о файлах с исходным кбдом, целевом микроконтроллере, кон- фигурационных флагах и тактовой частоте. Для создания нового проекта в интегри- рованной среде разработки следует выбрать команду меню Project ► New Project или нажать кнопку New Project панели инструментов. В результате откроется диа- лотовое окно, показанное на рис. 13.2. Рис. 13.2. Диалоговое окно New Project
284 Глава 13. Компилятор mikroC В этом окне следует указать имя проекта (поле Project Name), папку размещения его файлов (поле Project Path), дать строку описания (поле Description), указать тип микроконтроллера (раскрывающийся список Device) и его тактовую частоту (поле Clock), а также задать с помощью флажков конфигурацию разрядов предохранения (список Device Flags). ПРИМЕЧАНИЕ Для обнуления всех конфигурационных разрядов можно нажать кнопку Clear АП, а для уста- новки конфигурации по умолчанию — кнопку Default. После того как все установки выполнены, в диалоговом окне New Project следу- ет нажать кнопку ОК. В результате будет создан новый проект, и в окне редактора откроется пустой файл . с, имя которого будет совпадать с именем проектного фай- ла . ррс. В качестве примера введите в нем программу, показанную в листинге 13.1. Листинг 13.1. Программа SOS. а для компилятора mikroC void Pause(int ms) { PORTD = OxFF; Vdelay_ms (ms) ; } //Все светодиоды отключены //Задержка void Point(void) { PORTD = 0; delay_ms(500); Pause(500); //Включаем все светодиоды //Короткая задержка //Пауза с погасшими светодиодами void Dot(void) { PORTD = 0; delay_ms(1000); Pause(500); //Включаем все светодиоды //Длинная задержка //Пауза с погасшими светодиодами void main (void) TRISD = 0; while(1) { // Настройка порта D для вывода //Бесконечный цикл Point(); Point(); Dot(); Dot(); Dot(); //- Point(); Point(); Point() Pause(5000); Point() Это — версия уже знакомой нам по предыдущим главам программы “SOS”, включающей и отключающей светодиоды, соединенные с выводами порта D. ©Программу SOS . с можно также найти на прилагаемом к книге компакт-диске в папке Projects\mikroC\SOS.
Компиляция проекта 285 Для сохранения исходных файлов проекта служат три команды меню File: • Save (комбинация клавиш <Ctrl+S>) — сохранение файла, открытого в данный момент в окне редактора, под именем по умолчанию; • Save As — сохранение файла, открытого в данный момент в окне редактора, под именем, заданным пользователем; • Save All (комбинация клавиш <Ctrl+Shift+S> — сохранение всех файлов проекта под именами по умолчанию. фт. -г а ✓ ' , УМ - \ /J' ' А, у/ a у тм У ,v' t,’ W"' v,"r /МП? ПРИМЕЧАНИЕ Настройки проекта можно в любой момент изменить, вызвав диалоговое окно Edit Project (см. рис. 13.2) с помощью команды меню Project ► Edit Project, комбинации клавиш <Ctrl+Shift+E> или кнопки Edit Project панели инструментов. Компиляция проекта Теперь можно откомпилировать проект. Для этого следует выбрать команду меню Project ► Build, нажать комбинацию клавиш <Ctrl+F9> или воспользоваться кнопкой Build Project панели инструментов. Если в исходном коде программы ин будут обнаружены ошибки, то их перечень с указанием номера строки, типа Wq ошибки и программного модуля . с, отобразится (красным цветом) в панели Messa- ges. Для быстрого перехода к той или иной ошибке достаточно дважды щелкнуть на ней мышью. Если ошибок нет, то в панели Messages появится сообщение (зеленого цвета) с текстом “Success”, а ниже будет показано, сколько откомпилированная про- грамма занимает места в ОЗУ (рис. 13.3). Рис. 13.3. Окно Messages: вверху — обнаружены ошибки; внизу — компиляция прошла успешно В результате компиляции в папке проекта всегда создаётся файл . hex с тем же именем, что и файл . с. Кроме того, по умолчанию создаются файлы . asm (ассемб- лерный код) и . 1st (листинг). Формирование последних двух файлов можно отме- нить с помощью диалогового окна Preferences которое открывается по команде ме- ню Tools ► Options, по нажатию клавиши <F12> или с помощью кнопки Show ЕЕГ Options панели инструментов. Настройки компилятора в диалоговом окне Preferences находятся в разделе Out- put (рис. 13.4). Здесь с помощью соответствующих флажков можно отменить или активизировать формирование тех или иных выходных данных, а также задать уро-. вень оптимизации откомпилированного кода (раскрывающийся список Optimization Level).
286 Глава 13. Компилятор mikroC В этом же окне Preferences, в разделе Project ► Search Path можно указать пути, по которым компилятор ищет файлы с исходным кодом и библиотечные программ- ные модули (рис. 13.5). По умолчанию в список включена папка проекта, а также — две стандартные папки mikroC с определениями для разных типов устройств. Рис. 13.4. Настройки компилятора mikroC Рис. 13.5. Пути поиска файлов с исходным кодом и библиотечных модулей Для того чтобы добавить новый путь поиска, следует нажать кнопку Add, а для удаления текущего элемента списка — кнопку Remove. Для быстрого, автоматиче- ского удаления из списка путей, отсутствующих физически, можно воспользоваться кнопкой Purge Invalid Paths.
Добавление в проект файлов с исходным кодом 287 Добавление в проект файлов с исходным кодом Для того чтобы добавить в проект новый файл с исходным кодом, можно вос- пользоваться одним из двух способов: • выбрать команду меню Project ► Add То Project, а затем указать в стандартном диалоговом окне тип (. с, . h или . mcl) и имя добавляемого файла; • перейти в панель Project Summary, выделить в списке интересующий тип фай- лов, щелкнуть правой кнопкой мыши и выбрать в контекстном меню команду Add То Project (рис. 13.6). ПРИМЕЧАНИЕ Следует отметить, что добавление файла в проект mikroC не позволяет автоматически уви- деть его содержимое в окне редактора. Для просмотра непосредственно самого исходного кода служит команда меню File ► Open, комбинация клавиш <Ctrl+O> и кнопка Open панели инструментов. г^? Для удаления из проекта какого-либо файла (кроме главного с функцией main), следует выделить соответствующий элемент в иерархическом списке панели Project Summary, щелкнуть правой кнопкой мыши и выбрать в контекстном меню команду Remove From Project (рис. 13.7). Можно также выбрать команду меню Project ► Re- move From Project. Project Setup Ptoject Summary | Project ties. Project Setup P®|KI Summary | Project fifes- Add To Project. c Fits ..... । OiMV^RemoveFfom₽rojert.<. сз H ........ > PLD Fites S3 Library Add To Protect. 0 utpuj_ __ H fifes PLD Fdes Remove From Project... Рис. 13.6. Добавления файла в проект Рис. 13.7. Удаление файла из проекта Если при выборе команды Remove From Project в панели Project Summary не был выделен ни один файл с исходным кодом, то откроется диалоговое окно Remove File from Project (рис. 13.8), в котором необходимо выделить интересующий элемент списка (для фильтрации файлов по типам служит группа переключателей File Туре) и нажать кнопку Remove Selected. Рис. 13.8. Диалоговое окно Remove file From Project Прсле того как список файлов сформирован, для его подтверждения следует нажать кнопку ОК. Для отмены удаления файлов из проекта следует нажать кнопку Cancel.
288 Глава 13. Компилятор mikroC Эмуляция выполнения программы Для эмуляции выполнения программы в интегрированной среде mikroC вначале следует убедиться, что активен программный имитатор. Ему соответствует флажок, установленный возле пункта меню Debugger ► Select Debugger ► Software Pic Simula- tor. Если этот флажок установлен, и программа успешно откомпилирована, то для перехода в режим эмуляции следует выбрать команду меню Run ► Start Debugger, нажать клавишу <F9> или воспользоваться кнопкой Start Debugger панели ин- |~~ струментов. В результате mikroC перейдет в режим отладки (в нем текущая 1=2 строка исходного кода обозначается зеленой стрелкой и по умолчанию выделена синим цветом), и откроется окно Watch, позволяющее отслеживать в ходе эмуляции программы содержимое различных переменных, регистров, стека, счетчика команд и флагов состояния (рис. 13.9). Рис. 13.9. {Среда mikroC перешла в режим эмуляции Для добавления в список окна Watch той или иной переменной, значение кото- рой необходимо отслеживать, ее следует выбрать в раскрывающемся списке Select variable from list и нажать кнопку Add. Для добавления всех существующих перемен- ных служит кнопка Add АП. После того как переменная добавлена в список окна Watch, можно настроить параметры отображения ее значения в столбце Value. Для этого можно воспользо- ваться одним из трех способов: • дважды щелкнуть мышью на соответствующей строке списка Watch в столбце Name или Address; • выделить строку списка Watch и нажать кнопку Properties; • щелкнуть в поле Value и нажать расположенную справа от него кнопку .... В любом случае на экране появится диалоговое окно Edit Value, позволяющее отредактировать значение переменной прямо в ходе выполнения программы или же изменить формат ее отображения (десятичное, шестнадцатеричное, двоичное, экс- поненциальное или символьное представление) (рис. 13.10). Установка флажка Signed означает активизацию отображения знака. Для того чтобы подтвердить изменения, внесенные в значение или формат ото- бражения переменной, в диалоговом окне Edit Value следует нажать кнопку ОК. На- жатие кнопки Cancel отменяет все внесенные изменения. Для удаления текущего элемента в списке Watch служит кнопка Remove, а для полной очистки этого списка — кнопка Remove АП.
Эмуляция выполнения программы 289 Рис. 13.10. Активизация шестнадцатеричного отображения значения регистра PORTD Режимы (с заходом в подпрограммы, без захбДа в подпрограммы и т.д.) и обра- ботка точек прерывания в mikroC типичны для подобных средств программной раз- работки, поэтому останавливаться на них подробно мы не будем. Отметим только, что соответствующие им команды и кнопки находятся в меню Run, а также — в главной панели инструментов среды mikroC и в окне Watch (рис. 13.11). Run [ Took Helf Start Debugger F9 Run/Pause Debugger F6 ЙЯ Stop Debugger Ctrl+F2 Step Into F7 Step Over F8 Step Out Ctrl+F8 Run To Cursor F4 & Toggle Breakpoint F5 Clear Breakpoints Shift +Ctrl+F5 Щ View Breakpoints Shift+F4 i DisAssembly View Alt+D Рис. 13.11. Инструменты отладки в среде mikroC Кроме рассмотренного выше окна Watch, среда mikroC предоставляет в распо- ряжение пользователя следующие основные окна отладчика: • RAM (рис. 13.12) — текущее содержимое ОЗУ с возможностью коррекции зна- чений непосредственно в ходе выполнения программы (вкладка RAM), а также просмотр истории обращения команд к ОЗУ (вкладка History); • Stopwatch (рис. 13.13) — состояние счетчика циклов, счетчики времени, секун- домер (обнуляется по нажатию кнопки Reset То Zero), значение тактовой часто- ты процессора; ПРИМЕЧАНИЕ Значения в полях окна Stopwatch обнуляются только при останове эмуляции по команде ме- ню Run ► Pause Debugger (клавиша <F6>), при достижении точки прерывания или при поша- говой отладке. EEPROM — просмотр памяти EEPROM (при ее наличии).
290 Глава 13. Компилятор mikroC Команды вызова окон отладчика находятся в подменю View ► Debug Windows. Рис. 13.12. Окно RAM Рис. 13.13. Окно Stopwatch Для выхода из режима эмуляции служит команда меню Run ► Stop Debug- ger, комбинация клавиш <Ctrl+F2> и кнопка Stop Debugger панели инструмен- тов. Вспомогательные инструменты среды mikroC Среда разработки mikroC предоставляет пользователю множество полезных вспомогательных инструментов, доступ к которым можно получить с помощью ко- манд меню Tools. ПеречисЛйм некоторые из них: • ASCII Chart — таблица символов ASCII, позволяющая увидеть код любого сим- вола в десятичном, шестнадцатеричном и двоичном представлении и скопиро- вать его в буфер обмена с помощью команд контекстного меню (рис. 13.14); • USART Terminal (комбинация клавиш <Ctrl+T>) — терминал обмена данными по последовательному COM-интерфейсу (рис. 13.15); • HID Terminal — терминал обмена данными по последовательному USB-интер- фейсу (рис. 13.16); • UDP Terminal — терминал обмена данными по UDP-интерфейсу; • GLCD Bitmap Generator — генератор С-кода для графических изображений, за- гружаемых в ЖК-дисплеи (рис. 13.17); • Seven Segment Decoder — генератор числового кода для одного разряда семи- сегментного индикатора (рис. 13.18); • LCD Custom Character — генератор кода для компилятора mikroC, формирующе- го произвольный символ на экране ЖК-дисплея (рис. 13.19); • EEPROM Editor — редактор памяти EEPROM (рис. 13.20).
Вспомогательные инструменты среды mikroC 291 Рис. 13.14. Таблица символов ASCII Рис. 13.15. Терминал обмена данными по СОМ-интерфейсу
292 Глава 13. Компилятор mikroC Рис. 13.16. Терминал обмена данными по USB-интерфейсу Рис. 13.17. Генератор С-кода для графических изображений, загружаемых в ЖК-дисплеи Рис. 13.18. Генератор числового кода для одного разряда семисегментного индикатора
Вспомогательные инструменты среды mikroC 293 Рис. 13.19. Генератор кода для компилятора mikroC, формирующего произвольный символ на экране ЖК-дисплея Рис.13.20. Редактор памяти EEPROM
Глава 14 Компиляторы СЗО и С32 Компиляторы СЗО и С32 — разработки компании Microchip (www.microchip, coin), используемые для создания программ на языке С для новых микроконтролле- ров семейств PIC24 (см. главу 9) и PIC32 (см. главу 10) соответственно. Они ис- пользуются совместно с интегрированной средой MPLAB, рассмотренной в главе 12, поэтому перед установкой данных компиляторов необходимо иметь в наличии MPLAB. е Установочные файлы бесплатных, урезанных версий компиляторов СЗО и С32 можно найти на прилагаемом к книге компакт-диске в папке Sof tware\PIC\C30-32. Рассмотрим использование компиляторов СЗО и С32 в среде MPLAB. Компилятор СЗО Выполните следующую последовательность действий. 1. Откройте интегрированную среду разработки MPLAB. 2. Выберите команду меню Project ► Project Wizard^ чтобы активизировать мастер создания проектов. 3. В первом окне мастера нажмите кнопку Next (Далее). 4. Выберите какой-либо микроконтроллер семейства PIC24 (например, PIC24 FJ128GA010) и нажмите кнопку Next. 5. В раскрывающемся списке Active Toolsuite (Активный инструментальный набор) выберите элемент Microchip СЗО Toolsuite. 6. Если слева от каких-либо элементов в списке Toolsuite Contents (Содержимое набора) отображен красный крестик, то это говорит, что MPLAB не нашел раз- мещение соответствующих программ. Для того чтобы исправить это, выделите такой элемент, нажмите кнопку Browse и найдите в папке \Program Files\ Microchip\MPLAB СЗО\bin файл . ехе, указанный в элементе списка. Напри- мер, компилятору СЗО соответствует файл pic30-gcc. ехе. 7. Нажмите кнопку Next 8. В поле Create New Project File (Создать файл нового проекта) имя проектного файла с указанием полного пути к нему и нажмите кнопку Next. 9. В следующем окне мастера можно добавить в проект файлы с исходным кодом. Просто нажмите кнопку Next, поскольку сейчас мы не будем копировать каких- либо исходных файлов из предыдущих проектов. 10. Нажмите кнопку Finish (Готово) для завершения работы мастера. 11. Создайте новый файл исходного кода по команде меню File ► New. 12. Введите следующие три строки с комментариями:
Компилятор СЗО 295 13. Выберите команду меню File ► Save As и сохраните файл под произвольным именем с расширением .с. 14. Выберите команду меню Project ► Save Project, чтобы сохранить проект. 15. Введите в окне редактора строку кода: #include <p24fj128ga010.h> Это — директива, указывающая компилятору прочитать содержимое файла со специфическими настройками микроконтроллера. Этот файл с расширением . h со- держит длинный список внутренних регистров специального назначения для вы- бранной модели PIC24. Ниже представлен фрагмент из файла p24fjl28ga010.h, в котором определен счетчик команд и несколько других регистров специального назначения: extern volatile unsigned int PCL ___attribute___((_sfr___)); extern volatile unsigned char PCH __attribute___((_sfr___)); extern volatile unsigned char TBLPAG ___attribute__((__sfr__)); extern volatile unsigned char PSVPAG ___attribute__((__sfr__)); extern volatile unsigned int RCOUNT ____attribute_((___sfr__)); extern volatile unsigned int SR ___attribute__((__sfr__)); Теперь в наш исходный код осталось только добавить функцию main и другие программные элементы. Например, простейшая программа, включающая светодио- да на порту А, выглядит следующим образом: #include <p24fj128ga010.h> main() { TRISA =0; // Все выводы порта A - выходы PORTA = Oxff; } Для того чтобы указать MPLAB файлы . с для компиляции и компоновки по команде меню Project ► Build АП (комбинация клавиш <Ctrl+F 10>), их имена необ- ходимо добавить в список исходных файлов проекта — папка Source Files панели Files (открывается по команде меню View ► Project). Для того чтобы компоновщик мог назначить корректные адреса каждой пере- менной и функции, MPLAB необходимо предоставить имя специфического для уст- ройства сценария компоновки (файл с расширением . gid). Точно так же как вклю- чаемый файл . h описывает имена регистров специального назначения для компиля- тора СЗО, сценарий компоновки информирует о предопределенном размещении этих регистров в памяти (согласно спецификациям устройства). Кроме того, он со- держит важную информацию о пространстве памяти: доступный объем флэш-памя- ти и ОЗУ, а также —т соответствующие диапазоны адресов. Сценарий компоновки — это обычный текстовый файл, который можно от- крыть и исследовать в редакторе MPLAB. Фрагмент файла p24f j 128ga010. gid, в котором определены адреса счетчика команд и нескольких других регистров спе- циального назначения имеет следующий вид: PCL = 0х2Е; PCL = 0х2Е;
296 Глава 14. Компиляторы СЗО и С32 РСН = 0x30; РСН = 0x30; TBLPAG — 0x32; TBLPAG = 0x32; PSVPAG = 0x34; PSVPAG = 0x34; RCOUNT = 0x36; RCOUNT = 0x36; SR = 0x42; SR = 0x42; Для добавления в проект сценария компоновки необходимо щелкнуть правой кнопкой мыши на элементе Linker Scripts в панели Files, выбрать в контекстном ме- ню команду Add file (Добавить файл), и найти требуемый файл .gid (например, p24fj128ga010.gid) в подкаталоге Program Files\Microchip\MPLAB C30\ support\gld. Теперь можно выполнить компиляцию и отладку проекта, как это было показа- но в главе Y2. Примеры программ для компилятора СЗО будут рассмотрены позже, в главе 22. Компилятор С32 Процесс использования компилятора С32 совместно со средой MPLAB анало- гична рассмотренному выше для СЗО, поэтому отметить лишь некоторые отличия: • на первом этапе работы мастера создания проекта в MPLAB необходимо вы- брать какой-либо микроконтроллер семейства PIC32 (например, PIC32 MX360F512L); • на следующем этапе в раскрывающемся списке Active Toolsuite следует выбрать элемент Microchip PIC32 C-Compiler Toolsuite (если он в списке отсутствует, уста- новите флажок Show all installed toolsuites, расположенный в правом нижнем уг- лу окна мастера); • программные компоненты пакета С32 по умолчанию устанавливаются в папку \Program Files\Microchip\MPLAB С32 Suite\bin; • включаемые файлы . h имеют вид р32х. h, где х обозначает модель микрокон- троллера (например, p32mx360f5121. h); • файл сценария компоновки для всех типов микроконтроллеров PIC32 называ- ются одинаково: procdef s. Id. Такие файлы распределены по папкам, назва- ния которых соответствуют маркировке устройств. Например, файл procdef s. id для микроконтроллера PIC32MX360F512L по умолчанию находится в папке \Program Files\Microchip\MPLAB С32 Suite\pic32mx\lib\proc. Примеры программ для компилятора С32 будут рассмотрены позже, в главе 23.
Глава 15 Программаторы для микроконтроллеров PIC После того как будет получен исполняемый код в виде файла . hex, он должен быть загружен в память программ микроконтроллера с помощью устройства, назы- ваемого программатором. Тип такого устройства зависит от модели программируе- мого микроконтроллера. Например, некоторые аппаратные программаторы поддер- живают только устройства серии PIC16, а другие — PIC 16 и PIC18. Кроме того, многие отладочные платы поддерживают возможность внутрисхемного программи- рования, когда микроконтроллер не нужно извлекать из гнезда и подключать к от- дельному устройству. Рассмотрим некоторые популярные аппаратные программаторы, применяемые при работе с микроконтроллерами PIC. Первый из них — недорогое устройство от компании Microchip (www.microchip.com) под названием PICSTART Plus (рис. 15.1). Этот программатор подключается к ПК через последовательный COM-порт и поддерживается средой разработки MPLAB. Без адаптера PICSTART Plus позволяет программировать большой спектр микроконтроллеров PIC в корпусах с двухрядным расположением выводов типа DIP (число выводов — от 18 до 40). При наличии специальных адаптеров этот программатор применим и для устройств, выполнен- ных в других типах корпусов. Еще один программатор, который можно отметить, — это USB+ от компании Forest Electronics Developments (www. f ored. co. uk) (рис. 15.2). Рис. 15.1. Программатор PICSTART Plus Рис. 15.2. Программатор FED USB+
298 Глава 15. Программаторы для микроконтроллеров PIC Этот программатор поддерживает микроконтроллеры серий PIC12C5, PIC16 и PIC18 в корпусах с числом выводов от восьми до 40. Подключение к ПК осущест- вляется через порт USB, благодаря чему для FED USB+ не требуется внешний ис- точник питания. Еще один программатор, поддерживающий все микроконтроллеры PIC, кроме семейства PIC32, в корпусах с числом выводов от восьми до 40, — это Mach X от компании CCS (www.ccsinfo.com) (рис. 15.3). Он подключается к ПК через порт USB (т.е. не требует внешнего питания), позволяет считывать из микроконтроллера программный код, формируя файлы .hex и .asm, а также поддерживает внутри- схемное программирование через стандартный ICD-соединитель. Наконец, упомянем недорогой программатор Easy Prog PIC от компании Embed (www.embedinc.com) (рис. 15.4). Он поддерживает микроконтроллеры серий PIC10F, PIC12F, PIC16F и PIV18F в корпусах с числом выводов до 40. Подключение к ПК — по последовательному СОМ-интерфейсу. Рис. 15.3. Программатор Mach X Рис. 15.4. Программатор EasyProg PIC Программные средства для программирования микроконтроллеров Кроме отладочной платы и/или аппаратного программатора (адаптера), для за- писи программ в память микроконтроллера требуется также специальное про- граммное обеспечение. В большинстве случаев оно совместимо с популярными средствами эмуляции и отладки, что позволяет программировать устройства непо- средственно из интегрированной среды разработки. Основная тема данной книги — применение языка С для разработки встроен- ных приложений, поэтому подробно на процессе программирования мы останавли- ваться не будем. За дополнительной информацией по этому вопр'осу обращайтесь к специализированным изданиям. В среде MPLAB для получения доступа к установленным в системе драйверам программаторов служит подменю Programmer ► Select Programmer. По умолчанию в нем выбран пункт None (Отсутствует). Если в этом подменю отметить какой-либо
Программные средства для программирования микроконтроллеров 299 из доступных программаторов, то в меню Programmer появятся дополнительные ко- манды, набор которых зависит от выбранного устройства. Эти команды, например, позволяют установить соединение с программатором, проверить содержимое памя- ти программ или EEPROM микроконтроллера, ну и, конечно же, выполнить про- граммирование. Для настроек программирования служит команда меню Program- mer ► Settings, которая вызывает диалоговое окно, содержимое которого, опять- таки, зависит от выбранного устройства. Следует отметить, что при активизации программного обеспечения программа- тора в среде MPLAB обычно появляется дополнительная панель инструментов, ко- торая дублирует команды меню Programmer. Если такая панель не отображается, это можно исправить, выбрав соответствующий пункт подменю View ► Toolbars. Программирование устройств в среде CCS-PICC В среде CCS-PICC инструмент программиро- вания выбирают с помощью подменю Compile ► Program Chip (рис. 15.5). В комплект поставки CCS-PICC традиционно входит специальная программа icd.exe (по умолчанию, устанавливается в папку \Program Files\PlCC; в оценочной версии компилятора отсутствует), организующая передачу данных в программатор через последовательный порт ком- пьютера (формат объектного файла — восьмираз- Рис. 15.5. Выбор инструмента программирования в среде CCS-PICC рядный . hex). Для запуска этого средства из среды разработки CCS-PICC следует выполнить команду меню Compile ► Program Chip ► ICD. В результате на экране поя- вится диалоговое окно, в котором'следует выбрать последовательный порт и ско- рость передачи данных и нажать кнопку Connect После того как связь будет уста- новлена, откроется окно, в котором необходимо указать имя записываемого файла . hex и затем нажать кнопку Download to target. В последних версиях CCS-PICC наряду с ICD в пакет включена программа ccsload.exe с современным графическим интерфейсом (рис. 15.6). Рис. 15.6. Программа CCS Load
300 Глава 15. Программаторы для микроконтроллеров PIC Она предоставляет пользователю полный спектр возможностей взаимодействия с программируемым устройством: диагностика,, чтение, очистка и запись памяти; запуск программы на микроконтроллере; калибровка кристалла. Файл с исполняемым кодом указывают в поле File, а целевое устройство — в поле Target. Для настройки параметров соединения с программатором служит кнопка Set- tings. ПРИМЕЧАНИЕ —------ Еще один способ вызвать программу CCS Device Programmer — с помощью команды меню Tools ► CCSLQAD. Программирование устройства в среде mikroC Для программирования целевого микроконтроллера из среды mikroC использу- ется специальная программа PicFLASH, которая включена в установочный пакет mikroC и вызывается одним из двух способов: • из интегрированной среды разработки — с помощью команды меню Tools ► mE Programmer, нажатия клавиши <F11> или кнопки mE Programmer, располо- ГТ"] женной у правого края окна mikroC; lSs • как отдельную программу — с помощью команды меню Пуск ► Все програм- мы ► Mikroelektronika ► PICFLASH with mikro ICO ► PICFLASH или соответствую- щего ярлыка Рабочего стола Windows. Окно программы PicFLASH показано на рис. 15.7. Рис. 15.7. Программа PicFLASH При работе с PicFLASH исполняемый код (файл .hex) загружается вначале в буфер программы с помощью команды меню File ► Load HEX, комбинации клавиш <Ctrl+O> или кнопки Load HEX. Просмотреть код, который будет загружен в память программ, можно с помощью команды меню Windows ► CODE View или кнопки
Программные средства для программирования микроконтроллеров 301 CODE (рис. 15.8). Если программой используется память EEPROM, то просмотреть ее содержимое (в буфере) можно с помощью команды меню Windows ► EEPROM View или кнопки EEPROM. Рис. 15.8. Просмотр кода, который должен быть записан в память программ Кнопка Erase в любом из этих окон очищает соответствующую область буфера (эту же функцию выполняет команда меню Buffer ► Erase), а кнопка Randomize — за- полняет ее хаотическим кодом (эту же функцию выполняет команда меню Buffer ► Randomize). Целевое устройство выбирают в раскрывающемся списке Device, а взаимодейст- вие с ним реализуют расположенные ниже кнопки Read (чтение памяти микрокон- троллера в программный буфер), Write (запись содержимого буфера в память микро- контроллера), Verify (проверка соответствия буфера и содержимого памяти микрокон- троллера), Erase (очистка памяти микроконтроллера) или аналогичные команды меню Device. Конфигурационные разряды, программируемые по нажатию кнопки Write оп- ределяют с помощью списков и флажков в разделе Configuration Bits. Содержимое памяти микроконтроллера, считанное командой Read в буфер Pic- FLASH, можно сохранить в файле . hex. Для этого служит команда меню File ► Save HEX, комбинация клавиш <Ctrl+S> и кнопка Save HEX.
ЧАСТЬ V Язык С и директивы препроцессора
Г ЛАВА 16 Основы языка С В этой главе кратко рассматривается синтаксис языка С, а также директивы препроцессора в том объеме, которого будет достаточно для изучения примеров из следующих двух частей книги. Даже если читатель уже знаком с представленными здесь вопросами, все же рекомендуем просмотреть эту главу, чтобы выяснить осо- бенности, характерные для различных компиляторов. Вводные понятия Прежде всего, рассмотрим такие вводные понятия как комментарии, ключевые слова, идентификаторы, литералы, операторы и знаки пунктуации. Комментарий — это некоторый поясняющий текст, который при компиляции не учитывается. Комментарии бывают многострочными (начинаются с символов / * и заканчиваются символами */) и однострочными (начинаются с символов //). В последнем случае комментарием считается вся часть строки, расположенная справа от символов //. Примеры: /* Многострочный комментарий часто размещают в начале файла, где он содержит имя автора и описание программы */ #include <avr/io.h> //Подключаем заголовочный файл io.h Идентификатор — это последовательность букв, цифр и символов подчерки- вания которая не должна начинаться с цифры, используемая для именования различных программных элементов, наподобие переменных, констант, функций, типов и т.д. Регистр букв имеет значение. Ключевое слово — это зарезервированное слово четко определенного назначе- ния. Ключевые слова не могут использоваться в качестве идентификаторов: asm, auto, bit, bool, break, case, char, const, continue, default, defined, do, double, eeprom, else, enum, explicit, extern, false, flash, float, for, goto, if, inline, int, long, register, return, rom, short, signed, sizeof, static, struct, switch, true, typedef, union, unsigned, void, volatile, while. Литерал — постоянное значение некоторого типа, используемое в выражениях. Примеры числовых литералов: • 10 — число 10 в десятичной форме; • ОхА — число 10 в шестнадцатеричной форме (префикс Ох); • 0Ы010 — число 10 в двоичной форме (префикс 0Ь); • 012 — число 10 в восьмеричной форме (префикс 0); • 10.5 — число с плавающей точкой; • 10 5 е -1 — число 10,5 в экспоненциальной форме; • 10U — беззнаковая константа (суффикс и);
304 Глава 16. Основы языка С • 10L — знаковая константа (суффикс L). Символьные литералы заключаются в одинарные кавычки, например, ' в', ' *'. Для обозначения непечатаемых и специальных символов в литералах используются так называемые escape-последовательности: • ' \а' — звуковой сигнал; • ' \Ь' — клавиша <Backspace>; • ' \ f' — прогон листа; • ' \п' — символ перевода строки; • ' \ г' — возврат каретки; • ' \ t' — горизонтальная табуляция; • ' \ v' — вертикальная табуляция; • ' \0' — нулевой символ; • ' \ \ ' — обратная косая; • ' \' — апостроф. Кроме того, любой символ можно представить с помощью литерала по его ASCII-коду, например, литерал ' \t' равнозначен '\х09' (в шестнадцатеричном представлении). Строковые литералы ограничиваются двойными кавычками, а в памяти хранят- ся как последовательности символов, заканчивающиеся нулевым символом ' \0 Специальные символы внутри строки должны предваряться обратной косой (“\”). Примеры строковых литералов: • " " — пустая строка: один символ ' \ 0'; • "в"—два символа: 'В' и ’\0'; • "A\tB\n"—пять символов: ' А', табуляция, ' В', перевод строки, '\0'. Оператор — это символ, указывающий компилятору, какие действия выпол- нить над операндами. Некоторые символы могут трактоваться по-разному в зависи- мости от контекста. Например, знак может использоваться для изменения знака числа или в качестве оператора вычитания. Операторы, соединяющие операнды, представляют собой выражения. Выражения могут быть заключены в круглые скобки и отделяются друг от друга символом точки с запятой (“;”). Приоритетность выполнения операторов в выражениях языка С указана в табл. 16.1 (приоритет с меньшим номером уровня — выше). Объединенные по, некоторому признаку последовательности выражений заклю- чаются в фигурные скобки { }. Так, к примеру, обозначаются границы функций, а также блоки выражений в циклических и условных конструкциях (см. ниже соот- ветствующие разделы этой главы). Структура программы на С Структуру программы, написанной на языке С, изучим на основании примера SOS. с (см. листинг 11.1). Программы обычно начинаются с директив препроцес- сора (начинаются с символа которые, по сути, не являются конструкциями языка С и обрабатываются до фактической компиляции программы. Их смысл — подстановка некоторого кода в программу.
Структура программы на С 305 Таблица 16.1. Приоритетность выполнения операторов в выражениях языка С Уро- вень Операторы Категория Описание 1 0 Круглые скобки [] Элемент массива • Доступ к дан- ным Обращение к элементу структуры, например: PORTB. 1 — разряд 1 порта В Обращение к элементу структуры, опреде- ленной указателем, например: pStruct->x — элемент х структуры, на ко- торую указывает pStruct ++, — (постфиксы) Арифмети- ческие Операторы автоинкремента и автодекремента после того как выражение, в котором задейст- вованы соответствующие операнды, вычис- лено. Примеры: а = Ь++; равнозначно а = b; Ь = Ь+1; а = Ь—; равнозначно а = b; Ь = Ь-1; 2 ++, — (префиксы) Операторы автоинкремента и автодекремента перед тем как выражение, в котором задейст- вованы соответствующие операнды, будет вычислено. Примеры: а = ++Ь; равнозначно Ь = Ь+1; а = Ь; а = —Ь; равнозначно Ь = Ь-1; а = Ь; Логические Логическое (унарное) отрицание Поразрядные Поразрядное отрицание & Доступ к дан- ным Адрес 3 +, - (унарные) Арифмети- ческие Изменение знака операнда * (унарный) Доступ к дан- ным Разыменование указателя 4 * (бинарный) Арифмети- ческие Умножение / Деление % Остаток от деления 5 +, - (бинарные) Сложение и вычитание 6 << Поразрядные Поразрядный сдвиг влево >> Поразрядный сдвиг вправо 7 < > <= >= Сравнения Меньше, больше и т.д. 8 == । = Равно, не равно 9 & Поразрядные Поразрядное "И" 10 А Поразрядные Поразрядное "Исключающее ИЛИ" 11 1 Поразрядные Поразрядное "ИЛИ" 12 && Логические Логическое "И" 13 11 Логические Логическое "ИЛИ" 14 = Присваива- ние Возможны сочетания оператора присваивания с арифметическими и поразрядными операто- рами^ += Ь; равнозначно а = а + Ь;
306 Глава 16. Основы языка С //Директивы препроцессора #include C18F45S.h> #use delay(clock=20000000) #fuses HS,WDT //Объявления глобальных типов, переменных и констант //Функции Functionl { //Объявления локальных типов, переменных и констант //Операторы } FunctionN { //Объявления локальных типов, переменных и констант //Операторы } //Главная функция программы int main (void) { //Объявления локальных типов, переменных и констант //Операторы } В программах на С очень часто используется директива #include, которая включает в файл с исходным кодом текст внешнего заголовочного файла (с расши- рением . h). Заголовочные файлы содержат определения глобальных типов, кон- стант, переменных и функций. Более подробно директивы препроцессора рассмат- риваются в конце этой главы. Типы данных, переменные, константы Тип данных определяет диапазон допустимых значений и пространство, отво- димое в памяти данных, для переменных, констант и результатов, возвращаемых функциями. Типы данных, используемых в различных компиляторах с языка С, пе- речислены в табл. 16.2. Рассмотрим некоторые определения подробнее, чтобы понять, каким образом получаются перечисленные в табл. 16.2 диапазоны допустимых значений. Бит — это базовая единица информации в вычислительной технике, означаю- щая одно из двух состояний: 0 или 1, высокий уровень сигнала или низкий уровень сигнала. К примеру, при подключении светодиодов к выводам микроконтроллера
Типы данных, переменные, константы 307 для каждого такого вывода программист, опять таки, оперирует понятием бита, по- скольку в данном случае речь идет об двух уровнях напряжения, один из которых включает, а другой — отключает светодиод. В общем случае, говорят, что бит со- держит логический “0” или логическую “1”. Таблица 16.2. Типы данных языка С Тип Компиляторы Размер, в битах Диапазон значений bit CodeVisionAVR 1 0,1 inti CCS-PICC char Bee 8 . -128.. 127 signed char WinAVR, mikroC, C30/32, CodeVisionAVR signed int8 CCS-PICC unsigned char WinAVR, mikroC, C30/32, CodeVisionAVR 8 0..255 int8 CCS-PICC int Bee 16 -32768..32767 short WinAVR, C30/32 short int CodeVisionAVR signed int mikroC, C30/32, CodeVisionAVR signed intl6 CCS-PICC unsigned int Bee 16 0..65535 unsigned short WinAVR, C30/32 intl6 CCS-PICC long WinAVR, mikroC, C30/32 32 i —2147483648..2147483647 long int CodeVisionAVR signed long C30/32 signed long int CodeVisionAVR, mikroC signed int32 CCS-PICC unsigned long WinAVR, C30/32 32 0..4294967295 unsigned long int CodeVisionAVR, mikroC int32 CCS-PICC long long signed long long C30/32 64 —9223372036854775808.. 9223372036854775807 unsigned long long C30/32 64 18446744073709551615 float Bee 32 ±1,175-Ю-38.. ±3,402-Ю38 float32 CCS-PICC double CodeVisionAVR, C30/32 long double mikroC double WinAVR 64 ±2,2-Ю-308.. ±1,8-Ю308 long double C30/32 64 ±2-1022.. ±2-Ю1024 Следующая фундаментальная единицы информации — байт, состоящий из вось- ми битов. С его помощью можно представить 256 различных состояний (0..255), что иллюстрирует табл. 16.3 (полностью таблица представления чисел в различных сис- темах счисления дана в приложении Б).
308 Глава 16. Основы языка С Таблица 16.3. Значения, которые можно получить с помощью одного байта Значе- ние Двоичное представление Восьмеричное представление Шестнадцатеричное представление 0 оьоооооооо 0000 0x00 1 0Ь00000001 0001 0x01 2 оьоооооою 0002 0x02 3 ObOOOOOOll 0003 0x03 4 > ObOOOOOlOO 0004 0x04 ObOOOOOlOl 0005 0x05 .6 ObOOOOOllO 0006 0x06 7 ObOOOOOlll 0007 0x07 8 ObOOOOlOOO 0010 0x08 9 ObOOOOlOOl ООН 0x09 10' ObOOOOlOlO 0012 0х0А 11 ObOOOOlOll 0013 ОхОВ 12 ObOOOOllOO 0014 ' ОхОС 13 ObOOOOllOl 0015 0x0D 14 ObOOOOlllO 0016 0х0Е 15 ObOOOOllll 0017 0x0F 16 ObOOOlOOOO 0020 0x10 254 OblllllllO 0376 OxFE 255 Obllllllll 0377 OxFF Правила преобразований из одной системы счисления в другую Схема преобразования из некоторой системы счисления в десятичную очень проста: каждый разряд умножаем на основание системы, возведенное в соответст- вующую разряду степень (начиная с 0), и затем складываем полученные произведе- ния для всех разрядов. Пример для десятичного числа 100: ObOllOOlOO = 0-27 + 1-26 + 1-25 + 0-24 + 0-23 + 1-22 + 0-21 + 0-2° = 0 + 64 + 32 + 0 + 0 + 4 + 0 + 0 = 100; 0 1 44 = 1-82 + 4-81 + 4-8° = 64 + 32 + 4 = 100; 0x64 = 6-16'+416° = 96+ 4= 100. Для преобразования из десятичного представления в другую систему счисления число следует разделить на основание системы, запомнить остаток, затем частное еще раз разделить на основание системы, опять запомнить остаток и т.д. до тех пор, пока не будет получено неделимое частное. Это частное является старшим разрядом полученного представления, а остальные разряды формируются из остатков, начи- ная от последнего к первому.. Пример преобразования числа 100 в двоичную систему счисления: 100/2 = 50, остаток 0 50/2 = 25, остаток 0 25/2 = 12, остаток 1 12/2 = 6, остаток 0 6/2 = 3, остаток 0 3/2 = 1, остаток 1 1 — на 2 не делится. Результат: 100 = 0Ы100100.
Типы данных, переменные, константы 309 Пример преобразования числа 100 в восьмеричную систему счисления: 100/8 = 12, остаток 4 12/8 = 1, остаток 4 1 — на 8 не делится. Результат: 100 = 0144. Пример преобразования числа 100 в шестнадцатеричную систему счисления: 100/16 - 6, остаток 4 6 — на 16 не делится. Результат: 100 = 0x64. Тип char Байту данных в языке С соответствует тип char. Он получил свое название от английского слова “character”, поскольку чаще всего используется в программах для хранения символов (т.е. их ASCII-кодов). Тем не менее, с его помощью можно об- ращаться и к небольшим целым числам в диапазоне от -128 до +127, а для типа unsigned char — от 0 до 255, поскольку в этом случае знаковый разряд не ис- пользуется (использование слова unsigned имеет такой же смысл и в случае цело- численного типа int). Во многих компиляторах с языка С вместо типа unsigned char используется его эквива- лент вида byte или Byte. Пользовательские типы Язык С позволяет, кроме стандартных, объявлять собственные типы. Для этого используется ключевое слово typedef, например: Z typedef unsigned char byte; //объявляем тип byte typedef unsigned int word; //объявляем тип word Другими словами, для объявления пользовательского типа используется конст- рукция вида typedef стандартный_тип идентификатор_пользовательского_типа; Так, в компиляторе WinAVR определены следующие пользовательские типы: • typedef signed char int8_t — в заголовочном файле stdint. h; • typedef unsigned char uint8_.t—- в заголовочном файле stdint. h; • typedef int intl6__t — в заголовочном файле stdint. h; • typedef unsigned int uintl6_t — в заголовочном файле stdint. h; • typedef signed long int int32_t — в заголовочном файле stdint. h; • typedef unsigned long int uint32_t — в заголовочном файле stdint. h; • typedef signed long long int int64_t — в заголовочном файле stdint.h; • typedef unsigned long long int uint64_t— в файле stdint. h; • typedef struct {int quot; int rem;} div_t;—в заголовочном файле stdlib. h (этот тип используется стандартной функцией div ()); • typedef struct {long quot; long rem;} ldiv_t; —в заголовочном файле stdlib. h (этот тип используется стандартной функцией Idiv ()).
310 Глава 16. Основы языка С Переменные Переменная — это именованная величина определенного типа, которая может изменяться в ходе выполнения программы. Для объявления переменных (т.е. выде- ления для них памяти) в программе на С используется следующая конструкция: тип_переменной идентификатор!, идентификатор2, . ..; Например: int i; //Объявление целочисленной переменной i char cl, с2; //Объявление символьных переменных с! и с2 ПРИМЕЧАНИЕ Ш А. Ukiik.UU. а. A. a X . А..*.*.. а . . »..Аж k k i А . A k k А А А . h А Я А А а А • А А А А М А < • Пользовательский тип, используемый при объявлении переменной, должен быть объявлен выше в тексте программы. Для доступа к переменной в программе используется соответствующий иден- тификатор (обязательно после объявления переменной). Значения, присваиваемые переменной, должны соответствовать ей по типу (или правилам приведения типов, рассматриваемым ниже). Примеры: i = 2; //Ошибка! Переменная i еще не объявлена int i; //Объявление целочисленной переменной i float f; //Объявление вещественной переменной f i = 2; //Переменной i присвоено значение 2 f = 3.3 //Переменной f присвоено значение 3,3 f = i; //Переменной f присвоено значение переменной i //(в данном случае будет выполнено автоматическое //приведение типов, т.е. f = 2.0) По области видимости переменные могут быть глобальными и локальными. К глобальным переменным имеют доступ все функции программы. Такие пере- менные объявляются в программе перед объявлением всех функций. К локальным переменным имеет доступ только та функция, в которой они объявлены. Область видимости переменных Имена переменных обладают определенной областью видимости, которая подразумевает, что компилятор использует переменные в соответствии с тем, где они находятся. Имена переменных, объявленных внутри функции, имеют область видимости, ограниченную конкретной функцией. Например, в нескольких функциях можно объявить переменную int i, которая в каждой функции не будет иметь ни- какой связи с аналогичными переменными в других функциях. Точно так же и пе- ременная, объявленная внутри блока (ограничен фигурными скобками {}), остается локальной по отношению к этому блоку. Глобальные переменные имеют область видимости, которая начинается от мес- та их объявления и продолжается до конца программного файла. Для того чтобы глобальную переменную можно было использовать в других файлах, ее нужно объ- явить с помощью ключевого слова extern: extern int n; Объявленную таким образом переменную, прежде, чем ее использовать, следу- ет обязательно инициализйровать во внешнем файле некоторым значением.
Типы данных, переменные, константы 311 ж Использование переменных, объявленных с помощью ключевого слова extern, часто при- водит к ошибкам в программах, поэтому применяйте их только тогда, когда нет другой аль- тернативы, и будьте при этом очень внимательны. Константы Константа — это именованная величина определенного типа, которая, в отли- чие от переменной, не может изменяться в ходе выполнения программы, а имеет конкретное значение, определенное в момент объявления. Для объявления констант в программе на С используется следующая конструкция: const тип_константы идентификатор = значение; Например: const int i = 10; //Объявление целочисленной константы i Пользовательский тип, используемый при объявлении константы, должен быть объявлен выше в тексте программы. Величина, объявленная как константа, будет размещена компилятором в памяти программ, а не в ограниченной области переменный в ОЗУ. Для доступа к константе используется ее идентификатор. Примеры: с = ’А’; //Ошибка! Константа с еще не объявлена int i; //Объявление целочисленной переменной i const с = ' А/; //Объявление константы с i = 2; //Переменной i присвоено значение 2 с = i; //Ошибка! Попытка присвоить значение константе i = с; //Переменной i присвоено значение константы с. //В данном случае будет выполнено автоматическое //приведение типов, т.е. i = 65 (ASCII-код символа ’А’) Как было отмечено ранее, в микроконтроллерах AVR и Р1С используется раздельная память для данных (SRAM) и программ (Flash), а также память типа EEPROM. Переменные, если не указано иного, по умолчанию размещаются в памяти SRAM, но, встречая слово const (или flash в случае CodeVisionAVR), компилятор относит соответствующие значения к постоян- ной флэш-памяти. Кроме того, некоторые компиляторы позволяют записывать константы в память EEPROM (например, CodeVisionAVR) и рабочие регистры (например, WinAVR и Co- deVisionAVR). В этом случае вместо слова const используют слово eeprom или register соответственно. Перечислимые типы Перечислимый тип — это объявление списка целочисленных констант, кото- рые можно явно не инициализировать (в этом случае компилятор считает, что пер- вая константа в списке принимает значение 0, вторая — 1 и т.д.). Для подобного объявления используется ключевое слово enum: int n; enum (zero, one, two); //zero = 0; one = 1; two = 2
312 Глава 16, Основы языка С n = one; //п = 1 Если требуется изменить начальное значение для списка констант, то можно указать его явно при объявлении, например: enum (three = 3, four, five); //three = 3; four = 4; five = 5 Приведение типов Приведение типов — это принудительное преобразование значения одного ти- па к другому, совместимому с исходным. Это важно при выполнении арифметиче- ских операций, когда полученные значения могут выходить за допустимые пределы. Приведение типов бывает явным и неявным. Неявное приведение типов исполь- зуется в операторах присваивания, когда компилятор сам выполняет необходимые преобразования без. участия программиста. Примеры подобного приведения уже рассматривались выше в подразделах, посвященных переменным и константам. Для явного приведения типа некоторой переменной перед ней следует указать в круглых скобках имя нового типа, например: int X; int Y = 200; char С = 30; X = (int)С * 10 + Y; //Переменная С приведена к типу int Если бы в этом примере не было выполнено явное приведение типов, то компи- лятор предположил бы, что выражение С * 10 — это восьмиразрядное умножение (разрядности типа char) и вместо корректного значения 300 (0х12С) в стек было бы помещено урезанное значение 44 (0x2с). Таким образом, в результате вычисле- ния выражения с * 10 + Y переменной х было бы присвоено значение 640, а не корректное 3200. В результате приведения типа переменная С распознается компи- лятором как 16-разрядная, и описанной выше ошибки не возникает. Оператор sizeof Оператор sizeof применяется для вычисления размера области памяти (в бай- тах), отводимой под некоторую переменную, результат выражения или тип. Напри- мер: int а; float f; а = sizeof(int); //а = 2 а = sizeof(f); //а = 4 f = 3.3; а = sizeof(f + a); //a = 4, поскольку тип результата - float Функции Функция представляет собой “контейнер”, в котором выполняется некоторый фрагмент программного кода. Использование функций упрощает написание и от- ладку программ, поскольку в них удобно размещать повторяющиеся группы опера- торов. Любая программа на языке С содержит главную функцию под названием main (). Эта функция при запуске программы выполняется первой. Стандартные, а также характерные для различных компиляторов библиотечные функции перечислены в следующей главе.
Функции 313 Пользовательские функции определяются после директив препроцессора и гло- бальных объявлений типов, переменных и констант в файле с исходным кодом или в заголовочном файле. При этом используется следующий синтаксис: Тип_возвращаемого_значения Имя_функции(Список_параметров) { //Тело функции Предварительное объявление функции может отсутствовать. В этом случае она доступна только внутри того файла, в котором определена. В качестве типа возвращаемого значения может использоваться ключевое слово void. Это означает, что функция не возвращает никакого значения (в некоторых языка программирования такие функций называют процедурами). Функцию вызывают по ее имени с указанием в круглых скобках перечня пере- даваемых параметров (если их нет; то в скобках ничего не указывается), например: void Functionl(int n, char c) { int Function2() { int main() int x; char y; Functionl(x, y); x = Function2(); Параметры — это идентификаторы, которые могут использоваться внутри функции. Вместо них подставляются соответствующие значения, указанные при вызове функции (если в функцию передается более одного параметра, то они отде- ляются друг от друга запятыми как при объявлении, так и при вызове). Значения, переданные в функцию, фактически не изменяются, а просто копи- руются в параметры, который в этом смысле выполняют роль локальных перемен- ных. При этом следует следить за тем, чтобы тип передаваемых значений соответ- ствовал типу параметров, объявленных в заголовке функции. Возвращаемые значения Если функция предназначена для возврата значения некоторого типа, то для этого в ее теле используют ключевое слово return, после которого (через пробел) указывают возвращаемое значение. При этом все операторы после слова return игнорируются, и происходит возврат в вызывающую функцию. Пример:
314 Глава 16. Основы языка С int power3(int n) { return n*n*n; } void main() { int ,x; x « power3(2); //x = 8 } Слово return может также использоваться без указания возвращаемого выра- жения. В этом случае оно просто означает выход из функции. Прототипы функций В обычном варианте функции используются только после их определения, од- нако бывают случаи, когда функции вызывают друг друга, и организовать их “пра- вильное” определение невозможно. Обойти подобную проблему позволяют прото- типы функций, которые представляют собой объявление до определения. Такое объявление представляет собой только заголовок функции, причем в списке пара- метров указывают только типы, без идентификаторов, например: int fl(int); void f2(intz int); int fl(int x) { } void f2(int a, int b) { } Прототипы функций часто используются в заголовочных файлах, включаемых в текст программы с помощью директивы препроцессора #include. Классы памяти при объявлении локальных переменных Локальные переменные могут быть объявлены внутри функций как принадле- жащие к одному из трех классов памяти: • auto (значение по умолчанию, можно явно не указывать) — при объявлении переменная не инициализируется никаким значением (значение — текущее со- держимое области памяти, отведенной под переменную); при выходе из функ- ции переменная удаляется из памяти; • static — статическая переменная доступна только в пределах функции, хотя память для нее выделяется в пространстве глобальных переменных; при первом обращении к функции инициализируется нулевым значением и после выхода из функции из памяти не удаляется (таким образом, при последующих обращениях к функции в ней содержится старое значение);
Функции 315 • register — аналог автоматической локальной переменной за тем исключени- ем, что компилятор попытается выделить для нее не область памяти данных, а рабочий регистр микроконтроллера, что значительно ускоряет обращение к значению переменной.. Пример использования статической переменной: int plus5() { static int x; return x + 5; } void main() { int y; у = plus5(); //у = 5 у = plus5(); //у = 10 у = plus5(); //у = 15 } Рекурсия Рекурсия — это вызов функцией самой себя. Эта возможность бывает трудна в понимании, и потому не удивительно, что эксперты по языку С так любят рекур- сивные функции. Пример рекурсивного вызова: void fl(int n) { int x; fl(x); } Несмотря на сложность восприятия, рекурсия довольно часто используется в стандартных библиотечных функциях, а также во многих алгоритмах сортировки. Тем не менее, при программировании микроконтроллеров использование рекурсии, как правило, чревато проблемами из-за ограниченного объема оперативной памяти. Дело в том, что при каждом вызове рекурсивной функции часть памяти расходуется на сохранение данных, помещаемых в стек. Эти данные хранятся там до тех пор, пока не будет выполнен возврат из функции. Таким образом, когда рекурсивная функция снова и снова вызывает саму себя, в стеке остается все меньше и меньше свободной памяти. Можно сказать, что в подавляющем большинстве случаев использование рекур- сии при программировании микроконтроллеров — это надежный способ быстрого и непредсказуемого заполнения стека. Это очень часто приводит к возникновению ошибочного состояния, называемого переполнением стека. Область стека обычно размещается в верхней части памяти и растет “вниз”, тогда как область переменных размещается в нижней части памяти и растет “вверх”. Поэтому еслц объем данных, помещаемых в стек, превысит размер области стека, эти данные могут достигнуть области переменных и затереть собой ее значения. При этом ошибку переполнения стека не всегда легко выявить, поскольку она может проявляться лишь периодиче- ски.
316 Глава 16. Основы языка С ПРИМЕЧАНИЕ Подобная проблема может также возникнуть при многократном вложении функций, то есть когда функция fl вызывает функцию f2, которая вызывает функцию f3, которая вызывает функцию f 4 и т.д. ............................................................................................................................................................................................. Структуры Структура — это особый тип данных, состоящий из нескольких разнотипных переменных (полей). В общем случае объявление структуры имеет следующий вид: struct имя_структуры { тип поле_1; тип поле_Ы; }; Как и любой другой тип, структуру можно в дальнейшем использовать для объ- явления переменных, например: struct MyStructure { //Объявление структуры MyStructure int Fieldl; char Field2; float Field3; }; //Объявление переменных YourStruct и OurStruct типа MyStructure struct MyStructure YourStruct, OurStruct; Кроме того, можно создавать переменные непосредственно при объявлении структуры: struct MyStructure { //Объявление структуры MyStructure int Fieldl; char Field2; float Field3; } YourStruct, OurStruct; Допускается инициализация полей непосредственно при объявлении перемен- ных-структур с помощью перечня значений в фигурных скобках, например: struct DATE { int Day; int Month; int Year; } struct DATE MyBirthday = {7, 8, 1974}; Второй вариант этой же инициализации: struct DATE { int Day; int Month; int Year; } MyBirthday = {7, 8, 1974};
Структуры 317 Многие компиляторы (например, CodeVisionAVR и mikroC) позволяют опреде- лять при объявлении структуры так называемые битовые поля шириной от одного до 32 бит. Они служат для экономии памяти микроконтроллера и определяются с помощью символа Например: struct si { unsigned long A: 10; unsigned long B:8; unsigned long C:ll; } В этом случае структура s 1 займет в памяти четыре байты, в которых младшие 10 разрядов будут отведены под поле А, следующие восемь — под поле в, и сле- дующие 11 — под поле С. Старшие три разряда области, занимаемой структурой, в таком случае не используются. Для доступа к полям структуры в программе служит запись вида имя структуры.поле. Так, в представленном выше примере структуры DATE для инициализации полей можно было воспользоваться следующими операторами: MyBirthday.Day = 7; MyBirthday. Month = 8; MyBirthday.Year = 1974; Структуры, в свою очередь, могут быть полями других структур, например: struct ME { char MyName[30]; //Строка длиной 30 символов - имя struct DATE MyBirthday; //Структура, хранящая день рождения } struct ME MyData; MyData.MyName = "John Smith"; MyData.MyBirthday.Day = 7; ata.MyBirthday.Month = 8; M^.^ta.MyBirthday.Year = 1974; Струю >ры могут выступать в качестве параметров функций, а также возвра- щаемого результата. Ниже представлен пример функции, возвращающей структуру типа DATE: struct DATE Januaryl(int CurYear) { struct DATE JanOl; JanOl.Day == 1; JanOl.Month = 1; JanOl.Year = CurYear; return JanOl; } struct DATE BeginOfTheYear; BeginOfTheYear = Januaryl (2006)
318 Глава 16. Основы языка С Указатели и адреса переменных Указатель — это переменная, содержащая адрес некоторого элемента данных (переменной, константы, функции, структуры). В языке С указатели тесно связаны с обработкой массивов и строк, которые будут рассмотрены в следующем разделе. Для объявления переменной как указателя используется оператор *: int *р; //р - указатель на целое число Для присвоения адреса некоторой переменной указателю используется опера- тор &, например: char *р; //указатель на символ char с; //символьная переменная с = • А ’; р = &с; // р содержит адрес переменной с (указывает на ’А’) Для того чтобы извлечь значение переменной, на которую указывает указатель, используется оператор разыменования *. char *р; char с, Ь; с = ’А’; р = &с; Ь = *р; //Теперь Ь = ’А’ Аналогичным образом, этот оператор можно использовать и для присвоения некоторого значения переменной, на которую указывает указатель: char *р; char cf b; b = 'A'; p = &c; = b; //Теперь c = ’A’ Применительно к программировацию микроконтроллеров, указатели можно ис- пользовать, к примеру, для записи данных в порт ввода/вывода. Предположим, ре- гистр данных порта расположен в памяти по адресу 0x16. В этом случае, для записи в него значения OxFF можно воспользоваться следующим фрагментом программно- го кода: unsigned char *thePort; thePort = 0x16; *thePort = OxFF; Передача в функции параметров по ссылке С помощью указателей, используемых в качестве параметров функций, можно организовать возврат более одного значения. Рассмотрим следующий пример: int SumAndDiv(int *а, int *b) { int bufA, bufB; bufA = *a; bufB = *b; *a = bufA / bufB; //Указатель ссылается на результат //целочисленного деления без остатка
Указатели и адреса переменных 319 *b = bufA % bufB; //Указатель ссылается на остаток от //целочисленного деления return bufA + bufB; //Функция возвращает сумму } int vl, v2, sum; vl = 10; v2 = 3; sum = SumAndDiv(&vl, &v2); //sum = 13; vl = 3; v2 = 1 В функции SumAndDiv вначале сохраняются в буферных переменных значения, на которые указывают указатели а и Ь. Затем в переменную, на которую указывает указатель а записывается результат деления переданных в функцию значений без остатка, а в переменную, на которую указывает указатель b — остаток от такого де- ления. Поскольку с помощью указателей мы напрямую обращались к ячейкам памя- ти, а не к переменным, то после выхода из функции содержимое этих ячеек остается неизменным. При вызове функции SumAndDiv в нее передаются адреса переменных vl и v2, которым в теле функции соответствуют указатели а и Ь. Указатели на структуры На структуры можно создавать указатели точно так же, как и для любого друго- го типа данных. Пример применения такого указателя: struct DATE { int Day; "int Month; int Year; } struct DATE MyBirthday, *dateP; dateP = &MyBirthday; //dateP указывает на структуру MyBirthday В таком случае для доступа к полям структуры через указатель используется оператор ->: dateP->Day = 7; dateP->Month =8; dateP->Year = 1974; Можно также использовать и разымецование указателя: (*dateP).Day = 7; (*dateP).Month = 8; (*dateP).Year = 1974; В последнем примере операция *dateP заключена в скобки, поскольку оператор разымено- вания * имеет меньший приоритет по сравнению с оператором доступа к полю структуры . (см. табл. 16.1). Указатели также могут быть полями структуры. Это часто используется для создания в памяти цепочек однотипных структур, когда каждая предыдущая указы- вает на следующую:
320 Глава 16. Основы языка С struct DATE { int Day; int Month; int Year; struct DATE *next__date; //указатель на другую структуру х //того же типа struct DATE datel, date2; datel. next__date = &date2; Теперь, например, оператору datel .next_date->Year соответствует доступ к полю Year структуры date2 (т.е. это эквивалентно записи date2. Year). Массивы и строки Массив — это тип данных, который используется для представления последо- вательности однотипных значений. Массивы объявляются подобно обычным пере- менным, с указанием в квадратных скобках размерности (количества элементов в массиве): int digits[10]; //Массив из десяти элементов типа int char str[10]; //Массив из десяти символов (строка) Доступ к элементам массива реализуется с помощью индекса (порядкового но- мера элемента, начиная с 0): digits[0] = 0; digits[1] = 1; str[0] = ’А’; str[1] = 1 В ’ ; По сути, имя массива — это указатель на его первый элемент. Так в последнем примере, оператор str [0] = ’А’; можно было бы заменить оператором * str - ’А’;, а опера- тор str (1] = ’ Воператором * (str + 1) = ’В';. Зачастую гораздо удобнее инициализировать массив непосредственно при его объявлении, например: int digits[10] == {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; char str[10] = {’T’, ’h’, ’e’, ’ ’1’, *i’, *n’, ’e’}; int n; char c; n = digits[2]; //n = 2 c = str[1]; //с = 'h’ ВНИМАНИЕ! ihikk Hill i > U k i ku inn t Ы M . t 1 . I < t .1 < bi 1 l.kik I . i Ш i « 14 kt/b i < k 4 k 4 kl . 1 « 1 I > i k I > i < > ntik 4klik kiln 4U4k4>U k ikUHlinink При разработке программ следует учитывать, что компилятор не всегда может отследить вы- ход индекса за пределы массива. Другими словами, если бы в представленном выше приме- ре мы использовали оператор с « str [п+10], то на этапе компиляции ошибки не возник- нет, но в ходе выполнения программы переменной с будет присвоено значение “13-го”, несу- ществующего элемента массива, т.е. извлечено содержимое области памяти, адрес которой на 12 элементов смещен относительно начального адреса массива.
Операторы ветвления 321 Строки Строка в языке С — это массив типа char. Выше был рассмотрен пример объ- явления такого массива, соответствующего строке “The line”. Это объявление мож- но было бы выполнить и с помощью строкового литерала: char str[10] = "The line"; Однако в таком случае следует помнить, что компилятор неявно завершает строковые литералы символом ’ \0 •, и, таким образом, реальная длина строки больше на единицу. Это следует учитывать, чтобы при инициализации массива не выйти за его пределы. При инициализации строк размерность массива можно явно не указывать: char str[] = "The line"; В этом случае компилятор определит размерность самостоятельно (это правило применимо и к инициализации любых других массивов). ПРИМЕЧАНИЕ Для того чтобы строковые константы размещались не в памяти SRAM, а в флэш-памяти мик- роконтроллера, их следует объявлять с использованием слова const (или, в некоторых ком- пиляторах, — flash)const char str[]. Многомерные массивы Язык С допускает использование многомерных массивов, т.е. массивов, эле- ментами которых являются массивы. Примеры объявления таких массивов: int а2[10][2]; //Двухмерный массив 10x2 int а3[3][2][5]; //Трехмерный массив 3x2x5 Фактически, все элементы многомерного массива хранятся в памяти последова- тельно, поэтому представленные ниже примеры инициализации аналогичны: int а[2][3-] = { {1, 2, 3}, {4, 5, 6} }; и int а [2] [3] = {1,2, 3Z 4, 5,6}; Для доступа к элементам многомерного массива используются индексы по каж- дой из размерностей или операции разыменования указателя. Например, чтобы из- влечь в некоторую переменную п цифру 4 из представленного выше массива а, можно воспользоваться одним из двух вариантов: п = а[1][0]; //Извлекаем элемент из "строки" 1 (вторая), //"столбца" 0 (первый), то есть - цифру 4 п = *(а + 3); //а - указатель на первый элемент массива, //следовательно а + 3 - указатель на 4-й элемент Операторы ветвления Операторы ветвления используются для выполнения того или иного блока кода в зависимости от некоторого условия.
322 Глава 16. Основы языка С К таким операторам в языке С относятся if-else и switch-case. Оператор if-eise В простейшем случае оператор if-else имеет следующую структуру: if (условное_выражение) блок_кода_1; else блок_кода_2; Если условное выражение истинно, то выполняется блок кода 1, в противном случае — блок кода 2. При этом в качестве блока кода 2 допускается использовать последовательность операторов else-if: if (выражение!) блок_кода_1; else if (выражение2) блок_кода_2; else if (выражениеЗ) блок_кода_3; ... else блок_кода_Ы; В данном случае каждое выражение будет вычисляться поочередно до тех пор, пока не будет найдено выражение, давшее истинный результат. Если же результаты вычислений всех выражений окажутся ложными, то будет выполнен блок кода N. В тех случаях, когда при ложных результатах всех условных выражений не тре- буется выполнять никаких операторов, можно опустить завершающий блок кода вместе с последней ветвью else. Например: if(а == 1) b = а*3; else if(а == 2) Ь = а + 10; else if(а == 3) b = 0; Если выражение в первой строке будет истинным, остальные операторы будут пропущены, в противном случае начнется последовательная проверка выражений, указанных в следующих строках, до тех пор, пока не будет найдено выражение, дающее ненулевой результат, или до тех пор, пока не будет проверено последнее выражение. Если ни одно из выражений не будет истинным, никакие действия с переменной Ь выполнены не будут. Условные выражения Язык С позволяет вместо оператора if-else использовать условные выраже- ния. Так, конструкцию вида v if (условие) блок_кода_1; else блок_кода_2; можно заменить следующим условным выражением: условие ? блок_кода_1 : блок_кода 2; Например: (а == 1) ? b = а*3 : b = 0; //Если а=1, то Ь=а*3, иначе Ь=0 Оператор switch-case В операторе if-else можно использовать только выражения, которые сводятся к значению TRUE или FALSE. В тех случаях, когда необходимо применять выраже- ния, дающие произвольный числовой результат, удобнее воспользоваться операто- ром switch-case. Этот оператор позволяет с помощью некоторой переменной вы- бирать одно из выражений, соответствующее заданной константе. Его синтаксис:
Циклические конструкции 323 switch (выражение) { case константа-выражение! : блок_кода case константа-выражение2 : блок_кода case константа-выражениеЗ : блок_кода ' default: блок_кода } Продемонстрируем использование оператора switch-case на примере рас- смотренного выше фрагмента, реализованного с помощью оператора if-else: switch (а) { case 1 : b = а * 3; break; case 2 : b = a + 10; break; case 3 : b = 0; break; default: } Оператор break приводит к немедленному выходу из блока switch. Если по каким-то причинам необходимо продолжить проверку соответствия выражения вы- бора тем константам, которые указаны в ветвях case, следует убрать операторы break. Ко всему прочему, ветви case можно каскадировать. Такой прием особенно удобен в тех случаях, когда необходимо, например, проверить введенный символ, не заботясь о том, представляет ли он прописную букву или строчную, или когда требуется получить одну и ту же реакцию на несколько разных чисел. Рассмотрим это на примере фрагмента некоторой абстрактной программы: switch (input) { case ’а’ : case ’А’ : DoA(); break; , case ’b’ : case ’B’ : DoB(); break; case ’0’ : case ’1’ : case ’2’ : case ’3’ : Do0123(); break; case ’4’ : case ’5’ : case ’6’. : case ’7’ : D04567 (); break; default : DoDefaultO; break; Циклические конструкции Циклические конструкции применяют для повторения некоторого блока кода на основании условия цикла. В языке С используются циклические конструкции while, for и do-while. Конструкция while Цикл while имеет следующий синтаксис. while (условное_выражение) { // Выполнение тела цикла, если выражение истинно } ' Другими словами, циклы while имеет смысл использовать в тех случаях, когда соответствующий оператор или блок операторов необходимо выполнять до тех пор, пока условное выражение истинно. Пример формирования строки, состоящей из не- четных цифр:
324 Глава 16. Основы языка С int с, i; const char str [ ] = "0123456789"; char OddNums[5]; //Строка для хранения нечетных цифр с = 0; //Счетчик циклов i = 0; //Индекс массива OddNums while (с < 10) //До тех пор, пока с меньше 10,... { //Если остаток от деления с на 2 = 1, то записываем в i-ю //позицию массива OddNums с-й элемент строки str, после чего //значение i автоматически инкрементируется if ((с % 2) == 1) OddNums[i++] = str[с]; с++; //с = с +1 } Конструкция for Цикл for имеет следующий синтаксис. for (выражение!; выражение2; выражениеЗ) // Выполнение тела цикла } Выражение! выполняется только один раз при входе в цикл, и обычно пред- ставляет собой оператор присваивания некоторого начального значения счетчику цикла. Выражение2 — это условное выражение, определяющее момент выхода из цикла (цикл выполняется до тех пор, пока оно равно TRUE или 1). ВыражениеЗ — еще один оператор присваивания, в котором обычно изменяется счетчик цикла или некоторая переменная, влияющая на выполнение условия в Выражении2. Выраже- ния могут быть представлены любыми операторами, включая пустые (т.е. вместо выражения можно поставить только символ точки с запятой Циклы while и for в большинстве случаев взаимозаменяемы. Так, представ- ленный выше пример для цикла while, можно переписать в следующем виде: int с, i; const char str[] = "0123456789"; char OddNums[5]; //Строка для хранения нечетных цифр i = 0; //Индекс массива OddNums for (с =0; с < 10; с++) //До тех пор, пока с меньше 10,... if ((с % 2) == 1) OddNums[i++] = str[с]; В одних ситуациях удобнее применять циклы for, в других — while. Достоин- ством циклов for является более наглядная инициализация и организация измене- ния счетчика цикла. С другой стороны, циклы while более гибкие и обеспечивают больше возможностей для реализации нестандартных программных решений при организации повторяющихся вычислений. Конструкция do-while Кроме циклов while и for, в которых вначале выполняется проверка истинно- сти условия цикла, и только потом управление передается блоку операторов цикла, в языке С имеется также конструкция do-while. Она отличается от первых двух тем, что в ней вначале выполняется блок операторов, и только потом проверяется
Стандартные функции ввода/вывода 325 выполнение условия. Другими словами, цикл do-while всегда выполняется как минимум один раз, вне зависимости от условия цикла. Цикл do-while имеет следующий синтаксис. do { // Выполнение блока операторов цикла } while (условное_выражение); Организация бесконечных циклов Для организации бесконечного цикла в качестве условного выражения в конст- рукции while или do-while можно просто указать значение TRUE или 1: while(1) блок_операторов; В случае циклов for это будет выглядеть следующим образом: for (;;) блок_операторрв; Операторы break U continue Если в теле любого цикла встречается оператор break,то управление тут же передается на оператор, следующий за оператором цикла, вне зависимости от ис- тинности или неистинности условного выражения. При этом во вложенных циклах выход осуществляется не на самый верхний уровень вложенности, а лишь на один уровень вверх. При выполнении оператора continue все находящиеся после него, операторы блока пропускаются, а управление передается в начало цикла для следующей ите- рации. На практике операторы continue используются гораздо реже, чем операто- ры break, однако в сложных циклах, требующих принятия решений на основании многих факторов, использование операторов continue может быть весьма удоб- ным. Стандартные функции ввода/вывода Стандартные функции ввода/вывода позволяют обмениваться информацией с выполняемой программой, что, к примеру, очень удобно в процессе отладки. Все они построены на основе функций посимвольного ввода/вывода, которые легко приспособить к аппаратным требованиям системы. Если при обычном применении языка С эти функции используются для ввода данных с клавиатуры и вывода на эк- ран или принтер, то применительно к микроконтроллерам AVR и PIC речь идет об обмене данными через приемопередатчик UART/USART (по умолчанию) или по- следовательный порт. Таким образом, прежде, чем начать ввод/вывод в программе должны быть выполнены соответствующие настройки (например, в компиляторе CCS-PICC для этой цели используется директива препроцессора #use, о чем речь пойдет чуть позже). Стандартные функции ввода-вывода компиляторов WinAVR, CodeVisionAVR, CCS-PICC, mikroC и C30/32 перечислены в следующей главе.
326 Глава 16. Основы языка С Ввод/вывод символов С ПОМОЩЬЮ функций getchar () U putchar() Простейшими функциями ввода/вывода в языке С являются getchar () и put- char (), которые предназначены для посимвольного обмена данными (обе объявле- ны в стандартном заголовочном файле stdio.h). Функция getchar () возвращает символ, принятый от UART/USART или по последовательному интерфейсу, а функ- ция put char (), наоборот, выводит символ. Все остальные стандартные функции ввода/вывода базируются на них. ПРИМЕЧАНИЕ Функции getchar () и put char () в компиляторах для микроконтроллеров реализуют ожи- дание готовности именно приемопередатчика UART/USART для передачи/приема символа. В том случае, если требуется организовать обмен данными по другому интерфейсу (напри- мер, по SPI), необходимо разработать собственные функции аналогичного содержания. Рассмотрим пример простой программы, выводящей в бесконечном цикле через приемопередатчик UART/USART символы “1”, “2”, “3”, “4” и “5”. Исходный код программы put char, с для компилятора WinAVR и микроконтроллера AT90S8515 представлен в листинге 16.1. Листинг 16.1. Программа putchar. с для компилятора WinAVR | ♦include <avr/io.h> ♦include <stdio.h> int main (void) { const char str[] = ”12345”; int i; UBRR = 25; //Скорость обмена через UART - 9600 бод UCR = 0x18; //Устанавливаем разряды TXEN и RXEN для //активизации UART в режиме ввода/вывода через //выводы 0 и 1 порта D. //Разряд CHR9=0 - передача 8 бит данных i = 0; //Индекс строки символов while (1) //Бесконечный цикл { if (i > 4) i = 0; //Проверка выхода за пределы массива putchar(str[i]); //Выводим i-й символ через UART } } • Файлы put char. с и makefile есть также на прилагаемом к книге компакт-диске в папке Proj ects\WinAVR\Putchar. Для микроконтроллеров PIC этот же пример будет выглядеть несколько иначе (листинг 16.2). Так, в компиляторе CCS-PICC для настройки частоты системной синхронизации и параметров обмена данными через UART используются директива препроцессора ♦use (рассматривается в конце этой главы). еФайл put char. с для компилятора CCS-PICC есть также на прилагаемом к книге компакт- диске в папке Pro j ects\CCS-PICC\Putchar.
Стандартные функции ввода/вывода 327 Листинг 16.2. Прогрг 1мма putchar. с для компилятора CCS-PICC #include <18F458.h> #fuses HS, NOWDT #use delay(clock=10000000) #use rs232 (baud=9600,parity=N,xmit=PIN_C6, rcv=PIN_C7, stream=RS232,bits=8) void main() { const char str[] = "12345"; int i; i = 0; while (1) { if (i > 4) i = 0; putchar(str[i]); } j Функции вывода строк puts о и printfo Функции puts () и print f () используют функцию put char () для вывода по- символьно строки в порт RS232, назначенным последним. Предположим, у нас есть определение строки, предназначенной для вывода через последовательный интер- фейс: char s[6] = "12345"; Вызов функции puts () для вывода этой строки выглядит просто как puts (s);. Функция printf () несколько сложнее, поскольку позволяет применить форма- тированный вывод. Она имеет следующий синтаксис вызова: printf("Строка, в которую подставляются переменные ", переменная!, переменная2, .... ); В выводимой строке обычно используются спецификации форматирования зна- чений переменных, переданных в качестве параметров. Каждая такая спецификация начинается со знака “%”, после которого следуют обозначения параметров форма- тирования: • с — вывод параметра в виде символа ASCII; • d — вывод параметра в виде целого числа; • е — вывод параметра в экспоненциальном формате; • f — вывод параметра в виде вещественного числа; • Id — вывод параметра в виде длинного целого со знаком; • 1и — вывод параметра в виде беззнакового длинного целого; • Lx —вывод параметра в виде беззнакового длинного целого в шестнадцатерич- ном представлении, используя нижний регистр символов; • LX —вывод параметра в виде беззнакового длинного целого в шестнадцатерич- ном представлении, используя верхний регистр символов; • s — вывод параметра в виде строки;
328 Глава 16. Основы языка С • и — вывод параметра в виде оеззнакового целого; • х —вывод параметра в виде беззнакового целого в шестнадцатеричном пред- ставлении, используя нижний регистр символов; • X —вывод параметра в виде беззнакового целого в шестнадцатеричном пред- ставлении, используя верхний регистр символов; • % — вывод знака процента. Количество спецификаций должно совпадать с количеством переменных. При этом первая встретившаяся спецификация соответствует первой переменной в спи- ске, вторая — второй и т.д. В случае вывода числовых значений сразу же после знака “%” может быть ука- зано количество символов и формат для отображения чисел, например: • 8 — восемь знаков; • 08 — восемь знаков с дополнением ведущими нулями; • 8.2 — восемь знаков, два знака после десятичной точки. Примеры использования спецификаций форматирования: int п = 123; char с = ’$ ’; float f = 23.5; char str[] = "Hello"; printf("n = %d, str = %s", n, str); //n = 123, str = Hello printf("n = %d : 0x%04X", n, n); //n = 123:0x007B printf("Salary = %c%8.2f", c, f); //Salary = $23.50 Функции ввода строк gets о U scanfo Функции gets () и scanf () выполняют действия, обратный функциям puts () и printf (): считывают посимвольно строку через назначенный последним после- довательный интерфейс. Рассмотрим пример использования функций gets () и puts О для компилятора CCS-PICC (листинг 16.3). Листинг 16 3 Программа gets. с для компилятора CCS-PICC _________ ♦include <18F458.h> ♦fuses HS, NOWDT ♦use delay(clock=10000000) ♦use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) char si[12]; //Буфер, в который будет помещена принятая строка void main() { while (1) { gets(si); puts(si); //Считываем строку из стандартного входного потока //Выводим строку в стандартный выходной поток
Директивы препроцессора 329 еФайл gets. с можно также найти на прилагаемом к книге компакт-диске в папке Pro j ects \ CCS-PICC\Gets. Функция scant () считывает из входного потока значения в формате, опреде- ленном в первом параметре, и сохраняет их в переменных, адреса которых переда- ны ей В качестве последующих параметров. Спецификации форматирования для этой функции такие же, как и для printf (). Обычно функция scanf () использует- ся в паре с printf (): int х, у; puts("Enter two integers: ”); scanf(”%d,%x\n”, &x, &y); //Считывает два числа, введенные //через запятую: одно - в десятичной, //а другое - в шестнадцатеричной форме printf (”х = %d, у = %|04Х”, х, у); ПРИМЕЧАНИЕ В среде CCS-PICC также реализована функция get__string (), которой в качестве первого параметра передается указатель на символьный массив (буфер для считывания строки), а в качестве второго — количество считываемых символов;.^ина строки). Директивы препроцессора Как уже было отмечено ранее, директивы препроцессора, по сути, не являются составной частью языка С, а используются для подстановки кода в текст програм- мы. Препроцессор — это особая программа, которая выполняет предварительную обработку данных до начала компиляции. Рассмотрим стандартные директивы пре- процессора, а также директивы, характерные для различных компиляторов. Директива ^include Выше, в разделе “Структуры программы на С” уже упоминалась самая распро- страненная директива # include, которая используется фактически во всех про- граммах для включения в текст программы заголовочных файлов (с определения- ми), имеющий расширение . h, или файлов . с (не содержащих функцию main ()). Эта директива может использоваться в двух формах: #include <имя_файла> или #include "имя_файла" Если имя файла заключено между знаками “<” и “>”, то он считается частью стандартной библиотеки, поставляемой вместе с компилятором. Если же имя файла заключено в двойные кавычки, то считается, что он расположен в той же папке, что и файл с исходным кодом. Директива ^define Директива # de fine указывает препроцессору на необходимость выполнить подстановку в тексте программы определенной последовательности символов дру- гой последовательностью. Формат директивы:
330 Глава 16. Основы языка С ♦define заменяемая_последовательность фрагмент_подстановки Например: ♦define MyName "John Smith" ♦define Condition (a > b) ♦define Operation a = b char str[] = MyName; //Равнозначно char str[] = "John Smith"; int a, b; if Condition Operatrion; //Равнозначно if (a > b) a = b; В директиве ♦define могут использоваться параметры, благодаря чему она ста- новится очень мощным и гибким инструментом, позволяющим заменять один про- стой текстовый элемент сложным выражением. Такие подстановки называют мак- росами. Например, выражение, в котором выбирается большее из двух значений, можно представить в виде следующего макроса. ♦define larger(x, у) ( (х)>(у) ? (х) : (у) ) Если определен такой макрос, то код, использующий его, может иметь следую- щий вид. int а = 9; int b = 7; int с = 0; с = larger(а, Ь); Напоминает вызов функции, однако это не функция — компилятор получит от препроцессора последнюю строку в следующем виде. с = ( (а)>(Ь) ? (а) : (Ь) ); Основное отличие макроса от функции заключается в том, что код макропод- становки вставляется препроцессором в программный код везде, где встречается за- данный текстовый элемент, код же функции определяется только в одном месте, а в тех местах, где указано ее имя, осуществляется вызов этого кода. Есть и еще одно отличие, особенно важное при программировании микрокон- троллеров. При использовании макросов, в отличие от функций, ничего не помеща- ется в стек, что позволяет сэкономить оперативную память. Кроме того, макросы преобразуются в обычный код, который выполняется бы- стрее, чем код функции, на вызов которого и возврат управления в вызывающую функцию уходит дополнительное машинное время. Наконец, при использовании макросов не требуется формального объявления типов данных. Перечислим некоторые правила использования директивы ♦define: • при создании комментариев в строке с ♦define всегда используется коммента- рий вида/* ... */; • следует помнить, что конец строки — это конец ♦define, и весь текст слева заменит текст справа; • для преобразования параметра макроса в текстовую строку можно указать пе- ред ним символ например: ♦define OutString(s) puts(^s) OutString(Line); //Равнозначно puts("Line");
Директивы препроцессора 331 • для конкатенации двух параметров можно воспользоваться оператором ##, на- пример: #define Concat(x, у) х ## у int i = Concat(2,l); //Равнозначно int i = 21; • для переноса текста подстановки на другую строку используется символ обрат- ной косой “\”, например: #define LongStr "О 123456789 10 \ 11 12 13 14 15 16 17 18 19 20 " • для отмены определения используется директива #undef, например: #define A_Char ’А* #undef A_Char #define A_Char ’a*. Директивы условной компиляции Многие микроконтроллеры отличаются лишь некоторыми параметрами, коли- чеством выводов, размером памяти и размещением регистров. Это позволяет созда- вать на языке С программный код для всего модельного ряда. Однако для этого сле- дует каким-то образом заменить те параметры, которые отличаются у разных моде- лей. Для таких целей используются директивы условной компиляции #ifdef, #if- ndef, #else и #endif, а также — #if и #elif. Синтаксис для директивы #ifdef: #ifdef имя_макроса последовательность_операторов_1 #else последовательность_операторов_2 #endif Если имя макроса определено в программе, то компилируется первая последо- вательность операторов, в противном случае — вторая последовательность (ветка #else может и отсутствовать). Пример использования для компилятора CCS-PICC: #define DEBUGGING_ON #ifdef DEBUGGING_ON #use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7) #endif Синтаксис для директивы #ifndef: #ifndef имя_макроса последовательность_операторов_1 #else последовательность_операторов_2 #endif В данном случае, в отличие от директивы #ifdef, первая последовательность операторов выполняется в том случае, если имя макроса в программе не определе- но.
332 Глава 16. Основы языка С Для условной компиляции можно также воспользоваться директивами #if и ♦elif. Их синтаксис: ♦ if выражение! последовательность_операторов_1 # elif выражение2 последовательность_операторов_2 #else последователь ность_операторов_3 #endif Эта конструкция работает аналогично условному оператору if-else. Компи- лятор оценивает выражения после #if и #elif до тех пор, пока одно из них не даст в результате TRUE, после чего в текст программы подставляется соответствующая последовательность операторов. Если оба выражения дают FALSE, то подставляется последовательность операторов после директивы #else (если она присутствует). Допустим, для передачи и приема данных через UART у абстрактного микро- контроллера SomeMicl6 используются выводы 12 и 13, у микроконтроллера SomeMic8 — выводы 6 и 14, а у SomeMic4 — выводы 1 и 2. Тогда мы можем соз- дать заголовочный файл SomeMic. h и включить в него следующие директивы. # if SomeMicX == 16 ♦define TXD 12 ♦define RXD 13 # elif SomeMicX == 8 ♦define TXD 6 ♦define RXD 14 ♦ elif SomeMicX == 4 ♦define TXD 1 ♦define RXD 2 ♦ else ♦error "Pins TXD и RXD for SomeMicX are not defined" ♦endif ) Теперь, если программный проект будет построен на микроконтроллере SomeMic8, то в заголовочный файл следует поместить следующий текст. ♦ifndef SomeMicX ♦define SomeMicX = 8 ♦include <SomeMic.h> ♦endif Встретив директиву ♦ifndef, препроцессор включит в текст программы ♦de- fine SomeMicX =, 8 и ♦include <SomeMic.h>. Поскольку после этого элемент SomeMicX получит значение, равное 8, то любая повторная обработка директивы ♦ ifndef не приведет к дублированию в выходном тексте соответствующей инфор- мации. Другими словами, содержимое заголовочного файла SomeMic.h будет по- мещено в исходный код файлов, использующих заголовочный файл с ♦ifndef, только один раз. Использование директивы ♦ifndef с последующими директивами ♦define и ♦include — стандартный прием, позволяющий избежать дублирования инфор- мации из заголовочных файлов в исходном коде проекта. Если этого не сделать, то при дублировании компилятор обычно выдает множество сообщений об ошибках, связанных с многократным объявлением переменных.
Директивы препроцессора 333 Директива terror Директива #еггог используется совместно с директивами условной компиля- ции. Встретив ее, компилятор сгенерирует сообщение об ошибке, указанное справа от директивы (см. пример в предыдущем подразделе). Директива tpragma компилятора CodeVisionAVR В компиляторе CodeVisionAVR используется особая директива #pragma, акти- визирующая специальные функции компилятора. Некоторые из наиболее распро- страненных вариантов ее использования представлены в табл. 16.4. Таблица 16.4. Директива #pragma компилятора CodeVisionAVR Вариант использования Описание Примеры ♦pragma opt Активизация/отключение оптими- затора кода. Должна быть указана в начале программного файла ♦pragma opt- ♦pragma opt+ ♦pragma regalloc Активизация/отключение автома- тического распределения гло- бальных переменных в регистрах. Если такое распределение отклю- чено, то глобальные переменные, как правило, размещаются в об- ласти SRAM ♦pragma regalloc- ♦pragma regalloc+ ♦pragma ruslcd Активизация/отключение автома- тической перекодировки символов кириллицы при их выводе в ЖК- ' модуль ♦pragma ruslcd- ♦pragma ruslcd+ ♦pragma savereg Активизация/отключение автома- тического сохранения и восста- новления регистров RO, R1, R15, R22..R27, R30, R31 и SREG при обработке прерываний ♦pragma savereg- ♦pragma savereg+ ♦pragma u-char Активизация/отключение обработ- ки символа char как беззнакового восьмиразрядного значения ♦pragma uchar- ♦pragma uchar+ - ——— ПРИМЕЧАНИЕ В компиляторе CodeVisionAVR также используются директивы #asm и #endasm, позволяю- щие вставлять в программы на С ассемблерный код. Они будут рассмотрены позже в этой же главе, в подразделе “Исполнение ассемблерного кода’’ Директивы, характерные для компилятора CCS-PICC Компилятор CCS-PICC поддерживает множество встроенных, нестандартных директив. Рассмотрим некоторые из них. ПРИМЕЧАНИЕ Ниже, в разделах “Обработка прерываний" и "Исполнение ассемблерного кода”, будут также рассмотрены директивы #asm и fendasm.
334 Глава 16. Основы языка С Директива #ыъ Директива'Препроцессора #bit используется для получения доступа к отдель- ным разрядам регистров или переменных. Ее синтаксис: # bit идентификатор = х.у где х — константа, определяющая регистр, или переменная; у — константа от О до 7. Например, следующим образом переменная ТО IF объявляется как разряд 2 ре- гистра по адресу OxОВ: # bit T0IF = ОхОВ.2 Пример для разряда переменной: inc с; # bit CBitO = с.0; if (CBitO ==0) ... Директива #byte Директива #byte имеет следующий синтаксис: # byte идентификатор = X где х — имя переменной или константы. Если идентификатор — это уже объявленное ранее имя переменной, то компи- лятор помещает эту переменную по адресу х, в противном случае компилятор соз- дает новую переменную и помещает ее по адресу х как восьмиразрядное целое чис- ло. В обоих случаях в ячейку памяти с адресом х могут быть помещены любыё дру- гие переменные. Фактически, если х — имя переменной, то ей будет соответство- вать тот же адрес в памяти, что и для объявленного идентификатора: char с; //Переменная с размещается в памяти компилятором #byte а = с; //Переменной b назначен тот же адрес, что и с Директива #case Директива препроцессора #case указывает компилятору быть чувствительным к регистру символов. По умолчанию, компилятор CCS-PICC не чувствителен к ре- гистру символов. Директива #device Директива #device определяет, какой микроконтроллер является целевым для программы. Ее синтаксис: idevice имя_микроконтроллера опции Опции являются необязательными и влияют на управление памятью, аналого- цифровым преобразованием и возможностью отладки. Так, опции управления памя- тью позволяют пользователю задать количество разрядов, используемых для хране- ния указателя памяти. Возможные значения: *=5 (для всех семейств микроконтрол- леров PIC), *=8 (для 14-ти- и 16-тиразрядных микроконтроллеров), *=16 (для 14- тиразрядных микроконтроллеров). Например, следующая директива определяет для микроконтроллера PIC16F877 16-тиразрядный указатель памяти: #device PIC16F877 *=16
Директивы препроцессора 335 Для управления АЦП предназначена опция ADC=x, где х — количество разрядов, считываемых из преобразователя с помощью внутренней функции read adc (). Если необходимо, чтобы сгенерированный код был совместим с отладочным программным обеспечением ICD от компании Microchip, в директиву #device сле- дует включить опцию ICD=TRUE. ПРИМЕЧАНИЕ Если опции не указаны, то компилятор использует соответствующие значения, выбранные по умолчанию. Директива «fuse Директива «fuse определяет, какие предохранители должны быть установлены при программировании микроконтроллера. Ее синтаксис: «fuse опции Набор опций для различных устройств отличается. Для того чтобы просмотреть список предохранителей для конкретного микроконтроллера, в среде разработки CCS-PKpC следует выполнить команду меню View ► Valid Fuses. К примеру, для микроконтроллера PIC18F458 используется следующий перечень предохранителей: • BORV20 — сброс при падении питающего напряжения до 2 В; • BORV27 — сброс при падении питающего напряжения до 2,7 В; • BORV42 — сброс при падении питающего напряжения до 4,2 В; • BORV45 — сброс при падении питающего напряжения до 4,5 В; • BROWNOUT — сброс при обнаружении провала питания; • СРВ — защита кода в блоке начальной загрузки; • CPD — включена защита данных в памяти EEPROM; • DEBUG — активен режим отладки с помощью ICD; • ЕС — внешний источник синхроимпульсов с CLKOUT; • ЕС_10 — внешний источник синхроимпульсов; • HS — высокоскоростной осциллятор с частотой > 4 МГц; • LP — осциллятор малой мощности с частотой < 200 кГц; • LVP — низковольтное программирование по выводу ВЗ (PIC 16) или В5 (PIC18); • NOBROWNOUT — сброс при провале питания не используется; • NOCPB — защита кода в блоке начальной загрузки отключена; • NOCPD — защита данных в памяти EEPROM отключена; • NODEBUG — отсутствие режима отладки для ICD; • NOLVP — низковольтное программирование не используется; вывод ВЗ (PIC16) или В5 (PIC18) задействован для ввода/вывода; • NOOSCSEN — переключение осциллятора запрещено; • NOPROTECT — код не защищен от чтения; • NOPUT — таймер включения питания не используется; • NOSTVREN — переполнение или выход за нижнюю границу стека не приводит к сбросу;
336 Глава 16. Основы языка С • NOWDT — сторожевой таймер не используется; • NOWRT — защита от записи в память программ отключена;1 • NOWRTB — защита от записи в блок начальной загрузки отключена; • NOWRTC — защита от записи в регистры конфигурации отключена; • NOWRTD — защита от записи данных в память EEPROM отключена; • OSCSEN — активно переключение осциллятора; • PROTECT — защита кода от чтения; • PUT — используется таймер включения питания; • RC — RC-осциллятор с CLKOUT; • RC_10 — RC-осциллятор; • STVREN — переполнение или выход за нижнюю границу стека приводит к сбросу; • WDT — используется сторожевой таймер; • WDT 1 — сторожевой таймер, использует постделитель 1:1; • WDT2 — сторожевой таймер использует постделитель 1:2; • WDT4 — сторожевой таймер использует постделитель 1:4; • WDT8 — сторожевой таймер использует постделитель 1:8; • WDT16 — сторожевой таймер использует постделитель 1:16; • WDT32 — сторожевой таймер использует постделитель 1:32; • WDT64 — сторожевой таймер использует постделитель 1:64; • WDT128 — сторожевой таймер использует постделитель 1:128; • WRT — защита от записи в память программ; • WRTB — защита от записи в блок начальной загрузки; • WRTC — защита от записи в регистры конфигурации; • WRTD — защита от записи данных.в память EEPROM; • XT — осциллятор на кристалле с частотой <= 4 МГц. Так, следующий пример директивы #fuses устанавливает высокоскоростной осциллятор, активизирует сброс при обнаружении провала питания и отключает сторожевой таймер: #fuses HS, BROWNOUT, NOWDT Директива #iocate Директива препроцессора #locate по своему назначению и синтаксису анало- гична директиве #byte за тем исключением, что назначает переменной ячейку па- мяти, в которую не может быть помещена никакая другая переменная. Например: ♦locate с = 0x50; //Размещение переменной с по адресу 0x50 Директива #org Директива #org позволяет компилятору определить, где должна быть размеще- на в памяти следующая ниже функция. Она имеет синтаксис четырех видов: #org начало, конец #org сегмент
Директивы препроцессора 337 #org начало, конец {} #org начало, конец auto=0 где начало всегда определяет первую, а конец — последнюю ячейку в используе- мой области памяти; сегмент — начало области из предыдущей директивы #org. Если ранее был определен некоторый сегмент, и необходимо только добавить к не- му еще одну функцию, идентификатор окончания может быть опущен. Пример использования директивы #org: #org OxlEOO, OxlFFF fl 0 ( //Эта функция будет размещена, начиная с адреса OxlEOO } #org OxlEOO //Сегмент - тот же, который был определен выше f 2 () { //Эта функция будет размещена в сегменте OxlEOO-OxlFFF } #org 0x800, 0x820 {} //Пустой сегмент Директива #opt Директива #opt задает уровень оптимизации, применяемой при компиляции. Она имеет синтаксис «opt уровень где уровень — число от 0 до 9 (9 — полная оптимизация). Директива «priority Директива препроцессора «priority может быть использована для установки порядка, в котором опрашиваются флаги прерываний. Некоторые микроконтролле- ры PIC имеют только один вектор прерываний. Когда возникает прерывание, управ- ление передается по адресу, указанном в векторе. По умолчанию, компилятор CCS- PICC помещает по этому адресу диспетчерскую подпрограмму, которая опрашивает флаги прерываний, чтобы определить, какое из них имело место, и вызвать соответ- ствующую подпрограмму обслуживания прерывания. Обработка прерываний рассматривается в следующем разделе этой же главы. Синтаксис директивы: «priority список_прерываний Пример использования: «priority rtcc, rb Прерывания с большим приоритетом расположены в списке первыми.
338 Глава 16. Основы языка С Директива «reserve Директива «reserve определяет области ОЗУ, не доступные для использова- ния компилятором. Ее синтаксис имеет две формы: «reserve адрес, адрес, адрес ... «reserve начальный_адрес_диапазона:конечный_адрес_диапазона ПРИМЕЧАНИЕ Директиве «reserve должна предшествовать директива «device, иначе она не будет иметь никакого эффекта. Примеры резервирования области 0х20..0х22: «reserve 0x10, 0x11, 0x12 «reserve 0x10:0x12 Директива «гот Директива препроцессора «гот позволяет вставлять данные в файл .hex. Ее синтаксис: «гот адрес = {список} где адрес — адрес в памяти, а список — список слов через запятую. Пример: «гот 0х2100={1, 2, 3, 4, 6, 7, 8} Директива «type Директива препроцессора «type позволяет переопределять типы, поддержи- ваемые компилятором. Ее синтаксис: «type стандартный_тип=размер, стандартный_тип=размер, ... К примеру, по умолчанию, компилятор CCS-PICC отводит под переменную ти- па char восемь бит, а пот переменную типа int — 16 бит (см. табл. 16.2). Для того чтобы изменить эту ситуацию, в текст программы можно добавить следующую ди- рективу: «type char=16, int=32 Директива «use delay Директива «use delay предназначена для задания рабочей частоты процессора и разрешает использование в программе внутренних функций delay_ms () (задерж- ка в миллисекундах) и delay_us() (задержка в микросекундах). Ее синтаксис име- ет две формы: «use delay(частота) «use delay(частота, restart_WDT) Частота указывается в герцах. С помощью опции restart_DWT можно указать компилятору перезагружать сторожевой таймер во время программных задержек. Директивы «use xxx_io Директивы вида «use xxx_io влияют на код, сгенерированный при реализа- ции доступа к портам ввода/вывода, и имеют отношение к установке регистров TRIS. В случае стандартного доступа на ввод/вывод (выбор по умолчанию), компи-
Директивы препроцессора 339 лятор генерирует код, переводящий некоторый вывод микроконтроллера в состоя- ние входа или выхода при каждом обращении к нему. Такой способ доступа активи- зируется директивой препроцессора #use standard_io: #use standard_io(X) где x — символ порта (A...G). Если пользователь должен устанавливать разряды регистров TRIS вручную пе- ред обращением к соответствующим выводам напрямую или с помощью встроен- ной функции set_tris_x (), то в программе должна быть указана директива пре- процессора #use fast_io: #use fast_io(X) где x — символ порта (A...G). Подобная по смыслу директива #use fixed_io принимает в качестве пара- метров идентификаторы выводов, устанавливаемых в качестве входов/выходов: #use fixed_io (X_outputs=BUBOfl, вывод, вывод...) где X — символ порта (a...g), вывод — константа, соответствующая выводу (пере- чень таких констант можно найти в заголовочном файле устройства). Примеры для вывода 0 порта В: #use standard_io(В) #use fast_io(B) #use fixed_io(b_outputs=PIN_BO) Директива «use i2c Директива #use i2c определяет порт I2C микроконтроллера. Ее синтаксис: #use i2c(опции) В качестве опций (указываются через запятую) могут использоваться следую- щие значения: • ADDRESS=nn — задание адреса ведомого устройства; • FAST — использование спецификации быстрой шины 12С; • FORCE_HW — использование аппаратных функций 12С; • master — установка режима ведущего устройства; • RESTART_WDT перезагрузка сторожевого таймера во время ожидания в про- цессе выполнения встроенной функции i2c\read (); • ЗСЬ=вывод — задание вывода SCL (вывод — адрес разряда); • 30А=вывод — задание вывода SDA; • slave — установка режима ведомого устройства; • SLOW — использование спецификации медленной шины 12С. В следующем примере в качестве линии данных устанавливается вывод 0 порта В, а в качестве тактирующей линии — вывод 1 того же порта (режим ведущего уст- ройства): fuse i2c(MASTER, sda=PIN_PIN_BO, scl=PIN_Bl)
340 Глава 16. Основы языка С Пример для режима ведомого устройства: #use i2c(SLAVE, sda=PIN_C4, scl=PIN_C3, ADDRESS=0xA0, FORCE_HW) Директива #use i2c считается активной до тех пор, пока в тексте программы не встретится другая директива #use i2c« Эта директива позволяет воспользоваться встроенными функциями, реализую- щими обмен данными по шине 12С (если включена опция FORCE HW, то программ- ные функции не генерируются и используется аппаратный порт MSSP). Директива #use rs232 Директива препроцессора #use rs232 используется для инициализации после- довательного порта, работающего по стандарту RS232. В зависимости от того, как заданы выводы передачи и приема, реализация порта может быть аппаратной или программной. Если выводы соответствуют приемопередатчику USART, то исполь- зуется аппаратный порт, в противном случае — программный UART. Общая форма директивы # u s е г s 2 32: #use rs232 (опция, опция, опция, ...) Возможны следующие опции: • baud=x — установка скорости передачи; • BlTS=x — установка разрядности в х, где х — 5-9 в случае программного UART и 8-9 в случае аппаратного UART; • ЕГ4АВЬЕ=вывод — во время передачи компилятор переводит указанный вывод в состояние высокого уровня; • errors — ошибки приема сохраняются в переменной RS232 ERRORS; • FLOAT—HIGH — использование на выходе схем с открытым коллектором; • INVERT — инвертирует полярность выводов последовательного порта (исполь- зуется только с программным приемопередатчиком UART); • parity=x — контроль по четности: x=N — отсутствует; х=Е — контроль по четности; х=о — контроль по нечетности; • RCV=BbiBOfl — установка вывода для приема данных; • RESTART—WDT — сброс сторожевого таймера при ожидании символа в функции getchar(); • STREAM=mm4_потока — ассоциирует идентификатор потока с портом RS232 (этот идентификатор может использоваться в функциях, наподобие fputc ()). • хм1Т=вывод — установка вывода для передачи данных. При выборе скорости передачи следует учитывать частоту системной синхронизации микро- контроллера. По этой причине перед директивой #use rs232 обязательно должна быть указана директива #use delay. Если указанная скорость не может быть достигнута (с от- клонением 3%), то генерируется сообщение об ошибке.
Обработка прерываний 341 Директива #zero_ram Директива препроцессора ♦zero_ram указывает компилятору обнулять перед началом выполнения программы всё внутренние регистры, которые могут быть ис- пользованы для хранения переменных. Обработка прерываний Обработка прерываний в среде WinA VR В различных компиляторах обработка прерываний реализована по-разному. Так, в среде WinAVR используется предустановленная таблица векторов прерыва- ний, содержащая адреса соответствующих подпрограмм обслуживания с заранее определенными именами. Для каждой такой подпрограммы в библиотечном файле \avr\include\avr\interrupt.h определены три макроса: INTERRUPT (), ISR() и signal (). Эти макросы регистрируют и помечают некоторую функцию как обра- ботчик прерывания. Их различие в том, что макросы INTERRUPT () и ISR () опреде- ляет функцию обработчика для случая, когда разрешено общее прерывание (т.е. об- работчик может быть прерван), a SIGNAL () — для случая, когда общее прерывание запрещено (т.е. обработчик не может быть прерван). Например, так выглядит определение обработчика для прерывания от АЦП: ♦include <avr/interrupt.h> INTERRUPT(SIG—ADC) { // Здесь вносится пользовательский код } или ♦include <avr/interrupt.h> SIGNAL(SIG_ADC) { // Здесь вносится пользовательский код } Если возникает неожиданное прерывание (т.е. такое, для которого не определен обработчик), то по умолчанию происходит сброс микроконтроллера в результате перехода по соответствующему вектору. Во избежание этого, следует перекрыть библиотечную функцию__vector default, что можно сделать с помощью макро- са SIGNALO: ♦include <avr/signal.h> SIGNAL(__vector_default) { // Здесь вносится пользовательский код - } ' В качестве идентификаторов прерываний, передаваемых в качестве параметров макросам INTERRUPT, ISR и SIGNAL, могут служить следующие:
342 Глава 16. Основы языка С • SIG_2WIRE_serial — двухпроводной последовательный интерфейс (PC); • SIG_ADC — аналого-цифровое преобразование завершено; • SIG_COMPARATOR — прерывание от аналогового компаратора; • sig_eeprom_ready — память EEPROM готова; • SIG_INPUT_CAPTURE1 - sig_input_capture3 — прерывание по захвату на входе; • SIG_INTERRUPTO - SlG_lNTERRtJPT7 — внешнее прерывание; • SIG_OUTPUT_COMPAREO - SIG_OUTPUT_COMPARE2 — прерывание по сравнению на выходе; • sig_output_compare1a - sig_output_compare3A — прерывание по совпа- дению с регистром сравнения А; • SIGOUTPUTCOMPARE1 В - SIG_OUTPUT_COMPARE3B — прерывание по совпадению с регистром сравнения В; • sig_output_compare1c - sig_output_COMPARE3c — прерывание по совпа- дению с регистром сравнения С; • SIG_overflowo - SIG_OVERFLOW3 — прерывание по переполнению счетчика; • SIG_pin — прерывание по сигналу на выводе параллельного порта; • SIG_PIN_CHANGEO, SIG_PIN_CHANGE1 — прерывание пр изменению уровня на выводе параллельного порта; • SIG_SPI — прерывание от SPI; • SIG_UARTO — прерывание от UART(0); • SIG_UARTO_DATA — прерывание по опустошению регистра данных UART(0); • SIG_UARTO_RECV — прерывание по завершению приема UART(0); • sig_uartO_trans — прерывание по завершению передачи UART(0); • SIG_UART 1 — прерывание от UART( 1); • SIG_UART1_DATA — прерывание по опустошению регистра данных UART(1); • SIG_UART 1_RECV — прерывание по завершению приема UART( 1); • SIG_UART1_TRANS — прерывание по завершению передачи UART(1); • SIG_uart_data — прерывание по опустошению регистра данных UART; • SIG_UART_RECV — прерывание по завершению приема UART; • SIG_UART_TRANS — прерывание по завершению передачи UART; • SiG_USART0_DATA — прерывание по опустошению регистра данных USART(0); • SIG_USARTO_RECV — прерывание по завершению приема USART(O); • SIG_USARTO_TRANS — прерывание по завершению передачи USART(0); • SIG_USART1_DATA — прерывание по опустошению регистра данных USART(1); • SIG_USART1_RECV — прерывание по завершению приема USART(1); • SIG_USART1_TRANS — прерывание по завершению передачи USART(1); • sig_usb_hw — прерывание от порта USB.
Обработка прерываний 343 Кроме того, в библиотечном файле interrupt.h объявлены макро-функции sei() и cli (). Первая устанавливает флаг общего разрешения прерываний в реги- стре управления SREG, а вторая, наоборот, — сбрасывает его. Подробнее эти мак- роопределения рассмотрены в следующей главе. Обработка прерываний в среде CodeVisionAVR В программах, предназначенных для компилятора CodeVisionAVR, обработку прерываний реализуют в отдельных функциях. При этом перед объявлением каждой такой функции указывают ключевое слово interrupt, а после него в квадратных скобках — номер соответствующего вектора прерывания (в виде числа или стан- дартного макроопределения). Пример объявления функции обработки прерывания по переполнению таймера О микроконтроллера ATmegal6: interrupt [10] void overflow_tinter0 (void) { } или interrupt [TIMO_OVF] void overflow_timerO(void) { . ) Макроопределения, обозначающие типы прерываний для микроконтроллера ATmegal6 (взято'из файла \cvavreval\inc\megal6.h): ♦define EXT_INT0 2 ♦define EXT_INT1 3 // Внешнее прерывание 0 // Внешнее прерывание 1 ♦define TIM2_COMP 4 // Сравнение, таймер 2 ♦define TIM2_OVF 5 // Переполнение, таймер 2 ♦define TIM1_CAPT 6 • // Захват на входе, таймер 1 ♦define TIM1_COMPA 7 // Сравнение с регистром А, таймер 1 ♦define TIM1_COMPB 8 // Сравнение с регистром В, таймер 1 ♦define TIM1_OVF 9 // Переполнение, таймер 1 ♦define TIMO_OVF 10 // Переполнение, таймер 0 ♦define SPI_STC 11 // Интерфейс SPI ♦define USART_RXC 12 // Завершение приема через USART ♦define USART_DRE 13 // Готовность данных USART ♦define USART_TXC 14 // Завершение передачи через USART ♦define ADC_INT 15 // Завершение преобразования АЦП ♦define EE_RDY 16 // Память EEPROM готова ♦define ANA_COMP 17 // Аналоговый компаратор ♦define TWI 18 ( // Интерфейс TWI ♦define EXT_INT2 19 // Внешнее прерывание 2 ♦define TIMO_COMP 20 // Сравнение, таймер 0 ♦define SPM READY 21 // Готовность SPM Обработка прерываний в среде CCS-PICC В среде компилятора CCS-PICC для определения подпрограмм обработки пре- рываний используются директивы препроцессора #int_default, #int_global
344 Глава 16. Основы языка С и #int_xxx (указываются непосредственно перед функцией). Во многих микрокон- троллерах PIC используется единственный вектор прерывания, и, следовательно, в случае возникнове'ния прерывания вызывается только одна подпрограмма, назы- ваемая диспетчером прерываний. Диспетчер отвечает за опрос флагов прерываний и вызова соответствующих подпрограмм обслуживания. Если обнаружено прерыва- ние, и ни один из флагов прерывания не установлен, то диспетчер вызывает функ- цию, обозначенную с помощью директивы #int_default. Директива #int_global позволяет определить функцию, заменяющую диспет- чер компилятора (такие функции используются крайне редко, и с ними следует со- блюдать большую осторожность). Директива lint xxx определяет функцию, отве- чающую за обслуживание того или иного прерывания. Перечислим наиболее распространенные директивы этого типа: • #int ad — аналого-цифровое преобразование завершено; • #int_adof — задержка аналого-цифрового преобразования; • #int_buscol — конфликт шины; • # int_but t on — нажатие кнопки; • #int_ccpl — захват или совпадение в модуле ССР1; • # int_ccp2 — захват или совпадение в модуле ССР2; • #int_comp — прерывание от аналогового компаратора; • #int_eeprom — запись в EEPROM завершена; • #int_ext — внешнее прерывание; • #int_ext 1 — внешнее прерывание 1; • # int_ext2 — внешнее прерывание 2; • # i nt_i 2 с — прерывание от шины 12С; • # i nt_l cd — ЖК-дисплей активен; • #int_lowvolt — обнаружено низкое напряжение; • #int_psp — запись данных в порт PSP; • #int_rb — изменение состояния выводов 4-7 порта В; • #int_rc — изменение состояния выводов 4-7 порта С; • #int_rda — доступен прием данных по интерфейсу RS232; • #int_rtcc — переполнение таймера TMR0; • #int_ssp — активность интерфейса SPI или 12С; • #int_tbe — буфер передачи по интерфейсу RS232 пуст; • #int_timerO — переполнение таймера TMR0; • #int_timerl — переполнение таймера TMR1; • #int_timer2 — переполнение таймера TMR2; • # i nt_t ime г 3 — переполнение таймера TMR3. В ряде микроконтроллеров PIC (например, в PIC18F458) используется два век- тора прерываний. Эта позволяет установить высокий приоритет некоторому преры- ванию на аппаратном уровне. Компилятор CCS-PICC использует эту аппаратную возможность с помощью опции FAST директивы #int_xxx: #int_xxx FAST
Обработка прерываний 345 НИМАНИЕ! Этот уровень приоритета можно назначить только одному прерыванию, поэтому флаг FAST может быть использован в программе только один раз. В случае использования флага fast соответствующее прерывание не сохраняет всех регистров так, как это делает обычное прерывание. Сохраняются только основ- ные регистры процессора. Таким образом, к примеру, можно быстро выполнять ка- кие-то очень простые операции. Обработка прерываний в среде mikroC В программах, предназначенных для компилятора mikroC, вся обработка пре- рываний (в том числе — с высоким приоритетом) происходит внутри функции interrupt: void interrupt () { ) В том случае, если в программе может возникать несколько различных видов прерывания, это необходимо проверять внутри функции interrupt путем опроса соответствующих флагов, например: void interrupt() { if (INTCON.TMROIF) { counter++; TMRO = 96; INTCON.TMROF = 0; } else if (INTCON.RBIF) { counter++; TMRO = 96; INTCON.RBIF = 0; } } Если целевой микроконтроллер поддерживает распределение приоритетности, то для обработки низкоприоритетных прерываний служит еще одна дополнительная функция: void interrupt low(void), — которая используется аналогично функции interrupt. Обработка прерываний в среде СЗО Для связывания некоторой функции с тем или иным вектором прерывания в про- граммах, предназначенных для компилятора СЗО (микроконтроллеры PIC24), служит следующий синтаксис: void ___ISR __ОбозначениеТипаПрерывания (void) { } Для обозначения типа прерывания служат макроопределения, заданные в соот- ветствующем файле сценария компоновки .gid. Например, подпрограмма обслу-
346 Глава 16. Основы языка С живания прерывания от таймера 1 обозначена как _TlInterrupt. В качестве при- мера рассмотрим перечень таких макроопределений для микроконтроллера PIC24 FJ128GA010: • OscillatorFail — сбой осциллятора; • AddressError — ошибка адреса; • StackError — ошибка стека; • MathError — математическая ошибка; • INTOInterrupt — внешнее прерывание 0; • INTlInterrupt — внешнее прерывание 1; • INT2Interrupt — внешнее прерывание 2; • INT3Interrupt — внешнее прерывание 3; • INT4 interrupt — внешнее прерывание 4; • Тllnterrupt — прерывание по переполнению Таймера 1; • T2interrupt — прерывание по переполнению таймера 2; • T3lnterrupt — прерывание по переполнению таймера 3; • Т4 interrupt — прерывание по переполнению таймера 4; • T5Interrupt — прерывание по переполнению таймера 5; • IClInterrupt — прерывание от модуля захвата на входе 1; • IC21 nt er rupt — прерывание от модуля захвата на входе 2; • IC3Interrupt — прерывание от модуля захвата на входе 3; • IC4 Interrupt — прерывание .от модуля захвата на входе 4; • IC5Interrupt — прерывание от модуля захвата на входе 5; • OCIInterrupt — прерывание от модуля сравнения на выходе 1; • ОС2 interrupt — прерывание от модуля сравнения на выходе 2; • OC3Interrupt — прерывание от модуля сравнения на выходе 3; • ОС 41 nt е г rupt — прерывание от модуля сравнения на выходе 4; • ОС5Interrupt — прерывание от модуля сравнения на выходе 5; • SPIlErrInterrupt — сбой в интерфейсе SPI1; • SPI lTInterrupt — прерывание по завершению передачи по SPI 1; • SPl2Errlnterrupt — сбой в интерфейсе SPI2; • SPI2Interrupt — прерывание по завершению передачи по SPI2; • UIRXInterrupt — завершение приема по UART1; • UlTXinterrupt — завершение передачи по UART1; • UlErrlnterrupt — ошибка передачи по UART1; • ,U2RXInterrupt — завершение приема по UART2; • U2TXInterrupt — завершение передачи по UART2; • U2ErrInterrupt — ошибка передачи по UART2; • ADC1 Interrupt — прерывание от АЦП; • Sl2Cllnterrupt — прерывание от ведомого устройства на шине I2C 1; • MI2ClInterrupt — прерывание от ведущего устройства на шине I2C 1;
Обработка прерываний 347 • Sl2C2interrupt — прерывание от ведомого устройства на шине 12С 2; • MI2C2Interrupt — прерывание от ведущего устройства на шине 12С 2; • Comp interrupt — прерывание от аналогового компаратора; • PMPlnterrupt — прерывание от порта РМР; • RTCClnterrupt — прерывание от часов реального времени. Фактическую реализацию прерывания можно проиллюстрировать на примере следующего простого шаблона. // Подпрограмма обслуживания прерывания от модуля Timer1 void _JSR _TlInterrupt(void) { // He забудьте обнулить перед выходом флаг прерывания _T1IF = 0; } main() { // Инициализация _Т11Р =4; // Установка приоритетности таймера 1, // (4 - значение по умолчанию) TMR1 =0; // Обнуление таймера PR1 = period-1; // Инициализация регистра периода // Конфигурирование источника тактирования модуля Timer1 // и настройка синхронизации T1CON = 0x8000; // Проверка настроек регистра T1CON // Инициализация разрядов управления прерываниями от Time^l _T1IF =0; // Обнуление флага прерывания перед _Т11Е =1; // разрешением источника прерывания Т1 // Инициализация уровня приоритетности процессора _1Р = 0; // С — значение по умолчанию // Главный цикл while(1) { } } Обработка прерываний в среде С32 Для каждого микроконтроллера PIC32 в пределах одного уровня приоритетно- сти определен фиксированный порядок обработки запросов на прерывание от раз- личных источников. Если приоритеты группы и подгруппы прерываний идентичны, то два одновременно появившихся события обрабатываются в соответствии с за-
348 Глава 16. Основы языка С данным порядком. Так, порядок обработки запросов на прерывание с одинаковым уровнем приоритетности для микроконтроллера PIC32FJ512MX360L представлен в табл. 16.5. Типы прерываний, расположенные в верхней части таблицы, обрабаты- ваются первыми. Таблица 16.5. Порядок обработки прерываний с одинаковым уровнем приоритетности для микроконтроллера PIC32FJ512MX360L Порядок Макрос Описание 0 СТ Прерывание от таймера процессорного ядра 1 CS0 Программное прерывание от процессорного ядра 0 2 CS1 Программное прерывание от процессорного ядра 1 3 INTO Внешнее прерывание 0 4 Т1 Прерывание от таймера 1 5 IC1 Прерывание от модуля захвата на входе 1 6 ОС1 Прерывание от модуля сравнения на выходе 1 7 INT1 Внешнее прерывание 1 8 Т2 Прерывание от таймера 2 9 IC2 Прерывание от модуля захвата на входе 2 10 ОС2 Прерывание от модуля сравнения на выходе 2 11 INT2 Внешнее прерывание 2 12 ТЗ Прерывание от таймера 3 13 IC3 Прерывание от модуля захвата на входе 3 14 осз Прерывание от модуля сравнения на выходе 3 15 INT3 Внешнее прерывание 3 16 Т4 Прерывание от таймера 4 17 IC4 Прерывание от модуля захвата на входе 4 18 ОС 4 Прерывание от модуля сравнения на выходе 4 19 INT4 Внешнее прерывание 4 20 Т5 ' Прерывание от таймера 5 21 IC5 Прерывание от модуля захвата на входе 5 22 ОС 5 Прерывание от модуля сравнения на выходе 5 23 SPI1E Сбой в интерфейсе SPI1 24 SPI1TX Завершение передачи по интерфейсу SPI1 25 SPI1RX Завершение приема по интерфейсу SPI1 26 U1E Сбой передачи через UART 1 27 U1RX Прерывание от приемника UART1 28 U1TX Прерывание от передатчика UART 1 29 I2C1B Конфликт шины 12С1 30 I2C1S Прерывание от ведомого устройству на шине 12С1 31 I2C1M Прерывание от ведущего устройства на шине 12С1 32 CN Прерывание по изменению состояния входа 33 AD1 Завершение преобразования АЦП 34 РМР Прерывание от порта РМР 35 СМР1 Прерывание от аналогового компаратора 1 36 СМР2 Прерывание от аналогового компаратора 2 37 SPI2E Сбой в интерфейсе SPI2 38 SPI2TX Завершение передачи по интерфейсу SPI2 39 SPI2RX Завершение приема по интерфейсу SPI2
Обработка прерываний 349 Таблица 16.5. Окончание Порядок Макрос Описание 40 U2E Сбой передачи через UART2 41 U2RX Прерывание от приемника UART2 42 U2TX Прерывание от передатчика UART2 43 I2C2B Конфликт шины 12С2 44 I2C2S Прерывание от ведомого устройства на шине 12С2 45 I2C2M Прерывание от ведущего устройства на шине 12С2 46 FSCM Прерывание от монитора тактирования 47 RTCC Прерывание от часов реального времени 48 DMA0 Прерывание от канала DMA 0 49 DMA1 Прерывание от канала DMA 1 50 DMA2 Прерывание от канала DMA 2 51 DMA3 Прерывание от канала DMA 3 Компилятор С32 предоставляет два варианта определения обработчика преры- ваний по умолчанию (вектора 0) с заданным уровнем приоритетности (обозначим его, например, как ipll). Первый из них — с помощью макроса , ISR: void __ISR(0, ipll) InterruptHandler(void) { } Второй вариант — с помощью директивы препроцессора #pragma: #pragma interrupt InterruptHandler ipll vector 0 void InterruptHandler(void) { } Оба варианта равнозначны, и выбор одного из них — вопрос исключительно личных предпочтений программиста. Для использования средств обработки прерываний PIC32 к программе необхо- димо подключить стандартную библиотеку int.h. Это реализуется явно с помо- щью директивы tfinclude <int. h> или косвенно путем подключения библиотеки поддержки периферийных устройств #include <plib. h>. В обоих случаях мы получаем доступ к полезным функциям и макросам, вклю- чая следующие. • INTEnableSystemSingleVectoredlnt () — функция, следующая после по- следовательности команд, инициализирующих модуль управления прерыва- ниями. Она активизирует базовый режим обработки прерываний микрокон- троллеров PIC32. • mXXXSetintPriority (n) — назначает заданный уровень приоритетности п (от 0 до 7) источнику прерывания, определяемому именем макроса ххх (см. второй столбец табл. 16.5). • mXXXClearInt Flag () — сбрасывает флаг прерывания, определенного именем макроса ххх (см. второй столбец табл. 16.5). В качестве простого примера рассмотрим программу, которая активизирует мо- дуль таймера 2, задает период на 15 отсчетов и выдает запрос на прерывание по пе-
350 Глава 16. Основы языка С реполнению счетного регистра. Подпрограмма обслуживания прерывания каждый раз будет инкрементировать глобальную переменную count (листинг 16.4). ©Этой программе соответствует файл int_s . с, который находится на прилагаемом к книге компакт-диске в папке Projects\C32\Interrupts. Листинг 16.4. Пример обработки прерывания в случае компилятора С32 ♦include <p32mx360f5121.h> ♦include <plib.h> int count; ♦pragma interrupt InterruptHandler ipll vector 0 void InterruptHandler(void) { count++; mT2ClearIntFlag(); } main() { // Инициализируем таймеры PR2 = 15; T2CON = 0x8030; // Инициализируем прерывания mT2SetIntPriority(1); INTEnableSystemSingleVectoredlnt(); mT2IntEnable(1); // Главный цикл while(1); Если в программе используется несколько источников прерывания, назначение им различных уровней приоритетности решает только часть проблемы. В некото- рых случаях требуется учитывать возможность вложения запросов. Так, в момент обслуживания прерывания с низким приоритетом может потребоваться незамедли- тельная обработка прерывания с высоким приоритетом, что прервет работу текуще- го обработчика. Для разрешения вложения запросов необходимо повторно разрешать прерыва- ния в самом начале обработчика прерывания с помощью ассемблерной команды ei. Рассмотрим это на примере, где дополнительные запросы с более высоким уровнем приоритетности (3) периодически формирует таймер 3. На этот раз, вместо дирек- тивы ♦pragma, для определения обработчика прерываний воспользуемся макросом __ISR (листинг 16.5). ©Этой программе соответствует файл int_m. с, который находится на прилагаемом к книге компакт-диске в папке Projects\C32\Interrupts. Листинг 16.5. Пример обработки двух прерываний в случае компилятора С32 ♦include <p32mx360f5121.h> ♦include <plib.h>
Обработка прерываний 351 Листинг 16,5, Окончание int count; void __ISR(0, ipll) InterruptHandler(void) { // Повторно разрешаем прерывания asm(”ei"); // Обрабатываем прерывания в порядке приоритетности if ( mT3GetIntFlag() ) { count++; mT3ClearIntFlag(); } else if ( mT2GetIntFlag() ) { while(1); // Ожидание прерывания от ТЗ mT2ClearIntFlag(); } main() { // Инициализируем таймеры PR3 = 20; PR2 = 15; T3CON = 0x8030; T2CON = 0x8030; // Инициализируем прерывания mT2SetIntPriority(1); mT3SetIntPriority(3) ; INTEnableSystemSingleVectoredlnt(); mT2IntEnable(1); mT3IntEnable (1); // Главный цикл while (1); J Для обработки нескольких запросов на прерывания микроконтроллеры PIC32 также предоставляют альтернативный механизм распределения групп прерываний между различными векторами. Это избавляет от необходимости последовательно проверять все возможные источники для определения, какой из них требует обслу- живания. Так, перечень векторов для микроконтроллера PIC32MX360F512L пред- ставлен в табл. 16.6. Таблица 16.6. Векторы прерываний микроконтроллера PIC32MX360F512L Номер вектора Обозначение Г руппа 0 CORE TIMER VECTOR 1 CORE SOFTWARE 0 VECTOR 2 CORE SOFTWARE 1 VECTOR 3 EXTERNAL 0 VECTOR 4 TIMER 1 VECTOR
352 Глава 16. Основы языка С Таблица 16.6. Окончание Номер вектора Обозначение Г руппа 5 INPUT CAPTURE 1 VECTOR 6 OUTPUT COMPARE 1 VECTOR 7 EXTERNAL 1 VECTOR 8 TIMER 2' VECTOR 9 INPUT CAPTURE 2 VECTOR 10 OUTPUT COMPARE 2 VECTOR 11 EXTERNAL 2 VECTOR 12 TIMER 3 VECTOR 13 INPUT CAPTURE 3 VECTOR 14 OUTPUT COMPARE 3 VECTOR 15 EXTERNAL 3 VECTOR 16 TIMER 4 VECTOR 17 INPUT CAPTURE 4 VECTOR 18 OUTPUT COMPARE 4 VECTOR 19 EXTERNAL 4 VECTOR 20 TIMER 5 VECTOR 21 INPUT CAPTURE 5 VECTOR 22 OUTPUT COMPARE 5 VECTOR 23 SPIl VECTOR Три прерывания от SPI1 24 UART1 VECTOR Три прерывания от UART1 25 I2C1 VECTOR Три прерывания от 12С1 26 CHANGE NOTICE VECTOR 27 ADC VECTOR 28 PMP VECTOR 29 COMPARATOR 1 VECTOR 30 COMPARATOR 2 VECTOR 31 SPI2 VECTOR Три прерывания от SPI2 32 UART2 VECTOR Три прерывания от UART2 33 I2C2 VECTOR Три прерывания от 12С2 34 FAIL SAFE MONITOR VECTOR 35 RTCC VECTOR 36 DMAO VECTOR * 37 DMA1 VECTOR 38 DMA2 VECTOR 39 DMA3 VECTOR Преобразуем пример программы, показанный в листинге 16.5, таким образом, чтобы использовали два вектора прерываний (листинг 16.6). Обратите внимание, что прерыванию от таймера 3 теперь назначен наивысший уровень приоритетности (7). Это необходимо для активизации автоматического, безопасного использования альтернативного набора рабочих регистров (так называемых “теневых регистров”). Кроме того, теперь вместо функции INTEnableSystemSingleVectoredlnt () используется функция INTEnableSystemMultiVectoredlnt (). Этой программе соответствует файл int_m. с, который находится на прилагаемом к книге компакт-диске в папке Projects\C32\Interrupts.
Исполнение ассемблерного кода 353 Листинг 16.6, Использование двух векторов прерываний #include <p32mx360f5121.h> #include <plib.h> int count; void __ISR(_TIMER_3_VECTOR, ipl7) T3InterruptHandler(void) { count++; mT3Clear!ntFlag(); void __ISR(_TIMER_2_VECTOR, ipll) T2InterruptHandler(void) { asm(”ei"); while (1); mT2Clear!ntFlag (); main() { // Инициализируем таймеры PR3 = 20; PR2 = 15; T3CON = 0x8030; T2CON = 0x8030; // Инициализируем прерывания mT2Set!ntPriority(1); mT3SetIntPriority(3); INTEnableSystemMultiVectoredlnt(); mT2IntEnable(1); mT3IntEnable(1); // Главный цикл while (1); } Исполнение ассемблерного кода Иногда в программах, разрабатываемых на языке .С, требуется напрямую ис- пользовать команды ассемблера с целью оптимизации кода или просто из-за невоз- можности выполнить те или иные операции средствами С. Все современные компи- ляторы поддерживают вставку в исходный текст программы фрагментов на ассемб- лере. Рассмотрим эту возможность подробнее. ПРИМЕЧАНИЕ Система команд микроконтроллеров AVR и PIC представлена в приложениях В и Г. Использование ассемблера в компиляторе WinA VR В программах, разрабатываемых с помощью средств WinAVR, для выполнения ассемблерного кода доступен специальный оператор asm. Его синтаксис:
354 Глава 16. Основы языка С asm(код: список_выходных_операндов, список_входных_операндов) Поясним использование оператора asm на простом примере чтения значения из порта D: asm("in %0, %1" : "=r" (value) : "I" (_SFR_IO_ADDR(PORTD)) ); Смысл каждой части оператора asm, отделенной с помощью двоеточия: • ассемблерная команда, определенная как строковая константа: "in %0, %1"; • список выходных операндов, разделенных запятыми — в нашем примере есть только один операнд: "=r" (value); • список входных операндов, разделенных запятыми. В цашем примере есть только один операнд: "I" (_s FR_lo_addr(PORTD)). Вторая и третья части оператора asm предназначены для определения связи ме- жду регистрами микроконтроллера и операндами С. В самих ассемблерных инст- рукциях ссылки на операнды создаются с помощью символа “%” и порядкового но- мера операнда (начиная с нуля). Так, в рассмотренном выше примере ссылке % 0 со- ответствует входной операнд "=r " (value), а ссылке % 1 — выходной операнд " I" (_SFR_IO_ADDR(PORTD)). Синтаксис операндов мы рассмотрим чуть позже, а пока исследуем часть ас- семблерного листинга, который мог быть получен в результате компиляции пред- ставленного выше оператора asm: in r24, 12 В данном случае для хранения значения, считанного из порта D, компилятор выбрал регистр г24, хотя это мог бы быть и любой другой регистр. Компилятор мог бы даже выполнить неявную загрузку или сохранение значения или решить вообще не включать пользовательский ассемблерный код. Все эти решения — часть оптимизационной стратегии компилятора. Например, если бы значение переменной ни разу не использовалось в оставшейся части про- граммы, то представленный выше код, скорее всего, был бы исключен. Во избежа- ние подобного, к оператору asm следует добавить атрибут volatile: asm volatile("in %0, %1" : "=r" (value) : "I" (_SFr_iO_ADDR(PORTD))); Если ассемблерные инструкции не используют операндов, то соответствующие части оператора asm могут быть опущены. Например, в случае общего запрета пре- рываний это будет выглядеть следующим образом: asm volatile("cli"::); Ассемблерный код В первой части оператора asm можно использовать любые команды AVR- ассемблера. При этом для улучшения удобочитаемости каждую инструкцию можно помещать в отдельную строку с помощью символьных литералов перевода строки: asm volatile("nop\n" "nop\n" "nop\n" "nop\n"
Исполнение ассемблерного кода 355 Кроме того, можно использовать некоторые специальные символы, соответст- вующие тем или иным регистрам микроконтроллера: • SREG_— регистр состояния; • s Р_н — старший байт указателя стека; • s P L — младший байт указателя стека; • tmp reg_— регистр гО, используемый для промежуточного хранения; • zero reg_— регистр rl, всегда нулевой. Входные и выходные операнды Каждый входной и выходной операнд описывается строкой уточнений, после которой следует выражение языка С в круглых скобках. Компилятор WinAVR под- держивает уточнения, перечисленные в табл. 16.7. Таблица 16.7. Уточнения в определении входных операндов оператора asm Уточнение Использование Диапазон значений a Обычные старшие регистры г16..г23 b Регистры двойной длины для указателя базы У» z d Старшие регистры г16..г31 e Регистры двойной длины — указатели х, у, z G Вещественная константа 0,0 I Шестиразрядная положительная целая константа 0..63 J Шестиразрядная отрицательная целая константа -63..0 К Целая константа 2 L Целая константа 0 1 Младшие регистры Г0..Г15 M Восьмиразрядная целая константа 0..255 N Целая константа -1 0 Целая константа 8, 16, 24 P Целая константа 1 q Указатель стека SPH:SPL r Любой регистр г0..г31 t Временный регистр гО w Специальные старшие регистровые пары г24, г26, г28, гЗО X Регистр-указатель двойной длины X х (г27:г26) У Регистр-указатель двойной длины Y у (г29:г28) z Регистр-указатель двойной длины Z z (г31:г30) Символам уточнений могут предшествовать модификаторы (если модификатор не указан, операнд считается “только для чтения”): • = — операнд “только для записи” (для всех выходных операндов); • & — регистр должен использоваться только для вывода. Входные операнды — только для чтения. Но что делать, если необходимо, что- бы один и тот же операнд был и входным, и выходным одновременно? Для этого во входном операнде можно использовать в качестве уточнения цифру, соответствую- щую порядковому номеру выходного операнда. Например: asm volatile("swap %0" : "=r" (value) : "0" (value)); •
356 Глава 16. Основы языка С Этот оператор поменяет местами полубайты восьмиразрядной переменной value. Ограничитель "О" указывает компилятору использовать тот же входной ре- гистр, что и первый операнд. В тех случаях, когда код реализует различные регистры, используемые для входных и выходных операндов, к выходному операнду следует добавить модифи- катор &. Например: asm volatile("in %0,%1" "\n\t" "out %1, %2" "\h\t" : "=&r" (input) : "I" (_SFR_IO_ADDR(port)) , "r" (output) ) ; В этом примере входное значение считывается из порта, а затем в тот же самый порт записывается выходное значение. Если бы компилятор выбрал для ввода и вы- вода один и тот же регистр, то после выполнения первой ассемблерной команды выходное значение было бы потеряно. Благодаря использованию модификатора &, компилятор распознал, что для выходного значения следует использовать любой ре- гистр, не занятый под входные операнды. Возвращаясь к примеру перестановки, код перестановки старшего и младшего байта некоторого 16-разрядного значения будет выглядеть следующим образом: asm volatile("mov ___tmp_reg__, %A0" "\n\t" "mov %A0, %B0" "\n\t" =mov %B0, ___tmp_reg___" "\n\t" ; "=r" (value) : "0" (value) ) ; Пример перестановки байтов 32-разрядного значения: , asm volatile("mov ____tmp_reg__, %A0" "\n\t" "mov %A0, %DO" "\n\t" "mov %D0, ___tmp_reg___" "\n\t" "mov ___tmp_reg__, %B0" "\n\t" "mov %B0, %C0" . "\n\t" "mov %C0, ___tmp_reg___" "\n\t" : "=r" (value) : "0" (value) ) ; Если операнды не помещаются в один регистр, компилятор автоматически на- значит дополнительные регистры, общий размер которых будет достаточным для хранения всего операнда. В рассмотренных примерах спецификации %А0 соответст- вует младший байт первого операнда, а спецификации %А1 — младший байт второ- го операнда. Следующему байту первого операнда соответствует % во, следующе- му— %С0 и т.д. Резервирование регистров В том случае, если в операторе asm должны быть указаны регистры, которые не передаются в качестве операндов, об этом следует каким-то образом уведомить компилятор. Для этой цели служит еще одна, четвертая часть оператора asm, кото- рая в общем случае является необязательной, — часть резервированных регистров.
Исполнение ассемблерного кода 357 Рассмотрим пример реализации автоинкремента восьмиразрядного значения, на которое указывает переменная-указатель, без прерывания какой-либо подпрограм- мой обслуживания прерывания или параллельным процессом (мы должны исполь- зовать указатель, поскольку инкрементированное значение должно быть сохранено до разрешения прерываний). asm volatile( cli” "\n\t Id r24, %a0" "\n\t inc r24" "\n\t st %a0, r24" "\n\t sei" "\n\t : "е” (ptr) : "r24" ); В результате компилятор сгенерирует следующий ассемблерный код: cli Id г24, Z inc r24 st Z, r24 sei Для того чтобы избежать резервирования регистра г24, можно воспользоваться специальным буферным регистром___tmp_reg___ : asm volatile( cli" "\n\t Id tmp_reg t %a0" "\n\t inc tmp_reg ” "\n\t st %a0, tmp_reg " "\n\t sei" "\n\t : "е" (ptr) ); Еще одна проблема заключается в том, что рассматриваемый код не может быть использован в тех программных секциях, где прерывания запрещены и не должны активизироваться, поскольку в конце используется команда общего разрешения прерываний sei. Конечно, можно сохранять текущее состояние микроконтроллера, однако в таком случае потребуется еще один регистр. Опять таки, это можно реали- зовать без резервирования фиксированного регистра, а с помощью локальной пере- менной языка С: { ^unsigned char s; asm volatile( "in %0, SREG " "\n\t" "cli" "\n\t" "Id tmp_reg , %al" "\n\t" "inc tmp_reg " "\n\t" "st %alf tmp_reg " "\n\t" "out SREG , %0" "\n\t"
358 Глава 16. Основы языка С : "=&r" (s) : "е" (ptr) Теперь ассемблерный код модифицирует переменную, на которую указывает ptr, однако компилятор может этого не распознать и сохранить значение в каком- либо другом регистре. Кроме того, значение переменной может модифицировать сама программа на С, а компилятор не обновит ячейку памяти по причинам оптими- зации. Во избежание подобных проблем можно воспользоваться специальным ре- зервирующим определением "memory": unsigned char s; asm volatile( "in %0, SREG_ n "\n\t" "cli" "\n\t" "Id tmp_reg %al" "\n\t" "inc tmp_reg_ П "st %alf tmp_ reg " "\n\t" "out SREG , ’%0" "\n\t" "=&r" (s) "e" (ptr) "memory" Определение "memory" сообщает компилятору о том, что ассемблерный код может модифицировать любую ячейку памяти. В результате компилятор перед вы- полнением ассемблерного кода будет обновлять все переменные, содержимое кото- рых уже содержится в регистрах. И, конечно же, после выполнения этого кода все регистры будут восстановлены в исходное состояние. Использование ассемблера в компиляторе CodeVisionAVR Для включения ассемблерного кода в программы, предназначенные для компи- лятора CodeVisionAVR, служит пара директив препроцессора: #asm и #endasm. На- пример: #asm cli Id r24, Z inc r24 st Z, r24 sei #endasm Между директивами #asm и #endasm можно обращаться к регистрам rO, rl, г22..г27, гЗО и г31. Использование ассемблера в компиляторе CCS-PICC Как и в случае с CodeVisionAVR, в программах, разрабатываемых в среде CCS- PICC, для вставки ассемблерных фрагментов используются директивы препроцес- сора #asm и #endasm:
Исполнение ассемблерного кода 359 #asm ассемблерный код #endasm Если требуется, чтобы компилятор не выполнял автоматического переключения банков памяти для переменных, к которым нельзя получить доступ из текущего банка, в директиве #asm следует использовать опцию AS is: #asm ASIS ассемблерный код #endasm Без опции asis выполняется расширенное ассемблирование, в результате кото- рого доступ к переменным всегда реализуется корректно, благодаря добавлению (там, где это необходимо) переключения банков. Для назначения возвращаемого функцией значения непосредственно в ассемб- лерном блоке можно воспользоваться предустановленной переменной return : int find_parity(int data) { int count; #asm movlw 0x08 movwf count movlw 0 loop: xorwf data, w rrf data, f decfsz count, f goto loop movwf _return_ #endasm } Следует помнить, что любой код между директивой #endasm и окончанием функции может нарушить значение переменной return . Использование ассемблера в компиляторе mikroC В программах, предназначенных для компилятора mikroC, ассемблерный код вставляют с помощью ключевого слова asm: asm { ассемблерный код } Внутри таких подпрограмм можно использовать ранее определенные перемен- ные, например: unsigned char Temp = 10; asm { movlw Temp
360 Глава 16. Основы языка С То же самое относится и к глобальным макроопределениям: г asm { movwf PORTB Использование ассемблера в компиляторах СЗО и С32 В компиляторах СЗО и С32 ассемблерные команды добавляются в программу на С по одной, с помощью функции asm. Например: asm("mov.b [wl++], w0"); asm("ze wO, wO"); Для того чтобы на этапе оптимизации компилятор не изменял порядок следова- ния команд и позицию встроенного ассемблерного кода, к каждому вызову функции asm необходимо добавить атрибут volatile: volatile asm("mov.b [wl++], wO") ; volatile asm("ze wO, wO"); В ассемблерных командах можно использовать значения переменных С, и на- оборот — сохранять результаты выполнения команд в таких переменных. Для этого после команды необходимо разместить символ а после него — специальное обозначение переменной. Операнд, соответствующий переменной, обозначается в ассемблерной команде с помощью символа “%” и порядкового номера параметра, начиная с 0. Например, для считывания значения переменной v в регистр wl можно воспользоваться следующим оператором: asm("mov %0, wl" ::"U"(V)); Для сохранения значения регистра wl в переменной V служит следующий опе- ратор: asm("movwl, %0" :"=U"(V));
Глава 17 Функции и макросы языка С для различных компиляторов В этой главе будут кратко рассмотрены основные стандартные функции языка С, а также — основные библиотечные функции и макросы, определенные в различ- ных компиляторах (кроме С30/32). За подробным описанием представленных здесь функций и макроопределений обращайтесь к специализированным материалам. Стандартные функции языка С Для удобства, стандартные функции языка С рассмотрим с разбивкой по кате- гориям. Начнем с математических функций, перечисленных в табл. 17.1. Таблица 17.1. Стандартные математические функции языка С Функция Библиотека Заголовок Описание abs stdlib.h int abs(int X) Возвращает модуль целого числа X acos math.h float acos(float X) Возвращает арккосинус веще- ственного числа X (X — в диа- пазоне -1... 1). Результат — в диапазоне О...л asin math.h float asin(float X) Возвращает арксинус вещест- венного числа X (X — в диа- пазоне -1... 1). Результат — в диапазоне.-л/2...л/2. atan math.h float atan(float X) Возвращает арктангенс веще- ственного числа X. Результат лежит в диапазоне -л/2...л/2 atan2 math.h float atan2(float Y, float X) Возвращает арктангенс веще- ственного числа Y/Х. Резуль- тат лежит в диапазоне -л... л ceil math.h float ceil(float X) Возвращает значение X, ок- ругленное до ближайшего це- лого cosh math.h float cosh(float X) Возвращает гиперболический косинус вещественного числа X (значение угла в радианах) div stdlib.h div_t div(int num, int denom) Вычисляет значение num/ denom и возвращает частное и остаток в структуре div_t, содержащей два Целочислен- ных поля int: quot и rem
362 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.1. Продолжение Функция Библиотека Заголовок Описание ехр math.h float exp(float X) Возвращает значение ex fabs math.h float fabs(float X) Возвращает модуль вещест- венного числа X floor math.h float floor(float X) Возвращает целую часть ве- щественного числа X fmod math.h float floor(float X, float Y) Возвращает остаток от деле- ния вещественного числа X на вещественное число Y frexp math.h float frexp(float X, int *EXP) Возвращает мантиссу веще- ственного числа X в диапазо- не 0,5... 1,0 или 0, если Х=0. В переменной, переданной по ссылке в качестве параметра ЕХР, сохраняется степень 2 экспоненты X. Если Х=0, то в ЕХР также будет сохранен 0. Другими словами, вызову функции у = frexp (х, е) соответствует соотношение х = у * 2е labs stdlib.h long int abs(long int X) Возвращает модуль целого числа X Idexp math.h float Idexp(float X, int EXP) Возвращает X, умноженное на 2 в степени ЕХР, т.е. Х*2ехр Idiv stdlib.h ldiv_t Idiv(long int num, long int denom) Вычисляет значение num/ de- nom и возвращает частное и остаток в структуре ldiv_t, содержащей два поля типа long int: quot и rem log math.h float log(float X) Возвращает натуральный ло- гарифм числа X. Если X <= 0, возникнет ошибка loglO math.h float loglO(float X) Возвращает логарифм числа X по основанию 10. Если X <=0; возникнет ошибка modf math.h float modf(float X, float *IPART) Разбивает число X на целую и дробную части. Дробная часть возвращается как число со знаком, а целая сохраняется в параметре-переменной I PART pow math.h float pow(float X, float Y) Возвращает число X, возве- денное в степень Y sin math.h float sin(float X) Возвращает синус угла X, представленного в радианах sinh math.h float sinh(float X) Возвращает гиперболический синус угла X, представленного в радианах
Стандартные функции языка С 363 Таблица 17.1. Окончание Функция Библиотека Заголовок Описание sqrt math.h float sqrt(float X) Возвращает квадратный ко- рень положительного числа X. Для отрицательного X резуль- тат не определен tan math.h float tan(float X) Возвращает тангенс угла X, представленного в радианах tanh math.h float tanh(float X) Возвращает гиперболический тангенс угла X, представлен- ного в радианах Функции для работы со строками Следующая категория стандартных функций — предназначенные для работы со строками (табл. 17.2). Таблица 17.2. Стандартные функции языка С для работы со строками Функция Библиотека Заголовок Описание atoi stdlib.h int atoi(char *str) Преобразует строку в цело- численное представление atol stdlib.h long int atoi(char *str) Преобразует строку в цело- численное представление sprintf stdio.h char* sprintf(char *s, const char *fmt, [rargl, arg2...]) Копирует форматированный текст согласно формату, за- данному строкой fmt (анало- гично функции printf), и набору аргументов в строку s. В конце строки добавляет- ся “\0”. Размер строки должен быть достаточным для раз- мещения в ней данных и сим- вола “\0” strcat string.h •char* strcat(char *dest, const char *src) Добавляет строку src в конец строки dest. Строки не пере- крываются. Строка dest должна иметь достаточную длину. Функция возвращает указатель на dest strchr string.h char* strchr(char *src, char val) Возвращает указатель на первое вхождение символа val в строке src. Если сим- вол не найден, возвращается NULL strcmp string.h int strcmp(const char *sl, const char *s2) Сравнивает две строки и воз- вращает число < 0, если sl< s2;0, если si =s2 или чис- ло > 0, если si > s2
364 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.2. Продолжение Функция Библиотека Заголовок Описание strcpy - string.h char* strcpy(char *dest, const char *src) Копирует srcedestc учетом символа завершения строки “\0” Соответствующие области па- мяти не могут пересекаться. Функция возвращает указатель на dest strlen string.h int strlen(const char *src) Возвращает количество симво- лов в src, не включая символ конца строки “\0” strlwr string.h char* strlwr(char *s) Переводит символы строки s в нижний регистр и возвращает указатель на полученную строку strncmp string.h int zstrncmp(const char *sl, const char *s2, unsigned char len) Сравнивает первые len симво- лов строк si и s2 и возвращает число < 0, если si < s2; 0., если si = s2 или число > 0, если si > s2 strncpy string.h char* strncpy(char *dest, const char *src, unsigned char len) Копирует len символов строки src в строку dest с учетом символа завершения стгоки “\0” Соответствующие области па- мяти не могут пересекаться. Функция возвращает указатель на dest strrchr string.h char* strrchr(char *src, char val) Возвращает указатель на по- следнее вхождение символа val в строке src. Если символ не найден, возвращается NULL strstr string.h char* strstr(char *sl, char *s2) Ищет первое вхождение под- строки s2 в строке si (символы “\0” не учитываются). Возвраща- ет указатель на начало подстро- ки, или NULL, если подстрока не найдена. Если s2 указывает на строку нулевой длины, то воз- вращается s 1 strtod stdlib.h float strtod(char *s, char *endptr) Преобразует строку, на которую указывает s, в вещественное представление. Ведущие про- белы в строке игнорируются. Если параметр endpt г не ра- вен NULL, он должен указывать на символ, следующий после последнего в преобразуемой строке
Стандартные функции языка С 365 Таблица 17.2. Окончание Функция Библиотека Заголовок Описание strtol stlib.h long int strtol(char ★s, char *endptr, int base) Преобразует строку, на которую указывает s, в целочисленное представление по основанию base. Ведущие пробелы в стро- ке игнорируются. Если параметр endpt г не равен NULL, он дол- жен указывать на символ, сле- дующий после последнего в преобразуемой строке. Если base > 10, тр символу “А” соот- ветствует число 10, символу “В” — число 11 и т.д. strtoul stdlib.h unsigned long int strtol (char *s, cha,r *endptr, int base) Преобразует строку, на которую указывает s, в целочисленное представление по основанию base. Ведущие пробелы в стро^ ке игнорируются. Если параметр endpt г не равен NULL, он дол- жен указывать на символ, сле- дующий после последнего в преобразуемой строке. Если base > 10, то символу “А” соот- ветствуем число 10, символу “В” — число 11 и т.д. Функции для работы с символами Следующая категория стандартных функций — предназначенные для работы с символами (табл. 17.3). Таблица 17.3. Стандартные функции языка С для работы с символами Функция Библиотека Заголовок Описание isalnum ctype.h unsigned char isalnum(char C) Проверяет, является ли С бук- венно-цифровым символом. Ес- ли да, то возвращается 1 или код символа (зависит от компи- лятора), иначе — 0 isalpha ctype.h unsigned char isalpha(char C) Проверяет, является ли С бук- венным символом (от “а” до “z”) в верхнем или нижнем регистре. Если да, то возвращается 1 или код символа (зависит от компи- лятора), иначе — 0 iscntrl ctype.h unsigned char iscntrl(char C) Проверяет, является ли С управ- ляющим символом (коды в диа- пазоне от 0 до 31). Если да, то возвращается 1 или 255 (зави- сит от компилятора), иначе — 0
366 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.3. Продолжение Функция Библиотека Заголовок Описание isdigit ctype.h unsigned char isdigit(char C) i Проверяет, является ли С сим- волом цифры (от “0” до “9”). Ес- ли да, то возвращается 1 или код символа (зависит от компи- лятора), иначе — 0 isgraph ctype.h unsigned char isgraph*(char C) Проверяет, является ли С ото- бражаемым символом (коды в диапазоне от 33 до 127). Если да, то возвращается 1 или код символа (зависит от компилято- ра), иначе — 0 islower ctype. h unsigned char islower(char C) Проверяет, является ли С ла- тинской буквой в нижнем регист- ре. Если да, то возвращается 1 или код символа (зависит от компилятора), иначе — 0 isprint ctype.h unsigned char isprint(char C) Проверяет, является ли С печа- таемым символом (коды в диа- пазоне от 32 до 127). Если да, то возвращается 1 или код символа (зависит от компилятора), ина- че— 0 ispunct ctype.h unsigned char ispunct(char C) Проверяет, является ли С сим- волом-разделителем (любой символ, кроме управляющих и буквенно-цифровых). Если да, то возвращается 1 или 255 (зави- сит от компилятора), иначе — 0 isspace ctype;h unsigned char isspace(char C) Проверяет, является ли С про- белом или знаком табуляции. Если да, то возвращается 1 или код символа (зависит от компи- лятора), иначе — 0 isupper ctype.h unsigned char isupper(char C) Проверяет, является ли С ла- тинской буквой в верхнем реги- стре. Если да, то воззращается 1 или код символа (зависит от компилятора), иначе — 0 isxdigit ctype.h unsigned char isxdigit(char C) Проверяет, является ли С шест- надцатеричным символом (“0”, “1”, “2”, “3”, “4”, “5й, “6”, “7", “8”, “9”, “а”, “Ь”, “с”, “d”, “е”, “Г, “А”, “В”, “С”, “D”, “Е” или “F"). Если да, то возвращается 1 или код сим- вола (зависит от компилятора), иначе — 0
Стандартные функции языка С 367 Таблица 17.3. Окончание Функция Библиотека Заголовок Описание tolower ctype.h char tolower(char C) Преобразовывает символ С в нижний регистр toupper ctype.h char toupper(char C) Преобразовывает символ С в верхний регистр Функции для работы со случайными числами Далее рассмотрим стандартные функции, предназначенные для работы со слу- чайными числами (табл. 17.4). Таблица 17.4. Стандартные функции языка С для работы со случайными числами Функция Библиотека Заголовок Описание rand stdlib.h int rand(void) Возвращает псевдослучайное число в диапазоне от 0 до значения RAND_MAX. Начальное число для генерации псев- дослучайной последовательности зада- ется с помощью функции srand (). По умолчанию, это число равно 1 srand stdlib.h void srand(unsigned int seed) Устанавливает начальное число для ге- нерации псевдослучайной последова- тельности Функции для работы с памятью Следующая категория стандартных функций — предназначенные для работы с памятью (табл. 17.5). Таблица 17.5. Стандартные функции языка С для работы с памятью Функция Библиотека Заголовок Описание memchr string.h void* memchr(void *src, int val, size_t len) Просматривает первые len бай- тов области памяти, на которую указывает src, до символа val. Возвращает указатель на совпа- дающий байт или NULL, если сим- вол val в заданной области памя- ти найден не был memcmp string.h int memcmp(const void *sl, const void *s2, size_t len) Сравнивает первые len байтов областей памяти, на которые ука- зывают si и s2, и возвращает число < 0, если sl<s2; 0, если sl=s2 или число > 0, если si > s2 memcpy string.h void* memcpy(void *dest, const void *src, size_t len) Копирует len байтов из области памяти, на которую ссылается src, в область памяти, на которую ссылается dest. Эти области па- мяти не могут пересекаться. Функ- ция возвращает указатель на dest
368 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.5. Окончание Функция Библиотека Заголовок Описание memmove string.h void* memmove(void *dest, const void *src, size_t len) Переносит len байтов из области памяти, на которую ссылается src, в область памяти, на которую ссылается dest. Эти области па- мяти могут пересекаться. Функция возвращает указатель на dest memset string.h void* memset(void *dest, int val, size_t len) Заполняет первые len байтов из области памяти, на которую ссы- лается dest, байтом val. Функ- ция возвращает указатель на dest Функции и макросы компилятора WinAVR Математические макросы и функции Математические макроопределения WinAVR перечислены в табл. 17.6, а спе- цифические математические функции — в табл. 17.7. Таблица 17.6. Математические макросы компилятора WinAVR Макрос Библиотека Определение Описание М_Р1 math.h #define M_PI 3.141592653589793238462643 Число л M_SQRT2 math.h ♦define M_SQRT2 1.4142135623730950488016887 Квадратный ко- рень из 2 RAND_MAX stdlib.h ♦define RAND_MAX 0x7FFF Наибольшее зна- чение, которое может быть сгене- рировано функци- ей rand() RANDOM_MAX stdlib.h ♦define RANDOM_MAX 0x7FFFFFFF Наибольшее зна- чение, которое может быть сгене- рировано функци- ей random() Таблица 17.7. Математические функции компилятора WinAVR Функция Библиотека Заголовок Описание inverse math.h double inverse (double X) Возвращает 1/X isinf math.h int isinf(double X) Возвращает 1, если параметр X — положительное или отрицательное бесконечное значение. В противном случае возвращается 0 square math.h double square (double X) Возвращает число X, возведенное в квадрат
Функции и макросы компилятора WinAVR 369 Функции для работы со строками Специфические функции компилятора WinAVR, предназначенные для работы со строками, перечислены в табл. 17.8. Таблица 17.8. Функции компилятора WinAVR для работы со строками Функция Библиотека Заголовок Описание dtostre stdlib.h char* dtostre(double val, char *s, unsigned char prec, unsigned char flags) Преобразует значение val в строковое представление, которое сохраняется в переменной, переданной по ссылке s. Преобразование выполняется в форма- те “[-]d.ddde±dd”, где количество симво- лов после десятичной точки определя- ется параметром prec. Если prec = 0, то десятичная точка в полученной строке отсутствует. Параметр flags может содержать комбинацию констант: - DTOSTRE_UPPERCASE — знак экспо- ненты отображается в верхнем регистре; - DTOSTRE_ALWAYS_SIGN — перед положительными числами всегда встав- ляется пробел; - DTOSTRE_PLUS_SIGN — перед по- ложительными числами всегда вставля- ется знак “+”. Функция возвращает указатель на пре- образованную строку S dtostrf stdlib.h char* dtostrf(double val, char width, char prec, char *s) Преобразует значение val в строковое представление, которое сохраняется в переменной, переданной по ссылке s. Преобразование выполняется в форма- те tt[-]d.ddd”. Минимальная длина полу- ченной строки, включая десятичную точ- ку и возможный знак определяется параметром width, а количество сим- волов после десятичной точки — пара- метром prec. Функция возвращает ука- затель на преобразованную строку s itoa stdlib.h char* itoa(int val, char *s, int radix) Преобразует целочисленное значение val в строковое представление, которое сохраняется в переменной, переданной по ссылке s. Преобразование выполня- ется на основании значения параметра radix. Если radix = 2, то будет полу- чено двоичное представление числа. Если radix > 10, то число 10 будет обозначено в полученной строке симво- лом “а”, число 11 — “Ь” и т.д. Функция возвращает указатель на преобразован- ную строку S
370 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.8. Продолжение Функция Библиотека Заголовок Описание Itoa stdlib.h char* Itoa (long int val, char *s, int radix) Преобразует целочисленное значение val в строковое представление, ко- торое сохраняется в переменной, пе- реданной по ссылке s. Преобразова- ние выполняется на основании значе- ния параметра radix. Если radix = 2, то будет получено двоичное пред- ставление числа. Если radix >10, то число 10 будет обозначено в полу- ченной строке символом “а”, число 11 — “Ь” и т.д. Функция возвращает ука- затель на преобразованную строку s snprintf stdio.h int snprintf (char *s, size_t n, const char *fmt, [,argl, arg2.,..]) Копирует форматированный текст (п символов) согласно формату, задан- ному строкой f mt (аналогично функ- ции printf), и набору аргументов в строку s. В конце строки добавляет- ся “\0”. Размер строки должен быть достаточным для размещения в ней данных и символа “\0и. Функция воз- вращает количество символов, кото- рые были бы записаны в s, если бы там было достаточно места snprintf_P stdio.h int ! snprintf_P (char *s, size_t n, const char *fmt, [,argl, arg2...]) Копирует форматированный текст (п символов) согласно формату, задан- ному строкой fmt (аналогично функ- ции printf), и набору аргументов в строку s. Строка fmt хранится в памяти программ. В конце строки до- бавляется “\0”. Размер строки должен быть достаточным для размещения в ней данных и символа “\0”. Функция возвращает количество символов, ко- торые были бы записаны в s, если бы там было достаточно места sprintf_P stdio.h int sprintf_P (char *s, const char *fmt, [,argl, arg2...]) Копирует форматированный текст со- гласно формату, заданному строкой fmt (аналогично функции printf), и набору аргументов в строку s. Стро- ка fmt хранится в памяти программ. В конце строки добавляется “\0и. Размер строки должен быть достаточным для размещения в ней данных и символа “\0”
Функции и макросы компилятора WinAVR 371 Таблица 17.8. Продолжение Функция Библиотека Заголовок Описание strcasecmp string.h int strcasecmp (const char *sl, const char *s2) Сравнивает две строки без учета регистра символов и возвращает число < 0, если si < s2; 0, если si = s2 или число > 0, если si > s2 strlcat string.h size_t strlcat (char *dest, const char *src, size_t siz) Добавляет строку src в конец строки dest размером siz. Функция возвращает значение strlen(scr) + MIN(siz, strlen(initial dist).Если возвращаемое значение >= siz, строка урезается strlcpy string.h size_t strlcpy (char *dest, const char *src, size_t siz) Копирует строку src в строку dest размером siz (сучетом символа конца строки “\0”). Функ- ция возвращает значение strlen (src). Если возвращае- мое значение >= siz, строка уре- зается strncasecmp string.h int strncasecmp (const char *sl, const char *s2, size_t len) Сравнивает первые len симво- лов двух строк без учета регистра символов и возвращает число < 0, если si < s2; 0, если si = s2 или число > 0, если si > s2 strncat string.h char* strncat (char *dest, const char *src, size_t len) Добавляет первые len символов строки src в конец строки dest. Строки не могут перекрываться, и строка-приемник должна иметь достаточную длину. Функция воз- вращает указатель на dest strnlen string.h size_t strnlen (const char *src, size_t len) Возвращает количество символов в src, не включая символ конца строки “\0и, но не больше, чем len strrev string.h char* strrev (char *s) Возвращает строку, обратную строке s strsep string.h char* strsep (char *s, const char *delim) Находит в строке s первое вхож- дение любого символа из строки delim и заменяет его символом “\0”. Адрес следующего символа после найденного разделителя присваивается указателю s. Функ- ция возвращает указатель на ис- ходное значение s
372 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.8. Окончание Функция Библиотека Заголовок Описание strtok_r string.h char* strtok_r (char *s, char const *delim, char *last) Просматривает строку s в поиске первого символа, не входящего в строку delim. При этом предпола- гается, что si состоит из последо- вательности подстрок, разделенных символами из строки delim. Пер- вый вызов функции вернет указа- тель на первый символ-раздели- тель, после которого в строке будет вставлен символ “\0”. Последующие вызовы функции будут возвращать следующие подстроки со вставкой вместо разделителя символа “\0” до тех пор, пока не будут просмотрены все разделители. После этого воз- вращается NULL, last —это пользовательская строка, которая должна оставаться неизменной strupr string.h char* strupr (char *s) Переводит символы строки s в верхний регистр и возвращает указатель на полученную строку ultoa stdlib.h char* ultoa (unsigned long int val, char *s, int radix) Преобразует целочисленное значе- ние val в строковое представле- ние, которое сохраняется в пере- менной, переданной по ссылке s. Преобразование выполняется на основании значения параметра radix. Если radix = 2, будет по- лучено двоичное представление числа. Если radix >10, число 10 будет обозначено в строке симво- лом “а”, число 11 — “Ь” и т.д. Функ- ция возвращает указатель на пре- образованную строку S utoa stdlib.h char* utoa (unsigned int val, char *s, int radix) Преобразует целочисленное значе- ние val в строковое представле- ние, которое сохраняется в пере- менной, переданной по ссылке s. Преобразование выполняется на основании значения параметра radix. Если radix = 2, будет по- лучено двоичное представление числа. Если radix > 10, число 10 обозначено в полученной строке символом “а”, число 11 — “Ь” и т.д. Функция возвращает указатель на преобразованную строку s
Функции и макросы компилятора WinAVR 373 Функции для работы с символами Специфические функции компилятора WinAVR, предназначенные для работы с символами, перечислены в табл. 17.9. Таблица 17.9. Функции компилятора WinAVR для работы с символами Функция Библиотека Заголовок Описание isascii ctype.h int isascii (char C) Проверяет, соответствует ли С набору символов ASCII. Если да, то возвраща- ется 128, иначе — 0 isblank ctype.h int isblank (char C) Проверяет, является ли С пробелом или символом табуляции. Если да, то воз- вращается код символа, иначе — 0 toascii ctype.h unsigned char toascii(int C) Преобразовывает С в семиразрядное значение типа unsigned char, соот- ветствующее таблице ASCII, путем очи- стки старших разрядов Макросы и функции для организации ввода/вывода Макроопределения WinAVR, предназначенные для организации ввода/вывода, перечислены в табл. 17.10, а функции этой же категории — в табл. 17.11. Таблица 17.10. Макросы компилятора WinAVR для организации ввода/вывода Макрос Библиотека Определение Описание FILE stdio.h #define FILE struct file Структура, используемая в раз- личных стандартных функциях getc stdio.h #define getc( stream) fgetc( stream) Используется для “быстрой” мак- рореализации функциональности, идентичной вызову fgetc () getchar stdio.h #define getchar() fgetc(stdin) Считывает символ из стандартного потока stdin putc stdio.h #define putc( c, stream) fputc ( c, stream) Используется для “быстрой” мак- рореализации функциональности, идентичной вызову fputc () putchar stdio.h #define putchar( c) fputc( c, stdout) Выдает символ в стандартный по- ток stdout ' stderr stdio.h #define stderr (_iob[2J) Поток, предназначенный для вы- вода ошибок. Если отдельно не назначен с помощью функции fdevopen (), идентичен потоку stdout stdin stdio.h ♦define stdin (_iob[OJ) Поток, используемый в качестве входного упрощенными функция- ми, которые не принимают пара- метра stream. В качестве этого потока будет назначен первый по- ток, открытый на чтение с помо- щью функции fdevopen ()
374 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.10. Окончание Макрос Библиотека Определение Описание stdout stdio.h #define stdout (_iob[l]) Поток, используемый в качестве выходного упрощенными функ- циями, которые не принимают па- раметра stream. В качестве этого потока (а также stderr) будет назначен первый поток, открытый на запись с помощью функции fdevopen() Таблица 17.11. Функции компилятора WinAVR для организации ввода/вывода Функция Библиотека Заголовок Описание clearerr stdio.h void clearerr (FILE* stream) Сбрасывает флаги ошибки и конца файла потока stream fclose stdio.h int fclose(FILE* stream) Закрывает поток stream. Даль- нейший ввод/вывод для этого по- тока невозможен. В случае успеш- ного выполнения операции, функ- ция возвращает 0 fdevopen stdio.h FILE* fdevopen (int(*put)(char), int(* get)(void), int opts) Открывает поток для некоторого устройства. В случае успеха воз- вращается указатель на структуру открытого потока. Если передается указатель на функцию put, то по- ток открывается на запись. Функ- ция put должна принимать в ка- честве параметра один символ для записи в устройство и возвра- щать 0 в случае успешного выво- да. Если передается указатель на функцию get, то поток открывает- ся на чтение. Функция get не должна принимать параметров и возвращать символ, принятый от устройства. Об ошибке говорит возврат значения -1. Если передаются указатели одно- временно на функцию put и get, то поток открывает на чтение/за- пись. Первый поток, открытый на чте- ние, назначается в качестве stdin, а первый, открытый на за- пись, — в качестве stdout и stderr. Третий параметр opts зарезер- вирован и роли не играет
Функции и макросы компилятора WinAVR 375 Таблица 17.11. Продолжение Функция Библиотека Заголовок Описание feof stdio.h int feof(FILE* stream) Проверяет состояние флага “end- of-file” потока stream ferror stdio.h int ferror(FILE* stream) Проверяет состояние флага ошибки потока stream fgetc stdio.h int fgetc(FILE* stream) Считывает символ из потока stream. Возвращает считанный символ или -1 в случае ошибки fgets stdio.h char* fgets(char* str, int size, FILE* stream) Считывает size-1 байт из пото- ка stream (или пока не будет встречен символ новой строки) и сохраняет считанные символы в буфере, на который указывает str. Если при этом не возникло 'ошибок, строка будет завершена символом “\0”. В случае ошибки функция возвращает NULL и ус- танавливает флаг ошибки потока stream fprintf * stdio.h int fprintf(FILE* stream, const char* fmt, [argl, arg2, ...]) Выполняет вывод в поток stream форматированной стро- ки f mt в соответствии cd значе- ниями списка параметров (см. описание функции printf в гла- ве 3) fprintf_P stdio.h int fprintf_P (FILE* stream, const char* fmt, [argl,arg2, ...]) Выполняет вывод в поток stre- am форматированной строки fmt (хранится в памяти программ) в соответствии со значениями списка параметров (см. описание функции print f в главе 3) fputc stdio.h int fputc(int C, FILE* stream) Выводит в поток stream символ С. Возвращает символ или -1 в случае ошибки fputs stdio.h int fputs(const char *s, FILE* stream) Выводит в поток stream строку s. Возвращает 0 в случае успешного вывода или -1 в случае ошибки fputs_P stdio.h int fputs_P(const char *s, FILE* stream) Выводит в поток stream строку s из памяти программ. Возвра- щает 0 в случае успешного выво- да или -1 в случае ошибки fread stdio.h size_t fread (void *ptr, size_t size, size_t nmemb, FILE* stream) Считывает nmemb объектов по size байт каждый из потока stream в буфер, на который ука- зывает ptr. Возвращает количе- ство успешно считанных объектов
376 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.11. Продолжение Функция Библиотека Заголовок Описание fscanf / stdio.h int fscanf(FILE* stream, const char *fmt, [argl, arg2, ...]) Выполняет форматированный ввод в соответствии со строкой fmt (см. описание функции printf в главе 3), считывая дан- ные из потока stream. Результа- ты преобразования сохраняются в переменных, переданных в функ- цию по ссылке в качестве пара- метров argl, arg2... Любые па- раметры, для которых не заданы параметры форматирования в строке fmt, воспринимаются как текст fscanf_P stdio.h int fscanf_P (FILE* stream, const char *fmt, [argl,arg2, ...]) Выполняет форматированный ввод в соответствии со строкой fmt (см. описание функции printf в главе 3), считывая дан- ные из потока stream. Строка fmt хранится в памяти программ. Результаты преобразования со- храняются в переменных, пере- данных в функцию по ссылке в ка- честве параметров argl, arg2... Любые параметры, для которых не заданы параметры форматирова- ния в строке fmt, воспринимаются как текст fwrite stdio.h size_t fwrite (const void *ptr, size_t size, size_t nmemb, FILE* stream) Записывает nmemb объектов по size байт каждый в поток stream из буфера, на который указывает ptr. Возвращает коли- чество успешно записанных объ- ектов gets stdio.h char* gets(char *str) Считывает строку из потока stdin, пока не будет встречен символ новой строки, и сохраняет считанные символы в буфере, на который указывает str. В случае ошибки функция возвращает NULL и устанавливает флаг ошибки по- тока stdin printf stdio.h int printf(const char* fmt, [argl, arg2, ...]) Выполняет вывод в поток stderr форматированной строки fmt в соответствии со значениями спи- ска параметров (см. главу 3). Воз- вращает количество записанных символов или -1 в случае ошибки
Функции и макросы компилятора WinAVR 377 Таблица 17.11. Продолжение Функция Библиотека Заголовок Описание printf_P stdio.h int printf_P (const char* fmt, [argl, arg2,...]) Выполняет вывод в поток stderr форматированной строки fmt (хра- нится в памяти программ) в соответ- ствии со значениями списка парамет- ров (см. описание функции printf в главе 3). Возвращает количество за- писанных символов или -1 в случае ошибки puts stdio.h int puts(const char *s) Выводит в поток stdout строку S. Возвращает 0 в случае успешного вы- вода или -1 в случае ошибки puts_P stdio.h int puts_P(const char *s) Выводит в поток stdout строку S, хранимую в памяти программ. Воз- вращает 0 в случае успешного вывода или -1 в случае ошибки scanf stdio.h int scanf(const char *fmt, [argl, arg2, ...]) Выполняет форматированный ввод в соответствии со строкой fmt (см. описание функции printf в главе 3), считывая данные из потока stdin. Результаты преобразования сохраня- ются в переменных, переданных в функцию по ссылке в качестве па- раметров argl, arg2... Любые па- раметры, для которых не заданы па- раметры форматирования в строке fmt, воспринимаются как текст scanf_P stdio.h int scanf_P(const char *fmt, [argl, arg2, ...]) Выполняет форматированный ввод в соответствии со строкой fmt (см. описание функции printf в главе 3), считывая данные из потока stdin. Строка fmt хранится в памяти про- грамм. Результаты преобразования сохраняются в переменных, передан- ных в функцию по ссылке в качестве параметров argl, arg2... Любые па- раметры, для которых не заданы па- раметры форматирования в строке fmt, воспринимаются как текст sscanf stdio.h int sscanf(const char *buf, const char *fmt, [argl, arg2, ...]) Выполняет форматированный ввод в соответствии со строкой fmt (см. описание функции printf в главе 3), считывая данные из буфера, на кото- рый указывает buf. Результаты пре- образования сохраняются в перемен- ных, переданных в функцию по ссыл- ке в качестве параметров argl, arg2...
378 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.11. Окончание Функция Библиотека Заголовок Описание sscanf_P stdio.h int sscanf_P (const char *buf, const char *fmt, [argl, arg2, ...]) Выполняет форматированный ввод в соответствии со строкой fmt (см. описание функции print f в главе 3), считывая данные из буфера, на кото- рый указывает buf. Строка fmt хра- нится в памяти программ. Результаты преобразования сохраняются в пере- менных, переданных в функцию по ссылке в качестве argl, arg2... Функции управления микроконтроллером Специфические функции компилятора WinAVR, предназначенные для управле- ния микроконтроллером, перечислены в табл. 17.12. Таблица 17.12. Функции компилятора WinAVR для управления микроконтроллером Функция Библиотека Заголовок Описание abort stdlib.h void abort(void) Вызывает прерывание ра- боты программы _delay_ms util/delay.h void _delay_ms (double ms) Выполняет задержку на ms миллисекунд _delay_us util/delay.h void _delay_us (double ms) Выполняет задержку на us микросекунд exit stdlib.h void exit(int ‘ status) Прерывает работу прило- жения set_sleep_mode avr/sleep.h void s e t_s1e ep_mode (uint8_t mode) Устанавливает “спящий" режим процессора. Воз- можные значения для mode: - SLEEP_MODE_ADC - ре- жим пониженного шума от АЦП; - SLEEP_MODE_EXT_STANDBY - расширенный режим ожидания; - SLEEP_MODE_IDLE - ждущий режим; - SLEEP_MODE_PWR_DOWN - режим пониженного энер- гопотребления; - SLEEP_MODE_PWR_SAVE - режим энергосбереже- ния; - SLEEP_MODE_STANDBY - режим ожидания sleep__mode avr/sleep.h void sleep_mode (void) Переводит микроконтрол- лер в “спящий” режим
Функции и макросы компилятора WinAVR 379 Макросы для работы со сторожевым таймером Макроопределения WinAVR, предназначенные для работы со сторожевым тай- мером, перечислены в табл. 17.13. Таблица 17.13. Макросы компилятора WinAVR для работы со строжевым таймером Макрос Библиотека Определение Описание wdt_disable avr/wdt.h #define wdt_disable( ) _wdt_write(0) Отключает сторожевой таймер, если это возможно, посредством сброса разряда WDE в регистре WDTCR wdt_enable avr/wdt.h #define wdt_enable (timeout) _wdt_write (timeout) Включает сторожевой таймер, на- страивая его на срабатывание че- рез время, заданное через timeout (установка разрядов WDP[3:0]. Возможные значения timeout: - WDTO15MS —срабатывание через 16 мс (Vcc = 5 В) или 47 мс (Vcc = 3 В); - WDTO_30MS — срабатывание через 32 мс (Vcc = 5 В) или 94 мс (Vcc = 3 В); - WI5TO_60MS — срабатывание через 64 мс (Vcc = 5 В) или 190 мс (Vcc = 3 В); - WDTO_120MS — срабатывание через 128 мс (Vcc= 5 В) или 380 мс (Vcc = 3 В); - WDTO_250MS — срабатывание через 256 мс (Vcc= 5 В) или 750 мс (Vcc = 3 В); - WDTO_500MS — срабатывание через 512 мс (Vcc= 5 В) или 1,5 с (Vcc = 3 В); - WDTO_1S — срабатывание через 1 с (Vcc= 5 В) или 3 с (Vcc = 3 В); - WDTO 2S — срабатывание через 2,1 с (Vcc = 5 В) или 6 с (Vcc = 3 В); - WDTO_4S — срабатывание через 4 с при Vcc = 5 В (доступно не для всех моделей AVR); - WDTO_8S — срабатывание через 8 с при Vcc = 5 В (доступно не для всех моделей AVR) wdt_reset avr/wdt.h #define wdt_reset( ) asm volatile ("wdr”) Сброс сторожевого таймера
380 Глава 17. Функции и макросы языка С для различных компиляторов Функции для работы со случайными числами Функции компилятора WinAVR, предназначенные для работы со случайными чцслами, перечислены в табл. 17.14. Таблица 17.14. Функции компилятора WinAVR для работы со случайными числами Функция Библиотека Заголовок Описание random stdlib.h long int rand(void) Возвращает псевдослучайное число в диапазоне от 0 до значения RANDOM_MAX. Начальное число для генерации псевдослучайной по- следовательности задается с по- мощью функции srandom (). По умолчанию, это число равно 1 srandom stdlib.h void srand (unsigned long int seed) Устанавливает начальное число для генерации псевдослучайной по- следовательности Функции для работы с памятью Специфические функции компилятора WinAVR, предназначенные для работы с памятью, перечислены в табл. 17.15. Таблица 17.15. Функции компилятора WinAVR для работы с памятью Функция Библиотека Заголовок Описание calloc stdlib.h void* calloc (size_t nele, size_t size) Размещает в памяти nele элемен- тов размером size каждый и за- полняет выделенную область нуля- ми free stdlib.h void abort(void *ptr) Делает область памяти, на которую ссылается pt г, доступной для раз- мещения других объектов. Если ptr == NULL, то никаких дейст- вий не происходит malloc stdlib.h void* malloc (size_t size) Выделяет size байт памяти (нуля- ми не заполняются). В случае не- удачи возвращает NULL memcpy string.h void* memccpy (void *dest, const void *src, int val, size_t len) Копирует не более, чем len, байтов из области памяти, на которую ука- зывает src, в область памяти, на которую указывает dest. При на- хождении символа val копирова- ние прекращается. Функция воз- вращает указатель на следующий символ в dest после val или NULL, если символ val не был най- ден в первых len символах src
Функции и макросы компилятора WinAVR 381 Макросы для обработки прерываний Макроопределения WinAVR, предназначенные для обработки прерываний, пе- речислены в табл. 17.16. Таблица 17.16. Макросы компилятора WinAVR для обработки прерываний Макрос Библиотека Определение Описание cli avr/interrupt.h #define cli() asm volatile ("cli::") Запрещает все пре- рывания EMPTY_INTERRUPT avr/interrupt.h #define EMPTY_INTERRUPT (signame) Определяет функ- цию обработчика “пустого” прерыва- ния. signame — имя макроопределе- ния для типа преры- вания INTERRUPT avr/interrupt.h #define INTERRUPT (signame) Определяет функ- цию обработчика прерывания для случая, когда раз- решено общее пре- рывание (т.е, обра- ботчик может быть прерван), signame — имя макроопре- деления для типа прерывания ISR avr/interrupt.h #define ISR (vector) Аналог макроса INTERRUPT ISR_ALIAS, avr/interrupt.h #define ISR_ALIAS (vector, target_vector) Перенаправляет вектор vector на target_vector. Таким образом, реа- лизацию одного век- тора прерывания можно использовать для обслуживания нескольких источни- ков sei avr/interrupt.h #define sei() asm volatile ("sei::") Разрешает все пре- рывания путем уста- новки флага общего разрешения преры- ваний SIGNAL avr/interrupt.h #define SIGNAL (signame) Аналог макроса ISR для случая, когда запрещено общее прерывание
382 Глава 17. Функции и макросы языка С для различных компиляторов Макросы и функции для работы с памятью EEPROM Макроопределения WinAVR, предназначенные для работы с памятью EEPROM, перечислены в табл. 17.17, а функции этой же категории — в табл. 17.18. Таблица 17.17. Макросы компилятора WinAVR для работы с памятью EEPROM Макрос Библиотека Определение Описание eeprom_busy_wait avr/eeprom.h #define e ep r om_bu s y_wa i t () do {} while (!eeprom is ready 0) Организовывает бесконечный цикл до тех пор, пока па- мять EEPROM не освободится eeprom_is_ready avr/eeprom.h #define eeprom_is_ready 0 1, если память EEPROM готова к новой операции чте- ния/записи. В про- тивном случае — 0 Таблица 17.18. Функции компилятора WinAVR для работы с памятью EEPROM Функция Библиотека Заголовок Описание eeprom_read_block avr/eeprom.h void eeprom_read_block (void *buf, const void *addr, size_t n) Считывает блок из п байт по ад- ресу EEPROM addr в буфер buf eeprom_read_byte avr/eeprom.h uint8_t eeprom_read_byte (const uint8_t *addr) Считывает один байт по адресу EEPROM addr eeprom__read_word avr/eeprom.h uintl6_t eeprom_read_word (const uintl6_t ^addr) Считывает 16- разрядное слово по адресу EEPROM addr eeprom_write_block avr/eeprom.h void eeprom_write_block (const void *buf, void *addr, size_t n) Записывает блок из п байт из бу- фера buf по ад- ресу EEPROM addr eeprom_write_byte avr/eeprom.h void e eprom_wr i t e_byt e (uint8_t *addr, uint8 t val) Записывает байт val по адресу EEPROM addr eeprom_write_word avr/eeprom.h void eeprom_write_word (uintl6_t *addr, uintl6_t val) Записывает 16- тиразрядное слово val по адресу EEPROM addr
Функции и макросы компилятора CodeVisionAVR 383 Функции и макросы компилятора CodeVisionAVR Математические макросы и функции Математические макроопределения CodeVisionAVR перечислены в табл. 17.19, а специфические математические функции — в табл. 17.20. Таблица 17.19. Математические макросы компилятора CodeVisionAVR Макрос Библиотека Определение Описание PI math.h ♦define M PI 3.141592654 Число я HUGE_VAL math.h ♦define HUGE_VAL 3.402823466e+38F Предельно большое вещественное число Таблица 17.20. Математические функции компилятора CodeVisionAVR Функция Библиотека Заголовок Описание cabs math.h unsigned char cabs (signed char X) Возвращает абсолютное значение X csign math.h signed char csign (signed char X) Если X < 0, возвращается -1; если X = 0, возвращается 0; если X > 0, возвращается 1 стах math.h signed char стах(signed char Az signed char B) Возвращает большее из двух значений: А или В cmin math.h signed char cmin(signed char Az signed char B) Возвращает меньшее из двух значений: А или В fmax math.h float fmax(float Az float B) Возвращает большее из двух значений: А или В fmin math.h float fmin(float Az float B) Возвращает меньшее из двух значений: А или В fsign math.h signed char fsign (float X) Если X < 0, возвращается -1; если X = 0, возвращается 0; если X > 0, возвращается 1 isqrt math.h unsigned char isqrt (unsigned int X) Возвращает квадратный ко- рень X Imax math.h long int Imax(long int Az long int B) Возвращает большее из двух значений: А или В Imin math.h long int Imin(long int Az long int B) Возвращает меньшее из двух значений: А или В Isign math.h signed char Isign (long int X) Если X < 0, возвращается -1; если X = 0, возвращается 0; если X > 0, возвращается 1 Isqrt math.h unsigned int Isqrt (unsigned long X) Возвращает квадратный ко- рень X max math.h int max(int Az int B) Возвращает большее из двух значений: А или В min math.h int min(int Az int B) Возвращает меньшее из двух значений: А или В sign math.h signed char sign(int X) Если X < 0, возвращается -1; если X = 0, возвращается 0; если X > 0, возвращается 1
384 Глава 17. Функции и макросы языка С для различных компиляторе Функции для работы со строками Специфические функции компилятора CodeVisionAVR, предназначенные дл работы со строками, перечислены в табл. 17.21. Таблица 17.21. Функции компилятора CodeVisionAVR для работы со строками Функция Библиотека Заголовок Описание atof stdlib.h float atof(char *str) Преобразовывает строку str в вещественное число ftoa stdlib.h void ftoa(float n, unsigned char dec, char *str) Преобразовывает вещественное число п в его строковое представ- ление str с количеством знаков после запятой, заданным пара- метром dec ftoe stdlib.h void ftoe(float n, unsigned char dec, char *str) Преобразовывает вещественное число п в его строковое представ- ление str в экспоненциальной форме с количеством знаков по- сле запятой, заданным парамет- ром dec itoa stdlib.h void itoa(int n, char *str) Преобразовывает целое число п в его строковое представление str Itoa stdlib.h void itoa(long int n, char *str) Преобразовывает целое число п в его строковое представление str strchr string.h char *strchr(char *str, char c) Возвращает указатель на первый встретившийся символ с встроке str. Если символ не найден, воз- вращается NULL strcmpf string.h signed char strcmpf(char *strl, char flash *str2) Сравнивает строку strl, распо- ложенную в памяти SRAM, со строкой str2, расположенной в памяти программ. Если strl < str 2, возвращается значение < Q; если strl = str2, возвраща- ется 0; если strl > str2, воз- вращается значение >0 strcpyf string.h char *strcpyf (char *dest, char flash *src) , Копирует строку src, располо- женную в памяти программ, в строку dest, расположенную в памяти SRAM. Возвращает ука- зaтeльнadest strcspn string.h unsigned char strcspn(char *str, char *set) Ищет первое появление символа из строки set в строке str. Если такой символ найден, возвраща- ется его индекс в строке str. В противном случае возвращает- ся длина строки str
ункции и макросы компилятора CodeVisionAVR 385 аблица 17.21. Продолжение Функция Библиотека Заголовок Описание strcspnf string.h unsigned char strcspnf(char *str, char flash *set) Ищет первое появление символа из строки set, расположений© в памя- ти программ, в строке str. Если та- кой символ найден, возвращается его индекс в строке str. В против- ном случае возвращается длина строки str strlenf string.h unsigned int strlenf(char flash *str) Возвращает длину строки str, рас- положенной в памяти программ strlcat string.h char *strncat (char *strl, char *str2, unsigned char n) Присоединяет максимум п симво- лов строки str2 к концу строки strl и возвращает указатель на strl strncatf string.h char *strncatf (char *strl, char flash *str2, unsigned char n) Присоединяет максимум п симво- лов строки str2, расположенной в памяти программ, к концу строки strl и возвращает указатель на strl strncmpf string.h signed char strncmpf(char *strl, char flash *str2, unsigned char n) Сравнивает не более чем п симво- лов строки strl, расположенной в памяти SRAM, со строкой str2, расположенной в памяти программ. Если strl<str2, возвращается значение < 0; если strl = str2, возвращается 0; если strl > str2, возвращается значение > 0 strncpyf string.h char *strncpyf (char *dest, char flash *src, unsigned char) Копирует не более чем п символов строки src, расположенной в памя- ти программ, в строку dest, распо- ложенную в памяти SRAM, и воз- вращает указатель на dest strops string.h signed char strops(char *str, char c) Возвращает индекс первого встре- тившегося символа с в стрке str. Если такой символ не найден, воз- вращает -1 strpbrk string.h char *strpbrk (char *str, char *set) Ищет в строке str первое появле- ние символа из строки set. Если такой символ найден, возвращает указатель на него. В противном случае возвращается NULL strpbrkf string.h char *strpbrk (char *str, char flash *set) Ищет в строке str первое появле- ние символа из строки set, распо- ложенной в памяти программ. Если такой символ найден, возвращает указатель на него. В противном случае возвращается NULL
386 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.21. Окончание Функция Библиотека Заголовок Описание strrops string.h signed char strrops(char *str, char c) Возвращает индекс последнего встретившегося символа с в стрке str. Если такой символ не найден, возвращает -1 strrpbrk string.h char *strrpbrk (char *str, char *set) Ищет в строке str последнее по- явление символа из строки set. Если такой символ найден, возвра- щает указатель на него. В против- ном случае возвращается NULL strrpbrkf string.h char *strrpbrkf (char *str, char flash *set) Ищет в строке str, расположен- ной в памяти SRAM, последнее по- явление символа из строки set, расположенной в памяти про- грамм. Если такой символ найден, возвращает указатель на него. В противном случае возвращается NULL strspn string.h unsigned char strspn(char *str, char *set) Возвращает индекс первого сим- вола строки str, не совпадающего с символом строки set. Если все символы этих двух строк совпада- ют, возвращается длина str strspnf string.h unsigned char strspn(char /str, char flash *set) Возвращает индекс первого сим- вола строки str (в памяти SRAM), не совпадающего с символом строки set (в памяти программ). Если все символы этих двух строк совпадают, возвращается длина str strstrf string.h char *strstrf (char *strl, char flash *str2) Ищет в строке strl, расположен- ной в памяти SRAM, первое вхож- дение строки str2, расположен- ной в памяти программ. Если такое вхождение найдено, возвращается индекс его первого символа. В противном случае возвращается NULL strtok string.h char *strtok (char *strl, char flash *str2) Строка strl, расположенная в па- мяти SRAM, рассматривается как последовательностиь символов, отделенных разделителями в виде одного или нескольких символов из строки str2, расположенной в па- мяти программ. Функция возвра- щает указатель на первую такую последовательность, после чего заполняет ее нулевым символом
Функции и макросы компилятора CodeVisionAVR 387 Функции для работы с символами Специфические функции компилятора CodeVisionAVR, предназначенные для работы с символами, перечислены в табл. 17.22. Таблица 17.22. Функции компилятора CodeVisionAVR для работы с символами Функция Библиотека Заголовок Описание isascii ctype.h unsigned char isascii(char C) Возвращает 1, если С — символ ASCII (код — от 0 до 127), или 0 в противном случае toascii ctype f h char toascii(char C) Возвращает ASCII-эквивалент символа С toint ctype.h unsigned char toint(char C) Интерпретирует С как шестнадца- теричную цифру и возвращает соответствующее значение от 0 ДО 15 Функции управления микроконтроллером Специфические функции компилятора CodeVisionAVR, предназначенные для управления микроконтроллером, перечислены в табл. 17.23. Таблица 17.23. Функции компилятора CodeVisionAVR для управления микроконтролле- ром Функция Библиотека Заголовок Описание delay_ms delay.h void delay__ms (unsigned int n) Задержка на n миллисе- кунд delay_us delay.h void delay_us (unsigned int n)• Задержка на п микросе- кунд extended_standby sleep.h void extended_standby (void) Переход в расширенный дежурный режим idle sleep.h void idle(void) Переход в ждущий режим powerdown sleep.h void powerdown (void) Переход в режим пони- женного энергопотребле- ния powersave sleep.h void powersave (void) Переход в экономичный режим sleep_disable sleep.h void sleep_disable (void) Запрет перехода в режим пониженного энергопо- требления sleep_enable sleep.h void sleep_enable (void) Разрешение перехода в режим пониженного энергопотребления standby sleep.h void standby (void) Переход в дежурный ре- жим Функции для организации ввода/вывода Специфические функции компилятора CodeVisionAVR, предназначенные для организации ввода/вывода, перечислены в табл. 17.24.
388 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.24. Функции компилятора CodeVisionAVR для организации ввода/вывода Функция Библиотека Заголовок Описание putsf stdio.h void putsf(char flash *str) Выводит строку str, располо- женную в памяти программ, ис- пользуя стандартную функцию putchar sscanf stdio.h signed char sscanf (char *str, char flash *fmt [,argl adr, arg2 adr ...] Функция, отличающаяся от стан- дартной функции scanf только тем, что форматированный текст вводится не с помощью функции getchar, а из строки str vprintf stdio.h void vprintf(char flash *fmt, va_list arg) Функция, отличающаяся от стан- дартной функции printf только тем, что указатель arg указывает на список переменных аргумен- тов. Тип va_list определен в заголовочном файле stdarg.h vsprintf stdio.h void vsprintf(char *str, char flash *fmt, va_list arg) Функция, отличающаяся от стан- дартной функции sprintf толь- ко тем, что указатель arg указы- вает на список переменных аргу- ментов. Тип va_list определен в заголовочном файле stdarg. h Функции для работы с памятью Специфические функции компилятора CodeVisionAVR, предназначенные для работы с памятью, перечислены в табл. 17.25. Таблица 17.25. Функции компилятора CodeVisionAVR для работы с памятью Функция Библиотека Заголовок Описание memccpy string.h void* memccpy (void *dest, void *src, char C, unsigned char n) Копирует не более п байтов строки src в строку dest, пока не будет встречен символ С. Если последним был скопирован символ С, то возвра- щается NULL. В противном случае возвращается указатель на dest+n+1 memcmpf string.h signed char memcmpf(void *bufl, void flash *buf2, unsigned char n) Сравнивает не более чем п байт об- ласти buf 1, расположенной в памяти SRAM, с областью buf 2, располо- женной в памяти программ. Если buf 1 < buf 2, возвращается значение < 0; если buf 1 = buf 2, возвращается 0; если buf 1 > buf 2, возвращается значение > 0 memcpyf string.h void* memcpyf (void *dest, void flash *src, unsigned char n) Копирует п байт из строки src, рас- положенной в памяти программ, в строку dest и возвращает указа- тель на dest
Функции и макросы компилятора CCS-PICC 389 Таблица 17.25. Окончание Функция Библиотека Заголовок Описание peekb mem. h unsigned char peekb (unsigned int addr) Считывает байт, расположен- ный по адресу addr peekw mem. h unsigned int peekw (unsigned int addr) Считывает двухбайтное слово, расположенное по адресу addr pokeb mem. h void pokeb(unsigned int addr, unsigned char data) Записывает байт data по ад- ресу addr pok£w mem. h void pokew(unsigned int addr, unsigned int data) Записывает двухбайтное'слово data по адресу addr Функции для работы с интерфейсом 12С Функции компилятора CodeVisionAVR, предназначенные для работы с интер- фейсом 12С, перечислены в табл. 17.26. Таблица 17.26. Функции компилятора CodeVisionAVR для работы с интерфейсом 12С Функция Библиотека Заголовок Описание i2c init i2c. h void i2c init(void) Инициализация шины l2C i2c_read i2c.h unsigned char i2c_read(unsigned char ack) Считывает байт из шины. Если ack = 1, то по завершении чте- ния будет выдан бит квитирова- ния i2c_start i2c. h unsigned char i2c_start(void) Создает условие начала пере- дачи. Если шина свободна, воз- вращает 1. В противном случае возвращает 0 i2c_stop i2c.h void i2c_stop(void) Создает условие завершения передачи i2c_write i2c. h unsigned char i2c_write(unsigned char data) Записывает в шину байт data. Возвращает 1, если ведомое устройство выдало подтверж- дение о получении байта. В про- тивном случае возвращает 0 Функции и макросы компилятора CCS-PICC Математические макросы Математические макроопределения CCS-PICC перечислены в табл. 17.27. Таблица 17.27. Математические макросы компилятора CCS-PICC Макрос Библиотека Определение Описание LN2 math.h #define LN2 0.6931471806 Натуральный лога- рифм от 2 LN10 math.h #define LN10 2.30258509 Натуральный лога- рифм от 10
390 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.27. Окончание Макрос Библиотека Определение Описание PI math.h ♦define PI 3.141592654 Число я PI_DIV_BY_TWO math.h ♦define PI_DIV_BY_TWO _1.570796326794896 Число я/2 RAND_MAX stdlib.h ♦define RAND_MAX 32767 Наибольшее значе- ние, которое может быть сгенерировано функцией rand ()_ SQRT2 math.h ♦define SQRT2 1.41421356 Квадратный корень из 2 TWOBYPI math.h ♦define TWOBYPI 0.6366197724 Число 2/л Функции для работы со строками Специфические функции компилятора CCS-PICC, предназначенные для работы со строками, перечислены в табл. 17.28. Таблица 17.28. Функции компилятора CCS-PICC для работы со строками Функция Библиотека Заголовок Описание atof stdlib.h float atof(char *str) Преобразовывает строку str в ве- щественное число atoi32 stdlib.h int32 atoi32(char *str) Преобразует строку str в целочис- ленное представление (32-разряд- ное целое) strcspn string.h unsigned char strcspn(char *str, char *set) Возвращает индекс первого симво- ла в строке str, который совпадает с символом в строке зет. Если ни одного из символов str нет в set, возвращается длина str. В про- тивном случае возвращается 0 stricmp string.h signed char stricmp(char *sl, char *s2) Сравнивает две строки без учета регистра символов и возвращает число < 0, если si < s2; 0, если sl= s2 или число > 0, если si > s2 strpbrk string.h char* strpbrk (char *str, char *set) Просматривает строку str в поис- ках первого вхождения некоторого символа из строки set. Если вхож- дение найдено, возвращается ука- затель на соответствующий символ в строке str. В противном случае возвращается NULL । strspn string.h unsigned char strspn(char *str, char *set) Возвращает индекс первого симво- | ла в строке str, который не соот- ветствует какому-либо символу в строке set. Если все символы str присутствуют в set, возвращается длина str. Иначе возвращается 0
Функции и макросы компилятора CCS-PICC 391 Таблица 17.28. Окончание Функция Библиотека Заголовок Описание strtok string.h char* strtok (char *s, char const *delim) Просматривает строку s в поиске пер- вого символа, не входящего в строку delim. При этом предполагается, что s 1 состоит из последовательности подстрок, разделенных символами из строки delim. Первый вызов функции вернет указатель на первый символ- разделитель, после которого в строке будет вставлен символ “\0”. После- дующие вызовы функции будут воз- вращать следующие подстроки со вставкой вместо разделителя символа “\0” до тех пор, пока не будут просмот- рены все разделители. После этого возвращается NULL Функции для организации ввода/вывода Специфические функции компилятора CCS-PICC, предназначенные для органи- зации ввода/вывода, перечислены в табл. 17.29. Таблица 17.29. Функции компилятора CCS-PICC для организации ввода/вывода Функция Библиотека Заголовок Описание assert i assert.h #use rs232 () void assert (condition) Проверяет любое условное выражение condition. Если condition дает в результате FALSE, то в стандартный поток stderr выдается сообщении об ошибке (имя файла и номер строки, в которой была вызвана функция assert). Если в программу включить директиву препроцессора #define NODEBUG, то компилятор проигнорирует вызов функции assert fgetc #use rs232 () char fgetc (stream) Ожидает приема символа из потока USART, заданного параметром stream. Имя этого параметра должно совпадать с тем, которое задано директивой #use rs232 fgets (fuse rs232() void fgets (char *str, stream) Ожидает приема строки из потока USART, заданного параметром stream. Имя этого параметра должно совпадать с тем, которое задано директивой #use rs232. Строка считывается в буфер str до тех пор, пока не встретится сим- вол возврата каретки. Приемный буфер должен иметь достаточный размер, что- бы поместить строку и завершающий символ “\0”
392 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.29. Продолжение Функция Библиотека Заголовок Описание fprintf (fuse rs232 () void fprintf (stream, char *fmt, [argl, arg2, ...]) Выводит форматированную строку fmt в поток USART, заданный параметром stream (должен совпадать со значени- ем в директиве #use rs232), с учетом подстановки параметров из списка argl, arg2... (не обязательный). Пра- вила форматирования строки вывода рассматриваются в главе 3 fputc \ fluse rs232() void fputc (char C, stream) Выводит символ С в поток USART, за- данный параметром stream (должен совпадать со значением в директиве #use rs232) fputs fluse rs232() void fputs (char *str, stream) Выводит строку str в поток USART, за- данный параметром stream (должен совпадать со значением в директиве #use rs232). Переданная строка ав- томатически дополняется символами “\л\г” getc fluse rs232() char getc() Ожидает приема символа из потока USART по умолчанию (задан последней директивой #use rs232 перед вызо- вом функции) gets fluse rs232() void gets (char *str) Ожидает приема строки из потока USART по.умолчанию (задан последней директивой #use rs232 перед вызо- вом функции). Строка считывается в буфер, на который указывает пара- метр str, до тех пор, пока не встретит- ся символ возврата каретки. Приемный буфер должен иметь достаточный раз- мер, чтобы поместить строку и завер- шающий символ “\0" input char input (const pin) Возвращает текущее состояние вывода pin. Используемый метод ввода-выво- да зависит от последней директивы #use * 10 input_X * char input X() Считывает байт из порта X (А, В, С...) kbhit fluse rs232() char kbhit() Возвращает 0 (FALSE), если функции getc необходимо ожидать прихода символа, или 1 (TRUE), если символ го- тов. В случае программной реализации USART функция возвращает TRUE, ес- ли на входной вывод поступил первый бит символа
Функции и макросы компилятора CCS-PICC 393 Таблица 17.29. Продолжение Функция Библиотека Заголовок Описание output—bit void output—bit (const pin, char value) Выводит value (0 или 1) через вывод pin. Используемый ме- тод ввода-вывода зависит от последней директивы #use * 10 output_float void output_float (const pin) Переводит вывод pin в со- стояние входа. Используемый метод ввода-вывода зависит от последней директивы #use * 10 output_high void output_high (const pin) Переводит вывод pin в со- стояние лог. 1. Используемый метод ввода-вывода зависит от последней директивы #use * 10 output_low void output_low (const pin) Переводит вывод pin в со- стояние лог. 0. Используемый метод ввода-вывода зависит от последней директивы #use * 10 output_X void output—X (char value) Выводит байт value в порт X (А, В, С ...) port_b_pullups void port—b_pullups (char value) Активизирует (value = TRUE) или отключает (value = FALSE) подтягивающие рези- сторы порта В printf #use rs232 () void printf (char *fmt, [argl, arg2, ...]) Выводит форматированную строку fmt в поток USART по умолчанию с учетом подста- новки параметров из списка argl, arg2... (не обязатёль- ный). Правила форматирования строки вывода рассматривают- ся в главе 3 putc (fuse rs232 () void putc (char C) Выводит символ С в поток USART по умолчанию puts #use rs232() void puts (char *str) Выводит строку str в поток USART по умолчанию. Пере- данная строка автоматически дополняется символами “\л\г” set_tris_X fluse fast_io void set—tris_X (char value) Задает направление передачи данных через порт X (А, В, С...) согласно value. Если в неко- тором разряде value установ- лена лог. 1, то соответствую- щий вывод порта работает как вход, иначе — как выход
394 Глава 17. Функции и макросы языка С для различных компилятор: Таблица 17.29. Окончание Функция Библиотека Заголовок Описание set_uart_speed #use rs232() void set_uart_speed (const int32 baud) Изменяет скорость передачи данных через аппаратный по- следовательный порт RS232. baud — константа в диапазоне от 100 до 115200 sprintf sprintf(char *str, char flash *fmt, [argl, arg2, ...]) Копирует форматированную строку fmt в строку str с уче- том подстановки параметров из списка argl, arg2... (не обя- зательный). Правила формати- рования строки вывода рас- сматриваются в главе 3. Стро- ка-приемник должна быть дос- таточного размера для сохра- нения сформированной форма- тированной строки Функции управления микроконтроллером Функции компилятора CCS-PICC, предназначенные для управления микрокон троллером, перечислены в табл. 17.30. Таблица 17.30. Функции компилятора CCS-PICC для управления микроконтроллером Функция Библиотека Заголовок Описание delay_cycles void delay_cycles (const unsigned char C) Создает задержку, длина кото- рой соответствует количеству С последовательностей из четы- рех тактов системной синхро- низации. Значение С может на- ходиться в диапазоне от 1 до 255. Функция не использует таймеров, поэтому, в результа- те возникновения запроса на прерывание в процессе ее ра- боты, фактическая задержка может оказаться больше delay_ms #use delay i void delay__ms (const unsigned char C) void delay__ms (const intl6 C) Создает задержку на С милли- секунд. Если С — переменная, то ее значение может нахо- диться в диапазоне от 1 до 255. Если С — константа, то ее зна- чение может находиться в диа- пазоне от 1 до 65535. Функция не использует таймеров, по- этому в результате запроса на прерывание в процессе ее ра- боты фактическая задержка может оказаться больше
Функции и макросы компилятора CCS-PICC 395 Таблица 17.30. Продолжение Функция Библиотека Заголовок Описание delay_us #use delay void delay_us(const unsigned char C) void delay_us(const intl6 C) Создает задержку на С микросекунд. Если С — переменная, то ее значе- ние может находиться в диапазоне от 1 до 255. Если С — константа, то ее значение может нахо- диться в диапазоне от 1 до 65535. Эта функция не использует таймеров, по- этому, в результате воз- никновения запроса на прерывание в процессе ее работы, фактическая задержка может оказать- ся больше disable_interrupts #int_xxx void disable_interrupts (int_level) Запрещает прерывание на уровне int_level. int__level —это кон- станта, представляющая вид прерывания (совпа- дает с именем директивы #int_xxx). Например, прерыванию при пере- полнении TMR0 соответ- ствует константа INT_RTCC, а внешнему прерыванию — константа INT_EXT. Всем преры- ваниям соответствует константа GLOBAL enable_interrupts #int_xxx void enable_interrupts (int_level) Разрешает прерывание на уровне int_level. int_level — это кон- станта, представляющая вид прерывания (совпа- дает с именем директивы #int_xxx). Например, прерыванию при пере- полнении TMR0 соответ- ствует константа INT_RTCC, а внешнему прерыванию — константа INT_EXT. Всем преры- ваниям соответствует константа GLOBAL
396 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.30. Окончание Функция Библиотека Заголовок Описание ext_int_edge void ext_int_edge ([source]t edge) Определяет, какой фронт сиг- нала на входе внешнего запро- са на прерывание вызывает прерывание. Если edge = L_TO_H, то активным является нарастающий фронт, а значе- нию H_TO_L соответствует ниспадающий фронт. Параметр source используется только в микроконтроллерах, позво- ляющих задать источник внеш- него прерывания reset_cpu void reset cpu() Сброс микроконтроллера restart_cause char .restart_cause() Возвращает значение, указы- вающее на причину последнего сброса процессора, например: WDT_FROM_SLEEP; WDT_TIMEOUT, MCLR_FROM_SLEEP, NORMAL POWER UP И др. sleep void sleep() Выполняет команду sleep Функции для работы с таймерами и модулем ССР Функции компилятора CCS-PICC, предназначенные для работы с таймерами и модулем ССР, перечислены в табл. 17.31. Таблица 17.31. Функции компилятора CCS-PICC для работы с таймерами и ССР Функция Библиотека Заголовок Описание get_rtcc int8 get_rtcc() intl6 get_rtcc() Возвращает текущее зна- чение счетного регистра TMR0 get_timerX int8 get_timerO() intl6 get_timerl() int8 get_timer2() intl6 get timer3() Возвращает текущее зна- чение счетного регистра соответствующей} тайме- ра/счетчика restart_wdt #fuses WDT void restart_wdt() Сбрасывает сторожевой таймер s e t_pwmX_du t у void set_pwml_duty (intl6 value) void set_pwm2_duty (intl6 value) Записывает в модуль ССР 10-тиразрядное значение value для установки ра- бочего цикла ШИМ set_rtcc void set__rtcc (int8 value) void set_rtcc (intl6 value) Устанавливает значение счетного регистра TMR0
Функции и макросы компилятора CCS-PICC 397 Таблица 17.31. Продолжение Функция Биб- лиотека Заголовок Описание set_timerX void set_timerO (int8 value) void set_timerO (intl6 value) void set_timerl (int16 value) void set_tim^r2 (int8 value) voie set_timer3 (intl6 value) Устанавливает значение счетного ре- гистра соответствующего тайме- ра/счетчика setup_ccpX void setup_ccpl (const mode) void setup_ccp2 (const mode) Инициализирует ССР в соответствии со значением константы mode (к счетчикам ССР можно получить дос- туп с помощью глобальных перемен- ных сср_1 и сср_2): - CCP OFF — модуль ССР отключен; - CCP_CAPTURE_FE — захват со- стояния TMR1 по ниспадающему фронту на выводе ССРх; - CCP_CAPTURE_RE — захват со- стояния TMR1 по нарастающему фронту на выводе ССРх; - CCP__CAPTURE_DIV_4 — захват . состояния TMR1 по каждому четвер- тому нарастающему фронту на выво- де ССРх; - CCP-CAPTURE-DIV_16 — захват состояния TMR1 по каждому шестна- дцатому нарастающему фронту на выводе ССРх; - CCP_COMPARE_SET_ON_MATCH— установка лог. 1 на выводе ССРх при совпадении содержимого TMR1 и пе- ременной сср_х; - CCP_COMPARE_CLEAR_ON_MATCH — установка лог. 0 на выводе ССРх при совпадении содержимого TMR1 и пе- ременной сср_х; - CCP_COMPARE__INT — формирова- ние запроса на прерывание при сов- падении содержимого TMR1 и пере- менной сср_х; - CCP_COMPARE_RESET_TIMER — сброс таймера при совпадении содер- жимого TMR1 и переменной сср х; - ССР PWM — режим ШИМ
398 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.31. Окончание Функция Библиотека Заголовок Описание set up_time r_X void setup_timer_O (mode) void setup__timer_l (mode) void setup_timer_2 (mode, unsigned char period, int8 postscale) void setup__timer_3 (mode) Инициализация тайме- ра/счетчика. mode — кон- станта, состоящая из од- ной или нескольких опций. Параметр period (от 0 до 255) определяющее момент сброса значения счетчика. Параметр postscale (от 1 до 16) определяет, сколько сбро- сов таймера должно про- изойти перед возникнове- нием прерывания setup_wdt #fuses WDT void setup_wdt (mode) Инициализация стороже- вого таймера. Параметр mode — константа, со- стоящая из одной или не- скольких опций, опреде- ляющих время до наступ- ления сброса от стороже- вого таймера: WDT_18MS, WDT_36MS, WDT_72MS, WDT_144MS, WDT_288MS, WDT_576MS, WDT_1152MS, WDT 2304MS Функции для работы с разрядами и памятью Функции компилятора CCS-PICC, предназначенные для работы с разрядами и памятью, перечислены в табл. 17.32. Таблица 17.32. Функции компйлятора CCS-PICC для работы с разрядами и памятью Функция Библиотека Заголовок Описание bit_clear void bit_clear(int8 var, char bit) void bit_clear(intl6 var, char bit) void bit_clear(int32 var, char bit) Очищает разряд bit це- лочисленной переменной var. Если var имеет тип int8, bit может прини- мать значения от 0 до 7; для int 16 — от Одо 15, а для int 32 — от 0 до 31 bit_set void bit_set(int8 var, char bit) void bit_set(intl6 var, char bit) void bit_set(int32 var, char bit) Устанавливает в лог. 1 разряд bit целочислен- ной переменной var. Если var имеет тип int8, bit может принимать значения от 0 до 7; для int 16 — от Одо 15, а для int 32 —от 0 до 31
Функции и макросы компилятора CCS-PICC 399 Таблица 17.32. Продолжение Функция Библиотека Заголовок Описание bit-test inti bit_test(int8 var, char bit) inti bit—test(intl6 var, char bit) inti bit—test(int32 var, char bit) Возвращает состояние раз- ряда bit целочисленной пе- ременной var. В случае, ес- ли var имеет тип int8, bit может принимать значения от 0 до 7; для int 16 — от 0 до 15, а для int 32 —отО До 31 input char input(const pin) Возвращает текущее состоя- ние вывода pin (адрес-кон- станта вывода порта): 0 или 1. Используемый метод вво- да/вывода зависит от послед- ней директивы #use *_io перед вызовом функции makel6 intl6 makel6(int8 var_high, int8 var_low) Возвращает 16-разрядное значение, составленное из двух восьмиразрядных вели- чин var_high (старший байт) и var_low (младший байт). Если разрядность од- ного из параметров больше 8 бит, используются только младшие восемь разрядов make32 int32 make32(int8 varl [, int8 var2, int8 var3, int8 var4]) Возвращает 32-разрядное значение, Составленное из одного, двух, трех или четы- рех восьмиразрядных вели- чин. Параметр varl соот- ветствует самому старшему байту, a var4 — самому младшему. Если общее чис- ло разрядов меньше 32, то старшие разряды в возвра- щенном значении заполня- ются нулями make 8 int8 make8(intl6 var, int8 offset) int8 make8(int32 var, int8 offset) Возвращает восьмиразряд- ное значение, полученное из 16- или 32-разряд ной вели- чины var путем смещения на offset байтов offsetof stddef.h int8 offsetof (structure_type, field) Возвращает смещение (в байтах) поля field в структуре типа structure type
400 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.32. Окончание Функция Библиотека Заголовок Описание offsetofbit stddef.h int8 offsetofbit (structure_type, field) . Возвращает смещение (в би- тах) поля field в структуре типа structure type read_bank int8 read—bank (int8 bank, intl6 offset) Считывает байт данных из области RAM банка bank (1-3, в зависимости от мик- роконтроллера) по смеще- нию offset rotate_left void rotate_left (char *addr, char bytes) Выполняет циклический сдвиг влево на один разряд bytes байтов в области па- мяти, на которую ссылается addr rotate_right void rotate_right (char *addr, char bytes) Выполняет циклический сдвиг вправо на один разряд bytes байтов в области па-, мяти, на которую ссылается addr shift_left inti shift—left (char *addr, char bytes, inti value) Выполняет сдвиг влево на один разряд bytes байтов в области памяти, на кото- рую ссылается addr. Пер- вый разряд заполняется значением value. Функция возвращает сдвинутый раз- ряд (последний перед сдви- гом) shift—right inti shift—right (char *addr, char bytes, inti value) Выполняет сдвиг вправо на один разряд bytes байтов в области памяти, на кото- рую ссылается addr. По- следний разряд заполняется значением value. Функция возвращает сдвинутый раз- ряд (первый перед сдвигом) swap void swap(int8 x) Меняет местами старший и младший полубайты х write_bank void write_bank (int8 bank, intl6 offset, int8 value) Записывает байт данных value в область RAM банка bank (1-3, в зависимости от микроконтроллера) по сме- щению offset Функции для работы с памятью EEPROM Функции компилятора CCS-PICC, предназначенные для работы с памятью EEPROM, перечислены в табл. 17.33.
Функции и макросы компилятора CCS-PICC 401 Таблица 17.33. Функции компилятора CCS-PICC для работы с памятью EEPROM Функция Библиотека Заголовок Описание read_eeprom int8 read_eeprom (int8 addr) Считывает байт данных из памяти EEPROM по адресу addr write_eeprom voipl write_eeprom (int8 addr, int8 value) Записывает байт данных value в памяти EEPROM по адресу addr Функции для работы с интерфейсом SPI Функции компилятора CCS-PICC, предназначенные для работы с интерфейсом SPI, перечислены в табл. 17.34. Таблица 17.34. Функции компилятора CCS-PICC для работы с интерфейсом SPI Функция Библиотека Заголовок Описание setup_spi void setup_spi (const inodes) Инициализирует интер- фейс SPI в соответствии с константой modes, за- дающей режим и скорость обмена данными. Возмож- на комбинация значений из следующих категорий: - выбор режима — SPI_SS_DISABLED’ SPI_MASTER, S PI_SLAVE; - активный фронт синхро- импульса — SPI—L—ТО—Н, SPI_H_TO_L; - частота тактирования — SPI_CLK_DIV_4, SPI—CLK—DIV—16, SPI_CLK_DIV_64, SPI CLK Т2 spi_dataj_is__in char spi data is in() Возвращает TRUE, если в порт SPI приняты данные spi_read char spi_read() Возвращает значение, счи- танное из порта SPI spi_write void setup_spi (char c) Устанавливает очередной байт данных для передачи в порт SPI. Если устройст- во — ведущее, то функция генерирует тактовый сиг- нал и передает байт. Если устройство ведомое, то байт не будет передан до тех пор, пока не будет по- лучен тактовый сигнал от ведущего устройства
402 Глава 17. Функции и макросы языка С для различных компиляторе; Функции для работы с интерфейсом PSP Функции компилятора CCS-PICC, предназначенные для работы с интерфейсом PSP, перечислены в табл. 17.35. Таблица 17.35. Функции компилятора CCS-PICC для работы с интерфейсом PSP Функция Библиоте- ка Заголовок Описание psp_input_full inti psp_input_full() Возвращает 0, если из порта PSP не считывается никаких данных, или 1, ес- ли есть данные на чтение. Данные можно считывать с помощью глобальной переменной psp data psp_output_ful1 inti psp_output—full() Возвращает 0, если в пор- та PSP еще не было запи- сано никаких данных, или 1, если данные уже были записаны. Данные можно записывать в PSP с помо- щью глобальной перемен- ной psp data psp_overflow inti psp_overflow() Возвращает 0, если порта PSP не находится в со- стоянии переполнения (данные записываются внешним устройством до того как принятые прежде данные были прочитаны микроконтроллером), или 1 в противном случае setup_psp void setup_psp(mode) Инициализирует (mode = PSP_ENABLED) или от- ключает (mode = PSP- DISABLED) порт PSP Функции для работы с интерфейсом I2C Функции компилятора CCS-PICC, предназначенные для работы с интерфейсом 12С, перечислены в табл. 17.36. Таблица 17.36. Функции компилятора CCS-PICC для работы с интерфейсом 12С Функция Библиотека Заголовок Описание i2c_poll #use i2c inti i2c_poll() Используется только в случае при- сутствия аппаратного порта SSP (интерфейс 12С в режиме Slave). Функция возвращает TRUE, если принят байт в буфер приема, и FALSE, если буфер приема пуст
Функции и макросы компилятора CCS-PICC 403 Таблица 17.36. Окончание Функция Библиотека Заголовок Описание i2c_read #use i2c int8 i2c_read ( [inti ack]) Считывает байт по интерфейсу l2C. В режиме Master эта функция гене- рирует такт синхронизации, а в ре- жиме Slave — ожидает этого такта (для стробирования сторожевого таймера во время ожидания в ре- жиме Slave следует добавить в ди- рективу # u s е i 2 с флаг RESTART—WDT). Необязательный параметр ack (значение 1 или 0) определяет, должно ли быть под- тверждение байта при чтении i2c_start #use i2c void i2c_start() Создает условие начала передачи, когда микроконтроллер находится в режиме l2C Master. После созда- ния такого условия уровень сигнала в тактовой линии будет низким до тех пор, пока не будет вызвана функция i2c_write. Если до вы- зова функции i2c_stop функция i2c_start будет вызвана еще раз, это создаст условие рестарта i2c_stop #use i2c void i2c_stop() Создает условие завершения пере- дачи, когда микроконтроллер нахо- дится в режиме l2C Master i2c_write #use i2c inti i2c_write (int8 data) Передает байт по интерфейсу 12С. В режиме Master также генерирует тактовый сигнал, а в режиме Slave ожидает такт от ведущего устройст- ва. Возвращает бит квитирования. Младший разряд первой записи по- сле создания условия начала пере- дачи определяет направление пе- редачи: 0 — от ведущего ведомому, 1 — от ведомого ведущему Функции для работы с аналоговыми сигналами Функции компилятора CCS-PICC, предназначенные для работы с аналоговыми сигналами, перечислены в табл. 17.37. Таблица 17.37. Функции компилятора CCS-PICC для работы с аналоговыми сигналами Функция Заголовок Описание read_adc int8 read_adc() int16 гead_adc() Считывает результат аналого-цифрового преоб- разования, разрядность которого зависит от раз- рядности АЦП и параметров директивы #device adc
404 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.37. Продолжение Функция Заголовок Описание set_adc_channel void set_adc_channel (int8 channel) Выбирает аналоговый канал channel для использования при следующем вызо- ве функции read adc setup_adc void setup_adc(mode) Конфигурирует АЦП в соответствии со зна- чением константы mode: ADC_CLOCK_DIV_2, ADC_CLOCK_DIV_8, ADC_CLOCK_DIV_32 — деление частоты; ADC_OFF — АЦП от- ключен; ADC_CLOCK_ INTERNAL — часто- та без делителя setup_adc_ports void setup_adc_ports (mode) Конфигурирует выводы АЦП в соответст- вии со значением константы mode: - NO_ANALOGS — нет аналрговых входов; - ALL_ANALOG — АО, А1, А2, АЗ, А5, Е0, Е1, Е2; опорное напряжение — на выводе Vdd; - ANALOG_RA3_REF — АО, А1, А2, А5, Е0, Е1, Е2; опорное напряжение — на выводе АЗ; - А_ANALOG — АО, А1, А2, АЗ, А5; опорное напряжение — на выводе Vdd; - А_ANALOG—RA3_REF — АО, А1, А2, А5; опорное напряжение — на выводе АЗ; - RA0_RA1_RA3_ANALOG — АО, А1, АЗ; опорное напряжение — на выводе Vdd; - RAO_RA1_ANALOG_RA3_REF — АО, А1; опорное напряжение — на выводе АЗ; - ANALOG—RA3—RA2—REF — АО, А1, А5, Е0, Е1, Е2; опорное напряжение — на вы- водах А2, АЗ; - ANALOG—NOT—RE1—RE2 — АО, А1, А2, АЗ, А5, ЕО; опорное напряжение — на вы- воде Vdd; - ANALOG—NOT—RE 1—RE2—REF—RA3 -- AO, A1, A2, A5, ЕО; опорное напряжение — на выводе АЗ; - ANALOG_NOT_RE1_RE2_REF_RA3_RA2 — АО, А1, А5; опорное напряжение — на вы- водах А2, АЗ; - А_ANALOG—RA3—RA2—REF — АО, А1, А5; опорное напряжение — на выводах А2, АЗ; RA0—RA1—ANALOG—RA3—RA2—REF — АО, А1; опорное напряжение — на выводах А2, АЗ; - RAO—ANALOG — АО; - RAO—ANALOG—RA3—RA2—REF — АО; опорное напряжение — на выводах А2, АЗ
Функции компилятора mikroC 405 Таблица 17.37. Окончание Функция Заголовок Описание setup_comparator void setup_comparator (mode) Конфигурирует аналоговый компаратор в соответствии со значением константы mode (элементы представленных ниже констант соответствуют входам С1-, С1+, С2-ИС2+): - А0_АЗ_А1_А2; - А0_А2_А1_А2; - NC_NC_A1_A2; - NC_NC_NC_NC; - AO_VR_A1_VR; - A3_VR_A2_VR; - A3_A2_A1_A2; - AO A2 Al A2 OUT ON АЗ A4 Функции компилятора mikroC Математические функции Специфические математические функции компилятора mikroC представлены в табл. 17.38. Таблица 17.38. Математические функции компилятора mikroC Функция Библиотека Заголовок Описание lo unsigned short lo(long n) Возвращает младший (первый) байт числа п hi unsigned short hi(long n) Возвращает второй байт числа п higher unsigned short higher(long n) Возвращает третий байт числа п highest unsigned short highest(long n) Возвращает старший (четвертый) байт числа п max stdlib.h int max(int a, int b) Возвращает большее из двух чисел: а и b min stdlib.h int min(int a, int b) Возвращает меньшее из двух чисел: а и b Функции для работы со строками Специфические функции компилятора mikroC, предназначенные для работы со строками, перечислены в табл. 17.39. Таблица 17.39. Функции компилятора mikroC для работы со строками Функция Библиотека Заголовок Описание sprinti sprint.h int sprinti (char *bufz const char *fmt [,argl, arg2 ...] ) Функция, которая отличается от функции sprint f только тем, что не поддерживает целые числа ти- па long
406 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.39. Окончание Функция Библиотека Заголовок Описание sprintf sprint.h int sprintf (char *buf, const char *fmt [,argl, arg2 ] ) Форматирует набор строк и числовых значений, хранимых в буфере buf, со- гласно правилам форматирования, за- данным строкой fmt, и помещает ре- зультирующую строку в буфер (правила форматирования рассматриваются в главе 3). Возвращает количество сим- волов, фактически записанных в буфер sprintl sprint.h int sprintl (char *buf, const char *fmt [,argl, arg2...) Функция, которая отличается от функ- ции sprintf только тем, что не под- держивает вещественные числа strcspn string.h char strcspn(char * si, char * s2) Вычисляет длину наибольшего началь- ного сегмента строки si, состоящего исключительно из символов, отсутст- вующих в строке s2. Возвращает длину сегмента strncat string.h char *strncat (char, *sl, char *s2, int n) Добавляет не более п символов из строки s2 к строке si. Первый символ s2 затирает символ “\0” в конце si. Этот же символ автоматически добав- ляется в конце результирующей строки. Функция возвращает указатель на s 1 strpbrk string.h char * strpbrk (char * si, char * s2); Ищет в строке s 1 первое вхождение любого символа из строки s2 и возвра- щает индекс такого символа в si. Если символ не найден, возвращает значе- ние $FF. strspn string.h int strspn(char *sl, char *s2); Возвращает длину наибольшего на- чального сегмента si, состоящего ис- ключительно из символов, входящих в состав строки s2 strtok string.h char * strtok (char * si, char * s2) Просматривает строку s 1 в поиске пер- вого символа, не входящего в строку s2. При этом предполагается, что si состоит из последовательности под- строк, разделенных символами из стро- ки s 2. Первый вызов функции вернёт указатель на первый символ-раздели- тель, после которого в строке будет вставлен символ ц\0”. Последующие вы- зовы функции будут возвращать сле- дующие подстроки со вставкой вместо разделителя символа “\0” до тех пор, пока не будут просмотрены все разде- лители. После этого возвращается NULL
Функции компилятора mikroC 407 Функции преобразований Функции преобразований компилятора mikroC перечислены в табл. 17.40.' Таблица 17.40. Функции преобразований компилятора mikroC Функция Библиотека Заголовок Описание Bcd2Dec char Bcd2Dec (char bednum) Преобразовывает BCD- число bednum в его деся- тичный эквивалент Bcd2Decl6 unsigned Bcd2Dec (unsigned bednum) Преобразовывает BCD- число bednum в его деся- тичный эквивалент ByteToStr void ByteToStr (unsigned short number, char *output) Создает строку output длиной в три символа из числа number (0..256) Dec2Bcd char Dec2Bcd (char decnum) Преобразовывает десятич- ное число decnum в BCD- число Dec2Bcdl6 unsigned Dec2Bcdl6 (unsigned decnum) Преобразовывает десятич- ное число decnum в BCD- число FloatToStr void FloatToStr (float number, char *output) Создает строку output из вещественного числа number. Результирующая . строка представлена в экс- поненциальном формате с пятью знаками после запя- той ♦ IntToStr - void IntToStr (int number, char *output) Создает строку output длиной в шесть символов из числа number LohgToStr void LongToStr (long number, char *output) Создает строку output длиной в Ьдиннадцать сим- волов из числа number ShortToStr void ShortToStr (short number, char *output) Создает строку output длиной в четыре символа из числа number WordToStr void WordToStr (unsigned number, char *output) Создает строку output длиной в пять символов из числа number xtoi stdlib.h int xtoi(char *s) Преобразовывает строку s, состоящую из шестнадца- теричных символов в соот- ветствующее ей число Функции управления микроконтроллером Функции компилятора mikroC, предназначенные для управления микрокон- троллером, перечислены в табл. 17.41.
408 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.41. Функции компилятора mikroC для управления микроконтроллером Функция Библиотека Заголовок Описание Clock_Khz unsigned Clock_Khz(void) Возвращает значение такто- вой частоты микроконтролле- ра в кГц, округленное до бли- жайшего целого Clock_Mhz unsigned short Clock_Mhz(void) Возвращает значение такто- вой частоты микроконтролле- ра в МГц, округленное до ближайшего целого Delay_Cyc void Delay_Cyc (char C) Создает задержку, равную 10 машинным циклам, умножен- ным на параметр С Delay_ms void Delay_ms (const time) Создает задержку на число миллисекунд time Delay_us void Delay_us (const time) Создает задержку на число микросекунд time Time_dateDiff timelib.h long Time_dateDi f f (TimeStruct *tl, TimeStruct *t2) Возвращает разницу в секун- дах между датами tl и t2 Vdelay_ms void Vdelay_ms (unsigned time) Аналог функции Delay ms, однако в данном случае па- раметр time — не константа, а переменная Функции для работы с периферийными устройствами Функции компилятора mikroC, предназначенные для работы с периферийными устройствами, перечислены в табл. 17.42. Таблица 17.42. Функции компилятора mikroC для работы с периферией Функция Заголовок Описание Adc_Read unsigned Adc_Read (unsigned short ch) Возвращает 10-разрядное зна- чение, считанное из заданного параметром ch канала АЦП Pwm_Change_Dut у void Pwm_Change_Duty (unsigned short ratio) Устанавливает коэффициент за- полнения для ШИМ. Значению ratio = 0 соответствует коэф- фициент 0%, ratio = 127 — 50%; rat io = 255 — 100% Pwm_Init void Pwm_Init (unsigned long freq) Инициализирует модуль ШИМ с коэффициентом заполнения 0. Параметр freq задает желае- мую частоту ШИМ в герцах Pwm Start void Pwm Start (void) Активизирует ШИМ Pwm Stop void Pwm Stop (void) Останавливает ШИМ
Функции компилятора mikroC 409 Таблица 17.42. Окончание Функция Заголовок Описание Usart_Data_Ready unsigned short Usart_Data_Ready(void) Возвращает 1, если данные в буфере приемника USART, го- товы. В противном случае воз- вращает 0 Usart_Init void Usart_Init(const unsigned long baud) Инициализирует модуль USART, устанавливая скорость передачи данных baud (от 100 до 115200) Usart_Read unsigned short Usart_Read(void) Возвращает принятый через USART байт. Если байт не при- нят, возвращает 0 Usart_Write void Usart_Write (unsigned short data) Передает через USART байт data Функции для работы с памятью EEPROM и Flash Функции компилятора mikroC, предназначенные для работы с памятью Flash и EEPROM, перечислены в табл. 17.43. Таблица 17.43. Функции компилятора mikroC для работы с памятью EEPROM и Flash Функция Заголовок Описание Eeprom_Read unsigned short Eeprom_Read(unsigned int addr) Считывает байт по адресу addr памяти EEPROM Eeprom_Write void Eeprom_Write (unsigned int addr, unsigned short data) Записывает байт data по ад- ресу addr памяти EEPROM Flash_Erase void Flash_Erase (unsigned addr) Очищает блок Flash-памяти, начиная с адреса addr Flash_Erase_64 void Flash_Erase_64 (long addr) Очищает блок в 64 байта Flash-памяти, начиная с адре- са addr Flash_Erase_1024 void Flash_Erase_1024 (long addr) Очищает блок в 1024 байта Flash-памяти, начиная с адре- са addr Flash_Read unsigned Flash_Read (unsigned addr) Возвращает байт, хранимый во Flash-памяти по адресу addr Fla sh_Re ad_N_Byt e s unsigned Fla sh_Read_N_Byt e s (long addr, char* data, unsigned int N) Записывает N байт из Flash- памяти, начиная с адреса addr, в буфер data Flash_Write void Flash—Write (unsigned addr, unsigned int * data) Записывает содержимое бу- фера data по адресу addr Flash-памяти Flash_Write_8 void Flash—Write_8 (long addr, char* data) Записывает 8 байт data по адресу addr Flash-памяти
410 Глава 17. Функции и макросы языка С для различных компиляторов Таблица 17.43. Окончание Функция Заголовок Описание Flash_Write_16 void Flash_Writе_16 (long addr, char* data) Записывает 16 байт data по адресу addr Flash-памяти Flash_Write_32 void Flash_Write_32 (long addr, char* data) Записывает 32 байта data по адресу addr Flash-памяти Flash_Write_64 void Flash_Write_64 (long addr, char* data) Записывает 64 байта data по адресу addr Flash-памяти Функции для работы с интерфейсом 12С Функции компилятора mikroC, предназначенные для работы с интерфейсом 12С. перечислены в табл. 17.44. Таблица 17.44. Функции компилятора mikroC для работы с интерфейсом 12С Функция Заголовок Описание I2C_Init void !2C_Init(unsigned long clock) Инициализирует интерфейс l2C частотой тактирования clock I2C_Is_Idle unsigned short I2C_Is_Idle(void) Возвращает 1, если шина 12С свободна. В противном случае возвращает 0 I2C_Rd unsigned short I2C_Rd (unsigned short ack) Возвращает байт данных, при- нятый от ведомого устройства. Если параметр ack = р, то бит квитирования не выдается I2C_Repeated_Start void I2C_Repeated_Start (void) Создает повторяющееся усло- вие начала передачи I2C_Start unsigned short I2C_Start(void) Проверяет, свободна ли шина 12С, и создает условие начала передачи. Если ошибок не об- наружено, функция возвраща- ет 0 I2C_Stop void I2C_Stop(void) Создает условие завершения передачи I2C_Wr unsigned short I2C_Wr (unsigned short data) Выдает в шину 12С байт data. Если ошибок не обнаружено, возвращает 0 Функции для работы с интерфейсом SPI Функции компилятора mikroC, предназначенные для работы с интерфейсом SPI, перечислены в табл. 17.45.
Функции компилятора mikroC 411 Таблица 17.45. Функции компилятора mikroC для работы с интерфейсом SPI Функция Заголовок Описание Spi_Init void Spi_Init(void) Конфигурирует и нициализирует интерфейс SPI с параметрами по умолчанию Spi_Init_Advanced void Spi_Init_Advanced (unsigned, short m_s, unsigned short data_sample, unsigned short clock_idle, unsigned short tx_edge) Конфигурирует и нициализирует интерфейс SPL Параметр m s определяет ре- жим работы: - MASTER_OSC_DIV4; - MASTER_OSC_DIVI6; - MASTER_OSC_DIV64; - MASTER_TMR2; - SLAVE_SS_ENABLE; - SLAVE_SS_DIS. Параметр data sample зада- ет момент опроса бит данных: - DATA_SAMPLE_MIDDLE — в середине интервала; - DATA_SAMPLE>_END — в кон- це интервала. Параметр clock_idle опре- деляет состояние ожидания для тактового сигнала: - CLK_IDLE_HIGH; - CLK_IDLE_LOW. Параметр tx edge задает фронт тактового сигнала, по ко- торому передается бит данных: - LOW_2_HIGH — нарастаю- щий; - HIGH_2_LOW — ниспадаю- щий. Spi_Read unsigned short Spi_Read(unsigned short buffer) Возвращает байт, принятый по интерфейсу SPI Spi_Write void Spi_Write (unsigned short data) Записывает байт в буфер ин- терфейса SPI и сразу же начи- нает передачу
ЧАСТЬ VI Программные примеры для микроконтроллеров AVR
Глава 18 Примеры для компилятора WinAVR В этой главе мы рассмотрим две программы, рассчитанных на микроконтроллер ATmega8 и компилятор WinAVR. Управление ЖК-дисплеем Большинство ЖК-дисплеев позволяет отображать заданные пользователем знаки для получения на экране диаграмм, анимации и других подобных изображений. В данном примере будет реализована простая схема управления модулем ЖК-дисп- лея, совместимого с моделью HD44780 от компании Hitachi. О Техническое описание модуля HD44780U можно найти на прилагаемом к книге компакт-диске в папке Datasheets. Для нашего примера мы реализуем схему подключения ЖК-дисплея к микрокон- троллеру по шести линиям, из которых четыре будут задействованы для передачи данных, а остальные две — для управления. Для этой схемы потребуется рабочее на- пряжение 5 В (рис. 18.1). Рис. 18.1. Схема подключения модуля ЖК-дисплея к микроконтроллеру АТтедав Модули ЖК-дисплеев состоят из собственно дисплея и схемы управления. Микроконтроллер в таком случае служит для формирования последовательности управляющих команд, необходимых для получения на дисплее того или иного изо- бражения.
414 Глава 18. Примеры для компилятора WinAVR В сфере использования ЖК-модулей существует своеобразный “полустандарт’\ Само собой, на рынке существует множество устройств от разных производителей, поэтому единый, унифицированный стандарт получить нереально. Тем не менее, многие изготовители придерживаются совместимости с ЖК-контроллерами Hitachi HD44780, благодаря чему представленная на рис. 18.1 схема применима при работе к большинству ЖК-модулей. Даже если используется не HD44780, последователь- ность управляющих команд все равно будет распознана корректно. Большинство дисплеев предоставляют одну или две строки с количеством по- зиций от восьми до 16 в каждой строке. Для отображения одного знака требуется выполнить следующую последовательность действий. 1. Активизировать четырехразрядный режим (для нашего примера). 2. Выполнить дальнейшую настройку ЖК-модуля (например, использование двух строк; матрица символа 5x8 и т.д.). 3. Погасить ЖК-дисплей. 4. Включить ЖК-дисплей. 5. Передать знак контроллеру. Микроконтроллер может передавать команды из набора: • включить дисплей; • отключить дисплей; • очистить дисплей; • установить стартовый режим; • определить конфигурацию для установки отображения в одной или двух стро- ках, с матрицей символов 5x8 или 5x10; • установить адрес знакогенератора; • установить адрес в памяти дисплея; • установить курсор в начальную позицию; • сместить курсор; • установить особую функцию курсора (например, мерцание); • записать данные. Контроллер ЖК-модуля отличает команды от данных. Для каждой последова- тельности передачи модуль можно известить, что ему ожидать. Для этого служит управляющая линия RS (низкий уровень соответствует передаче команды, а высо- кий — передаче данных). Управляющая линия Е передает сигнал разрешения (вы- сокий уровень включает ЖК^модуль на прием). Таким образом, последовательность передачи данных/команд выглядит следующим образом. 1. Установка на линии RS сигнала высокого (передача данных) или низкого (пере- дача команды) уровня. 2. Выдача старших четырех разрядов на четыре линии данных. 3. Кратковременный (примерно на 1 мкс) перевод линии Е в состояние высокого уровня, вслед за которым следует возврат в состояние низкого уровня. 4. Выдача младших четырех разрядов на четыре линии данных. 5. Кратковременный (примерно на 1 мкс) перевод линии Е в состояние высокого уровня, вслед за которым следует возврат в состояние низкого уровня.
Управление ЖК-дисплеем 415 Команды для управления ЖК-модулем HD44780 перечислены в табл. 18.1. Таблица 18.1. Команды для управления ЖК-модулем HD44780 RS D7 D6 D5 D4 D3 D2 D1 DO Команда 0 0 0 0 0 0 0 0 1 Очистка дисплея 0 0 0 0 0 0 0 1 X Установка курсора в начало 0 0 0 0 0 0 1 ID s Направление смещения курсора 0 0 0 0 0 1 D C в Включение/отключение курсора/дисплея 0 0 0 0 1 sc RL X X Смещение курсора/дисплея 0 0 0 1 DL N F X X Параметры интерфейса 0 0 1 A A A A A A Курсор — в память знакогенератора 0 1 A A A A A A A Курсор — на дисплей 1 D D D D D D D D Выдача в ЖК-модуль данных Обозначения в табл. 18.1: • ID — направление смещения: 1 — на позицию вправо; 0 — на позицию влево; • S — тип сдвига: 1 — дисплея; 0 — курсора; • D — включение (1) или отключение (0) дисплея; • С — включение (1) или отключение (0) курсора; • В — включение (1) или отключение (0) мерцания курсора; • SC — смещение (1); • RL — направление смещения: 1 — вправо; 0 — влево; • DL — режим передачи данных: 1 — восьмиразрядный; 0 — четырехразрядный; • N — количество строк дисплея: 1 — две; 0 — одна; • F — размер матрицы символа: 1 — 5x10; 0 — 5x8; • А — разряд адреса; • D — разряд данных. Программа, представленная в листинге 18.1, инициализирует ЖК-модуль на индикацию в двух строках в четырехразрядном режиме, после чего на две секунды отображается строка “Starting...”. Затем в бесконечном цикле с периодом в две се- кунды чередуются слова “Hello” и “World”. Программу LCD. с и соответствующий сценарий компоновки можно найти на прилагаемом к книге компакт-диске в папке Pro j ects\WinAVR\LCD. Листинг 18.1. Программа LCD. с #define F_CPU 3686400 #include <avr/io.h> tinclude <util/delay.h> #define LCDPORT PORTD #define LCDDDR DDRD tdefine LCD_PIN_RS 2 #define LCD_PIN_E 3 tdefine LCD_PIN_D4 4 tdefine LCD PIN D5 5
416 Глава 18. Примеры для компилятора WinAVR Листинг 18.1. Продолжение J ♦define LCD_PIN_D6 ♦define LCD_PIN_D7 6 7 // Команды управления ЖК-дисплеем ♦define LCD_CLEAR ♦define LCD_HOME 0x01 0x02 ♦define LCD_ON 0x0C // Курсор невидим //♦define LCD_ON ♦define LCD_OFF ОхОЕ // Курсор видим 0x08 // Вспомогательные определения #define COMMAND 0 #define DATA 1 #define sbi(sfr, bit) (sfr | = (l«bit)) #de£ine cbi(sfrz bit) (sfr&=~ (l«bit) ) // Выдача байта в контроллер ЖК-модуля void lcd_send(unsigned char type, unsigned char c) { if (type=COMMAND) cbi(LCDPORT, LCD_PIN_RS); // RS=0: последует команда else sbi(LCDPORT, LCD_PIN_RS) ; // RS=1: последуют данные // Передача старшего полубайта if (bit_is_set(с, 7)) sbi(LCDPORT, LCD_PIN_D7); else cbi(LCDPORT, LCD_PIN_D7); if (bit_is_set(c, 6)) sbi(LCDPORT, LCD_PIN_D6); else cbi(LCDPORT, LCD_PIN_D6); if (bit_is_set(c, 5)) sbi(LCDPORT, LCD_PIN_D5); else cbi(LCDPORT, LCD_PIN_D5); if (bit_is_set(c, 4)) sbi(LCDPORT, LCD_PIN_D4); else cbi(LCDPORT, LCD_PIN_D4) ; // Формирование фронта для приема данных sbi(LCDPORT, LCD_PIN_E); cbi(LCDPORT, LCD_PIN_E); I/ Передача младшего полубайта if (bit_is_set(c, 3)) sbi(LCDPORT, LCD_PIN_D7); else cbi(LCDPORT, LCD_PIN_D7) ; if (bit_is_set(c, 2)) sbi(LCDPORT, LCD_PIN_D6); else cbi(LCDPORT, LCD_PIN_D6); if (bit_is_set(c, 1)) sbi(LCDPORT, LCD_PIN_D5); else cbi(LCDPORT, LCD_PIN_D5); if (bit_is_set(c, 0)) sbi(LCDPORT, LCD_PIN_D4); else cbi(LCDPORT, LCD_PIN_D4); // Формирование фронта для приема данных
Управление ЖК-дисплеем 417 Листинг 18.1, Продолжение sbi (LCDPORT, LCD__PIN_E) ; cbi(LCDPORT, LCD_PIN_E); // Ожидание контроллера ЖК-модуля _delay_ms(5); } // Отображение строки символов void lcd_write(char *t) { unsigned char i; for (i=0;i<255;i++) { if (t[i]==O) // Конец строки? return; else lcd_send (DATA, t [ i ]) ; } // Инициализация ЖК-модуля void lcd_init() { // Переключение порта на вывод LCDPORT = 0x00; LCDDDR = OxFF; _delay_ms(50); // Ожидание готовности ЖК-модуля / // Конфигурирование чётырехразрядного режима sbi(LCDPORT, LCD_PIN_D5); cbi(LCDPORT, LCD_PIN_D4); // Активизация четырехразрядного режима sbi(PORTD, LCD_PIN_E); cbi(PORTD, LCD_PIN_E); _delay_ms(5) ; //2 строки, передача по четыре разряда lcd_send(COMMAND, 0x28); lcd_send(COMMAND, LCD_OFF); lcd_send(COMMAND, LCD_CLEAR); lcd_send(COMMAND, 0x06); lcd_send(COMMAND, LCD_ON); } // Функция, реализующая ожидание i секунд void seconds(char i) { unsigned char k; for (;i>0;i—)
418 Глава 18. Примеры для компилятора WinAVR Листинг 18.1. Окончание J for (k=0;k<10;k++) _delay_ms(100); } } // Главная программа int main(void) { lcd_init() ; lcd__write ("Starting..."); while (1) { seconds(2); lcd_send (COMMAND, LCD_CLEAR); lcd_write("Hello"); seconds(2); 1 cd__send (COMMAND, LCD_CLEAR); lcd_write("World") ; } GPS-навигатор В следующем проекте, который мы рассмотрим, реализовано управление GPS- приемником, который обрабатывает GPS-данные и сохраняет их во внешней памяти EEPROM. В качестве микроконтроллера используется ATmega8, а в качестве моду- ля EEPROM — любая микросхема, совместимая с АТ24Схх (в нашем случае выбра- на М24Схх от компании STMicroelectronics). Управление памятью EEPROM осуще- ствляется по интерфейсу 12С. е Техническое описание микросхемы М24Схх можно найти на прилагаемом к книге компакт-диске в папке Datasheets. В нашем примере взаимодействие микроконтроллера с GPS-приемником осу- ществляется по последовательному интерфейсу RS232, соответственно должно быть выбрано GPS-устройство с этим интерфейсом (поддерживающее протокол NMEA). Для согласования уровней используется микросхема МАХ232 от компании MAXIM. е Техническое описание микросхемы МАХ232 можно найти на прилагаемом к книге компакт-диске в папке Datasheets. Схема подключений для управления GPS-навигатором показана на рис. 18.2. Задействованные компоненты: • С1,С6— 100 нФ; • С2-С5—-10 мкФ; • R1,R2 — 4k7; • R3 —330R.
GPS-навигатор 419 ATmega8-P Рис. 18.2. Схема подключений для управления GPS-навигатором GND
420 Глава 18. Примеры для компилятора WinAVR Программа, показанная в листинге 18.2, через заданные промежутки времени (в нашем примере — через 30 секунд) считывает GPS-координаты и сохраняет их в памяти EEPROM. Возможен также ручной режим работы, в котором считывание координат происходит только по нажатию кнопки на выводе 1 порта В. Выбор ре- жима осуществляют переключателем, подключенным к выводу 0 порта В. Для того чтобы смена режима вступила в силу, необходимо выполнить сброс микроконтрол» лера. К выводу 2 порта В подключен светодиод, который сигнализирует о готовности системы коротким световым сигналом. Через несколько секунд после подключения и активизации GPS-приемника светодиод начинает мерцать через заданные проме- жутки времени, сигнализируя об успешном сохранении полученных координат. В добавок ко всему, для управления системой к интерфейсу RS232 может быть подключен ПК, выдающий определенный набор команд, распознаваемых микро- контроллером. Программу GPS . с и соответствующий сценарий компоновки можно найти на прилагаемом к книге компакт-диске в папке Pro j ects\WinAVR\GPS. Листинг 18.2. Программа GPS. с fdefine PROCESSORTACT 3686400 // МГц finclude <avr/io.h> #include <string.h> finclude <stdlib.h> finclude <util/delay.h> finclude "AT24C.H" finclude ”rs232.h” // EEPROM-функции // RS232-функции // Конфигурация выводов // Переключатель для выбора режима работы ♦define MODE_SWITCH_PIN 0 fdefine MODE_SWITCH_P INPORT PINB fdefine MODE_SWITCHJDDR DDRB // Кнопка для сохранения GPS-данных в ручном режиме fdefine SNAPSHOT__KEY_PIN 1 fdefine SNAP SHOT_KEY_P INPORT PINB fdefine SNAPSHOT_KEY_DDR DDRB // Светодиод fdefine STATUS__LED_PIN 2 fdefine STATUS_LED_PINPORT PORTB fdefine STATUS_LED_DDR DDRB // Сохранение в памяти EEPROM fdefine COUNTER__ADDR_L 0x0000 fdefine COUNTER ADDR H 0x0001 // Счетчик (16-разрядный) // GPS-данных в EEPROM
GPS-навигатор 421 Листинг 18.2. Продолжение #define MAX_NUMBER__OF_ENTRIES 650 // Для АТ24С256 - // максимум 650 записей // Вспомогательные макросы #define setbit(Р,BIT) # define clearbit(P,BIT) // Режимы работу # define AUTOMATIC 1 # define MANUAL 2 ( (P) |= (1«(BIT))) ( (P) &= ~(1«(BIT) ) ) // Функции void setDataCounter(int val) { char h, 1; 1 = (char)val; h = (val » 8) ; AT24WriteByte(COUNTER_ADDR_L, 1); AT24WriteByte(COUNTER_ADDR_H, h) ; int getDataCount() { int h f 1; 1 = AT24ReadByte(COUNTER_ADDR_L); h = AT24ReadByte (COUNTER_ADDR_H) ; return ( (h « 8) | 1 ); void increaseDataCount() { int count =0; count = getDataCount(); count++; setDataCounter(count); } void addGPSData( char * longitude, char * latitude, char longitude_pos, char latitude_pos) { char gpsdata[50]; char t[2]; unsigned char i; int count; int offset; if (getDataCount () == MAX_NUMBER_OF__ENTRIES) return; // В памяти EEPROM не осталось места
422 Глава 18. Примеры для компилятора WinAVR Листинг 18.2. Продолжение /* GPS-данные сохраняются в следующем формате: 36000.0000#72000.0000#NE? */ strcpy(gpsdata, longitude); str cat (gpsdata, ”#”); strcat(gpsdata, latitude); strcat(gpsdata, "#") ; t[0] = longitude_pos; t[l] - 0; strcat(gpsdata, t); t[0] = lati tude__pos ; t[l] = 0; strcat(gpsdata, t); strcat(gpsdata, "?"); uart_putstring(’’SAVING: [”) ; uart_j?ut string(gpsdata); uart_putline(”]”); // По какому смещению записывать? // Одна GPS-запись занимает почти 25 байт count = getDataCount(); offset = count * 25; // Первые два байта в памяти содержат // количество GPS-записей, поэтому первая ячейка - // по адресу 0x0003 Offset += 0x0002; for (i=0;i<strlen(gpsdata);i++) < AT24WriteByte(offset+i, gpsdata[i]); } increaseDataCount(); } void getGPSData(int index, char *longitude, char *latitude, char *longitude_jpos, char *latitude_pos) { unsigned int offset; unsigned char i, d, c; // По какому смещению записывать? // —> Одна GPS-запись занимает почти 25 байт offset = index * 25; // Первые два байта в памяти содержат
GPS-навигатор 423 Листинг 18.2, Продолжение // количество GPS-записей, поэтому первая ячейка - // по адресу 0x0003 offset += 0x0002; i=0; d=0; с=0; // Считываем долготу do { с = AT24ReadByte (offset+i) ; if (с »= '#') { longi tude[ d] = c; d++; } } while (c != longitude[d] =0; // Завершаем строку // Считываем широту d = 0; do { с « AT24ReadByte (offset+i) ; if (c ?= '#’) { latitude[d] = c; d++; } i++; } while (c •= '#’); latitude[d] = 0; // Завершаем строку *longitude_pos = AT24ReadByte(offset+i); i++; *latitude_pos = AT24ReadByte (offset+i) ; char positionOfComma(char *buffer, char i) { // Поиск запятой unsigned char position=0; char number=0; while (buffer[position] != 0) { if (buffer[position] == ’,') { number++; // Начинаем с 1 if (number == i)
424 Глава 18. Примеры для компилятора WinAVR return position; } position++; } // He найдена? return 0; } void getValue (unsigned char start, unsigned char end, char *source, char* dest) ( // Вырезаем значение из строки unsigned char i; for (i=start;i<end;i++) dest[i-start] = source[i]; dest[end-start] =0; // завершаем строку } void process6PSInformation(char *buffer) { char longitude[15]; char latitude[15]; char longitude__dir; char latitude_dir; char test[9]; char startComma; char endComma; //strcpy(buffer, "$GPGGA,165642.218,4818.6432,N,01326.2558, E, 1, 06,2.5,411.2,M,,M,475.9,0000*67"); // Проверяем, есть ли полное GPGGA-сообщение strncpy(test, buffer, 6); test[6] =0; if ((strstr(test, "$GPGGA")) && (strstr(buffer, "*"))) { // Считываем координаты и данные // Считываем время UTC //startComma = positionOfComma(buffer, 1); //endComma = positionOfComma(buffer, 2); //getValue(startComma+1, endComma, buffer, time); // Считываем значение широты startComma = positionOfComma(buffer, 2) ; endComma = positionOfComma (buffer, 3) ; getValue(startComma+1, endComma, buffer, latitude); // Считываем сторону горизонта широты startComma = positionOfComma (buffer, 3) ; endComma = positionOfComma(buffer, 4) ;
GPS-навигатор 425 Листинг 18,2, Продолжение W>^№*'-w<c#S»UJ^w«wwo3Ro£w!frS4<3iw^^»yy83>««4<<5w«o««83w^ getValue (startComma+1, endComma, buffer r test) ; latitude__dir = test[O] ; // Считываем значение долготы startComma = positionOfComma(buffer, 4); endComma = positionOfComma(buffer, 5) ; getValue(startComma+1, endComma, buffer, longitude) ; // Считываем сторону горизонта долготы startComma = positionOfComma (buffer, 5) ; endComma = positionOfComma(buffer, 6); getValue(startComma+1, endComma, buffer, test); longitude_dir = test[O]; // Считываем высоту над уровнем моря //startComma = positionOfComma(buffer, 9); //endComma = positionOfComma(buffer, 10); //getValue(startComma+1, endComma, buffer, altitude); /* Вывод через последовательный интерфейс для отладки /* uart_putline(time); uart_putline(latitude); uart_putline(latitude_dir); uart_putline(longitude); uart_putline(longitude_dir); uart_putline(altitude); */ addCPSData(latitude, longitude, latitude__dir, longitude_dir) ; } ) char grabGPSInformation (char *buffer) { // Поиск GPS-данных в бесконечном цикле, который // прерывается при обнаружении одной корректной записи while (1) ( // Считывание строки от GPS uart_getline(buffer); // Проверяем, правильное ли сообщение if (strstr(buffer, "$GPGGA")) return 1; ) } void status(char blinkcount) J
426 Глава 18. Примеры для компилятора WinAVR Листинг 18.2. Продолжение — char i; // Установка состояния светодиода setbit (STATUS__LED__DDR, STATUS_LED_PIN) ; for (i=0;i<blinkcount;i++) { clearbit( STATUSJLEDJPINPORT, STATUS_LED_PIN) ; _delay__ms (100) ; setbit (STATUS__LED__P INPORT, STATUS_LED_PIN) ; _delay__ms (100) ; } void dumpGPSMemory () { volatile unsigned int i,j; volatile unsigned char c; int count; count = getDataCount(); for (i=0;i<count;i++) // Считываем ’’count” записей { for (j=0;j<25;j++) ( c = AT24ReadByte(0x0002 + (unsigned int)(i*(unsigned int)25) + j); if ((c>32) && (c<120)) // Передаются только ASCII-символы uart_j?utchar (c) ; } } void dumpEEPROM() { volatile unsigned int i; volatile unsigned char c; for (i=0;i<1000;i++) { c = AT24ReadByte(i) ; if (c<120) // Передаются только ASCII-символы uart_putchar(c); } // Главная программа int main(void) {
GPS-навигатор 427 Листинг 18.2, Продолжение char buffer[120]; char mode; char skipper; // Инициализация компонентов setup_uart(); // Настройка интерфейса RS232 initAT24(); // Настройка микросхемы АТ24хх EEPROM status(2); // Светодиод мерцает два раза: "Все ОК" uart_putline(”GPS Way Tracker [ready]"); // Проверка, получены ли от ПК управляющие команды skipper = 0; while (skipper<2) // Для этого считываются и проверяются две // полных строки { uart_getline(buffer); skipper++; if (strstr(buffer, "PC")) // Есть слово "PC" в данных? { // Начинаем взаимодействие с ПК uart_putline("ОК"); •// На ПК передается "ОК" status(5); // 5 мерцаний светодиода while (1) { // Считываем команду из ПК uart_getline(buffer); // Какая команда? // Копирование GPS-данных if (strstr(buffer, "DUMP")) { dumpGPSMemory () ; } // Копирование GPS-данных if (strstr(buffer, "DUMP1")) { dumpEEPROMO ; } // Копируем объем GPS-данных if (strstr(buffer, "COUNT")) { itoa(getDataCount(), buffer, 10); uart_putline(buffer); } // Очищаем GPS-данные if (strstr(buffer, "FORMAT")) { setDataCounter(0); int 1; for (1=0;l<1000;1++)
428 Глава 18. Примеры для компилятора WinAVR Листинг 18.2. Продолжение ШШШШШШШШШШКШШЯШШЯЯШЯШЛ AT24WriteByte (1, 0) ; } uart_putline("OK"); } // Перезагрузка GPS-навигатора if (strstr(buffer, "RESET")) { uart_putline("OK"); // Помещаем в стек 0x0000 и переходим // по этому адресу ==> сброс asm ("PUSH 0"); asm ("PUSH 0"); . asm ("RET"); ) ) ) // Определение режима работы // Установка по умолчанию - ручной режим mode = MANUAL; // Автоматическое отслеживание MODE_SWITCH_DDR = 0x00; if (bit_is_set (MODE_SWITCH_PINPORT ,MODE_SWITCH_PIN) ) mode = AUTOMATIC; // Учет дребезга контактов _delay_ms(500); if (mode==AUTOMATIC) uart_putline("AUTOMATIC MODE ON!"); // Обработка режима if (mode=MANUAL) { while (1) { // Ожидаем нажатия кнопки SNAPSHOT_KEY_DDR = 0x00; if (bit_is_set(SNAPSHOT_KEY_PINPORT, SNAPSHOT_KEY_PIN)) { // Ожидаем записи GPS-данных grabGPSInformation(buffer); // Обрабатываем и сохраняем processGPSInformation(buffer); status(2); // Сигнализируем: GPS-данные успешно записаны! ) _delay_ms(500); // Учет дребезга контактов ) )
GPS-навигатор 429 Листинг 18.2. Окончание else if (mode==AUTOMATIC) Л skipper = 0; while (1) { uart__putline(”grabGPSInformation") ; if (grabGPSInformation(buffer)) skipper++; if (skipper=10) { uart_joutline ("processGPSInformation”) ; // Обработка и запись в EEPROM processGPSInformation(buffer); status(2); // Сигнализируем: GPS-данные успешно записаны! skipper = 0; } } ) return 0; j
Глава 19 Примеры для компилятора CodeVisionAVR В этой главе мы рассмотрим два примера, в которых результаты работы про- граммы отображаются на дисплее ЖК-модуля, совместимого с HD44780 от компа- нии Hitachi (см. предыдущую главу). Дисплей — на две строки по 16 символов в каж- дой. В первом случае будем отображать результат аналого-цифрового преобразова- ния, а во втором — результат измерения температуры. Программы рассчитаны на компилятор CodeVisionAVR. Управление аналого-цифровым преобразованием В этом примере мы воспользуемся микроконтроллером ATmega8, который ос- нащен шестиканальным АЦП. Для управления ходом выполнения программы будут задействованы две кнопки: “Старт” на линии 2 порта D (INTO) и “Стоп’ на линии 3 того же порта (INT1). Первая служит для запуска аналого-цифрового преобразова- ния, а вторая — для его останова. Момент нажатия определяется по возникновению запроса на внешнее прерывание 0 или 1. Кроме того, для управления АЦП будет использован ПК, соединенный с микро- контроллером через интерфейс RS232 (UART) и микросхему согласования уровней МАХ232. От ПК могут передаваться управляющие команды в виде цифр от 1 до 9: — выбор рабочего канала АЦП; “7” — начало преобразования; “8” — оди- ночное преобразование; “9” — останов преобразования. Схема соединений для данного примера показана на рис. 19.1. Микроконтрол- лер работает от внутреннего RC-осциллятора на 4 МГц. Ш 8S8S388S :рр|. ЖК-модуль 14 15 te п 19 & to РКМСР РВ1ЮС1А PB&MOSVOC2 PB4MSC PBSSCK PBWKTALVrOSCI РВЖГА12ГО$С2 PDG/RXD РО1ЯХО РОЖГО РО&ИЧП РО4ЖКЛГ0 РО5Я1 PD6JAIN0 PD7MW1 RS232 £ 11 ••Старт” "Стоп- 3 PC2/ADC2 х PC4/ADC4fSDA « РСУАРСбЕО. 13 *5v AVCC AREF Рис. 19.1. Схема соединений для управления аналого-цифровым преобразованием
Управление аналого-цифровым преобразованием 431 е Технические описания ЖК-модуля и микросхемы МАХ232 можно найти на прилагаемом к книге компакт-диске в папке Datasheets. Программа управления АЦП для данного случая представлена в листинге 19.1. Листинг 19.1. ПрограммаADC.с # include <mega8.h> # include <delay.h> #include <stdio.h> # include <lcd.h> #asm .equ __Icd_j3ort=0xl8 ; Порт В - для ЖКИ #endasm // Кнопки # define start 2 # define stop 3 #define ADC_VREF_TYPE 0x00; char lcd_buffer[31]; unsigned int result; unsigned char channel » 1; unsigned char buf; unsigned char off =1; // Обработка прерывания от АЦП interrupt [ADC_INT] void adc_isr(void) { result = ADCW * 5 - ADCW /10; // Получаем мВ printf(’’Result = %dmv ”, result); // Выводим значение в UART printf(’’Channel # %d", channel); // Номер канала putchar(OxOD); // Перевод на новую строку // Записываем в буфер вторые два параметра sprintf(lcd_buffer, "ADC=%4umV channel=%lu”, result, channel); lcd_clear(); // Очищаем дисплей lcd_puts(lcd_buffer); // Отображение результата delayjms(1); if (off = 0) ADCSRA = ObllOlllll; ) // Обработка нажатия кнопки ’’Старт” interrupt [EXT_INT0] void ext_int0__isr (void) { off = 0; ADCSRA = ObllOlllll; // Обработка нажатия кнопки "Стоп" interrupt [EXT_INT1] void ext_intl_isr (void) J
432 Глава 19. Примеры для компилятора CodeVisionAVR Листинг 19.1. Окончание ADCSRA = О; off = 1; } void main (void) < // Инициализация ADCSRA = 0Ы0011111; ADMUX = 0; DDRD = 0x00; PORTD = OxFC; PORTB = 0x00; MCUCR = OxOA; GICR = OxCO; UCSRA = 0x00; UCSRB = 0x18; UCSRC = 0x86; UBRRH = 0x00; UBRRL = OxOC; #asm ("sei”); lcd_init(16); // Инициализация дисплея lcd__gotoxy (010) ; // В начало строки lcd_putsf("Example with ADC"); // Отображаем строку lcd__gotoxy (311) ; // Вторая строка lcd_putsf("and USART."); while(1) { buf = getchar(); // Получаем символ no USART switch (buf) { case case 0x31: case 0x32: case 0x33: 0x34: case 0x35: case 0x36: ADMUX = buf - 0x31; // Выбор канала АЦП channel = buf - 0x30; break; case 0x37: off =0; // Старт преобразования ADCSRA = ObllOlllll; break; case 0x38: ADCSRA = ObllOlllll; // Одиночное преобразование break; case 0x39: ADCSRA =0; // Останов преобразования off = 1; ); } } break; Программу ADC . с можно найти на прилагаемом к книге компакт-диске в папке Pro j ects\ CodeVisionAVR\ADC.
Измерение температуры 433 Измерение температуры В этом примере мы будем отображать на ЖК-дисплее результаты измерения температуры, полученные с помощью датчика LM75 от компании National Semicon- ductor. Этот датчик подключается по интерфейсу 12С. В нашем примере мы восполь- зуемся микроконтроллером AT90S8515, у которого линии SCL соответствует разряд О порта А, а линии SDA — разряд 1 того же порта. При этом на этих линиях исполь- зуются резисторы на 3,3..4,7 кОм, подтянутые к +5 В. е Технические описания датчика LM75 можно найти на прилагаемом к книге компакт-диске в папке Datasheets. Модуль ЖК-дисплея подключается к выводам порта С: РСО — RS; РС1 — RW; РС2 — Е; РС4 — D4; РС5 — D5; РС6 — D6; РС7 — D7. Исходный код программы показан в листинге 19.2. е Программу Тетр. с можно найти на прилагаемом к книге компакт-диске в папке Pro j ect s \ CodeVisionAVR\Temp. Мямнммммимммммммммимммммвмммвмммммннммм1 Листинг 19.2. Программа Temp. с finclude <stdio.h> finclude <delay.h> finclude <lm75.h> // Программы управления LM75 finclude <lcd.h> // Программы управления ЖК-модулем fasm .equ __i2c_jport=0xlb ; Порт А для I2C . equ scl_bit=O ; SCL - РАО .equ sda__bit=l ; SDA - PAI .equ __lcd_port=0xl5 ; Порт С для ЖКИ fendasm char lcd_buffer[31]; void main (void) { char sign; int temp; lcd_init(16) ; i2c_init(); /* Инициализируем LM75 кристалл с адресом 0. Гистерезис - 20°C. Температура отключения при перегреве - 40°C. Активный уровень для выхода O.S. - высокий.*/ Im75_init(0,20,40,1); while (1) { // Считываем температуру LM75 * 10°C из кристалла 0 temp = lm75 temperature 10 (0) ;
434 Глава 19. Примеры для компилятора CodeVisionAVR Листинг 19.2. Окончание ____________ sign = '+'; if (temp < 0) { sign = ’ - ’ ; temp = -temp; }; sprintf (lcd__buf fer, ”t=%c%i.%u\xdfC"t sign, temp/10, temp%10); // Отображаем температуру на дисплее lcd_clear() ; lcd_puts(lcd_buffer); delay__ms (200) ; } j
ЧАСТЬ VII Программные примеры для микроконтроллеров PIC
Глава 20 Примеры для компилятора CCS-PICC В этой главе мы рассмотрим несколько простых примеров, рассчитанных на микроконтроллер PIC16F877 и компилятор CCS-PICC. Учитывайте, что перед ком- пиляцией представленных ниже программ может потребоваться изменить значения временных задержек перед записью исполняемого кода в конечное устройство. Отображение состояния выводов порта В листинге 20.1 представлена программа, которая опрашивает состояние выво- дов порта В (все выводы — входы) и передает соответствующую информацию через приемопередатчик USART по интерфейсу RS232. [Листинг 20.1. Файл BitTest. с finclude <16F877.h> finclude <stdio.h> ffuses HS, NOWDT fuse delay(clock=10000000) fuse rs232 (baud=9600 ,parity=N,xmit=PIN_C6,rcv=PIN__C7, stream=RS232, bits=8) void main() { unsigned char c, bit_mask; //Переменные для счетчика выводов //и битовой маски проверки состояний port_b_jpullups (TRUE) ; //Активизируем внутренние подтягивающие //резисторы для порта В set_tris_b(OxFF); //Все выводы порта В - входы bitjmask » 1; //Начинаем сопоставление с вывода 0 for (с=0; с<8; C++) //Просматриваем 8 разрядов порта В { if (input_b() & bitjaask) //Сопоставляем значение регистра //данных порта В с маской //Если в разряде, заданном маской, установлена лог. 1,... printf(”Bit %d is high.\n", (int)с); else //Если в разряде, заданном маской, установлен лог. 0,... printffBit %d is low.\n”, (int) с) ; bit__mask «= 1; //Сдвигаем 1 в маске влево для проверки //состояния следующего разряда } while(1); //Бесконечная задержка }
Управление частотой мерцания светодиодов с помощью различных таймеров 437 еФайл этого примера BitTest.c находится на прилагаемом к книге компакт-диске в папке Projects\CCS-PICC\BitTest. Управление частотой мерцания светодиодов с помощью различных таймеров К выводам 0-2 порта D подключены светодиоды. Частотой мерцания светодио- да на выводе 0 управляет TMR0, светодиода на выводе 1 — TMR1, а светодиода на выводе 2 — управляет TMR2. Реализация программы — в листинге 20.2. Листинг 20.2. Файл BlnkCtrl. с #include <16F877.h> #fuses HS, WDT #use delay(clock=10000000) int cO, cl, c2; //Переменные, используемые для замедления мерцания #int_timerO //Обработчик прерывания при переполнении TMR0 void timerO_isr(void) { if (c0++ & 8) //Увеличиваем cO, и если 3-й разряд = 1,... output_bit(PIN_D0, 1); //включаем светодиод на выводе 0 else output_bit(PIN-DO, 0); //иначе выключаем светодиод на выводе 0 } #int_timerl //Обработчик прерывания при переполнении TMR1 void timerl_isr (void) { if (cl++ & 8) //Увеличиваем cl, и если 3-й разряд = 1,... output_bit(PIN_D1, 1); //включаем светодиод на выводе 1 else output—bit(PIN—D1, 0); //иначе выключаем светодиод на выводе 1 } #int—timer2 //Обработчик прерывания при переполнении TMR2 void timer2—isr(void) { if (c2++ & 8) //Увеличиваем c2, и если 3-й разряд = 1,... output—bit(PIN—D2, 1); //включаем светодиод на выводе 2 else output—bit(PIN—D2, 0); //иначе выключаем светодиод на выводе 2 } void main() { /* Инициализируем таймер TMR0 (функция setup_counters также используется для инициализации сторожевого таймера). Первый параметр указывает на тактирование внутренним сигналом, второй задает коэффициент деления частоты. Можно также было бы воспользоваться функцией
438 Глава 20. Примеры для компилятора CCS-PICC Листинг 20.2. Окончание ЯНННмНВНММ setup_timerO(RTCC_INTERNAL | RTCC_DIV_2) */ setup_counters (RTCC_INTERNAL, RTCCJDIV_2) ; //Инициализируем таймер TMR1. Коэффициент деления = 4 setup__timer__l (T1_INTERNAL | T1JDIV_BY_4); /*Инициализируем TMR2. Коэффициент деления = 16; сброс значения счетчика - по 255 импульсу; один сброс перед прерыванием */ setup_timer_2 (T2_DIV_BY_1 б, 255, 1) ; //Разрешаем прерывания при переполнении счетчиков enable_interrupts(int_timerO); enable_interrupts(int_timerl); enable_interrupts(int_timer2); enable_interrupts(global); //Общее разрешение прерываний while(1); //Бесконечный цикл в ожидании прерываний } Файл этого примера BlnkCtrl. с находится на прилагаемом к книге компакт-диске в папке Projects\CCS-PICC\BlnkCtrl. Управление светофорами на перекрестке , Рассмотрим пример использования микроконтроллера PIC16F877 для управле- ния светофорами на перекрестке. Схема подключения светодиодов и кнопок запроса на проход со стороны пешеходов, а также полного останова движения на перекрест- ке представлены в табл. 20.1 (светодиоды и кнопки соединены с микроконтролле- ром через резисторы 1 кОм). Таблица 20.1. Схема подключений для реализации управления перекрестком Направление Подключение Тип Вывод 1 Светодиод “Красный” 4 порта D 1 Светодиод “Желтый” 5 порта D 1 Светодиод “Зеленый” 6 порта D 1 Кнопка Запрос пешехода 0 порта В 2 Светодиод “Красный” 1 порта D 2 Светодиод “Желтый” 2 порта D 2 Светодиод “Зеленый” 3 порта D 2 Кнопка Запрос пешехода 1 порта В — Кнопка Останов движения 2 порта В В данном контексте “направление” означает направление движения по одной из пересекаю- щихся дорог (рис. 20.1), а “запрос пешехода” — нажатие кнопки на пешеходном переходе в на- правлении, пересекающем текущее. Кнопка “Ос- танов движения” может использоваться дорож- ными службами. Реализация программы пред- ставлена в листинге 20.3. Направление 1 Рис. 20.1. Направления на перекрестке
Управление светофорами на перекрестке 439 Листинг 20.3. Файл CrossCtr. с.. finclude <16F877.h> fuse delay(clock=10000000) ffuses HS, WDT fbyte PORTD = 8 //Определяем порты D и В fbyte PINB = 6 //Определяем выводы для подключения светодиодов fbit dirl_red = PORTD.4 fbit dirl_yellow = PORTD.5 fbit dirl_green = PORTD. 6 fbit dir2_red = PORTD.1 fbit dir2__yellow = PORTD.2 fbit dir2_green = PORTD. 3 //Определяем выводы для подключения кнбпок fbit dirl_button = PINB. О fbit dir2_button = PINB.l fbit stop_button = PINB.2 char time_left; ' //Счетчик времени для текущего состояния int current_state; /* Флаг текущего состояния светофоров. Его значение соответствует объявленному ниже перечислимому типу */ char toggle_flag; /* Флаг, определяющий мигание красного сигнала светофора в состоянии "stop” (то есть, при запрете движения через перекресток) */ /* Перечислимый тип, определяющий числовые значения для идентификаторов состояния перекрестка. dir1—moving - в направлении 1 движение разрешено (зеленый свет), в направлении 2 - запрещено (красный свет); dirl_warning - направление 1 сейчас будет перекрыто, на обоих светофорах горит желтый свет; dir2_moving - в направлении 2 движение разрешено (зеленый свет), в направлении 1 - запрещено (красный свет); dir2_warning - направление 2 сейчас будет перекрыто, на обоих светофорах горит желтый свет; stop - в обоих направлениях движение запрещено, мигает красный свет */ enum { di г 1—moving, dir l__warning, dir2_moving, dir2_warning, stop} ; void main() { port_b__pullups (TRUE) ; //Активизируем внутренние подтягивающие //резисторы для порта В set_tris_b(OxFF) ; //Все выводы порта В - входы set_tris_d(0x00); //Все выводы порта D - выходы current__state = dir2_warning; //Стартовое состояние - желтый //свет в обоих направлениях при разрешенном втором while(1) //Бесконечный цикл, в котором состояние опрашивается { //через каждую секунду
440 Глава 20. Примеры для компилятора CCS-PICC Листинг 20,3. Продолжение _________ delay_ms(1000); //Задержка на 1 с switch(curгent_state) //Опрос текущего состояния { //Если разрешено движение в направлении 1 case dirl_moving: dirl_red = 1; dirl_yellow = 1; dirl__green =0; //Зеленый свет для 1 dir2_red =0; //Красный свет для 2 dir2_yellow =1; dir2__green = 1; //Если нажата кнопка пешеходом или "стоп" if (dirl__button | | stop_button) { //сокращает остаток времени до 10 сч if (time_left > 10) time_left = 10; ) if (time_left ?= 0) //Если время еще не { //истеклб, уменьшаем —time__left; //счетчик на 1 с continue; //Переходим в начало цикла } time_left =5; //Если время истекло, даем // еще 5 с для желтого света //Включаем желтый предупреждающий сигнал curren t__state = dirl_warning; break; //Если разрешено движение в направлении 1, но уже включен //желтый предупреждающий сигнал case dirl_warning: dirl_red =1; dirl_yellow =0; //Желтый свет для 1 dirl__green = 1; dir2__red =0; //Для 2 - красный + dir2__yellow =0; //желтый свет dir2__green = 1; if (time__left •= 0) //Если время еще не { //истекло, уменьшаем —time__left; //счетчик на 1с continue; //Переходим в начало цикла } //Если время желтого света истекло,... if (stop_button) //Если нажато ’’стоп”, //переходим в режим закрытия перекрестка currentestate = blink; else { //Иначе, разрешаем на 30 с движение в //направлении 2 time_left = 30; current_state = dir2_moving ; } break; //Если разрешено движение в направлении 2
Управление светофорами на перекрестке 441 Листинг 20.3. Продолжение case dir2_moving: dirl__red = 0; dirl_yellow =1; dirl_green =1; dir2_red = 1; dir2_yellow «= 1; dir2__green =0; if (dir2_button | | stop_button) { if (time_left > 10) time_left = 10; } if (time__left != 0) { —time_left; continue; } time_left = 5; current_state = dir 2_warning; break; //Если разрешено движение в направлении 2Г но уже включен //желтый предупреждающий сигнал case dir2_warning: dirl__red =0; dirl__yellow =0; dirl_green =1; dir2_red = 1; dir2_yellow = 0; dir2__green = 1; if (time_left ?= 0) { —time__left; continue; } if (stop_button) current__state = blink; else { time_left = 30; current^ tate ® dirl_moving; break; //Если активен запрет на движение через перекресток case blink: dirl__yellow » 1; //На обоих светофорах dirl__green =1; //отключены зеленый и желтый dir2_yellow » 1; //сигналы dir2_green =1; toggle_flag А= 1; //Переключаем состояние //красного сигнала на противоположное if (toggle_jflag & 1) //Если флаг - 1,... { dirl_red =1; //красный сигнал горит dir2 red =0;
442 Глава 20. Примеры для компилятора CCS-PICC Листинг 20.3, Окончание _ - else { dirl__red =0; //иначе, красный сигнал гаснет dir2__red = 1; } //Если кнопка ’’стоп” отпущена, переходим в //рабочий режим if (!stop_button) current_state = dirl_warning ; break; //Состояние по умолчанию - dir2_warning default: currentestate = dir 2__warning; break; } } } ©Файл этого примера CrossCtr.c находится на прилагаемом к книге компакт-диске в папке Projects\CCS-PICC\CrossCtr. Обмен данными в режиме PSP Реализуем обмен данными между двумя микроконтроллерами PIC, один из ко- торых (главный) работает в режиме PSP порта D, а второй (внешний) принимает и передает данные через порт С. Три вывода порта Е обоих микроконтроллеров служат для обмена управляющими сигналами: RD — вывод 0, WR — вывод 1, CS — вывод 2. Главный микроконтроллер передает внешнему данные, принятые через порт В, а данные, принятые от внешнего, отображает с помощью светодиодов, подключен- ных к порту С. При этом обмен данными осуществляется по соответствующему за- просу на прерывание. Программа для главного микроконтроллера представлена в листинге 20.4. Внешний микроконтроллер постоянно считывает данные из главного микро- контроллера, а затем “эхом” отправляет их обратно. Программа для внешнего мик- роконтроллера представлена в листинге 20.5. е Файлы этого примера PSF_1. с и PSP_2. с находится на прилагаемом к книге компакт-диске в папке Projects\CCS-PICC\PSP. Листи“20 4 “| #include <16F877.h> fuse delay(clock=10000000) ffuses HS, NOWDT #byte TRISE » 0x89 //Определяем регистр TRISE #int_PSP //Обработчик прерывания от PSP PSP_isr() {
Обмен данными в режиме PSP Листинг 20.4. Окончание if (TRISE & 0x80) output_C(~input_D()); //Если запись в порт PSP (флаг IBF=1), //то выводим данные, принятые через //порт D, в порт С (на светодиоды) else //Если вывод через порт PSP, output_D (input__B ()) ; //то выводим через порт D данные порта В } void main () { рогt_b_pullups(TRUE); //Активизируем внутренние подтягивающие //резисторы для порта В setup_adc_ports(NO_ANALOGS); //Выводы порта Е не должны //использоваться в качестве аналоговых setup_psp(PSP_ENABLED) ; //Активизируем режим PSP enable_interrupts(INT_PSP); //Разрешаем прерывание от PSP enable_interrupts(global); //Общее разрешение прерываний while(1); //Бесконечный цикл в ожидании прерывания от PSP 2____________________________________________________________________ Листинг 20.5. Файл PSPJ2 . с #include <16F877.h> fuse delay(clock=10000000) ifuses HS, WDT //Будет использоваться сторожевой таймер int с; void main () setup_adc_jports (NO_ANALOGS) ; //Выводы порта E не должны //использоваться в качестве аналоговых setup_counters (RTCC_INTERNAL, WDTJ72MS) ; //Сброс от // сторожевого таймера через каждые 72 мс outputJE (0x7); //CS=1, RD=1, WR=1 while(1) { restart_wdt(); //Сбрасываем счетчик сторожевого таймера output_E(2); //CS=0, RD=0, WR=1 - запрос главному //микроконтроллеру на чтение данных с « input_c(); //Считываем данные от главного //микроконтроллера через порт С в переменную с output_E(7); //CS=1, RD=1, WR=1 delay_us(50); //Задержка 50 мкс между операциями PSP output__C(с) ; //Передаем данные главному микроконтроллеру output_E(l); //CS=0, RD=1, WR=0 - запрос главному //микроконтроллеру на запись данных output_E(7); //CS=1, RD=1, WR=1 delay__us(50) ; //Задержка 50 мкс между операциями PSP }
444 Глава 20. Примеры для компилятора CCS-PICC Контроль предельной скорости вращения двигателя Таймер TMR1 работает в режиме захвата на входе. На вход ССР1 (например, вывод 2 порта С) подается сигнал от тахометра, измеряющего скорость вращения двигателя. Если период следования импульсов становится меньше 1 мс, то это гово- рит о слишком высокой скорости вращения двигателя, а включается светодиод, подключенный к выводу 0 порта D. При измерении периода следования импульсов от тахометра следует учитывать возможность возникновения переполнения счетчика, поэтому в программе реализу- ем подсчет переполнений, а фактическое количество тактовых импульсов таймера будем вычислять по формуле: N — NOverflows * 0x10000 — Nstart + Nend, где Noverfiows — количество переполнений; Nstart — количество тактовых импульсов, принятых на начало периода; Ne„d — количество тактовых импульсов, принятых на конец периода. При рабочей частоте микроконтроллера 10 МГц и коэффициенте деления 1 за одну секунду счетчик подсчитывает 10 000 импульсов, поэтому будем сопоставлять полученную величину периода именно с этим значением. Реализация этого алгоритма представлена в листинге 20.6. еФайл этого примера SpeedCtr. с находится на прилагаемом к книге компакт-диске в папке Projects\CCS-PICC\SpeedCtr. ... . ||||| |Т!Г,— #include <16F877.h> fuse delay(clock=10000000) ffuses HS, NOWDT int N_overflows; unsigned long int N_start, N_end; long int N; #int_timerl //Обработка прерывания при переполнении TMR1 timer l_isr () { ++N__overflows; //Увеличиваем счетчик переполнений } #int_CCPl //Обработка прерывания при захвате на входе CCPl_isr() { N_end = ССР_1; //Количество тактовых импульсов, подсчитанных //с момента поступления предыдущего импульса на входе ССР1 //Вычисляем период между двумя последовательными импульсами ССР1 N = (N_overflows * 0x10000) - N__start + N_end; if (N < 10000) //Если период меньше 10000 импульсов, то... output_low(PIN_D0); //загорается сигнальная лампочка else output_high(PIN_D0); //Иначе лампочка гаснет N start = N end; //Запоминаем позицию текущего замера
Контроль предельной скорости вращения двигателя 445 — ------------—— -...| N__overflows = 0; //Сбрасываем счетчик переполнений } void main () { setup_ccpl (CCP_CAPTURE_RE) ; //Захват по нарастающему фронту //Инициализируем TMR1: тактируется от внутреннего осциллятора, //без предварительного деления частоты setup_timer_l (T1_INTERNAL | T1__DIV_BY_1) ; //Разрешаем прерывание при переполнении TMR1 enable_interrupts (INT_TIMER1) ; //Разрешаем прерывание при захвате на входе enable__interrupts (INT_CCP1) ; enable_interrupts(global); //Общее разрешение прерываний while(1); //Бесконечный цикл в ожидании сигнала на входе ССР1 j
Глава 21 Примеры для компилятора mikroC В этой главе мы рассмотрим три примера, рассчитанных на микроконтроллер PIC18F452 и компилятор mikroC. Игральные “кости” В этом примере одна игральная “кость” реализуется с помощью семи светодио- дов, расположенных в соответствии с размещением точек на гранях реальной кости (рис. 21.1). О о о о о о • • • • • • о • о • о • • • • ООО о • о • о • о о о о о о • • • • • • 1 2 3 4 5 6 Рис. 21.1. Схема размещения семи светодиодов для имитации игральной кости (черной точке соответствует включенный светодиод) Рис. 21.2. Схема подключения светодиодов и кнопки При запуске системы все светодиоды обеих “костей” отключены. По нажатию кнопки микроконтроллер генерирует два случайных числа от 1 до 6 для каждой из “костей”, которые отображаются с помощью соответствующей группы светодиодов в течение трех секунд. По истечении трех секунд все светодиоды опять гаснут. Схема соединений для данного примера показана на рис. 21.2. Можно было бы подключить 14 светодиодов к 14 выводам двух портов, однако для экономии выводов мы сгруппируем светодиоды на одном порту С, линии которого работают в режиме потреб- ления тока через ограничительные ре- зисторы на 100 Ом и 290 Ом. Кнопка для “бросания костей” подключена к выводу 0 порта В с использованием подтягивающего резистора. Для того чтобы понять принцип группирования светодиодов, рассмот- рим, какие из них должны включаться для каждого числа от 1 до 6 на одной “кости”: • 1—D4; • 2 — D2, D6; • 3 — D2, D4, D6; • 4 — D1,D3,D5,D7;
Игральные “кости" 447 • 5 — D1,D3,D4,D5,D7; • 6 — D1,D2,D3,D5,D6,D7. Отсюда следует, то светодиод D4 — единственный, который может включаться отдельно, а значит группировать его с другими светодиодами нельзя. Три пары све- тодиодов всегда включаются одновременно: D1 и D3; D2 и D6; D5 и D7, — а значит их можно включить последовательно через резистор на 100 Ом. В результате полу- чается, что для управления семью светодиодами одной “кости” требуется четыре линии, а значит мы можем управлять обеими “костями” с помощью одного восьми- разрядного порта. В нашем примере первой “кости” соответствуют выводы RC0- RC3, а второй — линии RC4-RC7. Двоичные шаблоны, выводимые в линии порта С в зависимости от числа, вы- павшего на одной из двух “костей”, представлены в табл. 21.1. Таблица 21.1. Двоичные шаблоны, выводимые в линии порта С Число RC3/RC7 RC2/RC6 RC1/RC5 RC0/RC4 В шестнадцатеричном виде 1 1 0 0 0 8 2 0 0 0 1 1 3 1 0 0 1 9 4 0 1 1 0 6 5 1 1 1 0 Е 6 0 1 1 1 7 Программа, реализующая “бросание костей”, показана в листинге 21.1. еФайл этого примера Dice . с находится на прилагаемом к книге компакт-диске в папке Pro- jects \mi kr оС\Dice. Т;----.............. Г-'.’..- Листинг 21.1. Программа Dice, с fdefine Switch PORTB.FO // Кнопка fdefinejPressed 0 // Если нажата, RBO = 0 // Функция, генерирующая псведослучайное число от 1 до Lim unsigned char Number(int Lim, int Y) { static unsigned int Y; Y = (Y * 32719 + 3) % 32749; return ((Y % Lim) + 1); } void main() { unsigned chai? LED1, LED2, Seed = 1; // Определяем массив с числами, соответствующими граням "кости" unsigned char Dice[] = {0,0x8,0x1,0x9,0x6,ОхЕ,0x7}; TRISC = 0; TRISB = 1; PORTC = 0; // Выводы порта С - выходы // RBO - вход // Выключаем все светодиоды
448 Глава 21. Примеры для компилятора mikroC Листинг 21.1. Окончание ll!l 111 while(1) // Бесконечный цикл { if(Switch == Pressed) // Кнопка нажата? { LED1 = Dice[Number(6 , seed)]; // Получаем шаблон для кости 1 LED2 = Dice[Number(6, seed)]; // Получаем шаблон для кости 2 PORTC = 16*LED2 + LED1 // Включаем светодиоды костей Delay_ms(3000); // Задержка на 3 секунды PORTC = 0; // Отключаем светодиоды } } } Вольтметр с ЖК-дисплеем В этом примере мы разработаем вольтметр, измеряющий напряжения в диапа- зоне 0..5 В, с индикацией результата на ЖК-дисплее. Измеряемое напряжение пода- ется на один из аналоговых входов микроконтроллера PIC18F452, а результат ана- лого-цифрового преобразования отображается с помощью ЖК-модуля, совместимо- го с HD44780 от компании Hitachi (см. главу 18). Модуль индикации подключается к выводам порта С и работает в четырехразрядном режиме. Схема соединений для данного примера показана на рис. 21.3. Рис. 21.3. Схема вольтметра с индикацией напряжения на ЖК-дисплее Программа, реализующая вольтметр, показана в листинге 21.2. Файл этого примера Vo It mt г . с находится на прилагаемом к книге компакт-диске в папке Proj ects\mikroC\Voltmtr.
Вольтметр с ЖК-дисплеем 449 Листинг 21,2. Программа Voltmtr. с void main() { unsigned long Vin, mV, Vdec, Vfrac; unsigned char op[12]; unsigned char i, j, led[5], chi, ch2; TRISC = 0; TRISA = OxFF; // Выводы порта С - выходы // Выводы порта А - входы // Конфигурируем ЖК-модуль Lcd_Init(&PORTC); // Подключен к порту с Lcd_Cmd(LCD_CLEAR); // Очищаем дисплей Lcd_Out(l, 1, "VOLTMETER"); // Выводим строку Delay_ms(2000); // Задержка на 2 секунды // Конфигурируем АЦП: канал ANO, Vref= +5 В ADCON1 = 0x80; while(1) { Lcd_Cmd(LCD_CLEAR) ; Vin = Adc_Read(0) * 488; Vdec = Vin / 100; Vfrac = Vin % 100; LongToStr(Vdec, op) // Очищаем дисплей // Напряжение на выводе ANO // Целая часть // Дробная часть // Преобразуем Vdec в строку // Удаляем лишние пробелы j = 0; for(i=0; i<=ll; i++) { if(op[i] ?= • ’) { lcd[j] = op[i]; } } // Выводим результат на ЖКИ Lcd_Out(l, 1, "mV = ") ; Lcd_Out(l, 6, led); Lcd_Out_Cp(". ") ; chi = Vfrac /10; // Формируем дробную часть ch2 = Vfrac % 10; Lcd_Chr_Cp(48 + chi); // Отображаем дробную часть Lcd_Chr__Cp(48 + ch2); // ’O’ + ... Delay_ms(1000); // Задержка 1 секунда ) } Поскольку АЦП микроконтроллера PIC18F452 — 10-разряДный, опорное на- пряжение 5 В можно разделить максимум на 1024 шагов дискретизации. Таким об-
450 Глава 21. Примеры для компилятора mikroC разом, каждый шаг соответствует 4,88 мВ. Именно поэтому переменная vin, полу- ченная в результате опроса вывода AN0, умножается на 488, а затем целочисленно делится на 100 для получения целой и дробной частей значения в милливольтах. Калькулятор В этом примере мы разработаем простой калькулятор на основе клавиатурной матрицы 4x4 и ЖК-модуля, совместимого с HD44780 от компании Hitachi (см. главу 18). Клавиатура будет подключена к выводам порта В, а ЖК-модуль — к выводам порта С (рис. 21.4). A+5V 11 32 ххф wkU Vdd и—4..1 MCLR 1—I PIC 4- 18F452 RB4 8О rb5 ENTER П ~с=иф Т RC21Z- RC3& RC4&. RC5& RC6& RC7&. Vss 31 LCD Л VDD VEE 4 X 11 1£ 11 11 RS Е D4 D5 D6 D7 VSS R/W 1 5 9 2 3 4 6 0 7 х £ RBO RB1 RB2 5^ явз OSC1 - 13 OSC2 14 4MHX Рис. 21.4. Схема калькулятора с ЖК-индикацией Алгоритм работы калькулятора следующий. 1. В первой строке дисплея отображается “Nol: ”. 2. Пользователь вводит с помощью клавиатуры первое число и нажимает клавишу “Enter”. 3. Во второй строке дисплея отображается: “No2: ”. 4. Пользователь вводит с помощью клавиатуры второе число и нажимает клавишу “Enter”. 5. Дисплей очищается, и в первой строке отображается: “Ор: ”. 6. Пользователь нажимает клавишу, соответствующую требуемой операции. 7. Дисплей очищается, и в первой строке выводится результат операции в течение пяти секунд, после чего дисплей очищается, и процесс повторяется с начала.
Калькулятор 451 Нажатие той или иной клавиши будем определять по ее порядковому номеру от О до 15 по следующей схеме: 0 — “1”; 1 — “2”; 2 — “3”; 3 — “4”; 4 — “5”; 5 — “6”; 6 — “7”; 7 — “8”; 8 — “9”; 9 — “0”; 10 — “ 11 — “Enter”; 12 — 13 — 14 — “х”; 15 — “Р\ Программа, реализующая калькулятор, показана в листинге 21.3. еФайл этого примера Calc. с находится на прилагаемом к книге компакт-диске в папке Рго- j ects\mikroC\Calc. Листинг 21.3. Программа Calc, с // Определяем номера управляющих клавиш #define Enter 12 #define Plus 13 #define Minus 14 #define Multiply 15 #define Divide 16 void main() { unsigned char Key, i, j, lcd[5], op[12]; unsigned long Calc, Opl, Op2; TRISC =0; // Выводы порта С - выходы Lcd_Init(&PORTC); // ЖК-модуль подключен к порту С Lcd_Cmd (LCD—CLEAR) ; // Очищаем дисплей Led—Out(1/ 1, "CALCULATOR"); // Выводим строку Delay_ms(2000); // Задержка 2 секунды Lcd_Cmd(LCD_CLEAR); // Очищаем дисплей Keypad—Init(&PORTB); // Клавиатура подключена к порту В while(1) { Key = 0; Opl = 0; Ор2 = 0; Led—Out(l, 1, "Nol: "); // Ввод 1-го числа whiled) { do Key = Keypad_Released();// Считываем номер нажатой клавиши while(!Key); // Пока клавиша не нажата, ожидаем if(Key == Enter) break; // Если нажато "Enter", то выход if(Key == 10) Key = 0; // Если нажат пробел, считаем за "1" Lcd_Chг_Ср(Key + ’О’); // Выводим число Opl = 10*Opl + Key; // Получаем первый операнд } Led—Out(2, 1, "No2: "); // Ввод 2-го числа while(1) {
452 Глава 21. Примеры для компилятора mikroC do Key = KeypadReleased(); while(!Key); if(Key == Enter) break; if(Key = 10) Key = 0; Lcd__Chr__Cp (Key + ’O’); Ор2 = 10*0р2 + Key; } // Получаем второй операнд Lcd_Cmd(LCD_CLEAR); // Очищаем дисплей Lcd_Out(1, 1,"Op: ”); // Ввод операции do Key = Keypad—Released() ; while (? Key); Lcd-Cmd (LCD-CLEAR) ; // Очищаем дисплей Led—Out(1, 1, ”Res=”); switch(Key) { // Вывод результата ease Plus: Calc = Opl + Op2; break; // Сложение case Minus: Calc = Opl - Op2; break; // Вычитание case Multiply: Calc = dpi * Op2; break; // Умножение case Divide: Calc = Opl / Qp2; break; ) // Деление LongToStr(Calc, op); // Преобразовываем // результат в строку // Удаляем лишние пробелы j = 0; for(i=0; i<=ll; i++) { if(op[i] •= ’ ’) { lcd[j]=op[i] ; } } Led—Out—Cp(led); Delay—ms(5000); Led—Cmd (LCD-CLEAR) ; // Выводим результат // Задержка 5 секунд // Очищаем дисплей
Глава 22 Примеры для компилятора СЗО В этой главе мы рассмотрим три примера, рассчитанных на компилятор СЗО и микроконтроллер PIC24FJ128GA010. Использование порта РМР Цель данного проект — изучить ведущий параллельный порт (РМР) — новый, гибкий интерфейс микроконтроллеров PIC24. В данном случае к РМР будет под- ключен ЖК-модуль, совместимый с HD44780 от компании Hitachi (см. главу 18). Ключевые функции порта РМР, требуемые для организации взаимодействия с ЖК-модулем: • активизация порта РМР; • выбор полностью демультиплексированного интерфейса (использование раз- дельных линий данных и адреса); • активизация разрешения сигнала стробирования (RD4); • разрешение сигнала чтения (RD5); • активизация высокого активного уровня стробирующих импульсов; • установка высокого активного уровня сигнала чтения и низкого активного уровня сигнала записи; • активизация режима ведущего устройства с сигналами чтения и записи на од- ном выводе (RD5); • использование восьмиразрядной шины (выводы порта Е); • требуется только один разряд адреса, поэтому мы остановимся на минимальной конфигурации, состоящей из разрядов РМАО (RB15) и РМА1. Кроме того, необходимо учитывать, что типичный ЖК-модуль — это чрезвы- чайно медленнодействующее устройство. По этой причине мы выберем наиболее щадящий временной график, добавим максимально возможное число циклов ожи- дания на каждом этапе процесса чтения или записи: • 4 х Тсу — время ожидания установки данных перед чтением/записью; • 15 х Тсу — время ожидания между сигналами R/W и Е; • 4 х Тсу — время ожидания установки данных после включения интерфейса. Небольшая библиотека функций для доступа кЖК-модулю Для начала разработаем подпрограмму инициализации ЖК-индикатора. Вполне естественно, она начнется с инициализации управляющих регистров порта РМР: void LCDinit( void) {
454 Глава 22. Примеры для компилятора СЗО // Инициализация РМР PMCON = 0x83BF; // Активизируем РМР, длинные периоды ожидания PMMODE = 0x3FF; // Режим ведущего 1 PMPEN = 0x0001; // Активизируем РМАО Теперь мы в состоянии обмениваться данными с ЖК-модулем, а значит сможем выполнить стандартную процедуру инициализации ЖК-дисплея, рекомендованную производителем. Эта процедура должна протекать в строго определенных времен- ных рамках и начинаться как минимум через 30 мс, необходимых ЖК-модулю для собственной внутренней инициализации (сброс по подаче питания). Для простоты и надежности мы жестко закодируем задержку в функции инициализации ЖК- модуля, а Для создания простых и точных временных циклов на всех последующих этапов воспользуемся таймером Timerl: // Инициализируем TMR1 T1CON = 0x8030; // Fosc/2, предделитель 1:256, 16 мкс/импульс // Выжидаем 30 мс TMR1 = 0; while(TMR1 < 2000); // 2000 х 16 мкс = 32 мс Для удобства мы также определим пару констант, чтобы сделать код более чи- табельным: #define #define #define LCDDATA LCDCMD PMDATA 1 0 PMDIN1 // RS = 1 ; доступ к регистру данных // RS = 0 ; доступ к регистру команд // Буфер данных РМР Для передачи каждой команды в ЖК-модуль вначале выбирают регистр команд (установка адреса РМАО = RS = 0), после чего начинается процедура записи через порт РМР путем размещения байта требуемой команды в выходном буфере данных РМР: PMADDR = LCDCMD; // Выбираем регистр команд (ADDR = 0) PMDATA = ObOOlllOOO; // Установка функции: 8-разрядный // интерфейс, две линии, 5x7 Порт РМР выполнит следующую полную процедуру записи в шину. 1. Адрес выставляет на шину адреса РМР (РМАО). 2. Содержимое регистра PMDATA выставляется на шину данных РМР (PMD0- PMD7). 3. По прошествии времени 4 х Тсу сигнал R/W стабилизируется на низком уровне (RD5). 4. По прошествии времени 15 х Тсу сигнал Е стабилизируется на высоком уровне (RD4). 5. По прошествии времени 4 х Тсу уровень сигнала Е понижается, и содержимое регистра PMDATA удаляется из шины. Как видим, процедура получается довольно длинной, поскольку длится более 20 х Тсу = 1,25 мкс. Другими словами, порт РМР все еще будет выполнять ее в то время, как микроконтроллер PIC24 уже выполнит не менее 20 команд. Впрочем, на этот раз нам не стоит беспокоиться о времени, необходимом порту РМР, поскольку мы все равно собирались выждать не менее 40 мкс, чтобы дать ЖК-модулю воз- можность выполнить команду:
Использование порта РМР 455 TMR1 = 0; while(TMR1 < 3) ; //3x16 мкс = 4 8 мкс Затем мы аналогичным образом пройдем остальные этапы процедуры инициа- лизации ЖК-модуля: PMDATA = ObOOOOllOO; // Включаем индикацию, скрываем // курсор, отключаем мерцание TMR1 = 0; while(TMR1 < 3) ; // 3 х 16 мкс = 4 8 мкс PMDATA = 0Ь00000001; // Очищаем дисплей TMR1 = 0; while(TMRl < 100); // 100 х 16 мкс = 1,6 мс PMDATA = ОЬОООООНО; // Смещаем курсор без сдвига индикации TMR1 = 0; while (TMR1 < 100); // 100 х 16 мкс = 1,6 мс После инициализации ЖК-модуля все немного упрощается, поскольку отпадает необходимость в циклах задержки, благодаря возможности использовать команду ЖК-модуля “Чтение флага занятости”. С ее помощью мы узнаем, что встроенный контроллер ЖК-модуля завершил выполнение последней команды и готов принять и обработать новую. Для того чтобы прочитать регистр состояния ЖК-индикатора, содержащий флаг занятости, необходимо, чтобы порт РМР выполнил процедуру чтения шины. Этот процесс протекает в два этапа. Вначале считывается (и игнори- руется) содержимое буфера данных РМР, чтобы начать процесс чтения. По завер- шении процедуры чтения в буфере данных окажется фактическое значение, прочи- танное из шины, и оно опять считывается из буфера данных РМР. Но как опреде- лить, что порт РМР завершил процедуру чтения? Очень просто. Мы можем прове- рить флаг занятости в управляющем регистре PMSTAT. Итак, для того чтобы проверить флаг занятости ЖК-модуля, необходимо внача- ле проверить флаг занятости порта РМР, выдать команду чтения, опять проверить флаг занятости порта РМР и, наконец, получить доступ к фактическому содержи- мому регистра состояния ЖК-модуля. Передав в функцию чтения в качестве параметра адрес регистра, мы получим более обобщенную подпрограмму, способную прочитать, как регистр состояния ЖК-индикатора, так и регистр данных: char LCDread(int addr) { int dummy; while(PMMODEbits.BUSY); // Ожидаем, пока порт РМР завершит // выполнение предыдущей команды PMADDR = addr; // Выбираем адрес команды dummy = PMDATA; // Инициализируем цикл чтения, // считываем фиктивное значение while(PMMODEbits.BUSY); // Ожидаем, пока порт РМР завершит // процедуру return(PMDATA); // Считываем регистр состояния } Регистр состояния ЖК-модуля содержит флаг занятости и текущее значение указателя на оперативную память ЖК-индикатора. Воспользуемся для извлечения этих элементов двумя простыми макросами: LCDbusyO и LCDaddr(). Еще один макрос задействуем для доступа к регистру данных: fdefine LCDbusyO LCDread(LCDCMD) & 0x80 fdefine LCDaddr() LCDread(LCDCMD) & 0x7F fdefine getLCD() LCDread(LCDDATA)
456 Глава 22. Примеры для компилятора СЗО Для записи данных и команд в ЖК-модуль можно воспользоваться функцией LCDbusy(): void LCDwrite(int addr, char c) { while(LCDbusy()); while(PMMODEbits.BUSY); // Ожидаем освобождения порта РМР PMADDR = addr; PMDATA = c; ) В дополнение к библиотеке напишем еще несколько макросов: • putLCD () — передача ASCII-данных в ЖК-модуль: #define putLCD(d) LCDwrite (LCDDATA, (d)) • LCDcmd () — передача команд в ЖК-модуль: #define LCDcmd(с) LCDwrite(LCDCMD, (c)) • LCDhome () — перемещение курсора к первому символу в строке: #define LCDhome() LCDwrite(LCDCMD, 2) • LCDclr () — очистка всего содержимого дисплея: #define LCDclr() LCDwrite(LCDCMD, 1) И наконец, для удобства создадим функцию puts LCD (), которая будет переда- вать в ЖК-модуль целые строки с завершающим нулевым символом: void putsLCD(char *s) { while(*s) putLCD(*s++); I Запустим все это в работу, добавив короткую функцию main: main( void) { // Инициализация LCDinit() ; // Выводим в первой строке заголовок putsLCD(”Flying the PIC24”); // Главный цикл (пока что пустой) while (1) { } } Расширенное управление ЖК-дисплеем Напомним, что содержимое дисплея формируется контроллером с помощью ге- нератора символов, размещенного в ПЗУ. Набор символов можно расширять с по- мощью дополнительного буфера, известного как CGRAM. Запись в память CGRAM создает новые графические элементы с помощью матрицы размерами 5x7.
Использование порта РМР 457 В качестве примера добавим к набору символов ЖК-дисплея два новых знака. Для этого нам понадобится функция, устанавливающая указатель на первый адрес памяти CGRAM (а еще лучше — макрос, использующий функцию LCDwrite()): «define LCDsetG(a) LCDwrite(LCDCMD, (a & 0x3F) | 0x40) Для формирования двух новых символьных матриц 5x7 мы воспользуемся функцией putLCD (). Пять младших разрядов каждого байта будут выделены для определения одной строки в матрице. После того, как определена последняя строка каждого символа, добавляется еще один (восьмой) байт данных для выравнивания по блоку соседнего символа. // Формируем два новых символа LCDsetG(O); putLCD (ОЬОООЮ) ; putLCD (ОЬОООЮ) ; putLCD(ObOO110); putLCD(Oblllll); putLCD(ObOOllO); putLCD (ОЬОООЮ) ; putLCD (ОЬОООЮ) ; putLCD(0); // Выравнивание putLCD(ObOOOOO); putLCD(ObOOlOO); putLCD(ObOl100); putLCD(OblllOO); putLCD(ObOOOOO); putLCD(ObOOOOO); putLCD(ObOOOOO); putLCD(0); // Выравнивание Теперь два новых символа доступны по кодам 0 и 1 в таблице генератора. Для того чтобы указатель на буфер опять указывал на память DDRAM, воспользуемся следующим макросом: #define LCDsetC(a) LCDwrite(LCDCMD, (a & 0x7F) | 0x80) 1РИМЕЧАНИЕ | Хотя первая строка индикатора соответствует адресам с 0 по Oxf буфера DDRAM, второй строке всегда соответствуют адреса с 0x40 по 0x4 f независимо от размеров дисплея (т е. ^количества символов в каждой его строке). Реализуем перемещение двух новых символов по дисплею. Для этого нам по- требуется простой механизм задержки. Реализуем его с помощью таймера Timerl. ЖК-индикаторы — медленнодействующие, и в том случае, если дисплей обновля- ется слишком быстро, изображение на нем исчезает, подобно призраку. «define TFLY 9000 // 9000 х 16 мкс = 144 мс «define DELAY() TMRl=0; while(TMR1 < TFLY) Настал момент разработать содержимое главного цикла: while(1) { // Символы появляются у правого края LCDsetC(0x40 + 14);
458 Глава 22. Примеры для компилятора СЗО putLCD(0); putLCD(l); DELAY () ; // Перемещение справа налево for(i=13; i>=0; i—) { LCDsetC(0x40 4- i) ; // Устанавливаем курсор в следующую // позицию putLCD(O); putLCD(1); // Новые символы putLCD(1 '); // Очищаем предыдущий символ DELAY () ; } // Первый символ исчезает за левым краем. Видим только второй LCDsetC(0x40); putLCD(1); putLCD(' •); DELAY (); // Удаляем второй символ LCDsetC(0x40); // Указатель на левый край второй строки putLCD(’ 1); // Рисуем только первый символ, появляющийся справа LCDsetC(0x40 + 15); // Указатель на правый край второй строки putLCD(0); DELAY () ; Полностью исходный код рассмотренной программы (без комментариев) пока- зан в листинге 22.1 HO® Файл этого примера РМР. с находится на прилагаемом к книге компакт-диске в папке Рг о- jects\mikroC\PMP. Листинг 22.1. Программа РМР. с - finclude <p24fj128ga010.h> #define LCDDATA 1 #define LCDCMD 0 #define PMDATA PMDIN1 #define LCDbusy() LCDread(LCDCMD) & 0x80 #define LCDaddr() LCDread(LCDCMD) & 0x7F #define getLCD() LCDread(LCDDATA) #define putLCD(d) LCDwrite(LCDDATA, (d)) #define LCDcmd(c) LCDwrite(LCDCMD, (c)) #define LCDhome() LCDwrite(LCDCMD, 2) #define LCDclr() LCDwrite(LCDCMD, 1) #define LCDsetG(a) LCDwrite(LCDCMD, (a & 0x3F) | 0x40) #define LCDsetC(a) LCDwrite(LCDCMD, (a & 0x7F) | 0x80) #define TFLY 9000 #define DELAY() TMRl=0; while (TMRKTFLY)
Использование порта РМР 459 Листинг 22.1. Продолжение void LCDinit(void) { PMCON = 0x83BF; PMMODE = 0x3FF; PMPEN = 0x0001; T1CON = 0x8030; TMR1 = 0; while (TMRK2000) ; PMADDR = LCDCMD; PMDATA = ObOOl11000; TMR1 = 0; while(TMR1<3); PMDATA = ObOOOOllOO; TMR1 = 0; while(TMR1<3); PMDATA = ObOOOOOOOl; TMR1 = 0; while (TMRK100) ; PMDATA = ObOOOOOllO; TMR1 = 0; while (TMRK100) ; char LCDreadfint addr) { int dummy; while(PMMODEbits.BUSY) ; PMADDR = addr; dummy = PMDATA; while(PMMODEbits.BUSY); return(PMDATA); void LCDwrite(int addr, char c) { while(LCDbusy()); while(PMMODEbits.BUSY); PMADDR = addr; PMDATA = c; void putsLCD(char *s) { while(*s) putLCD(*s++); main(void) { int i; LCDinit();
460 Глава 22. Примеры для компилятора СЗО Листинг 22.1. Окончание putsLCD("Hello"); LCDsetG(O); putLCD(ObOOOlO); putLCD(ObOOOlO); putLCD(ObOOllO); putLCD(Oblllll); putLCD(ObOOllO); putLCD(ObOOOlO); putLCD(ObOOOlO); putLCD(0); putLCD(ObOOOOO); putLCD(ObOOlOO); putLCD(ObOllOO); putLCD(OblllOO); putLCD(ObOOOOO); putLCD(ObOOOOO); putLCD (ObOOOOO-) ; putLCD(0); while(1) { LCDsetC(0x40+14); putLCD(0); putLCD( 1); DELAY(); for( i=13; i>=0; i—) { _LCDsetC (0x40+i) ; putLCD(0); putLCD(1); putLCD(’ ’); DELAY (); } LCDsetC(0x40); putLCD(1); putLCD(' ’); DELAY(); LCDsetC(0x40); putLCD(' ’); LCDsetC(0x40+15); putLCD(0); DELAY(); } j Работа с АЦП Все микроконтроллеры PIC24 оснащены скоростным АЦП, способным выпол- нять 500 000 преобразований в секунду, с входным мультиплексором, позволяющим быстро и с высоким разрешением опрашивать несколько аналоговых входов. Мы воспользуемся 10-разрядным модулем АЦП микроконтроллера PIC24FJ128GA010 для реализации двух простых измерений:
Работа с АЦП 461 • считывание уровня входного напряжения с потенциометра; • считывание уровня входного напряжения с датчика температуры. Считывание уровня напряжения с потенциометра Потенциометр на 10 кОм подключен напря- мую к шине электропитания, чтобы его выход мог охватить весь диапазон напряжений от 3,3 В до опорного уровня “земли”. Он соединен с вы- водом RB5, соответствующий аналоговому входу AN 5 входного мультиплексора АЦП (рис. 22.1). Создадим новый файл исходного кода pot. с со ссылкой на соответствующий заголовочный файл. В него мы добавим определение двух по- лезных констант. Цервая из них (рот) задает вхо- дной канал, назначенный потенциометру, а вто- +3.3V NL (RB5/AN5) Рис. 22.1. Схема подключения потенциометра рая (ainputs) представляет собой маску, определяющую распределение аналого- вых и цифровых входов: finclude <p24fjl28ga010.h> fdefine POT 5 // Понетциоментр на 10k подключен к выводу AN5 fdefine AINPUTS Oxffef // Аналоговые входы Фактическую инициализацию всех управляющих регистров АЦП лучше всего реализовать в виде небольшой функции initADC (), конфигурирующей следующие регистры: • AD1PCFG — маска выбора аналоговых входных каналов (0 в некотором разряде обозначает аналоговый, al — цифровой вход); • AD1CON1 — определяет автоматическое начало преобразования по завершению этапа выборки; результат будет отформатирован как обычное беззнаковое целое с выравниванием по правому разряду; • AD1CSSL — будет обнулен, поскольку функция опроса не используется (только один вход); • AD1CON2 — определяет использование мультиплексора MUXA и соединяет входы опорного сигнала АЦП с аналоговыми входами AVdd и AVss; • AD1CON3 — выбирает источник тактирования и коэффициент деления для пре- образования. Конфигурирование завершается установкой разряда ADON, что активизирует всю периферию АЦП. void initADC(int amask) { AD1PCFG — amask; // Выбираеми аналоговые входы AD1CON1 = 0; AD1CSSL = 0; AD1CON2 = 0; // Ручное начало преобразования // Опрос не требуется // Используем MUXA, входы AVss и AVdd // используются как Vref+/- AD1CON3 = 0xlF02; // Tad = 2 х Тсу = 125 нс > 75 нс ADlCONlbits.ADON = 1; // Активизируем АЦП }
462 Глава 22. Примеры для компилятора СЗО Передавая в подпрограмму инициализации параметр amask, мы делаем ее дос- таточно гибкой для восприятия нескольких входных каналов в будущих приложе- ниях. По сути, аналого-цифровое преобразование — это двухэтапный процесс. Преж- де всего необходимо снять сигнал, входного напряжения, после чего вход можно от- ключить и выполнить собственно преобразование считанного напряжения в число- вое значение. Эти этапы контролируются двумя управляющими разрядами в реги- стре AD1CON1: SAMP И DONE. Для обеспечения необходимой точности измерений важную роль играет хроно- метраж этих двух этапов. • На этапе выборки внешний сигнал подается на внутренний конденсатор, кото- рый необходимо зарядить до уровня входного напряжения. Для этого требуется выделить достаточно времени, которое обычно пропорционально импедансу источника входного сигнала (в нашем случае составляет менее 5 кОм), а также емкости конденсатора. В общем случае, чем больше время выборки, тем лучше результат, согласующийся с частотой входного сигнала (в нашем примере роли не играет). • Длительность этапа преобразования зависит от выбранного источника тактиро- вания АЦП. Тактовый сигнал обычно получают из синхросигнала центрального процессора после пропускания через делитель или с помощью независимого RC-осциллятора. Последний вариант, хотя и привлекает своей простотой, хо- рошо подходит в тех случаях, когда преобразование выполняется в “спящем” режиме (режиме пониженного энергопотребления) при отключенном осцилля- торе центрального процессора. В остальном, предпочтительный способ форми- рования тактового сигнала — с помощью делителя, поскольку он обеспечивает синхронизацию с центральным процессором и, как следствие, — более надеж- ное подавление внутреннего шума. Частота тактового сигнала должна быть максимально большой согласно спецификациям модуля АЦП (в нашем примере время Tad должно превышать 75 нс, учитывая минимальный коэффициент де- ления 2). > Рассмотрим базовую подпрограмму преобразования: int readADC(int ch) { AD1CHS = ch; // 1. Входной аналоговый канал ADlCONlbits.SAMP = 1; // 2. Начинаем выборку TMR1 = 0; // 3. Выжидаем время выборки while (TMR1< 100); // 6.25 мкс ADlCONlbits.DONE = 1; // 4 . Начинаем преобразование while (•ADlCONlbits.DONE); // // 5. Ожидаем завершения преобразования return ADC1BUF0; // 6. Считываем результат // преобразования } Как видим, согласно такому базовому методу мы сами отвечаем за обеспечение точных временных характеристик этапа выборки с помощью двух циклов ожида- ния. Однако микроконтроллеры PIC24 позволяют отчасти автоматизировать данный процесс. Длительность этапа выборки определяется без нашего участия при усло- вии, что импеданс входного источника достаточно мал для того, чтобы обеспечить
Работа с АЦП 463 максимальную продолжительность дискретизации 32 х Tad (в нашем примере 32 х 120 нс = 3,8 мкс). Этого можно достичь, записав в разряды SSRC регистра AD1CON1 значение 0Ы11, чтобы активизировать автоматическое начало преобразования по завершении периода дискретизации. Сам период выбирают с помощью разрядов sam регистра ad 1 con 3. Рассмотрим откорректированную функцию инициализации АЦП, использую- щую автоматический выбор длительности дискретизации и момента начала преоб- разования: void initADC(int amask) { AD1PCFG = amask; // Выбор аналоговых входов AD1CON1 = ОхООЕО; // Автоматическое начало преобразования AD1CSSL = 0; // Опрос не требуется AD1CON2 = 0; // Используем MUXA; // AVss и AVdd задействованы как Vref+/ AD1CON3 = 0xlF02; // Tsamp = 32 х Tad; Tad = 125 нс ADlCONlbits.ADON = 1; // Включаем АЦП } Автоматическое начало преобразования по завершении этапа выборки дает два преимущества: • гарантированно корректное время выборки без необходимости использовать какие-либо циклы задержки и/или другие ресурсы; • для выполнения всей процедуры дискретизации и преобразования достаточно одной команды (начала этапа выборки). / Когда АЦП сконфигурирован подобным образом, активизация преобразования и считывание результата становится совсем простой задачей: • AD1CHS выбирает входной канал для MUXA; • установка разряда SAMP в регистре AD1CON1 начинает этап выборки с автомати- ческим выбором длительности, после которого сразу же следует преобразова- ние; • как только будет выполнена вся процедура, и результат готов к использованию, в регистре AD1CON1 устанавливается разряд DONE; • чтение регистра ADC1BUF0 сразу же дает требуемый результат преобразования. int readADC(int ch) { AD1CHS = ch; // 1^ Выбор аналогового входного канала ADlCONlbits.SAMP = 1; // 2. Начало выборки while (?ADlCONlbits.DONE); // 3. Ожидаем завершения // преобразования return ADC1BUF0; // 4 . Считываем результат преобразования } Все что нам осталось сделать, — придумать какой-нибудь интересный способ проявить преобразованное значение. Наиболее очевидное решение — подключить светодиоды к порту А, однако вместо простого двоичного вывода восьми старших разрядов 10-разрядного результата мы немного усложним задачу, сделав визуаль- ную демонстрацию более близкой к аналоговой природе входного сигнала.
464 Глава 22. Примеры для компилятора СЗ Мы будем каждый раз включать по одному светодиоду, индицируя изменение угла поворота механического регулятора. Главная подпрограмма для тестирования наших аналого-цифровых функций выглядит следующим образом: main () { int а; // Инициализация initADC (AINPUTS) ; // Инициализируем АЦП TRISA = Oxff00; // Выбираем выводы порта А в качестве // выходов для управления светодиодами // Главный цикл while(1) { а ».readADC(РОТ); // Выбираем вход РОТ и выполняем // преобразование // Уменьшаем 10-разрядный результат до 3-разрядного значения // (0..7) (делим на 128 путем сдвига вправо 7 раз) а »= 7; // Включаем только соответствующий светодиод // 0 -> карйний слева светодиод.... 7-> крайний справа PORTA = (0x80 » а) ; } } После вызова подпрограммы инициализации (в которой с помощью маски оп- ределено, что разряд 5 — это аналоговый вход), мы инициализируем регистр trisa таким образом, чтобы выводы, подключенные к линейке светодиодов, были цифро- выми выходами. Затем в главном цикле мы выполняем преобразование на выводе AN5 и форма- тируем результат таким образом, чтобы он соответствовал нашим требованиям ин- дикации. Согласно заданной конфигурации будет получен 10-разрядный целочис- ленный результат преобразования, выровненный по правому краю (диапазон значе- ний 0..1024). Разделив это число на 128 (т.е. семикратно сдвинув его вправо), мы можем уменьшить диапазон до 0..7. Кроме того, для получения восьми необходи- мых светодиодных конфигураций конечный результат потребуется подвергнуть еще одной трансформации. Дело в том, что светодиод, соответствующий старшему зна- чащему разряду, находится на левом крае линейки. Для того чтобы согласовать движение потенциометра (по часовой стрелке) и смещение индекса светодиода (вправо), необходимо, начав с шаблона 0Ы0000000, сдвигать его вправо. Полностью исходный код рассмотренной программы (без комментариев) пока- зан в листинге 22.2. еФайл этого примера Pot. с находится на прилагаемом к книге компакт-диске в папке Pro- ject s\C3 О\ADC. Листинг 22.2. Программа Pot. с #include <р24fj128ga010.h> #define POT 5 #define AINPUTS Oxffef
Работа с АЦП 465 Листинг 22.2. Окончание void initADC(int amask) { AD1PCFG = amask; AD1CON1 - OxOOEO; AD1CSSL = 0; AD1CON2 = 0; AD1CON3 |= 0x1F02; ADlCONlbits.ADON = 1; int readADC(int ch) { AD1CHS = ch; ADlCONlbits.SAMP = 1; while (!ADlCONlbits.DONE); return ADC1BUF0; main () { > int a; initADC(AINPUTS); TRISA = OxffOO; while (1) { a = readADC(POT); a »= 7; PORTA = (0x80 » a); ) } Измерение температуры В этом примере для измерения температуры мы воспользуемся датчиком ТС1047А от компании Microchip. Он выдает строго линейное выходное напряже- ние. Потребление тока ограничено 35 мкА (типичное значение), в то время как на- пряжение питания может покрывать весь диапазон от 2,5 до 5,5 В. Выходное на- пряжение не зависит от напряжения питания и представляет собой строго линейную функцию температуры (обычно — в пределах 0,5°С) с наклоном ровно 10 мВ/°С. Смещение можно корректировать, чтобы получить абсолютную индикацию темпе- ратуры по формуле, показанной на рис. 22.2. few яЬ Техническое описание датчика ТС1047А находится на прилагаемом к книге компакт-диске в пап- ЧЦ ке Datasheets. Теперь можно применить АЦП микроконтроллера PIC24 для преобразования выходного напряжения в цифровые данные. Датчик температуры напрямую под- ключен к аналоговому входному каналу AN4 (рис. 22.3).
466 Глава 22. Примеры для компилятора СЗО Температура (°C) Рис. 22.2. Выходная характеристика датчика ТС1047 Рис. 22.3. Схема подключения датчика температуры ТС1047А Можно повторно использовать АЦП-функции, разработанные для предыдущего упражнения, поместив их в новый файл исходного кода Тетр. с. Начнем модификацию кода с включения определения новой константы tsens для входного канала АЦП, назначенного датчику температуры: #include <p24fj!28ga010.h> #define POT 5 #define TSENS 4 // Датчик температуры TC1047 #define AINPUTS Oxffcf // Аналоговые входы для POT и TSENS // Инициализируем АЦП для одного преобразования, выбираем // аналоговые входы void initADC(int amask) { AD1PCFG = amask; // Выбираем аналоговые входы AD1CON1 = OxOOEO; // Автоматическое преобразование по // завершении выборки AD1CSSL = 0; // Опрос не требуется
Работа с АЦП 467 AD1C0N3 = 0xlF02; // Максимальная длительность выборки // = 31 Tad, Tad = 2 х Тсу = 125 нс > 75 нс AD1CON2 = 0; // Используем MUXA; AVss и AVdd - как Vref4-/- ADlCONlbits.ADON =1; // Включаем АЦП } int readADC(int ch) { AD1CHS = ch; // Выбираем аналоговые входные каналы ADlCONlbits.SAMP =1; // Начинаем выборку с автоматическим // преобразованием по завершении while (!ADlCONlbits.DONE); // Ожидаем завершения // преобразования return ADC1BUF0; // Считываем результат преобразования } Как видим, с точки зрения конфигурирования АЦП и активизации процедуры преобразования ничего не изменилось, а вот отображение результата с помощью светодиодов — задача посложнее. Датчики температуры дают определенный уро- вень шума и потому для получения более достоверных данных обычно используют небольшую фильтрацию. Точный результат можно вычислить, усреднив значение 16 выборок: а = 0; for (j=16; j>0; j —) a += readADC(TSENS); // Накапливаем 16 последовательных // считываний температуры i = а » 4; // Делим результат на 16 для получения среднего Но как отобразить температуру с помощью линейки светодиодов? Мы могли бы взять старшие разряды результата преобразования и представить их в двоичной или двоично-десятичной форме, однако это, опять-таки, неинтересно. Один из вариан- тов — реализовать относительную индикацию температуры. Для этого мы перед главным циклом считаем исходное значение температуры и используем его в каче- стве смещения для центральной позиции линейки. В главном цикле позиция будет обновляться, смещаясь вправо в случае повышения температуры, или влево в случае ее понижения. Полный код, реализующий опрос температуры, выглядит следую- щим образом: main () { int a f i f j; // 1. Инициализация initADC (AINPUTS) ; // Инициализируем АЦП TRISA » OxffOO; // Выбираем вывода порта A // для управления светодиодами T1CON = 0x8030; // Включаем таймер TMR1, коэффициент // предделителя = 1:256 Tclk/2 // 2. Считываем исходное значение температуры а = 0; for (j=16; j>0; j—) a += readADC(TSENS); // Считываем температуру
468 Глава 22. Примеры для компилятора СЗО i = а » 4; // В результате мы получили основу для центрального // светодиода // 3. Главный цикл while(1) { //'3.1. Считываем новое (усредненное) значение температуры а = 0; for (j=16; j>0; j —) { TMR1 = 0; while (TMR1 < 3900); // 3900 x 256 x‘Tcy ~= 1 c a += readADC(TSENS); // Считываем температуру } a »= 4; // Усреднение 16 выборок // 3.2. Сравниваем с исходным значением и смещаем индикацию // на одну позицию на градус Цельсия а = 3 + (а - i) ; // 3.3. Поддерживаем результат в диапазоне 0..7; сохраняем // видимость индикации if (а > 7) а = 7; if (а < 0) а = 0; // 3.4. Включаем соответствующий светодиод PORTA = (0x80 » а) ; ) } В пункте 3.2 определяется разница между исходным значением i и новым ус- редненным значением а. Если она равна нулю, то включается центральный свето- диод. В пункте 3.3 результат проверяется на принадлежность к диапазону допусти- мых значений. Если разница — отрицательная, а ее ширина — более трех разрядов, то должен включиться крайний слева светодиод. Если разница — положительная, а ее ширина — более четырех разрядов, то должен включиться крайний справа све- тодиод. В пункте 3.4 результат отображается, как в предыдущем примере. Полностью исходный код рассмотренной программы (без комментариев) пока- зан в листинге 22.3. еФайл этого примера Тетр. с находится на прилагаемом к книге компакт-диске в папке Pro- ject s\C30\ADC. Листинг 22.3. Программа Тетр. с ♦include <p24fj128ga010.h> ♦define POT 5 ♦define TSENS 4 ♦define AINPUTS Oxffef
Работа с АЦП 469 _ _ ......:-- ~а;яж Листинг 22.3. Окончание void initADC(int amask) { AD1PCFG = amask; AD1CON1 = OxOOEO; AD1CSSL = 0; AD1CON3 = 0xlF02; AD1CON2 = 0; ADlCONlbits.ADON = 1; / int readADC(int ch) { AD1CHS = ch; ADlCONlbits.SAMP = 1; while (!ADlCONlbits.DONE); return ADC1BUF0; main () { int a, i, j, k; initADC(AINPUTS); TRISA = OxffOO; T1CON = 0x8030; a = 0; for (j= 16; j>0; j—) a += readADC(TSENS); i = a » 4; while(1) { a = 0; for (j=16; j>0; j—) { TMR1 = 0; while (TMR1 < 3900); a += readADC(TSENS); ) a »= 4; a = 3 + (a - i); if (a > 7) a=7; if (a < 0) a = 0; PORTA = (0x80 » a); } J
Глава 23 Примеры для компилятора С32 В этой главе мы рассмотрим два примера, рассчитанных на компилятор С32 и микроконтроллер PIC32MX360F512L. Работа с интерфейсом SPI Для исследования интерфейса SPI микроконтроллеров PIC32 воспользуемся микросхемой последовательной памяти EEPROM 25LC256 (32 Кбайт) от компании Microchip, подключенной к модулю SPI2 устройства PIC32MX360F512L. е Техническое описание микросхемы 25LC256 находится на прилагаемом к книге компакт-диске в папке Datasheets. Наиболее простой способ сконфигурировать модуль SPI2 на взаимодействие с памятью EEPROM — установить вручную необходимые значения всех разрядов в регистре SPI2CON: • MODE16 = б, MODE32 = 0 — активизация восьмиразрядного режима обмена дан- ными; • скр =0 — активный уровень тактового сигнала — высокий; • СКЕ = 1 — состояние линии данных изменяется при переходе с высокого уровня тактового сигнала к низкому; • MSTEN =1 — микроконтроллер выступает в качестве ведущего устройства на шине SPI. Результирующее конфигурационное слово можно определить в виде константы, которая позже будет записана в регистр SPI2CON: # define SPI_CONF 0x8120 Скорость обмена данными определяют по формуле: Fsck = FPB / (2 х (SPlxBRG + 1)). Мы можем или воспользоваться значением регистра SPI2BRG по умолчанию (0, что соответствует делению тактовой частоты на 2), или же записать в него значение побольше, чтобы уменьшить скорость обмена и тем саамы снизить потребление энергии микросхемой EEPROM: # define SPI_BAUD 15 При такой установке частота тактирования периферии будет разделена на 2 х (15 + 1) = 32. Таким образом, при FPB = 9 МГц частота тактирования SPI составит 280 кГц. Определения разрядов конфигурации будут выглядеть следующим образом: # pragma config POSCMOD=XT, FNOSC=PRIPLL
Работа с интерфейсом SPI 471 fpragma config FPLLIDIV=DIV_2, FPLLMUL=MUL_18 , FPLLODIV=DIV_1 fpragma config FPBDIV=DIV_8, FWDTEN=OFF, CP=OFF, BWP=OFF Далее определим линию CS для памяти EEPROM (вывод 12 порта D) и соответ- ствующий управляющий разряд регистра trisd: #define CSEE _RD12 fdefine TCSEE TRISD12 // Линия CS для памяти EEPROM // Разряд TRISD для вывода CSEE Теперь можно создать код инициализации интерфейса SPI: 1 TCSEE =0; // Вывод SSEE - выход CSEE =1; // Деактивируем модуль EEPROM SPI2CON = SPI_CONF; // Выбираем режим и активизируем SPI2BRG = SPI_BAUD; // Устанавливаем частоту тактирования Теперь разработаем небольшую функцию, которая будет использоваться для передачи данных в модуль EERPOM и обратно: int writeSPI2(int i) { SPI2BUF = i; // Записываем в буфер передачи while(?SPI2STATbits.SPIRBF); // Ожидаем завершения передачи return SPI2BUF; // Возврат принятого значения Эта функция записывает символ в буфер передачи и входит в цикл ожидания до установки флага приема данных от ведомого устройства. Следует отметить, что при обмене данными с модулем памяти бывают случаи, когда в модуль передается команда, на которую нет немедленного отклика. Или же при считывании данных из модуля памяти микроконтроллеру затем не нужно пере- давать никаких команд. В первом случае возвращаемое значение можно просто проигнорировать, а во втором в ходе считывания данных микроконтроллером в мо- дуль память можно передавать некоторое фиктивное значение. Создадим макроопределения для команд, используемых при работе с модулем 25LC256: > fdefine SEE_WRSR 1 // Запись в регистр состояния fdefine SEE_WRITE 2 // Запись fdefine SEE_READ 3 // Чтение fdefine SEE_WDI 4 // Запрет записи fdefine SEE_STAT 5 // Чтение регистра состояния fdefine SEE_WEN 6 // Разрешение записи Теперь реализуем обмен данными с модулем EEPROM. Например, мы можем выдать команду чтения регистра состояния SEE STAT, а во втором вызове функции writeSP!2 передать фиктивный байт для фиксации ответа от модуля памяти. При этом необходимо придерживаться такой последовательности действий. 1. Активизировать память, установив низкий уровень сигнала на линии CS. 2. Вывести восемь разрядов команды. 3. В зависимости от команды — выдать или принять данные. 4. Деактивировать память (т.е. перевести ее в режим ожидания), установив высо- кий уровень сигнала на линии CS. Соответствующий код выглядит следующим образом:
472 Глава 23. Примеры для компилятора С32 CSEE = 0; writeSPI2 (SEE_WEN) ; CSEE = 1; CSEE = 0; writeSPI2(SEE_STAT); 1 = writeSPI2(0) ; CSEE - 1; Полностью исходный код рассмотренной программы (без комментариев) пока- зан в листинге 23.1. Ц Файл этого примера SPI. с находится на прилагаемом к книге компакт-диске в папке Pro- ject s\C32\SPI. - _J * I 11 • IWVI MUiviivivl л» ♦include <p32mx360f5121.h> ♦pragma config POSCMOD=XT, FNOSC=PRIPLL' ♦pragma config FPLLIDIV=DIV_2, FPLLMUL=MUL_18, FPLLODIV=DIV_1 ♦ pragma config FPBDIV=DIV_8, FWDTEN=OFF, CP=OFF, BWP=OFF ♦ define CSEE _RD12 ♦ define TCSEE _TRISD12 ♦ define SPI_CONF 0x8120 ♦ define SPI_BAUD 15 ♦ define SEE_WRSR 1 ♦ define SEE_WRITE 2 ♦ define SEE_READ 3 ♦ define SEE_WDI 4 ♦ define SEE_STAT 5 ♦ define SEE_WEN 6 int writeSPI2(int i) { SPI2BUF = i; while(!SPI2STATbits.SPIRBF) ; return SPI2BUF; main() ( int i; TCSEE = 0; CSEE = 1; SPI2CON = SPI_CONF; SPI2BRG = SPI_BAUD; while(1) { CSEE = 0; writeSPI2(SEEJiEN); CSEE = 1;
Работа с модулем UART 473 CSEE = 0; writeSPI2(SEE_STAT); i = writeSPI2(0) ; CSEE = 1; Работа с модулем UART Для исследования передачи данных по последовательному интерфейсу RS232 воспользуемся модулем UART2 микроконтроллера PIC32MX360F512L. В нашем случае будем ориентироваться на следующую конфигурацию: • скорость обмена данными — 115 200 бод; • режим передачи — восьмиразрядный; • отсутствие контроля четности; • один стоп-бит; • аппаратное квитирование связи с использованием линий CTS и RTS. Начнем разработку программы с определений для линий CTS и RTS, а также — разряда управления выводом RTS регистра TRISF: «include <p32mx360f5121.h> «define CTS «define RTS «define TRTS _RF12 _RF13 TRISFbits.TRISF13 Аппаратное квитирование связи играет особенно важную роль при взаимодей- ствии с терминальными Windows-программами, поскольку Windows — это много- задачная операционная система, в которой иногда возникают длительные задержки в работе приложений, что чревато потерей данных. Для опроса готовности термина- ла к приему нового символа мы воспользовались линией RF12, а для оповещения терминала о готовности программы к приему символа — линией RF13. Для установки скорости обмена данными служит 16-разрядный счетчик U2BREG, выходной сигнал которого определяет частоту тактирования шины периферии. При обычном режиме работы (BREGH = 0) модуль UART тактовая частота делится на 16, в то время как в высокоскоростном режиме (BREGH = 1) — на 4. В последнем случае скорость обмена данными рассчитывается по формуле: Скорость = Fpb/(4 *(UxBREG + 1)). Отсюда получаем формулу для расчета значения регистра UxBRE(j: UxBREG = Fpb / (4 х Скорость) - 1. В нашем случае: UxBREG = 36 000 000 / (4 х 115 200) - 1 = 77,125. Для расчета этого значения в программе создадим следующие макроопределе- ния:
474 Глава 23. Примеры для компилятора С32 fdefine Ft>B 3600000OL fdefine BRATE (FPB/4/115200)-1 Определим также две константы для инициализации регистров управления мо- дулем UART2 U2MODE И U2STA: fdefine UJENABLE 0x8008 // BREGH=1, 1 стоп-бит, без контроля // четности, активизация UART fdefine U_TX 0x0400 // Начало передачи, сброс флагов В результате, функция Инициализации модуля UART2 будет выглядеть сле- дующим образом: void initU2(void) { U2BRG = BRATE; // Инициализация генератора скорости U2MODE = U_ENABLE; // Инициализация модуля UART2 U2STA = U_TX; // Включение передатчика TRTS = 0; // Вывод RTS - выход RTS = 1; // Устанавливаем состояние линии RTS // по умолчанию (не готова) } Теперь можно реализовать функции передачи и приема данных. Процесс пере- дачи символа в последовательный порт состоит из трех этапов. 1. Убедиться в готовности терминала. Для этого следует проверить состояние ли- нии CTS. Ожидаем, пока в этой линии не появится сигнал низкого уровня. 2. Убедиться, что модуль UART не занят передачей предыдущего пакета данных. Для этого необходимо дождаться освобождения по крайней мере верхнего уровня четырехуровневого FIFO-буфера (т.е. сброса флага UTXBF, указываю- щего на то, что буфер полностью заполнен}. 3. Передать символ в буфер передатчика UART. Учитывая все вышесказанное, функция передачи символа имеет следующий вид: , int putU2 (int с) { while (CTS); // Ожидаем, пока не будет CTS=O while (U2STAbits.UTXBF); // Ожидаем освобождения буфера U2TXREG = с; return с; } Для приема символа по последовательному порту используется процедура, по- добная рассмотренной выше. 1. Известить терминал о готовности к приему путем установки низкого уровня сигнала на линии RTS. 2. Дождаться заполнения буфера приемника, о чем известит флаг URXDA в реги- стре состояния U2STA. 3. Извлечь символ из буфера приемника. Функция приема символа выглядит следующим образом:
Работа с модулем UART 475 char getU2(void) RTS = 0; while (!U2STAbits.URXDA); RTS = 1; return U2RXREG; // Извещаем о готовности // Ожидаем получения символа // Считываем символ из буфера Теперь для проверки рассмотренных выше функций можно написать неболь- шую программу, которая инициализирует последовательный порт, выдает символ приглашения и позволяет ввести с клавиатуры терминала последовательность строк, которая затем эхом отображается на экране терминала. main() { char с; initU2 () ; putU2 (’>’); while (1) { с = getU2(); putU2(с); // Инициализация порта UART 2 // Символ приглашения // Ожидаем тимвол // Возвращаем символ терминалу Полностью исходный код рассмотренной программы (без комментариев) пока- зан в листинге 23.2. еФайл этого примера UART. с находится на прилагаемом к книге компакт-диске в папке Pro- jects \С32\ UART. Листинг 23.2. Программа UART. с #include <p32mx360f5121.h> ♦pragma config POSCMOD=XT, FNOSC=PRIPLL ♦pragma config FPLLIDIV=DIV_2, FPLLMUL=MUL_18, FPLLODIV=DIV_1 ♦pragma config FPBDIV=DIV_2, FWDTEN=OFF, CP=OFF, BWP=OFF ♦define FPB 36000000L ♦define BRATE (FPB/4/115200)-1 ♦define CTS _RF12 ♦define RTS _RF13 ♦define TRTS TRISFbits.TRISF13 . ♦define U_ENABLE 0x8008 ♦define U_TX ' 0x0400 void initU2(void) { U2BRG = BRATE; U2MODE = U_ENABLE; U2STA = U_TX; TRTS = 0;
476 Глава 23. Примеры для компилятора С32 Листинг 23.2. Окончание RTS = 1; int putU2(int с) { while (CTS); while (U2STAbits.UTXBF); U2TXREG = c; return c; char getU2(void) ( RTS = 0; while (!U2STAbits.URXDA); RTS = 1; return U2RXREG; main() { char c; initU2(); putU2(’>’); while (1) { c = getU2(); putU2(c); } }
ЧАСТЬ VIII Приложения
Приложение А Таблица символов ASCII Сим- вол Кодировка Сим- вол Кодировка Сим- вол Кодировка Сим- вол Кодировка Dec Hex Dec Hex Dec Hex Dec Hex (nul) 0 0x00 (sp) 32 0x20 @ 64 0x40 96 0x60 (soh) 1 0x01 1 33 0x21 A 65 0x41 a 97 0x61 (stx) 2 0x02 II 34 0x22 В 66 0x42 b 98 0x62 (etx) 3 0x03 # 35 0x23 C 67 0x43 c 99 0x63 (eot) 4 0x04 $ 36 0x24 D 68 0x44 d 100 0x64 (enq) 5 0x05 % 37 0x25 E 69 0x45 e 101 0x65 (ack) 6 0x06 & 38 0x2 6 F 70 0x4 6 f 102 0x66 (bel) 7 0x07 1 39 0x27 G 71 0x47 g 103 0x67 (bs) 8 0x08 ( 40 0x28 H 72 0x4 8 h 104 0x68 (ht) 9 0x09 ) 41 0x29 I 73 0x4 9 i 105 0x69 (nl) 10 OxOA * 42 0x2A J 74 0x4A j 106 0x6A (vt) 11 0x0В + 43 0x2B К 75 0x4B k 107 0x6B (np) 12 OxOC r 44 0x2C L 76 0x4C 1 108 0x6C (cr) 13 OxOD — 45 0x2D M 77 0x4D m 109 0x6D (so) 14 OxOE 46 0x2E N 78 0x4E n 110 0x6E (si) 15 OxOF / 47 0x2F 0 79 0x4F о 111 0x6F (die) 16 0x10 0 48 0x30 P 80 0x50 P 112 0x70 (del) 17 0x11 1 49 0x31 Q 81 0^51 q 113 0x71 (dc2) 18 0x12 2 50 0x32 R 82 0x52 r 114 0x72 (dc3) 19 0x13 3 51 0x33 S 83 0x53* s 115 0x73 (dc4) 20 0x14 4 52 0x34 T 84 0x54 t 116 0x74 (nak) 21 0x15 5 53 0x35 U 85 0x55 u 117 0x75 (syn) 22 0x16 6 54 0x36 V 86 0x56 V 118 0x7 6 (etb) 23 0x17 7 55 0x37 W 87 0x57 w 119 0x77 (can) 24 0x18 8 56 0x38 X 88 0x58 X 120 0x78 (em) 25 0x19 9 57 0x39 Y 89 0x59 У 121 0x79 (sub) 26 OxlA • 58 0x3A Z 90 0x5A z 122 0x7A (esc) 27 OxlB r 59 0x3B [ 91 0x5B { 123 0x7B (fs) 28 OxlC < 60 0x3C \ 92 0x5C i 124 0x7C (gs) 29 OxlD = 61 0x3D ] 93 0x5D } 125 0x7D (rs) 30 OxlE > 62 0x3E л 94 0x5E 126 0x7E (us) 31 OxlF ? 63 0x3F — 95 0x5F (del) 127 0x7F
Приложение Б Преобразование из одной системы счисления в другую 0 00000000 000 00 1 00000001 001 01 2 00000010 002 02 3 00000011 003 03 4 00000100 004 04 5 00000101 005 05 6 00000110 006 06 7 00000111 007 07 8 00001000 010 08 9 00001001 011 09 10 00001010 012 0А 11 00001011 013 ов 12 00001100 014 ОС 13 00001101 015 0D 14 00001110 016 0Е 15 00001111 017 0F 16 00010000 020 10 17 00010001 021 11 18 00010010 022 12 19 00010011 023 13 20 00010100 024 14 21 00010101 025 15 22 00010110 026 16 23 00010111 027 17 24 00011000 030 18 25 00011001 031 19 26 00011010 032 1А 27 00011011 033 1В 28 00011100 034 1С 29 00011101 035 ID 30 00011110 036 IE 31 00011111 037 IF 32 00100000 040 20 33 00100001 041 21 34 00100010 042 22 35 00100011 043 23 36 00100100 044 24 37 00100101 045 25 38 00100110 046 26 39 00100111 047 27 40 00101000 050 28 41 00101001 051 29 42 00101010 052 2A 43 00101011 053 2B 44 00101100 054 2C 45 00101101 055 2D 46 00101110 056 2E 47 00101111 057 2F 48 00110000 060 30 49 00110001 061 31 50 00110010 062 32 51 00110011 063 33 52 00110100 064 34 53 00110101 065 35 54 00110110 066 36 55 00110111 067 37 56 00111000 070 38 57 00111001 071 39 58 00111010 072 ЗА 59 00111011 073 ЗВ 60 00111100 074 ЗС 61 00111101 075 3D 62 00111110 076 ЗЕ 63 00111111 077 3F 64 01000000 100 40 65 01000001 101 41 66 01000010 102 42 67 01000011 103 43 68 01000100 104 44 69 01000101 105 45 70 01000110 106 46 71 01000111 107 47 72 01001000 110 48 73 01001001 111 49 74 ’01001010 112 4А 75 01001011 113 4В
480 Приложение Б. Преобразование из одной системы счисления в другую 76 01001100 114 4С 77 01001101 115 4D 78 01001110 116 4Е 79 01001111 117 4F 80 01010000 120 50 81 01010001 121 51 82 01010010 122 52 83 01010011 123 53 84 01010100 124 54 85 01010101 125 55 86 01010110 126 56 87 01010111 127 57 88 01011000 130 58 89 01011001 131 59 90 01011010 132 5А 91 01011011 133 5В 92 01011100 134 5С 93 010Ц101 135 5D 94 01011110 136 5Е 95 01011111 137 5F 96 01100000 140 60 97 01100001 141 61 98 01100010 142 62 99 01100011 143 63 100 01100100 144 64 101 01100101 145 65 102 01100110 146 66 103 01100111 147 67 104 01101000 150 68 105 01101001 151 69 106 01101010 152 6А 107 01101011 153 6В 108 , 01101100 154 6С 109 01101101 155 6D 110 01101110 156 6Е 111 01101111 157 6F 112 01110000 160 70 113 01110001 161 71 114 01110010 162 72 115 01110011 163 73 116 01110100 164 74 117 01110101 165 75 118 01110110 166 76 119 01110111 167 77 120 01111000 170 78 121 01111001 171 79 122 01111010 172 7А 123 01111011 173 7В 124 01111100 174 7С 125 01111101 175 7D 126 01111110 176 7Е 127 01111111 177 7F 128 10000000 200 80 129 10000001 201 81 130 10000010 202 82 131 10000011 203 83 132 10000100 204 84 133 10000101 205 85 134 10000110 206 86 135 10000111 207 87 136 10001000 210 88 137 10001001 211 89 138 10001010 212 8А 139 10001011 213 8В 140 10001100 214 8С 141 10001101 215 8D 142 10001110 216 8Е 143 10001111 217 8F 144 10010000 220 . 90 - 145 10010001 221 91 146 10010010 222 92 147 10010011 223 93 148 10010100 224 94 149 10010101 225 95 150 10010110 226 96 151 10010111 227 97 152 10011000 230 98 153 10011001 231 99 154 10011010 232 9А 155 10011011 233 9В 156 10011100 234 9С 157 10011101 235 9D 158 10011110 236 9Е 159 10011111 237 9F 160 10100000 240 АО 161 10100001 241 А1 162 10100010 242 А2 163 10100011 243 АЗ 164 10100100 244 А4 165 10100101 245 А5 166 10100110 246 А6 167 10100111 247 А7 168 10101000 250 А8 169 10101001 251 А9 170 10101010 252 АА 171 10101011 253 АВ
481 172 10101100 254 AC 173 10101101 255 AD 174 10101110 256 AE 175 10101111 257 AF 176 10110000 260 BO 177 10110001 261 Bl 178 10110010 262 B2 179 10110011 263 B3 180 10110100 264 B4 181 10110101 265 B5 182 10110110 266 B6 183 10110111 267 B7 184 10111000 270 B8 185 10111001 271 B9 186 10111010 272 BA 187 10111011 273 BB 188 10111100 274 BC 189 10111101 275 BD 190 10111110 276 BE 191 10111111 277 BF 192 11000000 300 co 193 11000001 301 Cl 194 11000010 302 C2 195 11000011 303 C3 196 11000100 304 C4 197 11000101 305 C5 198 11000110 306 C6 199 11000111 307 C7 200 11001000 310 C8 201 11001001 311 C9 202 11001010 312 CA 203 11001011 313 CB 204 11001100 314 CC 205 11001101 315 CD 206 11001110 316 CE 207 11001111 317 CF 208 11010000 320 DO 209 11010001 321 DI 210 11010010 322 D2 211 11010011 323 D3 212 11010100 324 D4 213 11010101 325 D5 214 11010110 326 D6 215 11010111 327 D7 216 11011000 330 D8 217 11011001 331 D9 218 11011010 332 DA 219 11011011 333 DB 220 11011100 334 DC 221 11011101 335 DD 222 11011110 336 DE 223 11011111 337 DF 224 11100000 340 EO 225 11100001 341 El 226 11100010 342 E2 227 11100011 343 E3 228 11100100 344 E4 229 11100101 345 E5 230 11100110 346 E6 231 11100111 347 E7 232 11101000 350 E8 233 11101001 351 E9 234 11101010 352 EA 235 11101011 353 EB 236 11101100 354 EC 237 11101101 355 ED 238 11101110 356 EE 239 11101111 357 EF 240 11110000 360 FO 241 11110001 361 Fl 242 11110010 362 F2 243 11110011 363 F3 244 11110100 364 F4 245 11110101 365 F5 246 11110110 366 F6 247 11110111 367 F7 248 11111000 370 F8 249 11111001 371 F9 250 11111010 372 FA 251 11111011 373 FB 252 11111100 374 FC 253 11111101 375 FD 254 11111110 376 FE 255 11111111 377 FF
Приложение В Система команд микроконтроллеров AVR Ниже, в описании машинных команд микроконтроллеров AVR будут использо- ваны некоторые условные обозначения: • С — флаг переноса (разряд 0 регистра SREG); • Z — нулевой флаг (разряд 1 регистра SREG); • N — флаг отрицательного результата (разряд 2 регистра SREG); • V — флаг переполнения при вычислениях в дополнительных кодах (разряд 3 регистра SREG); • S — флаг знака (разряд 4 регистра SREG); S = N Ф V; • Н — флаг половинного переноса (разряд 5 регистра SREG); • Т — флаг копирования (разряд 6 регистра SREG); • I — флаг общего разрешения прерываний (разряд 7 регистра SREG); • Rd — регистр назначения в регистровом файле; • Rr — передающий регистр; • R — результат выполнения некоторой команды; • Кп — n-битная константа (например, К8 = 1 байт); • к — адресная константа для работы со счетчиком команд (PC); • b — идентификатор некоторого разряда в рабочем регистре или в регистре вво- да/вывода (3 бита); • s — указывает на некоторый разряд в регистре состояния SREG; • X, Y, Z — указатель при косвенной адресации (X = R27:R26, Y « R29:R28, Z = R31:R30); • RAMPZ, RAMPY, RAMPZ — регистры, связанные с указателями X, Y и Z для формирования косвенных адресов > 64 Кбайт; • RAMPD — регистр, связанный с указателем Z, для непосредственной адреса- ции всего пространства данных, превышающего 64 Кбайт; • EIND — регистр, связанный с указателем Z, для реализации косвенного пере- хода и обращения ко всему пространству программы, превышающему 64 (или 128) Келов; • ' Р — адрес некоторого порта ввода/вывода; • q — смещение при косвенной адресации; • Стек — область памяти для хранения адреса возврата или регистр промежу- точного хранения данных; • SP — указатель вершины стека.
483 Все ассемблерные команды, используемые при работе с микроконтроллерами AVR, сведены в табл. В.1. Доступность той или иной команды при работе с кон- кретной моделью AVR можно определить по табл. В.2. Таблица В.1. Команды, используемые при работе с микроконтроллерами AVR Мне- моника Операнды Описание Операция Влияние на флаги Цик- лов ADC Rd, Rr Содержимое регистра Rr и флаг переноса прибавляют- ся к содержимому регистра Rd Rd Rd + Rr + С 0<d<31 0<r<31 H, s, V, N,Z, С 1 ADD Rd, Rr Содержимое регистра Rr при- бавляется к содержимому ре- гистра Rd Rd <— Rd + Rr 0<d<31 0 < r < 31 H, S, V, N,Z, С 1 ADIW Rd+1:Rd, K6 Константа Кб прибавляется к содержимому регистровой пары. Эта команда, главным образом, используется в опе- рациях с указателями Rdh:Rdl «- Rdh:Rdl + K6 d e {24, 26, 28, 30} 0 < K6 < 63 S, V, N, z, C 1 AND Rd, Rr Связывание логической опера- цией “И” содержимого регист- ров Rd и Rr. Результат запи- сывается в регистр Rd Rd <— Rd л Rr 0<d<31 0<r<31 S, V = 0, N, Z 1 ANDI Rd, K8 Связывание логической опера- цией “И” содержимого регистра Rd и восьмиразрядной кон- станты К8. Результат записы- вается в регистр Rd Rd Rd a K8 16<d<31 0 < K8 < 255 S, V = 0, N,Z , 1 ASR Rd Разряды 0...6 регистра Rd сдвигаются на одну позицию вправо; разряд 0 сохраняется как флаг переноса; разряд 7 не изменяется. Эта команда мо- жет испрльзоваться для деле- ния на два байтов со знаковым разрядом без изменения этого разряда. Флаг переноса может использоваться для округле- ния результата Rd(n)<- Rd(n+1), n = 0...6, C«- Rd(O) 0< d< 31 S, V, N, z, C 1 Г BCLR s Обнуление разряда s в регист- ре SREG SREG(s) <- 0 0< s< 7 I, T, H, s, V, N, Z, C 1 BLD Rd, b Копирование флага Т в разряд b регистра Rd Rd(b) T — 1 BRBC s, K7 Если разряд s регистра SREG содержит лог. 0, то выполняет- ся относительный переход по адресу в диапазоне от PC - 64 до PC + 63 (слов) Если SREG(s) = 0, to PC <- PC + K7 + 1, иначе PC «- PC +1 0<s<7 -64 < K7< +63 1 или 2
484 Приложение В. Система команд микроконтроллеров AVR Таблица В.1. Продолжение Мнемо- ника Опе- ранды Описание Операция Влияние на флаги Цик- лов BRBS s, К7 Если разряд s регистра SREG со- держит лог. 1, то выполняется отно- сительный переход по адресу в диапазоне от PC - 64 до PC + 63 (слов) Если SREG(s) = 1, то PC«— PC + К7 + 1, иначе PC «— PC +1 1 или 2 BRCC К7 Если сброшен флаг переноса, то выполняется относительный пере- ход по адресу в диапазоне от PC - 64 до PC + 63 (слов) Если флаг С = 0, то PC <— PC + К7 + 1, иначе PC <— РС + 1 — 1 или 2 BRCS К7 Если установлен флаг переноса, то выполняется относительный пере- ход по адресу в диапазоне от PC - 64 до PC + 63 (слов) Если флаг С = 1, то PC«— PC + К7 + 1, иначе PC «- РС + 1 — 1 или 2 BREAK — Перевод процессора в режим оста- нова, предоставляющий встроен- ному отладчику доступ к внутрен- ним ресурсам микроконтроллера — —— 1 BREQ К7 Если установлен нулевой флаг, то выполняется относительный пере- ход по адресу в диапазоне от PC - 64 до PC + 63 (слов). Нулевой флаг после выполнения операции вычитания или сравнения устанав- ливается только в том случае, если результат равен Если флаг Z = 1, то PC <— PC + К7 + 1, иначе PC <— РС + 1 -64 < К7< +63 1 или 2 BRGE К7 Если сброшен флаг знака, то вы- полняется относительный переход по адресу в диапазоне от PC - 64 до PC + 63 (слов). Флаг знака после выполнения операции вычитания или сравнения сбрасывается толь- ко в том случае, если содержимое первого операнда со знаком боль- ше или равно содержимого второго операнда со знаком Если флаг S = 0, то PC«— PC + К7 + 1, иначе PC «— РС + 1 -64 < К7< +63 1 или 2 BRHC К7 Если сброшен флаг половинного переноса, то выполняется относи- тельный переход по адресу в диа- пазоне от PC - 64 до PC + 63 (слов) Если флаг Н = 0, то PC <— PC + К7 + 1, иначе PC <— РС + 1 -64 < К7< +63 1 или 2 BRHS К7 1 Если установлен флаг половинного переноса, то выполняется относи- тельный переход по адресу в диа- пазоне от PC - 64 до PC + 63 (слов) Если флаг Н = 1, то PC <— PC + К7 + 1, иначе PC <— РС + 1 -64 < К7 < +63 1 или 2
485 Таблица В.1. Продолжение Мнемо- ника Опе- ранды Описание Операция Влияние на флаги Цик- лов BRID К7 Если сброшен флаг I (все прерыва- ния запрещены), то выполняется относительный переход по адресу в диапазоне от PC - 64 до PC + 63 (слов) Если флаг I = 0, то PC <— PC + К7 + 1, иначе PC <— РС + 1 -64 < К7< +63 1 или 2 BRIE К7 Если установлен флаг I (общее разрешение прерываний), то вы- полняется относительный переход по адресу в диапазоне от PC - 64 до PC + 63 (слов) Если флаг 1 = 1, то PC <— PC + К7 + 1, иначе PC <- РС + 1 -64 < К7< +63 1 или 2 BRLO К7 Если установлен флаг переноса, то выполняется относительный пере- ход по адресу в диапазоне от PC - 64 до PC + 63 (слов). Флаг перено- са в результате выполнения опера- ции вычитания или сравнения мо- жет быть установлен только в том случае, если содержимое первого беззнакового операнда меньше, чем содержимое второго беззнако- . ого операнда Если флаг С = 1, то PC <- PC + К7 + 1, иначе PC <- РС + 1 -64 < К7< +63 1 или 2 BRLT К7 Если установлен флаг знака, то вы- полняется относительный переход по адресу в диапазоне от PC - 64 до PC + 63 (слов). Флаг знака в ре- зультате выполнения операции вы- читания или сравнения может быть установлен только в том случае, если содержимое первого операнда со знаком меньше, чем содержимое второго операнда со знаком Если флаг S = 1, то PC <- PC + К7 + 1, иначе PC <- РС + 1 -64 < К7< +63 1 или 2 BRMI К7 Если установлен флаг отрицатель- ного результата, то выполняется относительный переход по адресу в диапазоне от PC - 64 до PC + 63 (слов) Если флаг N = 1, то PC 4— PC + k7 + 1, иначе PC <- РС + 1 -64 < К7< +63 1 или 2 BRNE К7 Если сброшен нулевой флаг, то вы- полняется относительный переход по адресу в диапазоне от PC - 64 до PC + 63 (слов). Нулевой флаг в результате выполнения операции вычитания или сравнения может быть сброшен только в том случае, если результат операции не равен 0x00 Если флаг Z = 0, то PC 4— PC + k7 + 1, иначе PC <— РС + 1 -64^ К7^ +63 1 или 2
486 Приложение В. Система команд микроконтроллеров AVR Таблица В.1. Продолжение Мнемо- ника Опе- ранды Описание Операция Влияние на флаги Цик- лов BRPL К7 Если сброшен флаг отрицательного результата, то выполняется относи- тельный переход по адресу в диа- пазоне от РС-64 до РС+63 (слов) Если флаг N = 0, то PC <— PC + К7 + 1, иначе PC РС + 1 — 1 или 2 BRSH К7 Если сброшен флаг переноса, то выполняется относительный пере- ход по адресу в диапазоне от PC - 64 до PC + 63 (слов). Флаг переноса в результате выполнения операции вычитания или сравнения может быть сброшен только в том случае, если содержимое первого беззнако- вого операнда больше или равно содержимого второго беззнакового операнда Если флаг С = 0, то PC <- PC + К7 + 1, иначе PC <— РС + 1 -64 < К7< +63 - 1 или 2 BRTC К7 Если сброшен флаг Т, то выполня- ется относительный переход по ад- ресу в диапазоне от PC - 64 до PC + 63 (слов) Если флаг Т = 0, то PC <— PC + k7 + 1, иначе PC <- РС + 1 — 1 или 2 BRTS К7 Если установлен флаг Т, то выпол- няется относительный переход по адресу в диапазоне от РС-64 до PC + 63 (слов) Если флаг Т = 1, то PC <- PC + k7 + 1, иначе PC РС + 1 — 1 или 2 BRVC К7 Если сброшен флаг переполнения, то выполняется относительный пе- реход по адресу в диапазоне от PC - 64 до PC + 63 (слов) Если флаг V = 0, то PC <- PC + k7 + 1, иначе PC РС + 1 — 1 или 2 BRVS К7 Если установлен флаг переполне- ния, то выполняется относительный переход по адресу в диапазоне от PC - 64 до PC + 63 (слов) Если флаг V = 1, то PC«— PC + k7 + 1, иначе PC «— РС + 1 1 или 2 BSET S Установка разряда s в регистре SREG SREG(s) <- 1 0< s< 7 I, T, H, s, V, N, Z, C 1 BST > Rd, b Копирование в флаг Т разряда b ре- гистра Rd Т Rd(b) 0<d<31 0<b<7 T 1 CALL К16 (К22) Вызов подпрограммы по абсолют- ному адресу К16 (в микроконтрол- лерах с 16-раз ряд ной шиной адре- са) или К22 (в микроконтроллерах с 22-разрядной шиной адреса). Ад- рес возврата (также 16- или 22- разрядный) (команда, следующая после команды call), сохраняется в стеке PC <— K16 (K22) 0 < К £ 64K (0 < К < 4M) Стек <r- РС+2 SP <_ SP-2 (SP <- SP-3) 3-5
487 Таблица В.1. Продолжение Мнемо- ника Опе- ранды Описание Операция Влияние на флаги Цик- лов CBI Р, ь Запись лог. 0 в разряд b регистра ввода/вывода Р l/O(P,b) 4- 0 0<Р<31 0<Ь<7 — 1 или 2 CBR Rd, К8 Сброс в регистре Rd разрядов, за- данных К8, с применением логиче- ской операции “И” с дополненной константой К8 Rd 4— Rd л (OxFF - К8) 16<d<31 0 < К8 < 255 — 1 CLC — Сброс флага переноса в регистре SREG С 4-0 С=0 1 CLH — Сброс флага половинного перено- са в регистре SREG Н4-0 н=о 1 CLI — Сброс флага общего разрешения прерываний в регистре SREG I 4— 0 1=0 1 CLN — Сброс флага отрицательного ре- зультата в регистре SREG N4-0 N=0 1 CLR Rd Благодаря применению логиче- ской операции “Исключающее ИЛИ” содержимого регистра само- му к себе, все разряды этого реги- стра обнуляются Rd«— Rd Ф Rd 0<d<31 S=0, V=0, N=0, Z=1 1 CLS — Сброс флага знака в регистре SREG S<-0 s=o 1 CLT — Сброс флага копирования в реги- стре SREG Т4-0 T=0 1 CLV — Сброс флага переполнения в ре- гистре SREG V4-0 v=o 1 CLZ — Сброс нулевого флага в регистре SREG Z4-0 z=o 1 СОМ Rd Дополнение до единицы содержи- мого регистра Rd Rd — OxFF - Rd 0<d<31 s, V = 0, N, Z, C = 1 1 СР Rd, Rr Сравнение регистров Rd и Rr. При этом Rr вычитается из Rr без со- хранения результата (содержимое Rd не изменяется). Флаги уста- навливаются как при обычном вы- читании, чтобы можно было про- верить условие перехода Rd-Rr 0<d<31 0<r<31 H, S, V, N, z, C 1 СРС Rd, Rr Содержимое регистров Rd и Rr сравнивается с помощью вычита- ния. При этом учитывается пере- нос, полученный в результате вы- полнения предыдущей операции. Содержимое регистров Rr и Rr не изменяется. Флаги можно исполь- зовать при условных переходах Rd-Rr-C 0 < d < 31 0 < r < 31 H, S, V, N, Z, C 1
488 Приложение В. Система команд микроконтроллеров AVR Таблица В.1. Продолжение Мнемо- ника Опе- ранды Описание Операция Влияние на флаги Цик- ЛОВ CPI Rd, K8 / Содержимое регистра Rd с помо- щью вычитания сравнивается с восьмиразрядной константой К8. При этом содержимое регистра не изменяется. Флаги можно исполь- зовать при условных переходах Rd-K8 16 < d < 31 0 < К8 < 255 H, S, V, N,Z, С 1 CPSE Rd, Rr Содержимое регистров Rd и Rr сравнивается с помощью вычита- ния, и в том случар, если Rd = Rr, следующая команда пропускается. Регистры и флаги остаются неиз- менными Если Rd = Rr, то PC <— PC + 2(3), иначе PC PC + 1 0<d<31 0^r<31 1-3 DEC Rd Из содержимого регистра Rd вы- читается 1. Флаг переноса не из- меняется, благодаря чему Rd можно использовать в качестве счетчика цикла при выполнении арифметических операций над не- сколькими байтами. При декре- ментировании беззнаковых опе- рандов можно использовать толь- ко сравнения на равенство и нера- венство Rd <— Rd - 1 0<d<31 S, V, N, Z 1 DES K4 Этой команде соответствует один проход алгоритма шифрования DES. Для полного формирования зашифрованного текста ее необ- ходимо выполнить 16 раз. Проме- жуточные результаты сохраняются в регистрах RO-R15. Константа К4 определяет номер выполняемого прохода, а флаг половинного пе- реноса Н — тип процесса (шифро- вание или дешифрование) Если H = 0, то шифрование, иначе — дешиф- рование 0<K4<15 1 или 2 EICALL Косвенный вызов подпрограммы, на которую указывают регистры Z и EIND. Эта команда позволяет обращаться ко всему пространству памяти программ (4 Мелов) РС(15:0)«— Z(15:0) PC(21:16)«—EIND Стек«- PC + 1 SP <- SP - 3 3 или 4 EIJMP Косвенный переход по адресу, за- данному регистрами Z и EIND. Эта команда позволяет обращаться ко всему пространству памяти про- грамм (4 Мелов), PC(15:0) «- Z(15:0) PC(21:16)«—EIND 2
489 Таблица В.1. Продолжение Мнемо- ника Операн- ды Описание Операция Влияние на флаги Цик- лов ELPM а) — б) Rd, Z в) Rd, Z+ Байт памяти программ, адре- суемый с помощью регистро- вой пары RAMPZrZ, загружает- ся в регистр R0 (вариант а) или Rd (вариант б и в). Разряд 0 указателя Z определяет, какой байт должен быть загружен: младший (разряд 0 = 0) или старший (разряд 0 = 1). Дос- тупно адресное пространство более 64К a) R0<- (RAMPZ:Z) б) Rd<- (RAMPZ:Z) в) Rd 4— (RAMPZ:Z); Z<-Z+ 1 0<d<31 3 EOR Rd, Rr Объединение логической опе- рацией “Исключающее ИЛИ” содержимого регистров Rd и Rr Rd <— Rd Ф Rr 0<d<31 0<r<31 s, v=o, N,Z 1 FMUL Rd, Rr Беззнаковое перемножение множителя Rr и множимого Rd. Результат записывается в ре- гистровую пару R1:R0 (R1 — старший байт; R0 — младший байт), после чего сдвигается на один разряд влево R1:R0<—RdxRr (unsigned (1.15) 4— unsigned(1.7) x un- signed(1.7)) 16<d<23 16<r<23 c.z 2 FMULS Rd, Rr Знаковое перемножение мно- жителя Rr и множимого Rd. Ре- зультат записывается в регист- ровую пару R1:R0 (R1 — стар- ший байт; R0 — младший байт), после чего сдвигается на один разряд влево R1:R0<—RdxRr (signed (1.15) 4- signed(1.7)x signed(1.7)) 16<d<23 16<r<;23 c,z 2 FMULSU Rd, Rr Знаковое перемножение без- знакового множителя Rr и зна- кового множимого Rd. Резуль- тат записывается в регистро- вую пару R1:R0 (R1 —старший байт; R0 — младший байт), по- сле чего сдвигается на один разряд влево R1:R0<—RdxRr (signed (1.15) <- signed(1.7) x un- signed(1.7)) 16<d<23 16<r<23 c,z 2 ICALL Косвенный вызов подпрограм- мы, на которую указывает ука- затель Z (г31:г30). Адрес воз- врата (команда, следующая после команды icall), сохра- няется в стеке PC<-Z Стек <— PC + 1 SP — SP - 2 (SP «— SP - 3) 2-4 IJMP — Косвенный переход по адресу, на который указывает указа- тель Z (г31 :г30) PC 4- Z — 2
490 Приложение В. Система команд микроконтроллеров AVR Таблица В.1. Продолжение Мнемо- ника Операн- ды Описание Операция Влияние на флаги Цик- ЛОВ IN Rd, P Загрузка в регистр Rd содер- жимого порта ввода/вывода Р Rd 4—Р 0<d<31 0 < Р < 63 — 1 INC Rd К содержимому регистра Rd прибавляется 1. Флаг переноса не изменяется, благодаря чему Rd можно использовать в каче- ству счетчика цикла при вы- полнении арифметических операций над несколькими байтами. При инкрементирова- нии беззнаковых операндов можно использовать только сравнения на равенство и не- равенство Rd <— Rd + 1 0^d<31 S, V, N, Z 1 JMP K16 (K22) Переход по абсолютному адре- су К16 (при 16-разрядной шине адреса) или К22 (при 22-раз- рядной шине адреса) PC «— K16 (K22) 0 < K16 < 64K 0 < k22 < 4M — 3 LD a) Rd, N 6) Rd, N+ b) Rd, -N Здесь N — X (г27:г26); У (г29:г28) или Z (г31 :г30). Байт из ячейки SRAM, адре- суемой с помощью N, загружа- ется в Rd. В случае (а) после выполнения операции содер- жимое N остается неизменным, в случае (б) оно увеличивается на 1, а в случае (в) — умень- шается на 1 еще до выполне- ния передачи a) Rd 4- (N); 6) Rd 4- (N); N4-N + 1; b)N4-N-1; Rd 4- (N) 0<d<31 1-3 LDD Rd, N+q Здесь N — У (г29:г28) или Z (г31:г30). Байт из ячейки SRAM, адре- суемой с помощью N, загружа- ется в регистр Rd. Содержимое N не изменяется, и во время выполнения операции склады- вается с q Rd 4— (N+q) 0<d<31 0 < q < 63 2 LDI Rd, K8 Загрузка в регистр Rd констан- ты К8 Rd 4—K8 16<d£31 0 < K8 < 255 — 1 LDS Rd, K16 Байт, извлеченный по абсо- лютному адресу К16, загружа- ется непосредственно в ре- гистр Rd Rd 4- (K16) 0<d<31 0 < K16 < 65535 — 2 или 3
491 Таблица В.1. Продолжение Мнемо- ника Операн- ды Описание Операция Влияние на флаги Цик- лов LPM а) — б) Rd, Z в) Rd, Z+ Байт памяти программ, адре- суемый с помощью содержимо- го указателя Z (г31:г30), загру- жается в регистр R0 (вариант а) или Rd (варианты б и в). Разряды 15... 1 указателя Z ад- ресуют 16-разрядную ячейку программной флэш-памяти. Разряд 0 указателя Z опреде- ляет, какой байт должен быть загружен: младший (разряд 0 = 0) или старший (разряд 0=1) a) R0 4- (Z) б) Rd 4- (Z) в) Rd 4- (Z); Z4-Z+ 1 0<d<31 3 LSL Rd Все разряды регистра Rd сдви- гаются на одну позицию влево; флагу переноса присваивается значение разряда 7, а в разряд 0 записывается лог. 0 0<d<31 H, s, V, N,Z, С 1 LSR Rd Все разряды регистра Rd сдви- гаются на одну позицию впра- во; флагу переноса присваива- ется значение разряда 0, а в разряд 7 записывается лог. 0. Флаг переноса может исполь- зоваться для округления 0<d<31 S, V, N=0, Z, C 1 MOV Rd, Rr Копирование содержимого ре- гистра Rr в регистр Rd. Содер- жимое регистра Rr остается неизменным Rd 4—Rr 0<d<31 0<r<31 1 MOVW Rd+1:Rd, Rr+1:Rr Копирование регистровой пары Rr+1:Rr в регистровую пару Rd+1:Rd. Содержимое регист- ровой пары Rr+1:Rr остается неизменным Rd+1:Rd4- Rr+1:Rr 0 < d < 30 0 < r < 30 1 MUL Rd, Rr Беззнаковое перемножение множителя Rr и множимого Rd. Результат записывается в ре- гистровую пару R1:R0 (R1 — старший байт; R0 — младший байт). Разряд 15 результата копируется в флаг переноса R1:R0 4- RdxRr (unsigned 4— un- signed x unsigned) 0 < d < 31 0<r<31 c 2 MULS Rd, Rr Перемножение множителя Rr и множимого Rd с учетом зна- ка. Результат записывается в регистровую пару R1:R0. Разряд 15 результата копиру- ется в флаг переноса R1:R0 4- RdxRr (signed 4— signed x signed) 16<d<31 16<r<31 c 2
492 Приложение В. Система команд микроконтроллеров AVR Таблица В.1. Продолжение Мнемо- ника Опе- ранды Описание Операция Влияние на флаги Цик- лов MULSU Rd, Rr Перемножение беззнакового мно- жителя Rr и знакового множимого Rd с учетом знака. Результат запи- сывается в регистровую пару R1 :R0 (R1 — старший байт; R0 — младший байт). Разряд 15 резуль- тата копируется в флаг переноса R1:R0<-RdxRr (signed <— signed x unsigned) 16<d<23 16<r<23 С 2 NEG Rd Реализация дополнения до двух содержимого регистра Rd Rd <- 0x00 - Rd 0<d<31 Н, S, V, N.Z, С 1 NOP — Эта команда задерживает ход про- граммы на один такт — — 1 OR Rd, Rr Объединение логической опера- цией “ИЛИ” содержимого регистров Rd и Rr. Результат записывается в регистр Rd Rd «- Rd v Rr 0 < d < 31 0<r<31 s, v=o, N.Z 1 ORI Rd, K8 Объединение логической опера- цией “ИЛИ” содержимого регистра Rd и восьмиразрядной константы К8. Результат записывается в Rd Rd Rd v K8 16<d<31 0 < K8 <; 255 S, V=0, N, Z 1 OUT P, Rr Передача в порт Р содержимого регистра Rr P <—Rr 0 < r < 31 0 < P < 63 — 1 POP Rd Указатель стека увеличивается на 1, после чего байт в памяти SRAM, на который указывает этот указа- тель, записывается в регистр Rd Rd*— Стек 0<d<31 2 PUSH Rr Содержимое регистра Rr сохраня- ется в ячейке SRAM, адресуемой с помощью указатель стека, после чего этот указатель уменьшается на 1 Стек«- Rd 0 < r < 31 2 RCALL K12 Вызов подпрограммы, начало кото- рой должно находиться в диапазо- не PC ± 2К слов. Адрес возврата (команда, Следующая после ко- манды rcall), помещается в стек PC«—PC + K12 + 1 -2K<K12<2K Стек <— PC + 1 SP <- SP - 2 (SP <— SP - 3) 2-4 RET Выход из подпрограммы. Указатель стека увеличивается на 1, после чего соответствующий байт из * SRAM копируется в старший байт счетчика команд. Затем указатель стека еще раз увеличивается на 1 и соответствующий байт из SRAM копируется в младший байт счет- чика команд PC <- Стек SP «— SP + 2 (SP <— SP + 3) 4 или 5
493 Таблица В.1. Продолжение Мнемо- ника Опе- ранды Описание Операция Влияние на флаги Цик- лов RETI Возврат из подпрограммы обработ- ки прерывания. Указатель стека увеличивается на 1, после чего байт из памяти SRAM, на который указывает этот указатель, копиру- ется в старший байт счетчика ко- манд. Затем указатель стека еще раз увеличивается на 1 и соответ- ствующий байт из SRAM копирует- ся в младший байт счетчика ко- манд. Устанавливается флаг обще- го разрешения прерываний PC«- Стек SP <- SP + 2 (SP «— SP + 3) 1=1 4 или 5 RJMP K12 Относительный переход по адресу, который должен находиться в диа- пазоне PC ± 2К слов. Адрес воз- врата (команда, следующая после команды г jmp), помещается в стек PC <- PC + К12 + 1 -2К<К12<2К Стек <- PC + 1 SP«—SP-2 (SP <- SP - 3) 2-4 ROL Rd Все разряды регистра Rd сдвига- ются на одну позицию влево; флаг С копируется в разряд 0, а разряд 7 —вС 0<d<31 н, s, V, N.Z, С 1 ROR Rd Все разряды регистра Rd сдвига- ются на одну позицию вправо; С копируется в разряд 7, а разряд 0 —в С 0<d<31 S, V, N, Z, C 1 SBC Rd, Rr Содержимое регистра Rr и флаг переноса вычитаются из содержи- мого регистра Rd Rd<—Rd-Rr-C 0<d<31 0<r<31 H, S, V, N, Z, C 1 SBCI Rd, K8 Восьмиразрядная константа К8 и флаг переноса вычитаются из содержимого регистра Rd Rd <- Rd - K8 - C 16<d<31 0 < К < 255 H, S, V, N,Z, C 1 SBI P, b Запись лог. 1 в разряд b регистра ввода/вывода Р l/O(P, b) 1 0 < P < 31 0<b<7 — 1 или 2 SBIC P.b Если разряд b регистра ввода/вы- вода Р содержит лог. 0, то сле- дующая команда пропускается Если l/O(b) = 0, to PC PC + 2 (3), иначе PC <- PC+1 #0<P<31 0<b<7 1-4 SBIS P, b Если разряд b регистра ввода/вы- вода Р содержит лог. 1, то сле- дующая команда пропускается Если l/O(b) = 1, to PC <— PC + 2 (3), иначе PC ♦- PC+1 0 < P < 31 0<b<7 1-4
494 Приложение В. Система команд микроконтроллеров AVR Таблица В.1. Продолжение Мнемо- ника Операнды Описание Операция Влияние на флаги Цик- лов SBIW Rd+1:Rd, K6 Шестиразрядная константа Кб вычитается из содержимого ре- гистровой пары Rd+1:Rd Rd+1:Rd«— Rd+1:Rd-K6 dl е{24, 26, 28, 30} 0 < Кб < 63 S, V, N, z.c 2 SBR Rd, K8 Установка в регистре Rd разря- дов, заданных с помощью опе- рации “ИЛИ” с константой К8 Rd <- Rd v К8 16 < d £ 31 0 < К8 < 255 S, V = 0, N.Z 1 SBRC Rr, b Если разряд b регистра Rr со- держит лог. 0, то следующая команда пропускается Если Rr(b) = 0, то PC «— PC + 2 (3), иначе PC «- РС+1 0 < г < 31 0<b<7 1-3 SBRS Rr, b Если разряд b регистра Rr со- держит лог. 1, то следующая команда пропускается Если Rr(b) = 1, то PC <- PC + 2 (3), иначе PC о- РС+1 0 < г < 31 0<Ь<7 1-3 SEC — Установка флага переноса в регистре SREG С«-1 \ C = 1 1 SEH — Установка флага половинного переноса в регистре SREG Н<-1 H = 1 1 SEI — Установка флага общего раз- решения прерываний в SREG |<-1 1 = 1 1 SEN — Установка флага отрицательно- го результата в SREG N <—1 N = 1 1 SER Rd Установка всех разрядов реги- стра путем записи непосредст- венного значения OxFF Rd <- OxFF 16 < d < 31 — 1 SES — Установка флага знака в реги- стре SREG S<- 1 S= 1 1 SET — Установка флага копирования в регистре SREG T«-1 T = 1 1 SEV — Установка флага переполнения в регистре SREG V<- 1 V= 1 1 SEZ — Установка нулевого флага в регистре SREG Zo-1 Z = 1 1 SLEEP — Процессор переходит в “спя- щий” режим, определенный с помощью регистра MCUCR — 1 SPM Служит для стирания некоторой страницы в памяти программ, для записи в память программ слова или страницы, а также — для установки разрядов блоки- ровки загрузчика a) (RAMPZ:Z) <- OxFFFF 6) (RAMPZ:Z) <- R1:R0 в) (RAMPZ:Z) TEMP r) BLBITS*—R1:R0 За- ви- сит от one ра- ции
Наличие команд в различных микроконтроллерах AVR 495 Таблица В.1. Окончание Мнемо- ника Операнды Описание Операция Влияние на флаги Цик- лов ST a) N, Rr 6) N+, Rr в) -N, Rr Здесь N — X(r27:r26), Y(r29:r28) или Z (r31:r30). Содержимое регистра Rr сохра- няется в ячейку SRAM, адре- суемую с помощью указателя N. В случае (а) после выполнения операции содержимое X оста- ется неизменным, в случае (б) оно увеличивается на 1, а в случае (в) — уменьшается на 1 еще до выполнения передачи a) (N) 4- Rr; б) (N) <- Rr; N <- N + 1; в) N <— N-1; (N) Rr 0 < г < 31 1 или 2 STD N+q, Rr Здесь N — Y (г29:г28) или Z (г31:г30). Содержимое регистра Rr сохра- няется в ячейку SRAM, адресуе- мую с помощью указателя N. Содержимое N не изменяется, и во время выполнения опера- ции складывается с q (N+q) <- Rr 0 < г < 31 0 < q < 63 2 STS K16, Rr Загрузка в ячейку SRAM по аб- солютному 16-разрядному ад- ресу К16 содержимого регистра Rr (К16) <- Rr 0 < г < 31 0<К16< 65535 2 SUB Rd, Rr Содержимое регистра Rr вычи- тается из содержимого регистра Rd Rd 4— Rd - Rr 0<d<31 0<r<31 H, S, V, N.Z, С 1 SUBI Rd, K8 Восьмиразрядная константа К8 вычитается из содержимого ре- гистра Rd Rd — Rd - K8 16<d<31 0 < K8 < 255 H, s, V, N.Z, С 1 SWAP Rd Старший и младший полубайты регистра Rd меняются местами Rd(7-4)<—Rd(3-0), Rd(3-O)<—Rd(7-4) 0<d<31 — 1 TST Rd Проверка, является ли содер- жимое регистра Rd нулевым или отрицательным, с помощью применения логической опера- ции “И”. Само содержимое реги- стра Rd остается неизменным Rd 4— Rd л Rd 0<d<31 s, v = о, N.Z 1 WDR — Устанавливает в исходное со- стояние сторожевой таймер — 1 Наличие команд в различных микроконтроллерах AVR Следует отметить, что все команды, перечисленные в табл. В.1, используются только в микроконтроллерах семейства ATxmega. Определенные группы ассемб- лерных команд в тех или иных устройствах AVR недоступны (см. табл. В.2).
496 Приложение В. Система команд микроконтроллеров AVR Таблица В.2. Команды, которые могут быть недоступны в различных моделях AVR Микроконт- роллер ADIW SBIW MULx FMULx JMP CALL IJMP ICALL EIJMP EICALL MOVW LDS LDD STD STS PUSH POP BREAK DES ELPM SPM AT90S1200 - AT90S2313 z - — z - - z z z z - - - - AT90S2323 z — — z — — z z z z — - - - AT90S2343 z - — z — — z z z z - - - - AT90S4414 z — — z — — z z z z — — - - AT90S4433 z — — z — — z z z z - - - - AT90S8515 z - — z — — z z z z - - - - AT90S8535 z - - z — — z z z z - - - - ATtiny 11 — ATtiny 12 - — — — — — — — — — — - - - ATtiny 13А z — — z — z z z z z — — — z ATtiny15L — - - — — — - - — - - - - - ATtiny2313 z — — z — z z z z z , — - — z ATtiny24 z - — z — z z z z z z - - z ATtiny25 z — — z — z z z z z z - - / ATtiny26 z — — z — — — z z z — — — - ATtiny261 z — — z — z z z z z z — — z ATtiny28L - - — — — - — — — - - - - - ATtiny44 z — — z — z z z z z z — - z ATtiny45 z — — z - z z z z z z - - z ATtiny461 z — - z — z z z z z z - — z ATtiny48 z — — z — z z z z z z - — / ATtiny84 z — — z — z z z z z z — — / ATtiny85 z - — z — z z z z z z - - z ATtiny861 z — — z — z z z z z z — — z ATtiny88 z - - z - z z z z z z - - z ATmega128 z z z z ' - z z z z z z - — z ATmega1280 z z z z z z z z z z z — z z ATmega1281 z z z z z z z z z z z — z z ATmega 1284 z z z z — z z z z z z - — z ATmega 16 z z z z — z z z z z z — — z ATmega 16A z z z z — z z Z ‘ z z z - — z ATmega 162 z z z z — z z z z z z — — z ATmega164P z z z z — z z z z z z — — z ATmega 165P z z z z — z z z z z z - - z ATmega 168P z z z z - z z z z z z — - z ATmega 169 z z z z - z z z z z z - - z ATmega2560 z z z z z z z z z z z — z / ATmega2561 z z z z z z z z z z z - z z ATmega32A z z z z — z z z z z z — — z ATmega324PA z z z z — z z z z z z — — z ATmega325P z z z z — z z z . Z z z — — z ATmega3250P z z z z — z z z z z z — — z ATmega328P z z z z - z z z z z z - - z
Команды по категориям 497 Таблица В.2. Окончание Микроконт- роллер ADIW SBIW MULx FMULx JMP CALL IJMP ICALL EIJMP EICALL MOVW LDS LDD STD STS PUSH POP BREAK DES ELPM SPM ATmega48PA z z - z - z z z z z z - — z ATmega64 z z z z — z z z z z z — — z ATmega640 z z z z z z z z z z z — z z ATmega644P z z z z - z z z z z z - - z ATmega645 z z z z - z z z z z z - - z ATmega6450 z z z z — z z z z z z - - z ATmega8 z z - z - z z z z z — - - z ATmega8515 z z z z - z z z z z - — — z ATmega8535 z z z z - z z z z z z — - / ATmega88PA z z - z - z z z z z z - — z Команды по категориям Наконец, для удобства тематического поиска распределим все команды, пере- численные в табл. В.1, по категориям (табл. В.З). Таблица В.З. Распределение команд AVR по категориями Арифметические Ветвления Пересылки Поразрядные Управления ADC BRCC/S ELPM ASR BREAK ADD BRBC/S IN BCLR NOP ADIW BREQ LD BLD SLEEP AND BRGE LDD BSET WDR ANDI BRHC/S LDI BST CBR BRID ' LDS CBI CLR BRIE LPM CLC COM BRLO MOV CLH DEC BRLT MOVW CLI DES BRMI OUT CLN EOR BRNE POP CLS FMUL BRPL PUSH CLT FMULS BRSH SPM CLV FMULSU BRTC/S ST CLZ INC BRVC/S STD LSL MUL CALL STS LSR MULS CP ROL MULSU CPC ROR NEG CPI SBI OR CPSE SEC ORI EICALL SEH SBC EIJMP SEI SBCI ICALL SEN SBIW IJMP SES SBR JMP SET SER RCALL SEV SUB RET SEZ SUBI RETI SWAP TST RJMP SBIC/S SBRC/S
Приложение Г Система команд микроконтроллеров PIC Команды восьмиразрядных микроконтроллеров Для начала рассмотрим команды восьмиразрядных микроконтроллеров PIC (табл. Г.1). При этом будут использованы следующие условные обозначения: • F — адрес регистра в регистровом файле; • W — рабочий регистр (накапливающий сумматор); • b — номер разряда в регистре; • К — литеральное поле, константа или метка; • А — адрес; • а — указатель доступа в микроконтроллерах семейства PIC 18: если а = 1, то при доступе используется регистр выбора банка, иначе — банк доступа; • Р — обозначение порта ввода-вывода; • d — указатель выбора направления; • s — указатель операции; • PC — счетчик команд; • SP — указатель вершины стека; • Стек — область памяти для промежуточного хранения данных; • С — флаг переноса (регистр STATUS); • DC — флаг десятичного переноса (регистр STATUS); • Z — флаг нулевого результата (регистр STATUS); • N — флаг отрицательного результата (регистр STATUS); • OV — флаг переполнения (регистр STATUS); • PD — флаг режима пониженного энергопотребления (регистр STATUS); • ТО — флаг подачи напряжения (регистр STATUS). 4 Сразу отметим, что не все команды, перечисленные в табл. Г. 1, используются в различных семействах микроконтроллеров PIC. Информация о поддержке той или иной команды конкретным семейством представлена в табл. Г.2. Таблица Г.1. Общие команды восьмиразрядных микроконтроллеров PIC Мнемо- ника Операнды Описание Операция Влияние на флаги Цик- лов ADDLW К Сложение константы К с со- держимым регистра W W<- W + K С, DC, Z (OV, N) 1
Команды восьмиразрядных микроконтроллеров 499 Таблица Г.1. Продолжение Мнемони- ка Операн- ды Описание Операция Влияние на флаги Цик- лов ADDWF a) F, d б) F, d, а Содержимое регистра F скла- дывается с содержимым реги- стра W. Результат размещается в соответствии со значением d Если (d = 1), то F <— F + W, иначе W 4—F + W с, DC, Z (N, OV) 1 ADDWFC a) F.d б) F, d, а Содержимое регистра F скла- дывается с содержимым реги- стра W и флагом переноса. Ре- зультат размещается в соот- ветствии со значением указа- теля d Если (d = 1), то W <-F + W + С, иначе F<-F + W+C C, DC, Z, OV (N) 1 ANDLW К Поразрядное объединение операцией “И” константы К с содержимым регистра W W<-W&K Z 1 ANDWF a) F, d б) F, d, а Поразрядное объединение операцией “И” содержимого ре- гистра F с содержимым регист- ра W. Результат размещается в соответствии со значением d Если (d = 1), то F <- F & W, иначе W*—F&W z 1 ВС К Переход к метке К, если уста- новлен флаг переноса ЕслиС=1,то PC 4— PC + 2 + К — 1 (2) BCF a) F,b б) F, Ь, а Обнуление разряда b регистра F F(b) <-0 — 1 BN К Переход к метке К, если уста- новлен флаг отрицательного результата Если N=1, то PC PC + 2 + К — 1 (2) BNC к Переход к метке К, если флаг переноса не установлен Если С=0, то PC <- PC + 2 + К — 1 (2) BNN к Переход к метке К, если флаг отрицательного результата сброшен Если N=0, то PC <— PC + 2 + К — 1 (2) BNOV к Переход к метке К, если сбро- шен флаг переполнения Если OV=0, то PC <— PC + 2 + К — 1 ' (2) BNZ к Переход к метке К, если ре- зультат выполнения предыду- щей операции не равен 0 Если Z=0, то PC «- PC + 2 + К — 1 (2) BOV к Переход к метке К, если уста- новлен флаг переполнения Если OV=1, то PC «- PC + 2 + К — 1 (2) BRA к Безусловный переход к метке К PC 4— PC + 2 + К — 2 BSF a) F.b б) F, Ь,а Установка в лог. 1 разряда b регистра F F(b) 1 — 1 BTFSC a) F, b б) F, Ь,а Пропуск следующей команды, если разряд b в регистре F ра- вен 0 Если F(b)=O, то PC 4- PC + 1 — 1 (2) BTFSS a) F, b б) F, Ь, а Пропуск следующей команды, . если разряд b в регистре F ра- вен 1 Если F(b)=1, то PC 4- PC + 1 — 1 (2)
500 Приложение Г. Система команд микроконтроллеров PIC Таблица Г.1. Продолжение Мнемони- ка Операн- ды Описание Операция Влияние на флаги Цик- лов BTG a) F, b б) F, Ь, а Изменение со- стояния разряда b регистра F F «— F Л (1 « Ь) — 1 BZ К Переход к метке К, если резуль- тат выполнения предыдущей операции = 0 Если Z=1, то PC <- PC + 2 + К 1 (2) CALL а) А б) А в) К г) К, s Переход к под- программе a) [SP] «- PC; SP <- SP+1; PC = ((STATUS & OxOEO) « 4+A; 6) [SP] PC; SP «- SP+1; PC = ((PCLATH « 8) & 0x01800) + A; в) [SP] 4- PC; PCLATH — PC(15:13) + K(12:8); PCL— K(7:0); r) [SP]«— PC. Если s = 1, то [SP] <-'W; [SP] — STATUS; . [SP] *- BSR. PC — К 2 CLRF a)F . б) F, s в) F, а Стирание реги- стра F a)F<-0 6) F 4— 0. Если s = 0, то W 4— 0 в) F <—0 Z+- 1 1 CLRW — Стирание реги- стра W W4-0 Z4-1 1 CLRWDT — Сброс стороже- вого таймера WDT 4-0 TO«—1; PD«—1 1 COMF a) F, d б) F, d, а Инвертирование содержимого ре- гистра F и раз- мещение ре- зультата в соот- ветствии со зна- чением указате- ля d Если d=1, to F «— F Л OxOFF, иначе W <- F л OxOFF Z(N) 1 CPFSEQ a) F б) F, а Сравнение со- держимого F и W. В случае ра- венства сле- дующая команда пропускается Если (F — W) = 0, то PC 4- PC + 1 1-3 CPFSGT a)F б) F, а Сравнение со- держимого реги- стров F и W. Ес- ли F больше W, то следующая команда пропус- кается Если (F — W) > 0, то PC <- PC + 1 1-3
Команды восьмиразрядных микроконтроллеров 501 Таблица Г.1. Продолжение Мнемони- ка Операн- ды Описание Операция Влияние на флаги Цик- лов CPFSLT a) F б) F, а Сравнение содержимого регистров F и W. Если F меньше W, то следующая команда пропускается Если (F - W) < 0, то PC PC + 1 — » 1-3 DAW a) F, s б)- Десятичная коррекция содержимого регистра W а) Если (W&OxOF) > 9, то при s=0 W *— (W&OxOF)+ 0x010, а при s=1 F *— (W&0x0F)+ 0x010; б) Если (W&0x0F) > 9, то при s=0 W *— (W&0x0F)+ 0x010 » 1 DCFSNZ a) F, d б) F, d, а Декрементирование со- держимого регистра F и размещение результата в соответствии со значе- нием указателя d. Если результат не равен 0, то следующая команда про- пускается Если d=1, то F *— F - 1, иначе W <— F - 1. Если (F—1) # 0, то PC PC + 1 1-3 DECF a) F, d б) F, d, а Декрементирование со- держимого регистра F и размещение результата в соответствии со значе- нием указателя d Если d=1, то F <— F - 1, иначе W <— F - 1 7. {ON, DC, C, N) 1 DECFSZ a) F, d б) F, d, а Декрементирование со- держимого регистра F и размещение результата в соответствии со значе- нием указателя d. Если результат равен 0, то следующая команда про- пускается Если d=1, то F F - 1, иначе W<-F-1. Если (F-1) = 0, to PC <- PC + 1 1 (2) GOTO а) А б) А в) К г) К Безусловный переход a) PC <- ((STATUS & OxOEO) « 4) + A; 6) PC ((PCLATH « 8) & 0x01800) + A; в) PCLATH *- PC(15:13) + K(12:8); PCL = K(7:0); r) PC 4— К 2 INCF a) F, d б) F, d, а Инкрементирование со- держимого регистра F и размещение результата в соответствии со значе- нием указателя d Если d=1, то F 4- F + 1, иначе W 4— F + 1 Z(OV, DC, C, N) 1
502 Приложение Г. Система команд микроконтроллеров PIC Таблица Г.1. Продолжение Мнемони- ка Операн- ды Описание Операция Влияние на флаги Цик- лов INCFSZ a) F, d б) F, d, а Инкрементирование содержи- мого регистра F и размещение результата в соответствии со значением указателя d. Если результат равен 0, то следую- щая команда пропускается Если d=1, то F <— F + 1, иначе W<—F + 1. Если (F+1) = 0, то PC <— PC + 1 1 (2) INFSNZ a) F, d б) F, d, а Инкрементирование содержи- мого регистра F и размещение результата в соответствии со значением указателя d. Если результат не равен 0, то сле- дующая команда пропускается Если d=1, то F *- F + 1, иначе W—F + 1. Если (F+1) # 0, то PC <- PC + 1 1-3 IORLW К Поразрядное объединение со- держимого регистра W и кон- станты К логической операци- ей “ИЛИ” W<-W|K Z(N) 1 IORWF a) F, d б) F, d, а Поразрядное объединение со- держимого регистров F и W ло- гической операцией “ИЛИ” с размещением результата в со- ответствии со значением ука- зателя d Если d=1, то F *- F | W, иначе W<—F|W Z(N) 1 LCALL К “Длинный” переход [SP]«- PC; SP+-SP+1; PCL <- K(7:0) — 2 LFSR F, К Загрузка константы К в ре- гистр, определенный регист- ром FSR FSR(F) — К — 2 MOVF a) F, d б) F, d, а Пересылка содержимого реги- стра F в регистр W в соответ- ствии со значением d Если d=0, то W<—F Z(N) \ 1 MOVFF Fs, F<j Пересылка содержимого реги- стра-источника Fs в регистр- приемник Fd Fd - Fs — 2 MOVFP F.p Пересылка содержимого реги- стра F в регистр из первичной области (00-1F) P F — 1 MOVLB К Загрузка константы К в млад- ший полубайт регистра BSR BSR(3:0) — К — 1 MOVLR к Загрузка константы К в стар- ший полубайт регистра BSR BSR(7:4) <- К — 1 MOVLW к Пересылка содержимого кон- станты К в регистр W W«-K — 1 MOVPF P.F Пересылка содержимого реги- стра из первичной области (00-1F) в регистр F F-P z 1
Команды восьмиразрядных микроконтроллеров 503 Таблица Г.1. Продолжение Мнемони- ка Операн- ды Описание Операция Влияние на флаги Цик- лов MOVWF a)F 6) F, a Загрузка содержимого ре- гистра W в регистр F F<—W — 1 MULLW К Умножение содержимого регистра W на константу К PRODH:PRODL *- K*W — 1 MULWF a)F 6) F, a Перемножение содержи- мого регистров W и F PRODH:PRODL «- F*W — 1 NEGF F, a. Изменение знака содер- жимого регистра W F«—F C, DC, Z, OV, N 1 NEGW F, s Изменение знака содер- жимого регистра W Если s=0, to F — -W; W <- -W C, DC, Z, OV (N) 1 NOP — Пустая операция — — 1 OPTION — Загрузка содержимого W в регистр OPTION OPTION <- W — 1 POP — Извлечение значения из стека в регистр W W *— Стек — 2 PUSH — Помещение значения ре- гистра W в стек Стек 4-~- W — 2 RCALL К Вызов подпрограммы по 11-разрядному адресу [SP] 4—PC; SP4- SP+1; PC 4— PC + 2 + К — 2 RESET — Перезапуск микрокон- троллера MCLR — 0; MCLR 4- 1 — 1 RETFIE a) — 6)- b) s Возврат из прерывания a)GIE4-1; SP4-SP-1; PC 4- [SP]; 6)SP4—SP-1; PC 4- [SP]; GLTIND 4- 0; в) SP4-SP-1; PC 4- [SP]; GIE 4- 0. Если s=1, то восста- навливаются из стека регистры W, STATUS и BSR 2 RETLW К Возврат из подпрограммы с загрузкой К в регистр W W«-K; SP«—SP-1; PC«- [SP] — 2 RETURN a) — 6) s Возврат из подпрограммы a) SP4-SP-1; PC4-[SP] 6) SP4-SP-1; PC4-[SP] Если s = 1, то восста- новление из стека со- держимого регистров W, STATUS и BSR 2 RLCF a)F, d 6) F, d, a Циклический сдвиг содер- жимого регистра F влево (через флаг переноса) и сохранение результата в соответствии со значением указателя d Если d=1, то F(7:1) 4— F(6:0); F(0) 4- С; С 4- F(7). Если d=0, то W(7:1) 4- F(S:O); W(0) 4- С; C 4- F(7)
504 Приложение Г. Система команд микроконтроллеров PIC Таблица Г.1. Продолжение Мнемони- ка Операн- ды Описание Операция Влияние на флаги Цик- лов RLF F, d Циклический сдвиг содер- жимого регистра F влево (через флаг переноса) и сохранение результата в соответствии со значе- нием указателя d Тетр <— С; С <—(F » 7)&1. Если d=1, то F *- (F « 1) +Тетр, иначе W<- (F « 1) + Тетр с 1 RLNCF a) F, d б) F, d, а Циклический сдвиг содер- жимого регистра F влево и сохранение результата в соответствии со значе- нием указателя d Если d=1, то F(7:1) 4— F(6:0); F(0) <- F(7). Если d=0, то W(7:1) +- F(6:0); W(0) <- F(7) (N) 1 RRCF a) F, d б) F, d, а Циклический сдвиг содер- жимого регистра F вправо (через флаг переноса) и сохранение результата в соответствии со значе- нием указателя d Если d=1, to F(6:0) <- F(7:1); F(7) — С; C «- F(0). Если d=0, to W(6:0) <- F(7:1); W(7) <- С; C <- F(0) C(N) 1 RRF F, d Циклический сдвиг содер- жимого регистра F вправо (через флаг переноса) и сохранение результата в соответствии со значе- нием указателя d Temp ♦- С; C ♦- F & 1. Если d=1, to F <— (F » 1) + (Temp « 7), иначе W <— (F » 1) + (Temp << 7) С 1 RRNCF a) F, d б) F, d, а Циклический сдвиг содер- жимого регистра F вправо и сохранение результата в соответствии со значе- нием указателя d Если d=1, to F(6:0) <- F(7:1); F(7) - F(0). Если d=0, to W(6:0) «- F(7:1); W(7) — F(0) (N) 1 SETF a) F, s б) F, s,а Установка в лог. 1 всех разрядов регистра F F <— OxOFF. Если s=0, T0W4-OXOFF — 1 SLEEP — Перевод микроконтролле- ра в режим ожидания WDT 4-0 TD4-1; PD4-0 1 SUBFWB F, d, а Вычитание содержимого регистра F и переноса из содержимого регистра W с размещением результа- та в соответствии со зна- чением указателя d Если d=1, to W4-W-F-IC, иначе F<—VV-F-!C c, DC, Z, OV, N 1 SUBLW К Вычитание содержимого регистра W из константы К W4-K+(Wa0x0FF)+1 C, DC, Z (OV, N) 1 SUBWF a) F, d б) F, d, а Вычитание содержимого регистра W из содержимо- го регистра F с размеще- нием результата в соот- ветствии со значением указателя d Если d=1, to W<—F+(WA0x0FF)+1, иначе F <— F + (WA0x0FF)+1 C, DC, Z (N, OV) 1
Команды восьмиразрядных микроконтроллеров 505 Таблица Г.1. Продолжение Мнемони- ка Операн- ды Описание Операция Влияние на флаги Цик- лов SUBWFB a) F, d б) F, d, а Вычитание содержимого W из содержимого F (с учетом переноса) с раз- мещением результата в соответствии со значе- нием d Если d=1, то W.<-F-W-!C, иначе F<-F-W-!C c, DC, Z, OV (N) 1 SWAPF a) F, d б) F, d, а Перестановка местами старшего и младшего полубайтов регистра F с размещением результа- та в соответствии со значением указателя d Если d=1, то F ((F & OxOFO) » 4) + ((F & OxOOF)« 4), иначе W<-((F & OxOFO) » 4) + ((F & OxOOF) « 4) 1 TABLRD a) t, I, F б) Option Табличное чтение. В случае (а) — считыва- ние через регистр TBLATH одного из двух байтов содержимого ячейки памяти про- грамм, определяемой указателем TBLPTR. В случае (б) — считыва- ние содержимого ячейки памяти программ, опре- деляемой табличным указателем TBLPTR a) F 4- TBLATH; если t=1, to TBLAT 4— Prog- Mem(TBLPTR). Если i=1, to TBLPTR 4—TBLPTR+1. б) Если Option = *, to TABLAT *— ProgMem (TBLPTR). Если Option = *+, to TABLAT 4-Prog- Mem(TBLPTR);TBLPTR 4—TBLPTR+1.Если Option = to TABLAT 4— Prog- Mem (TBLPTR); TBLPTR 4—TBLPTR-1. Если Op- tion = +*, to TBLPTR 4— TBLPTR + 1; TABLAT 4- ProgMem (TBLPTR) 2 (3) TABLWT a) t, I, F б) Option Табличная запись. В случае (а) — запись че- рез регистр TBLATH со- держимого регистра F в ячейку памяти про- грамм, определяемой указателем TBLPTR. В случае (б) — запись со- держимого табличного регистра в ячейку памя- ти программ, опреде- ляемую указателем TBLPTR. Если приемни- ком является встроен- ная память EEPROM, то команда завершается только по прерыванию a) TBLATH 4- F; если t=1, то TBLAT4— Prog- Mem(TBLPTR). Если i=1,TO TBLPTR 4— TBLPTR + 1. б) Если Option = *, to ProgMem(TBLPTR) 4— TABLAT. Если Option = *+, to ProMem (TBLPTR) 4- TABLAT; TBLPTR 4- TBLPTR+1. Если Option = to ProMem (TBLPTR) 4- TABLAT; TBLPTR 4-TBLPTR-1. Если Option = +*, to TBLPTR 4-TBLPTR + 1; ProgMem(TBLPTR) TABLAT. 2 или бо- лее
506 Приложение Г. Система команд микроконтроллеров PIC Таблица Г.1. Окончание Мнемони- ка Операн- ды Описание Операция Влияние на флаги Цик- лов TLRD t. F Считывание в регистр F содер- жимого старшего или младшего байта табличного регистра Если t=1, то F <- TBLATH, иначе F <- TBLATL — 1 TLWT t, F Запись содержимого регистра F в старший или младший байт табличного регистра Если t=1, то TBLATH F, иначе TBLATL <- F — 1 TSTFSZ a)F 6) F, a Если содержимое регистра F равно нулю, то пропускается следующая команда Если F = 0, то PC «— PC + 1 — 1 (2) TRIS p Пересылка содержимого реги- стра W в регистр управления порта TRIS TRIS(P)«- W — 1 XORLW к Поразрядное объединение со- держимого регистра W и кон- станты К логической операцией “Исключающее ИЛИ” W<- WAK Z(N) 1 XORWF a) F, d 6) F, d, a Поразрядное объединение со- держимого регистров F и W ло- гической операцией “Исклю- чающее ИЛИ” с сохранением результата в соответствии со значением указателя d Если d=1, to F *— F A W, иначе W*-FAW Z(N) 1 Таблица Г.2. Поддержка команд в различных семействах микроконтроллеров PIC Команда Вариант PIC с 12-раз рядным кодом операции PIC с 14-pазрядным кодом операции PIC17 PIC18 ADDLW addlw К — / J ADDWF addwf F, d / / V — addwf F, d, a — — — ADDWFC addwfc F, d j j — addwfc F, d, a — — — ANDLW andlw К j ANDWF andwf F, d j — andwf F, d, a — — — J BC be К — — — BCF bef F, b / — bef F, b, a — — — Y BN bn К — — — J BNC bnc К — — — S BNN bnn К — — — Y BNOV bnov К — — — J BNZ bhz К — — — BOV bov К — — - J
Команды восьмиразрядных микроконтроллеров 507 Таблица Г.2. Продолжение Команда Вариант PIC с 12-разрядным кодом операции PIC с 14-разрядным кодом операции PIC17 PIC18 BRA bra К — — — z BSF bsf F, b j z z — bsf F, b, a — — — z BTFSC btfsc F, b •j z — btfsc F, b, a — — — z BTFSS btfss F, b j z — btfss F, b, a — — — z BTG btg F, b — — z — btg F, b, a — — — z BZ bz К — — — z CALL call A j j — — call К — — z — call K, s — — — z CLRF clrf F Z j — — clrf F, s — — z — clrf F, a — — — z CLRW clrw Z j — — CLRWDT clrwdt j Y z z COMF comf F, d z — comf F, d, a — — —. z CPFSEQ cpfseq F — — z — cpfseq F, a — — — z CPFSGT cpfsgt F — — z — cpfsgt F, a — — — z CPFSLT cpfslt F — — > z — cpfslt F, a — — — z DAW daw F, s — — z — daw — — — z DCFSNZ dcfsnz F, d — — z — dcfsnz F, d, a — — — z DECF decf F, d Z z z — decf F, d, a — — — z DECFSZ decfsz F, d Z z z — decfsz F, d, a — — — z GOTO goto A j z — — goto К — — ' z z INCF incf F, d j z z — incf F, d, a — — — z INCFSZ incfsz F, d j z z — incfsz F, d, a — — — z INFSNZ infsnz F, d — — z — infsnz F, d, a — — — z IORLW iorlw К — — z z
508 Приложение Г. Система команд микроконтроллеров PIC Таблица Г.2. Продолжение Команда Вариант PIC c 12-разрядным кодом операции PIC с 14-разрядным кодом операции PIC17 PIC18 IORWF iorwf F, d z z — iorwf F, d, a — — z LCALL Icall К — — z — LFSR Ifsr F, К — — — z MOVF movf F, d z — — movf F, d, a — — — z MOVFF movff Fs, Fd — — — z. MOVFP movfp F, p — — z — MOVLB movlb К — — z z MOVLR movlr К — — z — MOVLW moviw К z z z MOVPF movpf p, F — — z — MOVWF movwf F j z z — movwf F, a — — — z MULLW mullw К — — z / MULWF mulwf F — — z — mulwf F, a — — — z NEGF negf F, a — — — z NEGW negw W, s — — z — NOP nop z z z z OPTION option Z \ z — — POP pop — — — z PUSH push — — — z RCALL rcall К — — — z RESET reset — — — z RETFIE retfie — z z — retfie s — — — z 4 RETLW retlw К z z z z RETURN return z z z — return s — — — z RLCF rlcf F, d — — z — rlcf F, d, a — — — z RLF rlf F, d z z — — RLNCF rlncf F, d — — z — rlncf F, d, a — — — z RRCF rrcf F, d — — z — rrcf F, d, a — — — z RRF rrf F, d z z — — RRNCF rrncf F, d — — z — rrncf F, d, a — — — z SETF setf F, s — — z — setf F, s, a — — — z SLEEP sleep z z z z SUBFWB subfwb F, d, a — — — z
Команды восьмиразрядных микроконтроллеров 509 Таблица Г.2. Окончание Команда Вариант PIC с 12-разрядным кодом операции PIC с 14-раз рядным кодом операции PIC17 PIC18 SUBLW sublw К s z z z SUBWF subwf F, d z z — subwf F, d, a — — — z SUBWFB subwfb F, d — — z — subwfb F, d, a — — — z SWAPF swapf F, d Z z z — swapf F, d, a — — — z TABLRD tablrd t, i, F — — z — tablrd Option — — — z TABLWT tablwt t, i, F — — Z‘ — tablwt Option — — — z TLRD tlrd t, F — — z — TLWT tlwt t, F — — z — TRIS tris P z — — TSTFSZ tstfsz F , — — z — tstfsz F, a — — — z XORLW xorlw Z z z z XORWF xorwf F, d z z z — xorwf F, d, a — — — z Команды по категориям Для удобства тематического поиска распределим все команды, перечисленные в табл. Г. 1, по категориям (табл. Г.З). Таблица Г.З. Распределение команд PIC по категориями Арифметические Ветвления Пересылки Поразрядные Управления ADDLW RLCF ВС LFSR BCF CLRWDT ADDWF RLF BN MOVF BSF NOP ADDWFC RLNCF BNC MOVFF BTG RESET ANDLW RRCF BNN MOVFP RLCF SLEEP ANDWF RRF BNOV MOVLB RLF CLRF RRNCF BNZ MOVLR RLNCF CLRW SETF BOV MOVLW RRCF COMF SUBFWB BRA MOVPF RRF DAW SUBLW BTFSC MOVWF RRNCF DCFSNZ SUBWF BTFSS OPTION SETF DECF SUBWFB BZ POP DECFSZ SWAPF CALL PUSH INCF XORLW CPFSEQ RCALL INCFSZ XORWF CPFSGT RETLW INFSNZ CPFSLT TABLRD IORLW GOTO TABLWT IORWF LCALL TLRD MULLW RETFIE TLWT MULWF RETLW TRIS NEGF RETURN NEGW TSTFSZ
510 Приложение Г. Система команд микроконтроллеров PIC Система команд микроконтроллеров PIC24 Система команд микроконтроллеров PIC24 представлена в табл. Г.4. В ней ис- пользуются следующие условные обозначения: • #текст — литерал; • {} — необязательное поле или операция; • <n:m> — битовое поле в регистре; • .Ь — выбор байтового режима; • .d — выбор режима двойного слова; • .S — выбор теневого регистра; • .w — выбор режима слова; • bit4 — четырехразрядное поле выбора бита: е {0.. 15}; • С — флаг переноса; • DC — флаг десятичного переноса; • Z — флаг нулевого результата; • N — флаг отрицательного результата; • OV — флаг переполнения; • Ехрг — абсолютный адрес, метка или выражение; • f—адрес файлового регистра: g {0x0000..0xlFFF}; • litl— одноразрядный беззнаковый литерал: g {0, 1}; • lit4— четырехразрядный беззнаковый литерал: g {0..15}; • lit5 — пятиразрядный беззнаковый литерал: g {0..31}; • lit8 — восьмиразрядный беззнаковый литерал: g {0..255}; • litl0 — 10-разрядный беззнаковый литерал: g {0..255} для байтового режима и g {0..1023} для режима слова; • Ш14— 14-разрядный беззнаковый литерал: g {0.. 16384}; • Ш16— 16-разрядный беззнаковый литерал: g {0..65535}; • lit23 — 23-разрядный беззнаковый литерал: g {0..8388608}; • None — поле может быть пустым; • PC — счетчик команд; • Slit 10 — 10-разрядный знаковый литерал: g {-512..511}; • Slitl6— 16-разрядный знаковый литерал: g {-32768..32767}; • SIit6 —- шестиразрядный знаковый литерал: g {-16.. 16}; • Wb — базовый рабочий регистр: g {W0..W15}; • Wd — целевой рабочий регистр: g {Wd, [Wd], [Wd++], [Wd—], [++Wd], [— Wd]}; • Wdo — целевой рабочий регистр: g {Wnd, [Wnd], [Wnd++], [Wnd—], [++Wnd], [-Wnd], [Wnd+Wb]}; • Wm, Wh — пара рабочих регистров: делимое и делитель; • Wn — один из 16 рабочих регистров: g {W0..W15}; • Wnd — один из 16 целевых рабочих регистров: g {W0..W15};
Система команд микроконтроллеров PIC24 511 • Wns — один из 16 рабочих регистров-источников: е {W0..W15}; • WREG — W0 (рабочий регистр, задействованный в командах, работающих с файловыми регистрами); • Ws — рабочий регистр-источник: g {Ws, [Ws], [Ws++], [Ws—], [++Ws], [—Ws]}; • Wso — рабочий регистр-источник: g {Wns, [Wns], [Wns++], [Wns—], [++Wns], [-Wns], [Wns+Wb]}. Таблица Г.4. Система команд микроконтроллеров PIC24 Мнемо- ника Синтаксис Описание Влияние на флаги Цик- лов ADD add f f=f+WREG С, DC, N, OV.Z 1 add f, WREG WREG =f +WREG С, DC, N, OV,Z 1 add Wn Wd = lit10 +Wd С, DC, N, OV, Z 1 add Wb, Ws, Wd Wd = Wb + Ws C, DC, N, OV, Z 1 add Wb, #lit5, Wd Wd = Wb + Iit5 C, DC, N, OV, Z 1 ADDC addc f f = f+ WREG + (C) C, DC, N, OV, Z 1 addc f, WREG WREG =f +WREG+ (C) C, DC, N, OV, Z 1 addc Wn Wd = lit10 + Wd + (C) C, DC, N, OV, Z 1 addc Wb, Ws, Wd Wd = Wb + Ws + (C) C, DC, N, OV, Z 1 addc Wb, #lit5, Wd Wd = Wb + Iit5 + (C) C, DC, N, OV, Z 1 AND and f f = f&WREG N,Z 1 and f, WREG WREG =f& WREG N,Z 1 and Wn Wd = lit10&Wd N.Z 1 and Wb, Ws, Wd Wd = Wb & Ws N, Z 1 and Wb, #lit5, Wd Wd = Wb & Iit5 N.Z 1 ASR asr f f <— результат арифметиче- ского сдвига вправо f C, N, OV, Z 1 asr f, WREG WREG 4— результат арифме- тического сдвига вправо f C, N, OV, Z 1 asr Ws, Wd Wd *— результат арифмети- ческого сдвига вправо Ws C, N, OV, Z 1 asr Wb, Wns, Wnd Wnd *— результат арифмети- ческого сдвига вправо Wb на Ws разрядов N, Z 1 asr Wb, #lit5, Wnd Wnd 4— результат арифмети- ческого сдвига вправо Wb на Iit5 разрядов N, Z 1 BCLR bclr f, #bit4 Обнуление разряда bit-4 в f — 1 bclr Ws, #bit4 Обнуление разряда bit4 в Ws — 1 BRA bra c, Expr Переход, если есть перенос — 1 (2) bra ge, Expr Переход, если больше или равно — 1 (2) bra geu, Expr Переход, если больше или равно, без учета знака — 1 (2) bra gt, Expr Переход, если больше — 1 (2) bra gtu, Expr Переход, если больше, без учета знака — 1 (2)
512 Приложение Г. Система команд микроконтроллеров PIC Таблица Г.4. Продолжение Мнемо- ника Синтаксис Описание Влияние на флаги Цик- лов BRA bra 1е, Ехрг Переход, если меньше или равно — 1 (2) bra leu, Ехрг Переход, если меньше или равно, без учета знака — 1 (2) bra It, Ехрг Переход, если меньше — 1 (2) bra Itu, Ехрг Переход, если меньше, без учета знака — 1 (2) bra n, Ехрг Переход, если отрицательный ре- зультат — 1 (2) bra nc, Expr Переход, если нет переноса — 1 (2) bra nn, Expr Переход, если результат не отрица- тельный — 1 (2) bra nov, Expr Переход, если нет переполнения — 1 (2) bra nz, Expr Переход, если результат не равен нулю — 1(2) bra ov, Expr Переход, если есть переполнение — 1 (2) bra Expr Безусловный переход — 2 bra, Z, Expr Переход, если результат равен нулю — 1(2) bra Wn Рассчитанный переход — 2 BSET bset f, #bit4 Установка в лог. 1 разряда bit-4 в f — 1 bset Ws, #bit4 Установка в лог. 1 разряда bit-4 в Ws — 1 BSW bsw.c Ws, Wb Запись содержимого разряда С в Ws<Wb> — 1 bsw.z Ws, Wb Запись содержимого разряда Z в Ws<Wb> — 1 BTG btg f, #bit4 Инвертирование разряда bit4 в f — 1 btg Ws, #bit4 Инвертирование разряда bit4 в Ws — 1 BTSC btsc f, #bit4 Проверка разряда bit4 в f. Если раз- ряд = 0, то пропуск следующей ко- манды — 1-3 btsc Ws, #bit4 Проверка разряда bit4 в Ws. Если разряд = 0, то пропуск следующей команды —- 1-3 BTSS btss f, #bit4 Проверка разряда bit4 в f. Если раз- ряд = 1, то пропуск следующей ко- манды — 1-3 btss Ws, #bit4 Проверка разряда bit4 в Ws. Если разряд = 1, то пропуск следующей команды — 1-3 BTST btst f,~#bit4 Проверка разряда bit4 в f на равен- ство нулю Z 1 btst.c Ws, #bit4 Запись в С результата проверки раз- ряда bit4 в Ws С 1 btst.z Ws, #bit4 Запись в Z результата проверки раз- ряда bit4 в Ws Z 1
Система команд микроконтроллеров PIC24 513 Таблица Г.4. Продолжение Мнемо- ника Синтаксис Описание Влияние на флаги Цик- лов BTST btst.c Ws, Wb Запись в С результата провер- ки разряда Ws<Wb> С 1 btst.z Ws, Wb Запись в Z результата провер- ки разряда Ws<Wb> Z 1 BTSTS btsts f, #bit4 Проверка разряда bit4 в f на равенство нулю, после чего в него записывается лог. 1 Z 1 btsts.c Ws, #bit4 Запись в С результата провер- ки разряда bit-4 в Ws, после че- го в него записывается лог. 1 с 1 btsts.z Ws, #bit4 Запись в Z результата провер- ки разряда bit4 в Ws, после че- го в него записывается лог. 1 Z 1 CALL call lit23 Вызов подпрограммы — 2 call Wn Косвенный вызов подпро- граммы — 2 CLR clr f f<-0 — 1 clr WREG WREG <- 0 — 1 clr Ws Ws <—0 — 1 CLRWDT clrwdt Сброс сторожевого таймера WDTO 1 COM com f f—Jf N, Z 1 com ff WREG WREG <- !f N, Z 1 com Ws, Wd Wd <- !Ws N, Z 1 СР cp f Сравнение f c WREG С, DC, N, OV, Z 1 cp Wb, #lit5 Сравнение Wb c Iit5 С, DC, N, OV, Z 1 cp Wb, Ws Сравнение Wb c Ws (Wb - Ws) C, DC, N, OV, Z 1 СРО cpO f Сравнение f c 0x0000 C, DC, N, OV, Z 1 cpO Ws Сравнение Ws c 0x0000 C, DC, N, OV, Z 1 СРВ cpb f Сравнение f c WREG с заемом C, DC, N, OV, Z 1 cpb Wb, #lit5 Сравнение Wb c Iit5 с заемом C, DC, N, OV, Z 1 cpb Wb, Ws Сравнение Wb c Ws с заемом (Wb-Ws-!C) C, DC, N, OV, Z 1 CPSEQ cpseq Wb, Wn Сравнение Wb c Wn и пропуск следующей команды, если Wb = Wn — 1-3 CPSGT cpsgt Wb, Wn Сравнение Wb с Wn и пропуск следующей команды, если Wb> Wn — 1-3 CPSLT cpslt Wb, Wn Сравнение Wb с Wn и пропуск следующей команды, если Wb< Wn — 1-3 CPSNE cpsne Wb, Wn Сравнение Wb с Wn и пропуск следующей команды, если Wb#Wn — 1-3 DAW daw Wn Десятичная коррекция Wh c 1
514 Приложение Г. Система команд микроконтроллеров PIC Таблица Г.4. Продолжение Мнемо- ника Синтаксис Описание Влияние на флаги Цик- лов DEC dec f f — f-1 С, DC, N, OV, Z 1 dec f, WREG WREG«—f-1 С, DC, N, OV, Z 1 dec Ws, Wd Wd <- Ws - 1 C, DC, N, OV, Z 1 DEC2 dec2 f f <- f-2 C, DC, N, OV, Z 1 dec2 f, WREG WREG<—f-2 C, DC, N, OV, Z 1 dec2 Ws, Wd Wd — Ws - 2 C, DC, N, OV, Z 1 DISI disi #litl4 Запрет прерываний на Iit14 командных циклов — 1 DIV div.sw Wm, Wn Целочисленное деление 16- разрядного числа на 16-раз- рядное с учетом знака N, C, Z, OV 18 div.sd Wm, Wn Целочисленное деление 32- разрядного числа на 16-раз- рядное с учетом знака N, C, Z, OV 18 div.uw Wm, Wn Целочисленное деление 16- разрядного числа на 16-раз- рядное без учета знака N, C, Z, OV 18 div.ud Wm ,Wn Целочисленное деление 32- разрядного числа на 16-раз- рядное без учета знака N, C, Z, OV 18 EXCH exch Wns, Wnd Перестановка местами Wns и Wnd — 1 FF?1L ffll Ws, Wnd Поиск первой единицы слева c 1 FF1R fflr Ws, Wnd Поиск первой единицы справа c 1 GOTO goto Expr Переход по адресу Ехрг — 2 goto Wn Косвенный переход — 2 INC inc f f — f+1 C, DC, N, OV, Z 1 inc f, WREG WREG*—f + 1 C, DC, N, OV, Z 1 inc Ws, Wd Wd *- Ws + 1 C, DC, N, OV,Z 1 INC2 inc2 f f*-f + 2 C, DC, N, OV, Z 1 inc2 f, WREG WREG<—f+2 C, DC, N, OV, Z 1 inc2 Ws, Wd Wd *- Ws + 2 C, DC, N, OV, Z 1 IOR ior f f *- f “Включающее ИЛИ” WREG N, Z 1 ior f, WREG WREG«- f “Включающее ИЛИ” WREG N, Z 1 ior #litlO, Wn Wd *- Iit10 “Включающее ИЛИ” Wd N,Z 1 ior Wb, Ws, Wd Wd *- Wb “Включающее ИЛИ” Ws N.Z 1 ior Wb, #lit5, Wd Wd ♦- Wb “Включающее ИЛИ” Iit5 N, Z 1 LNK Ink #lit!4 Установить связь с указате- лем фрейма — 1
Система команд микроконтроллеров PIC24 515 Таблица Г.4. Продолжение Мнемо- ника Синтаксис Описание Влияние на флаги Цик- лов LSR Isr f f результат логическо- го сдвига f вправо C, N, OV, Z 1 Isr f, WREG WREG <— результат логи- ческого сдвига f вправо C, N, OV, Z ' 1 Isr Ws, Wd Wd <— результат логиче- ского сдвига Ws вправо C, N, OV, Z 1 Isr Wb, Wns, Wnd Wnd *- результат логиче- ского сдвига Wb вправо на Wns разрядов N, Z 1 Isr Wb, #lit5, Wnd Wnd *- результат логиче- ского сдвига Wb вправо на Iit5 разрядов N, Z 1 MOV mov f, Wn Wn*-f — 1 mov [Wns+SlitlO], Wnd Wnd — [Wns+Slit10] — 1 mov f f«-f N, Z 1 mov f, WREG WREG*-f N, Z 1 mov Wn Wn *- 16-разрядный ли- терал — 1 mov.b #lit8, Wn Wn *- восьмиразрядный литерал — 1 mov Wn, f f*- Wn — 1 mov Wns, [Wns+SlitlO] [Wns+Slit10] — Wns — 1 mov Wso, Wdo Wd <— Ws — 1 mov WREG, f f*-WREG N, Z 1 mov.d Wns, Wd Wd <—W(ns):W(ns+1) — 2 mov.d Ws, Wnd W(nd+1):W(nd) — Ws — 2 MUL mul.ss Wb, Ws, Wnd {Wnd+1, Wnd} знако- вое Wb * знаковое Ws — 1 mul.su Wb, Ws, Wnd {Wnd+1, Wnd} ♦- знако- вое Wb * беззнаковое Ws — 1 mul.us Wb, Ws, Wnd {Wnd+1, Wnd} ♦- беззна- ковое Wb * знаковое Ws — 1 mul.uu Wb, Ws, Wnd {Wnd+1, Wnd} ♦- беззна- ковое Wb * беззнаковое Ws 1 mul.su Wb, #lit5, Wnd {Wnd+1, Wnd} <— знако- вое Wb * беззнаковый литерал Iit5 — 1 mul.uu Wb, #lit5, Wnd {Wnd+1, Wnd} ♦- беззна- ковое Wb * беззнаковый литерал Iit5 — 1 mul f Ws:W2<—f* WREG — 1 NEG neg f f<—!f+1 C, DC, N, OV, Z 1 neg f, WREG WREG*- !f+ 1 C, DC, N, OV, Z 1 neg Ws, Wd Wd <- !Ws + 1 C, DC, N, OV, Z 1
516 Приложение Г. Система команд микроконтроллеров PIC Таблица Г.4. Продолжение Мнемони- ка Синтаксис Описание Влияние на флаги Цик- лов NOP nop Нет операции — 1 nopr •Нет операции — 1 POP pop f Извлечь f с вершины стека — 1 pop Wdo Извлечь значение с вершины стека в Wdo — 1 pop.d Wnd Извлечь значение с вершины стека в W(nd):W(nd+1) — 2 pop. s Извлечь из стека “теневые” регист- ры Все 1 PUSH push f Поместить f на вершину стека — 1 push Wso Поместить на вершину стека Wso — 1 push.d Wns Поместить на вершину стека W(ns):W(ns+1) — 2 push s Поместить в стек “теневые” регист- ры — 1 PWRSAV pwrsav #lill Переход в “спящий” режим или ре- жим ожидания WDTO, Sleep 1 RCALL rcall Expr Вызов подпрограммы по относи- тельному адресу — 2 Rcall Wn , Вызов подпрограммы по вычислен- ному адресу — 2 REPEAT repeat #litl4 Повторить следующую команду Iit14 + 1 раз — 1 repeat Wn Повторить следующую команду (Wn) + 1 раз — 1 RESET reset Программный сброс микроконтрол- лера — 1 RETFIE retfie Возврат из прерывания — 2(3) RETLW retlw #litlO, Wn Возврат с литералом litl 0 в Wn — 2(3) RETURN return Возврат из подпрограммы — 2(3) RLC rlc f f <— результат циклического сдвига влево f через флаг переноса С, N, Z 1 rlc f, WREG WREG <— результат циклического сдвига влево f через флаг переноса С, N, Z 1 rlc Ws, Wd Wd <— результат циклического сдви- га влево Ws через флаг переноса С, N, Z 1 RLNC rlnc f f <— циклический сдвиг f влево N, Z 1 rlnc f, WREG WREG ♦- циклический сдвиг f влево N, Z 1 rlnc Ws, Wd Wd ♦- циклический сдвиг Ws влево N, Z 1 RRC rrc f f <— результат циклического сдвига вправо f через флаг переноса С, N, Z 1 rrc f, WREG WREG *- результат циклического сдвига вправо f через флаг переноса С, N, Z 1 rrc Ws, Wd Wd <— результат циклического сдви- га вправо Ws через флаг переноса С, N, Z 1
Система команд микроконтроллеров PIC24 517 Таблица Г.4. Продолжение Мнемо* ника Синтаксис Описание Влияние на флаги Цик- лов RRNC rrnc f f *- результат циклическо- го сдвига f вправо N, Z 1 rrnc f, WREG WREG <— результат цик- лического сдвига f вправо N, Z 1 rrnc Ws, Wd Wd <— результат цикличе- ского сдвига Ws вправо N, Z 1 SE se Ws, Wnd Wnd *- Ws с добавлением знака С, N, Z 1 SETM setm f f*-OxFFFF — 1 setm WREG WREG *- OxFFFF — 1 setm Ws Ws <- OxFFFF — 1 SL si f f <— результат сдвига f вле- во С, N, OV, Z 1 si f, WREG WREG *- результат сдвига (влево С, N, OV, Z 1 sl Ws, Wd Wd *- результат сдвига Ws влево С, N, OV, Z 1 si Wb, Wns, Wnd Wnd *- результат сдвига Wb влево на Wns разря- дов N, Z 1 sl Wb, #lit5, Wnd Wnd *- результат сдвига Wb влево на Iit5 разрядов N, Z 1 SUB sub f f<—f-WREG С, DC, N, OV, Z 1 sub f, WREG WREG*-f-WREG С, DC, N, OV, Z 1 sub #litlO, Wn Wn*-Wn-lit10 C, DC, N, OV, Z 1 sub Wb, Ws, Wd Wd <— Wb-Ws C, DC, N, OV, Z 1 sub Wb, #lit5, Wd Wd <- Wb - Iit5 C, DC, N, OV, Z 1 SUBB subb f f<—f-WREG-!C C, DC, N, OV, Z . 1 subb f, WREG WREG —f-WREG-!C C, DC, N, OV, Z 1 subb #litlO, Wn Wn*- Wn-lit10-!C C, DC, N, OV, Z 1 subb Wb, Ws, Wd Wd*- Wb-Ws-!C C, DC, N, OV, Z 1 subb Wb, #lit5, Wd Wd — Wb - Iit5 - !C C, DC, N, OV, Z 1 SUBR subr f f —WREG-f C, DC, N, OV, Z 1 subr f, WREG WREG*-WREG-f C, DC, N, OV, Z 1 subr Wb, Ws, Wd Wd *- Ws - Wb C, DC, N, OV, Z 1 subr Wb, #lit5, Wd Wd*-lit5-Wb C, DC, N, OV, Z 1 SUBBR subbr f f*-WREG-f-!C C, DC, N, OV, Z 1 subbr f, WREG WREG*- WREG -f-!C C, DC, N, OV, Z 1 subbr Wb, Ws, Wd Wd*- Ws-Wb-!C C, DC, N, OV, Z 1 subbr Wb, #lit5, Wd Wd <- Iit5 - Wb - !C C, DC, N, OV, Z 1 SWAP swap.b Wn Wn <- Wn с переставлен- ными полубайтами — 1 swap Wn Wn <— Wn с переставлен- ными байтами — 1
518 Приложение Г. Система команд микроконтроллеров PIC Таблица Г.4. Окончание Мнемо- ника Синтаксис Описание Влияние на флаги Цик- лов TBLRDH tblrdh Ws, Wd Чтение Prog<23:16> в Wd<7:0> — 2 TBLRDL tblrdl Ws, Wd Чтение Prog<15:0> в Wd — 2 TBLWTH tblwth Ws, Wd Запись Ws<7:0> в Prog<23:16> — 2 TBLWTL tblwtl Ws, Wd Запись Ws в Prog<15:0> — 2 ULNK ulnk Разрыв связи с указателем фрей- ма — 1 XOR xor f f — fOWREG N, Z 1 xor f, WREG WREG <—ГФ WREG N, Z 1 xor Wn Wd<—lit10®Wd N, Z 1 xor Wb, Ws, Wd Wd Wb Ф Ws N, Z 1 xor Wb, #lit5, Wd Wd <— Wb Ф Iit5 N, Z 1 ZE ze Ws, Wnd Wnd ♦- Ws с добавлением нуля C,Z, N 1
Приложение Д Область ввода/вывода микроконтроллеров AVR ATxmega А Адрес Название Описание $0000 GPIOR0 ’ Регистр общего назначения 0 $000F GPIOR15 Регистр общего назначения 15 $0010 VPDIR0 Регистр направления передачи данных (виртуальный порт 0) $0011 VPOUTO Регистр выходного значения для виртуального порта 0 $0012 VPIN0 Регистр входного значения для виртуального порта 0 $0013 VPINTFLAGSO Регистр флагов прерывания для виртуального порта 0 $0014 VPDIR1 Регистры направления передачи данных — виртуальный порт 1 $0015 VPOUT1 Регистр выходного значения для виртуального порта 1 $0016 VPIN1 Регистр входного значения для виртуального порта 1 $0017 VPINTFLAGS1 Регистр флагов прерывания для виртуального порта 1 $0018 VPDIR2 Регистр направления передачи данных (виртуальный порт 2) $0019 VPOUT2 Регистр выходного значения для виртуального порта 2 $001А VPIN2 Регистр входного значения для виртуального порта 2 $001В VPINTFLAGS2 Регистр флагов прерывания для виртуального порта 2 $001 с VPDIR3 Регистр направления передачи данных (виртуальный порт 3) $001D VPOUT3 ! Регистр выходного значения для виртуального порта 3 $001Е VPIN3 Регистр входного значения для виртуального порта 3 $001F VPINTFLAGS3 Регистр флагов прерывания для виртуального порта 3 $0034 ССР Регистр защиты от изменений конфигурации $0038 RAMPD Регистр, объединяемый с операндом для прямой адресации всего адресного пространства, когда объем памяти данных превышает 64 Кбайт $0039 RAMPX Регистр, объединяемый с регистром X для прямой адресации всего адресного пространства, когда объем памяти данных • превышает 64 Кбайт $003А RAMPY Регистр, объединяемый с регистром У для прямой адресации всего адресного пространства, когда объем памяти данных превышает 64 Кбайт $003В RAMPZ Регистр, объединяемый с регистром Z для прямой адресации всего адресного пространства, когда объем памяти данных превышает 64 Кбайт $003С EIND Регистр, объединяемый с регистром Z для разрешения кос- венных переходов и вызовов, когда объем памяти программ превышает 168 Кбайт $003D SPL Указатель стека, младший байт $003Е SPH Указатель стека, старший байт
520 Приложение Д. Область ввода/вывода микроконтроллеров AVR ATxmega А Адрес Название Описание $003F SREG Регистр состояния (такой же, как у других семейств AVR) $0040 CLKCTRL Регистр управления системным тактовым генератором $0041 PSCTRL Регистр предделителя частоты системной синхронизации $0042 LOCK Регистр блокировки системного тактового генератора $0043 RTCCTRL Регистр управления таймером реального времени v $0048 SLEEP Регистр управления “спящим” режимом $0050 OSCCTRL Регистр управления осцилляторами $0051 OSCSTATUS Регистр состояния осцилляторов $0052 XOSCCTRL Регистр управления внешним осциллятором $0053 XOSCFAIL Регистр обнаружения сбоя внешнего осциллятора $0054 RC32KCAL Регистр калибровки осциллятора частотой 32 кГц $0055 PLLCTRL Регистр управления системой фазовой автоподстройки час- тоты (PLL) $0056 DFLLCTRL Регистр управления системой цифровой автоподстройки час- тоты (DFLL) $0060 DFLLRC32M Регистр управления системой DFLL для калибровки частотой 32 МГц $0062 CALA Калибровочный регистр А $0063 CALB Калибровочный регистр В $0064 COMPO Регистр сравнения со значением осциллятора 0 $0065 i COMP1 Регистр сравнения со значением осциллятора 1 $0066 COMP2 Регистр сравнения со значением осциллятора 2 $0068 DFLLRC2M Регистр управления системой DFLL для калибровки частоты 2 МГц $0069 CALA Калибровочный регистр А $006А CALB Калибровочный регистр В $006В COMPO Регистр сравнения со значением осциллятора 0 $006С COMP1 Регистр сравнения со значением осциллятора 1 $006D COMP2 Регистр сравнения со значением осциллятора 2 $0070 PRGEN Регистр общего управления энергопотреблением $0071 PRPA Регистр управления энергопотреблением порта А $0072 PRPB Регистр управления энергопотреблением порта В $0073 PRPC Регистр управления энергопотреблением порта С $0074 PRPD Регистр управления энергопотреблением порта D $0075 PRPE Регистр управления энергопотреблением порта Е $0076 PRPF Регистр управления энергопотреблением порта F $0078 RSTSTATUS Регистр состояния сброса $0079 RSTCTRL Регистр управления сбросом $0080 WDTCTRL Регистр управления сторожевым таймером $0081 WINCTRL Регистр управления режимом “Window” $0082 WDTSTATUS Регистр состояния сторожевого таймера $0090 DEVID0 Первый байт идентификатора микроконтроллера $0091 DEVID1 Второй байт идентификатора микроконтроллера $0092 DEVID2 Третий байт идентификатора микроконтроллера $0093 REVID Идентификатор модификации микроконтроллера $0094 JTAGUID Идентификатор пользователя интерфейса JTAG $0096 MCUCR Регистр управления микроконтроллером
521 Адрес Название Описание $0098 EVSYSLOCK Регистр блокировки системы обработки событий $0099 AWEXLOCK Регистр блокировки системы AWeX (Advanced Waveform Ex- tension) $00А0 PMICSTATUS Регистр состояния контроллера прерываний $00А1 INTPRI Регистр приоритетности прерываний $00А2 PMICCTRL ' Регистр управления контроллером прерываний $оово MPCMASK Регистр маскирования при конфигурировании выводов на одновременное выполнение нескольких функций $00В2 VPCTRLA Регистр управления А картой виртуальных портов $00ВЗ VPCTRLB Регистр управления В картой виртуальных портов $00В4 CLKEVOUT Регистр конфигурирования выходов для сигнала тактирова- ния периферии и канала событий 0 $0000 AESCTRL Регистр управления модулем шифрования AES $0001 AESSTATUS Регистр статуса модуля шифрования AES $0002 STATE Регистр состояния шифрования AES $0003 KEY Ключ шифрования AES $0004 AESINTCTRL Регистр управления прерываниями от модуля AES $00F0 VBATCTRL Регистр управления модулем переключения на аварийное питание от батареи $00F1 VBATSTATUS Регистр состояния модуля переключения на аварийное пита- ние от батареи $00F2 BACKUPO Регистр данных 0 модуля переключения на аварийное пита- ние от батареи $00F3 BACKUP1 Регистр данных 1 модуля переключения на аварийное пита- ние от батареи $0100 DMACTRL Регистр управления контроллером прямого доступа к памяти $0103 INTFLAGS Регистр флагов прерываний от контроллера прямого доступа к памяти $0104 DMASTATUS Регистр состояния контроллера прямого доступа к памяти $0106 TEMPL Младший байт временного регистра контроллера прямого доступа к памяти $0107 TEMPH Старший байт временного регистра контроллера прямого доступа к памяти $0110 CHOCTRLA Регистр управления А каналом 0 контроллера прямого дос- тупа к памяти $0111 CHOCTRLB Регистр управления В каналом 0 контроллера прямого дос- тупа к памяти $0112 CHOADDRCTRL Регистр управления адресом канала 0 контроллера прямого доступа к памяти $0113 CHOTRIGSRC Регистр источника срабатывания для канала 0 контроллера прямого доступа к памяти $0114 CHOTRFCNTL Младший байт счетчика блоков данных, переданных по ка- налу 0 контроллера прямого доступа к памяти $0115 CHOTRFCNTH Старший байт счетчика блоков данных, переданных по кана- лу 0 контроллера прямого доступа к памяти $0116 CHOREPCNT Счетчик повторных передач блока данных по каналу 0 кон- троллера прямого доступа к памяти
522 Приложение Д. Область ввода/вывода микроконтроллеров AVR ATxmega А Адрес Название Описание $0118 CH0SRCADDR0 Первый байт адреса источника для канала 0 контроллера прямого доступа к памяти $0119 CH0SRCADDR1 Второй байт адреса источника для канала 0 контроллера прямого доступа к памяти $011А CH0SRCADDR2 Третий байт адреса источника для канала 0 контроллера прямого доступа к памяти $011С CH0DESTADDR0 Первый байт целевого адреса для канала 0 контроллера прямого доступа к памяти $011D CH0DESTADDR1 Второй байт целевого адреса для канала 0 контроллера пря- мого доступа к памяти $011Е CH0DESTADDR2 Третий байт целевого адреса для канала 0 контроллера пря- мого доступа к памяти $0120 CH1CTRLA Регистры канала 1 контроллера прямого доступа к памяти $012Е CH1DESTADDR2 (см. образец выше для диапазона адресов $0110..011Е) $0130 CH2CTRLA Регистры канала 2 контроллера прямого доступа к памяти $01 ЗЕ CH2DESTADDR2 (см. образец выше для диапазона адресов $0110..011Е) $0140 CH3CTRLA Регистры канала 3 контроллера прямого доступа к памяти $014Е CH3DESTADDR2 (см. образец выше для диапазона адресов $0110..011Е) $0180 сномих Регистр мультиплексора канала событий 0 $0181 CH1MUX Регистр мультиплексора канала событий 1 $0182 CH2MUX Регистр мультиплексора канала событий 2 $0183 снзмих Регистр мультиплексора канала событий 3 $0184 CH4MUX Регистр мультиплексора канала событий 4 $0185 CH5MUX Регистр мультиплексора канала событий 5 $0186 CH6MUX Регистр мультиплексора канала событий 6 $0187 CH7MUX Регистр мультиплексора канала событий 7 $0188 CH0CTRL Регистр управления каналом событий 0 $0189 CH1CTRL Регистр управления каналом событий 1 $018А CH2CTRL Регистр управления каналом событий 2 $018В CH3CTRL Регистр управления каналом событий 3 $018С CH4CTRL Регистр управления каналом событий 4 $018D CH5CTRL Регистр управления каналом событий 5 $018Е CH6CTRL Регистр управления каналом событий 6 $018F CH7CTRL Регистр управления каналом событий 7 $0190 STROBE Регистр стробирования событий $0191 DATA Регистр данных системы обработки событий $01 СО NVMADDR0 Первый байт адреса энергонезависимой памяти $01С1 NVMADDR1 Второй байт адреса энергонезависимой памяти $01С2 NVMADDR2 Третий байт адреса энергонезависимой памяти $01С4 NVMDATA0 Первый байт данных энергонезависимой памяти $01С5 NVMDATA1 Второй байт данных энергонезависимой памяти $01С6 NVMDATA2 Третий байт данных энергонезависимой памяти $01СА NVMCMD Командный регистр контроллера энергонезависимой памяти $01 СВ NVMCTRLA Регистр управления А контроллера энергонезависимой памяти
523 Адрес Название Описание $01 сс NVMCTRLB Регистр управления В контроллера энергонезависимой памяти $01 CD NVMINTCTRL Регистр управления прерываниями от контроллера энергоне- зависимой памяти $01CF NVMSTATUS Регистр состояния энергонезависимой памяти $01 DO NVMLOCKBITS Разряды блокировки энергонезависимой памяти $0200 ADCACTRLA Регистр управления А АЦП на порту А $0201 ADCACTRLB Регистр управления В АЦП на порту А $0202 ADCAREFCTRL Регистр управления источником опорного напряжения АЦП на порту А $0203 ADCAEVCTRL Регистр управления обработкой событий АЦП на порту А $0204 ADCAPRESCALER Регистр предделителя тактовой частоты АЦП на порту А $0206 ADCAINTFLAGS Регистр флагов прерывания от АЦП на порту А $0207 ADCATEMP Временный регистр АЦП на порту А $020C ADCACALL Младший байт калибровочного значения АЦП на порту А $020D ADCACALH Старший байт калибровочного значения АЦП на порту А $0210 ADCACHORESL Младший байт результата преобразования по каналу 0 АЦП на порту А $0211 ADCACHORESH Старший байт результата преобразования по каналу 0 АЦП на порту А $0212 ADCACH1RESL Младший байт результата преобразования по каналу 1 АЦП на порту А $0213 ADCACH1RESH Старший байт результата преобразования по каналу 1 АЦП на порту А $0214 ADCACH2RESL Младший байт результата преобразования по каналу 2 АЦП на порту А $0215 ADCACH2RESH Старший байт результата преобразования по каналу 2 АЦП на порту А $0216 ADCACH3RESL Младший байт результата преобразования по каналу 3 АЦП на порту А $0217 ADCACH3RESH Старший байт результата преобразования по каналу 3 АЦП на порту А $0218 ADCACMPL Младший байт регистра сравнения для АЦП на порту А $0219 ADCACMPH Старший байт регистра сравнения для АЦП на порту А $0220 ADCACHOCTRL Регистр управления каналом 0 АЦП на порту А $0221 ADCACHOMUXCTRL Регистр управления мультиплексором канала 0 АЦП на порту А $0222 ADCACHOINTCTRL Регистр управления прерываниями от канала 0 АЦП на порту А $0223 ADCACHOINTFLAG Регистр флагов прерываний от канала 0 АЦП на порту А $0224 ADCACHORESL Младший байт результата преобразования по каналу 0 АЦП на порту А $0225 ADCACHORESH Старший байт результата преобразования по каналу 0 АЦП на порту А $0228 ADCACH1CTRL Регистры для канала 1 АЦП на порту А (см. образец выше $022D ADCACH1RESH для диапазона адресов $0220..0225) $0230 ADCACH2CTRL Регистры для канала 2 АЦП на порту А (см. образец выше $0235 ADCACH2RESH для диапазона адресов $0220..0225)
524 Приложение Д. Область ввода/вывода микроконтроллеров AVR ATxmega А Адрес Название Описание $0238 $023D ADCACH3CTRL ADCACH3RESH Регистры для канала 3 АЦП на порту А (см. образец выше для диапазона адресов $0220..0225) $0240 $027D ADCBCTRLA ADCBCH3RESH Регистры для АЦП на порту В (см. образец выше для диапа- зона адресов $0200..023D) $0300 DACACTRLA Регистр управления А ЦАП на порту А $0301 DACACTRLB Регистр управления В ЦАП на порту А $0302 DACACTRLC Регистр управления С ЦАП на порту А $0303 DACAEVCTRL Регистр управления событиями ЦАП на порту А $0304 DACATiMCTRL Регистр управления синхронизацией ЦАП на порту А $0305 DACASTATUS Регистр состояния ЦАП на порту А $0308 DACAGAINCAL Регистр калибровки усиления для ЦАП на порту А $0309 DACAOFFSETCAL Регистр калибровки смещения для ЦАП на порту А $0318 DACACH0DATAL Младший байт регистра данных для канала 0 ЦАП на порту А $0319 DACACH0DATAH Старший байт регистра данных для канала 0 ЦАП на порту А $031А DACACH1DATAL Младший байт регистра данных для канала 1 ЦАП на порту А $031 в DACACH1DATAH Старший байт регистра данных для канала 1 ЦАП на порту А $0320 $033В DACBCTRLA DACBCH1DATAH Регистры для ЦАП на порту В (см. образец выше для диапа- зона адресов $0300..031В) $0380 ACA0CTRL Регистр управления аналогового компаратора 0 на порту А $0381 ACA1CTRL Регистр управления аналогового компаратора 1 на порту А $0382 ACA0MUXCTRL Регистр управления мультиплексором аналогового компара- тора 0 на порту А $0383 ACA1MUXCTRL Регистр управления мультиплексором аналогового компара- тора 1 на порту А $0384 ACACTRLA Регистр управления А аналогового компаратора на порту А $0385 ACACTRLB Регистр управления В аналогового компаратора на порту А $0386 ACAWINCTRL Регистр управления функцией “Window” аналогового компа- ратора на порту А $0387 ACASTATUS Регистр состояния аналогового компаратора на порту А $0390 $0397 ACB0CTRL ACBSTATUS Регистры аналогового компаратора на порту В (см. образец выше для диапазона адресов $0380..0387) $0400 RTCCTRL Регистр управления счетчика реального времени $0401 RTCSTATUS Регистр состояния счетчика реального времени $0402 RTCINTCTRL Регистр управления прерываниями от счетчика реального времени $0403 RTCINTFLAGS Регистр флагов прерывания от счетчика реального времени $0404 RTCTEMP Временный регистр счетчика реального времени $0408 RTCCNTL Младший байт счетного регистра счетчика реального времени $0409 RTCCNTH Старший байт счетного регистра счетчика реального времени $040А RTCPERL Младший байт регистра периода счетчика реального времени $040В RTCPERH Старший байт регистра периода счетчика реального времени $040С RTCCOMPL Младший байт регистра сравнения счетчика реального вре- мени
525 Адрес Название Описание $040D RTCCOMPH Старший байт регистра сравнения счетчика реального вре- мени $0420 RTC32CTRL Регистр управления 32-разрядного счетчика реального вре- мени $0421 RTC32SYNCTRL Регистр состояния и управления синхронизацией 32-раз- рядного счетчика реального времени $0422 RTC32INTCTRL Регистр управления прерываниями от 32-разрядного счетчи- ка реального времени $0423 RTC32INTFLAGS Регистр флагов прерывания от 32-разрядного счетчика ре- ального времени $0424 RTC32CNT0 Первый байт счетного регистра 32-разрядного счетчика ре- ального времени $0425 RTC32CNT1 Второй байт счетного регистра 32-разрядного счетчика ре- ального времени $0426 RTC32CNT2 Третий байт счетного регистра 32-разрядного счетчика ре- ального времени $0427 RTC32CNT3 Четвертый байт счетного регистра 32-разрядного счетчика реального времени $0428 RTC32PER0 Первый байт регистра периода 32-разрядного счетчика ре- ального времени $0429 RTC32PER1 Второй байт регистра периода 32-разрядного счетчика ре- ального времени $042А RTC32PER2 Третий байт регистра периода 32-разрядного счетчика ре- ального времени $042В RTC32PER3 Четвертый байт регистра периода 32-разрядного счетчика реального времени $042С RTC32COMPO Первый байт регистра сравнения 32-разрядного счетчика ре- ального времени $042D RTC32COMP1 Второй байт регистра сравнения 32-разрядного счетчика ре- ального времени $042Е RTC32COMP2 Третий байт регистра сравнения 32-разрядного счетчика ре- ального времени $042F RTC32COMP3 Четвертый байт регистра сравнения 32-разрядного счетчика реального времени $0440 EBICTRL Регистр управления внешним шинным интерфейсом (EBI) $0441 SDRAMCTRLA Регистр управления А памятью SDRAM $0444 REFRESHL Младший байт регистра периода обновления памяти SDRAM $0445 REFRESHH Старший байт регистра периода обновления памяти SDRAM $0446 INITDLYL Младший байт регистра инициализации задержки памяти SDRAM $0447 INITDLYH Старший байт регистра инициализации задержки памяти SDRAM $0448 SDRAMCTRLB Регистр управления В памятью SDRAM $0449 SDRAMCTRLC Регистр управления С памятью SDRAM $0450 CS0CTRLA Регистр управления А схемы выбора кристалла 0 $0451 CS0CTRLB Регистр управления В схемы выбора кристалла 0
526 Приложение Д. Область ввода/вывода микроконтроллеров AVR ATxmega А Адрес Название Описание $0452 CS0BASEADDRL Младший байт регистра базового адреса схемы выбора кри- сталла 0 $0453 CS0BASEADDRH Старший байт регистра базового адреса схемы выбора кри- сталла 0 $0454 CS1CTRLA Регистры схемы выбора кристалла 1 (см. образец выше для $0457 CS1BASEADDRH диапазона адресов $0450..0453) $0458 CS2CTRLA Регистры схемы выбора кристалла 2 (см. образец выше для $045В CS2BASEADDRH диапазона адресов $0450..0453) $045С CS3CTRLA Регистры схемы выбора кристалла 3 (см. образец выше для $045F CS3BASEADDRH диапазона адресов $0450..0453) $0480 TWICCTRL Регистр управления интерфейсом TWI на порту С $0481 TWICMCTRLA Регистр управления А ведущим устройством на интерфейсе TWI на порту С $0482 TWICMCTRLB Регистр управления В ведущим устройством на интерфейсе TWI на порту С $0483 TWICMCTRLC Регистр управления С ведущим устройством на интерфейсе TWI на порту С $0484 TWICMSTATUS Регистр состояния ведущего устройства на интерфейсе TWI на порту С . $0485 TWICMBAUD Регистр скорости передачи данных ведущим устройством на интерфейсе TWI на порту С $0486 TWICMADDR Регистр адреса ведущего устройства на интерфейсе TWI на порту С $0487 TWICMDATA Регистр данных ведущего устройства на интерфейсе TWI на порту С $0488 TWICSCTRLA Регистр управления А ведомым устройством на интерфейсе TWI на порту С $0489 TWICSCTRLB Регистр управления В ведомым устройством на интерфейсе TWI на порту С $048А TWICSCTRLC Регистр управления С ведомым устройством на интерфейсе TWI на порту С $048В TWICSSTATUS Регистр состояния ведомого устройства на интерфейсе TWI на порту С $048С TWICSADDR Регистр адреса ведомого устройства на интерфейсе TWI на порту С $048D TWICSDATA Регистр данных ведомого устройства на интерфейсе TWI на порту С $048Е TWICADDRMASK Регистр маскирования адреса ведомого устройства на ин- терфейсе TWI на порту С $0490 TWIDCTRL Регистры интерфейса TWI на порту D (см. образец выше для $049Е TWIDADDRMASK диапазона адресов $0480..048Е) $04А0 TWIECTRL Регистры интерфейса TWI на порту Е (см. образец выше для $04АЕ TWIEADDRMASK диапазона,адресов $0480..048Е)
527 Адрес Название Описание $04В0 $04ВЕ TWIFCTRL TWIFADDRMASK Регистры интерфейса TWI на порту F (см. образец выше для диапазона адресов $048Р..048Е) $0600 PORTADIR Регистр направления передачи данных через порт А $0601 PORTADIRSET Регистр установки разрядов в регистре направления переда- чи данных через порт А $0602 PORTADIRCLR Регистр обнуления разрядов в регистре направления пере- дачи данных через порт А $0603 PORTADIRTGL Регистр инвертирования разрядов в регистре направления передачи данных через порт А $0604 PORTAOUT Регистр значения, выводимого через порт А $0605 PORTAOUTSET Регистр установки разрядов в регистре значения, выводимо- го через порт А $0606 PORTAOUTCLR Регистр обнуления разрядов в регистре значения, выводимо- го через порт А $0607 PORTAOUTTGL Регистр инвертирования разрядов в регистре значения, вы- водимого через порт А $0608 PORTAIN Регистр значения, считанного в порт А $0609 PORTAINTCTRL Регистр управления прерываниями от порта А $060А PORTAiNTOMASK Регистр маскирования прерывания 0 от порта А $060В PORTAINT1MASK Регистр маскирования прерывания 1 от порта А $0600 PORTAINTFLAGS Регистр флагов прерывания от порта А $0610 PORTAPINOCTRL Регистр конфигурирования вывода 0 порта А $0611 PORTAPIN1CTRL Регистр конфигурирования вывода 1 порта А $0612 PORTAPIN2CTRL Регистр конфигурирования вывода 2 порта А $0613 PORTAPIN3CTRL Регистр конфигурирования вывода 3 порта А $0614 PORTAPIN4CTRL Регистр конфигурирования вывода 4 порта А $0615 PORTAPIN5CTRL Регистр конфигурирования вывода 5 порта А $0616 PORTAPIN6CTRL Регистр конфигурирования вывода 6 порта А $0617 PORTAPIN7CTRL Регистр конфигурирования вывода 7 порта А $0620 $0637 PORTBDIR PORTBPIN7CTRL Регистры порта В (см. образец выше для диапазона адресов $0600..0617) $0640 $0657 PORTCDIR PORTCPIN7CTRL Регистры порта С (см. образец выше для диапазона адресов $0600-0617) $0660 $0677 PORTDDIR PORTDPIN7CTRL Регистры порта D (см. образец выше для диапазона адресов $0600-0617) $0680 $0697 PORTEDIR PORTEPIN7CTRL Регистры порта Е (см. образец выше для диапазона адресов $0600-0617) $06А0 $06В7 PORTFDIR PORTFPIN7CTRL Регистры порта F (см. образец выше для диапазона адресов $0600-0617)
528 Приложение Д. Область ввода/вывода микроконтроллеров AVR ATxmega А Адрес Название Описание $06Е0 $06F7 PORTHDIR PORTHPIN7CTRL Регистры порта Н (см. образец выше для диапазона адресов $0600. .0617) $0700 $0717 PORTJDIR PORTJPIN7CTRL Регистры порта J (см. образец выше для диапазона адресов $0600-0617) $0720 $0737 PORTKDIR PORTKPIN7CTRL Регистры порта К (см. образец выше для диапазона адресов $0600-0617) $07С0 $07D7 PORTQDIR PORTQPIN7CTRL Регистры порта Q (см. образец выше для диапазона адресов $0600-0617) $07Е0 $07F7 PORTRDIR PORTRPIN7CTRL Регистры порта R (см. образец выше для диапазона адресов $0600-0617) $0800 TCC0CTRLA Регистр управления А таймером/счетчиком 0 на порту С $0801 TCC0CTRLB Регистр управления В таймером/счетчиком 0 на порту С $0802 TCC0CTRLC Регистр управления С таймером/счетчиком 0 на порту С $0803 TCC0CTRLD Регистр управления D таймером/счетчиком 0 на порту С $0804 TCC0CTRLE Регистр управления Е таймером/счетчиком 0 на порту С $0806 TCC0INTCTRLA Регистр управления прерываниями А таймера/счетчика 0 на порту С $0807 TCC0INTCTRLB Регистр управления прерываниями В таймера/счетчика 0 на порту С $0808 TCCOCTRLFCLR Регистр управления F таймером/счетчиком 0 на порту С (за- пись в него обнуляет соответствующие разряды конфигура- ции) $0809 TCCOCTRLFSET Регистр управления F таймером/счетчиком 0 на порту С (за- пись в него устанавливает в 1 соответствующие разряды конфигурации) $080А TCC0CTRGCLR Регистр управления G таймером/счетчиком 0 на порту С (за- пись в него обнуляет соответствующие разряды конфигура- ции) $080В TCQ0CTRLGSET Регистр управления G таймером/счетчиком 0 на порту С (за- пись в него устанавливает в 1 соответствующие разряды конфигурации) $0800 TCC01NTFLAGS Флаги прерываний от таймера/счетчика 0 на порту С $080F TCC0TEMP Временный регистр таймера/счетчика 0 на порту С, исполь- зуемый при 16-разрядном доступе $0820 TCC0CNTL Счетный регистр таймера/счетчика 0 на порту С (младший байт) $0821 TCC0CNTH Счетный регистр таймера/счетчика 0 на порту С (старший байт) $0826 TCC0PERL Регистр периода таймера/счетчика 0 на порту С (младший байт) $0827 TCC0PERH Регистр периода таймера/счетчика 0 на порту С (старший байт)
529 Адрес Название Описание $0828 TCC0CCAL Регистр А для сравнения/фиксации значений при работе с таймером/счетчиком 0 на порту С (младший байт) $0829 ТССОССАН Регистр А для сравнения/фиксации значений при работе с таймером/счетчиком 0 на порту С (старший байт) $082А TCCOCCBL Регистр В для сравнения/фиксации значений при работе с таймером/счетчиком 0 на порту С (младший байт) $082В ТССОССВН Регистр В для сравнения/фиксации значений при работе с таймером/счетчиком 0 на порту С (старший байт) $082С TCCOCCCL Регистр С для сравнения/фиксации значений при работе с таймером/счетчиком 0 на Корту С (младший байт) $082D тссосссн Регистр С для сравнения/фиксации значений при работе с таймером/счетчиком 0 на порту С (старший байт) $082Е TCCOCCDL Регистр D для сравнения/фиксации значений при работе с таймером/счетчиком 0 на порту С (младший байт) $082F TCCOCCDH Регистр D для сравнения/фиксации значений при работе с таймером/счетчиком 0 на порту С (старший байт) $0836 TCCOPERBUFL Буферный регистр периода таймера/счетчика 0 на порту С (младший байт) $0837 TCCOPERBUFH Буферный регистр периода таймера/счетчика 0 на порту С (старший байт) $0838 TCCOCCABUFL Буферный регистр А для сравнения/фиксации значений при работе с таймером/счетчиком 0 на порту С (младший байт) $0839 TCCOCCABUFH Буферный регистр А для сравнения/фиксации значений при работе с таймером/счетчиком 0 на порту С (старший байт) $083А TCCOCCBBUFL Буферный регистр В для сравнения/фиксации значений при работе с таймером/счетчиком 0 на порту С (младший байт) $083В TCCOCCBBUFH Буферный регистр В для сравнения/фиксации значений при работе с таймером/счетчиком 0 на порту С (старший байт) $083С TCCOCCCBUFL Буферный регистр С для сравнения/фиксации значений при работе с таймером/счетчиком 0 на порту С (младший байт) $083D TCCOCCCBUFH Буферный регистр С для сравнения/фиксации значений при работе с таймером/счетчиком 0 на порту С (старший байт) $083Е TCCOCCDBUFL Буферный регистр D для сравнения/фиксации значений при работе с таймером/счетчиком 0 на порту С (младший байт) $083F TCCOCCDBUFH Буферный регистр D для сравнения/фиксации значений при работе с таймером/счетчиком 0 на порту С (старший байт) $0840 $087F TCC1CTRLA TCC1CCDBUFH Регистры таймера/счетчика 1 на порту С (см. образец выше для диапазона адресов $0800..083F) $0880 AWEXCCTRL Регистр управления системой AWeX на порту С $0882 AWEXCFDEMASK Маска событий обнаружения сбоев в системе AWeX на порту С $0883 AWEXCFDCTRL Регистр управления обнаружением сбоев в системе AWeX на порту С $0884 AWEXCSTATUS Регистр состояния системы AWeX на порту С $0886 AWEXCDTBOTH Запись значения в этот регистр приводит к одновременному обновлению содержимого регистров AWEXCDTHS и AWEXCDTLS
530 Приложение Д. Область ввода/вывода микроконтроллеров AVR ATxmega А Адрес Название Описание $0887 AWEXCDTBOTHBUF^ Запись значения в этот регистр приводит к одновременному обновлению содержимого регистров AWEXCDTHSBUF и AWEXCDTLSBUF $0888 AWEXCDTLS Число циклов тактирования периферии для неинвертирован- ной составляющей в системе AWeX на порту С с учетом пе- риода задержки $0889 AWEXCDTHS Число циклов тактирования периферии для инвертированной составляющей в системе AWeX на порту С с учётом периода задержки $088А AWEXCDTLSBUF Буфер для регистра AWEXDTLS $088В AWEXCDTHSBUF Буфер для регистра AWEXDTHS $0880 AWEXCOUTOVEN Регистр, разрешающий подмену выходов порта, при исполь- зовании системы AWeX на порту С $0890 HIRESCCTRLA Регистр управления А системой расширения разрешающей способности порта С $08А0 USARTCODATA Регистр данных USART0 на порту С $08А1 USARTCOSTATUS Регистр состояния USART0 на порту С $08АЗ USARTCOCTRLA Регистр управления A USART0 на порту С $08А4 USARTCOCTRLB Регистр управления В USART0 на порту С $08А5 USARTCOCTRLC Регистр управления С USART0 на порту С $08А6 BAUDCTRLA Регистр управления А скоростью передачи через USART0 на порту С $08А7 BAUDCTRLB Регистр управления В скоростью передачи через USART0 на порту С $08В0 USARTC1DATA Регистры USART1 на порту С (см. образец выше для диапа- $08В7 BAUDCTRLB зона адресов $08А0..08А7) $0800 SPICCTRL Регистр управления интерфейсом SPI на порту С $0801 SPICINTCTRL Регистр управления прерываниями от интерфейса SPI на порту С $0802 SPICSTATUS Регистр состояния интерфейса SPI на порту С $0803 SPICDATA Регистр данных интерфейса SPI на порту С $08F0 IRCOMTXPLCTRL Регистр управления передатчиком ИК-модуля $08F1 IRCOMRXPLCTRL Регистр управления приемником ИК-модуля $08F2 IRCOMCTRL Регистр управления ИК-модулем $0900 TCDOCTRLA Регистры таймера/счетчика 0 на порту D (см. образец выше $093F TCDOCCDBUFH для диапазона адресов $0800..083F) $0940 TCD1CTRLA Регистры таймера/счетчика 1 на порту D (см. образец выше $097F TCD1CCDBUFH для диапазона адресов $0800..083F) $0980 AWEXDCTRL Регистры системы М\1еХ на порту D (см. образец выше для $0980 AWEXDOUTOVEN диапазона адресов $0880..$0880) $0990 HIRESDCTRLA Регистр управления А системой расширения разрешающей способности порта D
531 Адрес Название Описание $09А0 $09А7 USARTDODATA BAUDCTRLB Регистры USARTOna порту D (см. образец выше для диапа- зона адресов $08А0..08А7) $09В0 $09В7 USARTD1DATA BAUDCTRLB Регистры USART1 на порту D (см. образец выше для диапа- зона адресов $08А0..08А7) $09С0 $09СЗ SPIDCTRL SPIDDATA Регистры интерфейса SPI на порту D (см. образец выше для диапазона адресов $08С0..$08СЗ) $0А00 $0A3F TCEOCTRLA TCEOCCDBUFH Регистры таймера/счетчика 0 на порту Е (см. образец выше для диапазона адресов $0800..083F) $0А40 $0A7F TCE1CTRLA TCE1CCDBUFH Регистры таймера/счетчика 1 на порту Е (см. образец выше для диапазона адресов $0800..083F) $0А80 $0А8С AWEXECTRL AWEXEOUTOVEN Регистры системы AWeX на порту Е (см. образец выше для диапазона адресов $0880..$088С) $0А90 HIRESECTRLA Регистр управления А системой расширения разрешающей способности порта Е $ОААО $0АА7 USARTEODATA . BAUDCTRLB Регистры USART0 на порту Е (см. образец выше для диапа- зона адресов $08А0..08А7) $ОАВО $0АВ7 USARTE1DATA BAUDCTRLB Регистры USART1 на порту Е (см. образец выше для диапа- зона адресов $08А0..08А7) $ОАСО $0АСЗ SPIECTRL SPIEDATA Регистры интерфейса SPI на порту Е (см. образец выше для диапазона адресов $08С0..$08СЗ) $0В00 $0B3F TCFOCTRLA TCFOCCDBUFH Регистры таймера/счетчика 0 на порту F (см. образец выше для диапазона адресов $0800..083F) $0В40 $0B7F TCF1CTRLA TCF1CCDBUFH Регистры таймера/счетчика 1 на порту F (см. образец выше для диапазона адресов $0800..083F) $0В80 $0В8С AWEXFCTRL AWEXFOUTOVEN Регистры системы AWeX на порту F (см. образец выше для диапазона адресов $0880..$0880) $0В90 HIRESFCTRLA Регистр управления А системой расширения разрешающей способности порта F $ОВАО $0ВА7 USARTFODATA BAUDCTRLB Регистры USART0 на порту F (см. образец выше для диапа- зона адресов $08А0..08А7) $овво $0ВВ7 USARTF1DATA BAUDCTRLB Регистры USART1 на порту F (см. образец выше для диапа- зона адресов $08А0..08А7) $овсо $0ВСЗ SPIFCTRL SPIFDATA Регистры интерфейса SPI на порту F (см. образец выше для диапазона адресов $0800..$0803)
Список литературы 1. Шпак Ю. А. Программирование на языке С для AVR и PIC микроконтроллеров. — К.: “МК-Пресс”, 2006. 2. Вольфганг Трамперт. AVR-RISC микроконтроллеры. — К.: “МК-Пресс”, 2006. 3. Тим Уилмсхерст. Разработка встроенных систем с помощью микроконтролле- ров PIC. Принципы и практические примеры. — К.: “МК-Пресс”, СПб.: “КОРОНА-ВЕК”, 2008. 4. Лусио ди Джасио. Программирование на С микроконтроллеров PIC24. — К.: “МК-Пресс”, СПб.: “КОРОНА-ВЕК”, 2009. 5. Анна и Манфред Кёниг. Полное руководство по Р1С-микроконтроллерам. — К.: “МК-Пресс”, 2006. 6. Joe Pardue. С Programming for Microcontrollers Featuring ATMEL's AVR Butterfly and the free WinAVR Compiler. — Smiley Micros, 2005. 7. Richard Barnett, Larry O'Cull, Sarah Cox. Embedded C Programming with the Mi- crochip PIC. — Delmar Learning, 2004. 8. Лебедев M. Б. CodeVisionAVR: пособие для начинающих. — M.: “Додэка-XXI”, 2008. 9. Dogan Ibrahim. Advanced PIC Microcontroller Projects in C. — Newnes, 2008. 10. Roman Mittermayr. AVR-RISC. Embedded Software selbst entwicklen. — Franzis Verlag, 2008. 11. Lucio Di Jasio. Programming 32-bit Microcontrollers in C. Exploring the PIC32. — Newnes, 2008. 12. Lucio Di Jasio, Tim Wilmshurst, Dogan Ibrahim, John Morton, Martin Bates, Jack Smith, D.W. Smith, Chuck Hellebuyck. PIC Microcontrollers. — Newnes, 2008.
Содержимое прилагаемого к книге компакт-диска Содержимое прилагаемого к книге компакт-диска разбито на следующие ката- логи: • Datasheets — технические описания (на английском языке) популярных мик- роконтроллеров AVR (подпапка avr) и Р1С (подпапка Pic), а также — уст- ройств, задействованных в рассмотренных в книге проектах; • Pro j ects — примеры рассмотренных в книге программ (примеры распределе- ны по папкам в соответствии с типом компилятора: СЗО, С32, CCS-PICC, Code- VisionAVR, mikroC, WinAVR); • Sowtware — установочные пакеты программных средств (компиляторов, средств разработки и программаторов), рассмотренных в книге:АУИ Studio; CodeVisionAVR, PonyProg2000, USBProg, WinAVR; СЗО, C32, CCS-PICC, Mik- roC, MPLAB.
Издательство “МК-Пресс” представляет Авраменко Ю.Ф. Транзисторы в SMD-исполнении. Том 1 ISBN 966-8806-25-5 544 стр., мягкая обложка Этот справочник продолжает новую серию “Элементная база”, в которой представлены технические данные на современные полупроводниковые приборы и интегральные схемы ве- дущих производителей, и содержит в себе справочные данные на биполярные транзисторы в SMD-исполнении. Справочник предполагается как издание из 3-5 томов, в которое будут вклю- чены биполярные и полевые транзисторы, предназначенные для поверхностного монтажа. При составлении этого тома использовалась техническая документация следующих производителей: HITACHI, NEC, PANASONIC, RENESAS, ROHM, SANYO и TOSHIBA. Авраменко Ю.Ф. Транзисторы в SMD-исполнении. Том 2 ISBN 978-966-8806-12-4 640 стр., мягкая обложка Справочник продолжает новую серию «Элементная база», в которой представлены тех- нические данные на современные полу-проводниковые приборы и интегральные схемы ведущих производителей. Второй том содержит в себе справочные данные на биполярные транзисторы в SMD-исполнении, транзисторные сборки разных структур, транзисторные ключи для работы в цифровых схемах и их наборы. При составлении этого тома использовалась техническая документация следующих про- изводителей: NEC, PANASONIC, SANYO и TOSHIBA. Книги издательства “МК-Пресс” можно заказать: по адресу: 02002, г.киев, а/я 294, по телефону/факсу: (044) 362-04-38, по e-mail: info@mk-press.com Посетите наш Internet-магазин: http://www.mk-press.com
Издательство “МК-Пресс” представляет СЕРВИСНОЕ О5СПУЖИ8ДНИЕ унашасси КШЕИ1АКхх ... НДЬ/0 М>.ИЮ, НАКМРТИ Безверхний И.Б. TV-приемники на шасси VESTEL 11АКхх (+CD) ISBN 978-966-8806-11-7 304 стр., мягкая обложка В данной книге рассмотрены телевизионные приемники на основе шасси 11АК20, 11 АКЗО 11АК36 и РТ92 турецкой компании VESTEL. Сегодня на базе этих шасси десятки раз- личных производителей поставляют на рынок под различными торговыми марками сотни моде- лей телевизоров. Подробно описаны: элементная база, схемы, сервисные режимы, регулировка и ряд вопросов практического характера. Отдельная глава посвящена современным видеопро- цессорам производства PHILIPS. В приложении представлены справочные данные на совре- менные видеопроцессоры различных производителей. * Книга предназначена для работников сервисных служб занимающихся ремонтом теле- визоров, студентов радиотехнических специальностей ВУЗов, техникумов (колледжей), учащих- ся ПТУ и курсов радиомехаников, а также квалифицированных радиолюбителей. Оуэн Бишоп Настольная книга разработчика роботов (+CD) ISBN 978-5-7931-0504-0 400 стр., мягкая обложка Эта книга представляет собой справочное руководство для тех, кто хочет научиться про- ектировать и конструировать роботов. Благодаря представленным в ней пошаговым инструкци- ям, вы быстро освоите методики создания забавных и захватывающих роботов. На основании своего обширного практического опыта автор открывает важные аспекты программирования, электроники и механики, характерные для робототехники. Поскольку все проекты основаны на использовании всемирно популярных микроконтроллеров PIC, методики программирования ос- ваиваются быстро и безболезненно. Данное руководство — идеальный вариант для новичков в сфере робототехники. Оно будет также полезно тем опытным разработчикам, которые хотят расширить свои познания в области программирования роботов. Книги издательства “МК-Пресс” можно заказать: по адресу: 02002, г.Киев, а/я 294, по телефону/факсу: (044) 362-04-38, по e-mail: info@mk-press.com Посетите наш Internet-магазйн: http://www.mk-press.com
Издательство “МК-Пресс” представляет Авраменко Ю.Ф. Мобильные телефоны LG. Ремонт и обслуживание. Том I (+CD) ISBN 978-966-8806-29-2 576 стр., мягкая обложка Книга составлена на основании сервисной документации LG Electronics. В ней подробно рассмотрены схемотехнические решения современных мобильных телефонов на базе БИС об- работки аналоговых и цифровых сигналов производства ANALOG DEVICES. Представлены све- дения о работе всех функциональных устройств телефонов стандарта GSM. На прилагаемом к книге компакт-диске, приводятся электрические принципиальные схемы на рассмотренные мо- дели и справочные данные на элементную базу ведущих производителей интегральных схем для систем беспроводной связи. Книга рассчитана на широкий круг специалистов, занимающих- ся сервисным обслуживанием мобильных телефонов. Авраменко Ю.Ф. Мобильные телефоны LG. Ремонт и обслуживание. Том II (+CD) ISBN 978-966-8806-32-2 576 стр., мягкая обложка Книга составлена на основании сервисной документации LG Electronics. В ней подробно рассмотрены схемотехнические решения современных мобильных телефонов на базе БИС об- работки аналоговых и цифровых сигналов производства ANALOG DEVICES. Представлены све- дения о работе всех функциональных устррйств телефонов стандарта GSM. На прилагаемом к книге компакт-диске, приводятся электрические принципиальные схемы на рассмотренные мо- дели, а также сервисная документация на мобильные телефоны производства SAMSUNG и NOKIA. Книга рассчитана на широкий круг специалистов, занимающихся сервисным обслужива- нием мобильных телефонов. Книги издательства “МК-Пресс” можно заказать: по адресу: 02002, г.Киев, а/я 294, по телефону/факсу: (044) 362-04-38, по e-mail: info@mk-press.coin Посетите наш Internet-магазин: http://www.mk-press.com
Издател ьство “ М К-Пресс” п ред ста в л яет Крид Хадлстон Проектирование интеллектуальных датчиков с помощью Microchip dsPIC (+CD) ISBN 978-966-8806-38-4 320 стр., мягкая обложка На страницах этой книги раскрыты способы применения популярных цифровых контрол- леров сигналов Microchip dsPIC, в которых вычислительный потенциал мощных цифровых про- цессоров сигналов удачно объединен с возможностями микроконтроллеров PIC. Рассматрива- ются вопросы не только программирования, но и проектирования электронного оборудования. Таким образом, читатель получает полное представление о процессе создания интерфейса для трех конкретных типов датчиков: температуры, давления/нагрузки и расхода. Эта практичная, легкая в восприятии книга раскрывает реальные проблемы, возникающие в повседневной рабо- те разработчиков, и показывает решения, позволяющие реализовать все сильные стороны тако- го мощного средства, как интеллектуальные датчики. Авраменко Ю.Ф. Качественный звук — сегодня это просто ISBN 966-8806-27-1 286 стр., мягкая обложка В книге максимально подробно приведены все рекомендации разработчиков - инжене- ров NSC, как правильно построить усилительный тракт на основе мощных ОУ. Современный подход, основанный на рекомендациях инженеров AD и TI, к топологии печатной платы, к выбо- ру «правильных» пассивных компонентов для звуковоспроизводящего тракта поможет реализо- вать основной принцип: как можно меньше ухудшить качество записи. Большое количество при- меров построения качественных УМЗЧ будет наглядным пособием для реализации собственной конструкции в короткие сроки с небольшими материальными затратами и главное, с предска- зуемым результатом. Книги издательства “МК-Пресс” можно заказать: по адресу: 02002, г.Киев, а/я 294, по телефону/факсу: (044) 362-04-38, по e-mail: info@mk-press.com Посетите наш Internet-магазин: http://www.mk-press.com
Издательство “МК-Пресс” представляет Санджая Маниктала Импульсные источники питания от А до Z (+CD) ISBN 978-5-903383-59-7 544 стр., мягкая обложка Эта книга основывается на десятилетнем авторском опыте проектирования источников питания. Здесь читатель найдет наглядное и доступное введение в курс “Источники питания"; изложение основ без пугающего математического анализа; полную и, в то же время, уникальную по своей простоте методику проектирования импульсных преобразователей и их магнитных компонентов; подробный расчет всех видов потерь в импульсных источниках питания; описание основных схемотехнических решений импульсных источников; исчерпывающее исследование аспектов контроля и измерения паразитных электромагнитных излучений, связанных с работой импульсных преобразователей. Г.-Й. Берндт, Б. Каинка Измерение, управление и регулирование с помощью макросов VBA в Word и Excel (+CD) ISBN 978-5-7931-0504-0 256 стр., мягкая обложка Эта книга представляет новый подход, согласно которому весь диапазон задач измере- ния, управления и регулирования реализуется средствами популярного программного пакета Microsoft Office. Хотя это звучит необычно, с помощь^ приложений Word и Excel можно получить прямой доступ к аппаратному обеспечению, что делает их универсальными и простыми в ис- пользовании инструментами. В книге показано, как с помощью макросов VBA реализовать управление цифровыми мультиметрами, релейными картами и ПК-интерфейсами, организовать взаимодействие с мик- роконтроллерными системами и многое другое на основе стандартного последовательного ин- терфейса RS232. Книги издательства “МК-Пресс” можно заказать: по адресу: 02002, г.Киев, а/я 294, по телефону/факсу: (044) 362-04-38, по e-mail: info@mk-press.com Посетите наш Internet-магазин: http://www.mk-press.com
Издательство “МК-Пресс” представляет Вольфганг Трамперт Измерение, управление и регулирование с помощью AVR микроконтроллеров (+CD) ISBN 966-8806-14-Х 208 стр., мягкая обложка Книга описывает особенности применения AVR-микроконтроллеров в технике измере- ния, управления и регулирования. При этом основной акцент поставлен на измерении напряже- ния, выводе и отображении результатов измерений, а также на регулировании аналоговых на- пряжений. Изложенный материал дает возможность поэтапно проследить весь процесс разра- ботки устройства, понять, почему программное^ аппаратное обеспечение скомпоновано именно таким, а не каким-либо другим образом, и суметь в случае необходимости выполнить самостоя- тельную разработку. Дитер Кохц Измерение, управление и регулирование с помощью PIC-микроконтроллеров (+CD) ISBN 966-8806-15-8 304 стр., мягкая обложка Книга посвящена применению PIC-микроконтроллеров семейства PIC16C5X, а также PIC16C71 и PIC16F84 в схемах измерения, управления и регулирования. Рассмотрены следую- щие примеры: программируемый счетчик-частотомер, измерение температуры, реле времени, гигрометр с реле, температурное реле для регулирования нагрева, управление шаговым элек- тродвигателем, регулирование уровня заполнения. Книги издательства “МК-Пресс” можно заказать: по адресу: 02002, г.Киев, а/я 294, по телефону/факсу: (044) 362-04-38, по e-mail: info@mk-press.com Посетите наш Internet-магазин: http://www.mk-press.com
Издательство “МК-Пресс” представляет Кравченко А.В. 10 практических устройств на AVR-микроконтроллерах. Книга 1 (+CD) ISBN 978-966-8806-41-4 224 стр., мягкая обложка Данная книга открывает серию сборников с практическими примерами применения мик- роконтроллеров. В ней рассмотрены десять завершенных устройств на базе микрокон- троллеров AVR, которые можно легко собрать в домашних условиях и применять в быту или профессиональной деятельности: генератор световых эффектов; счетчик событий; музыкаль- ный звонок; индикатор уровня звука; повышающий преобразователь, схема управления шаго- вым двигателем; цифровой термометр и др. Благодаря подробному анализу аппаратной и программной части устройств, книга будет интересна и полезна как начинающим, так и опытным радиолюбителям, желающим изучить ме- тоды эффективного применения микроконтроллеров. Заец Н.И. Радиолюбительские конструкции на PIC-микроконтроллерах (+CD). Книга 4 ISBN 966-8806-42-1 336 стр., мягкая обложка Данная книга — практическое пособие по освоению микроконтроллеров PICmicro компа- нии Microchip и другой современной элементной базы, наподобие индикаторов, выполненных по COG-технологии. Рассмотрены алгоритмы работы, схемы и программы для различных полезных устройств: многофункциональных часов, отображающих текущее время и температуру воздуха; автомобильных часов, фиксирующих время в пути и сообщающих о поломке реле-регулятора; автомата включения освещения; цифрового устройства для блока питания с установкой защиты по току и напряжению; специализированных термометров и др. Для начинающих дана глава о наладке устройств на микроконтроллерах. Книга предназначена для широкого круга радиолюби- телей, а также может быть полезна студентам, изучающим программиррвание микроконтролле- ров. Книги издательства ‘‘МК-Пресс” можно заказать: по адресу: 02002, г.Киев, а/я 294, по телефону/факсу: (044) 362-04-38, по e-mail: info@mk-press.com Посетите наш Internet-магазин: http://www.mk-press.com
Издательство “МК-Пресс” представляет Тим Уилмсхерст Разработка встроенных систем с помощью микроконтроллеров PIC. Принципы и практические примеры (+CD) ISBN 978-5-903383-61-0 544 стр., мягкая обложка Благодаря полезным примерам и иллюстрациям, этаtкнига дает глубокие познания в сфере проектирования систем с помощью микроконтроллеров PIC, а также — программирова- ния этих устройств на ассемблере и С. Подробно рассмотрены микроконтроллеры 16F84A, 16F873A и 18F242. Даны примеры реальных проектов, включая модель робота, выполненного в виде транспортного средства с автономным управлением. Дополнительно рассматриваются такие вопросы повышенной сложности, как применение устройств в сетевой среде и построение операционных систем реального времени. Барри Брэй Применение микроконтроллеров PIC18. Архитектура, программирование и построение интерфейсов с применением С и ассемблера (+CD) ISBN 978-5-7931-0516-3 576 стр., мягкая обложка Сегодня микроконтроллеры используются повсеместно в автомобилях, бытовой технике, промышленном и медицинском оборудовании и т.п. Этот учебник дает всестороннее представ- ление об архитектуре, программировании и построении интерфейсов этого современного чуда. На примере семейства микроконтроллеров PIC18 производства Microchip в книге объясняется архитектура, программирование и построение интерфейсов. Семейство PIC18 выбрано не слу- чайно, поскольку оно относится к самым современным восьмиразрядным микроконтроллерам. Изложенный в книге материал также применим как к более ранним версиям микроконтроллеров Microchip, так и к аналогичным устройствам других производителей. Он рассчитан на опытных практиков и радиолюбителей, интересующихся микроконтроллерами. Книги издательства “МК-Пресс” можно заказать: по адресу: 02002, г.Киев, а/я 294, по телефону/факсу: (044) 362-04-38, по e-mail: mfo@mk-press.com Посетите наш Internet-магазин: http://www.mk-press.com
Издательство “МК-Пресс” представляет Лусио ди Джасио Программирование на С микроконтроллеров PIC24 (+CD) ISBN 978-5-7931-0529-3 336 стр., мягкая обложка Лусио ди Джасио, эксперт из компании Microchip, предлагает свой уникальный взгляд на революционную технологию PIC24, проводя читателя от основ 16-разрядной архитектуры до сложных программных разработок средствами языка С, включая реализацию многозадачности с помощью прерываний PIC24, управление ЖК-дисплеями, формирование звуковых и видеосиг- налов, доступ к запоминающим устройствам большой емкости и др. Вне всякого сомнения, эта книга будет полезна как опытным PIC-разработчикам, так и новичкам в мире встроенных систем. Заец Н.И. Радиолюбительские конструкции на PIC-микроконтроллерах (+CD). Книга 1 ISBN 978-5-7931-0518-7 304 стр., мягкая обложка Это издание переработано с целью исправления замеченных ошибок и уменьшения объема за счет переноса статей, не пользующихся спросом, на прилагаемый компакт-диск. В книге представлено 20 описаний радиолюбительских устройств различного назначения, вы- полненные на микроконтроллере PIC16F84. Начинающие радиолюбители, не знакомые с про- граммированием микроконтроллеров, смогут без труда воспроизвести любое устройство. Ра- диолюбители, имеющие опыт программирования, могут изменить программы и печатные платы под свои цели. Для этого в книге даны алгоритмы и исходные тексты программ с подробными комментариями. Автор также делится опытом работы с ассемблером MPLAB и различными средствами программирования. Рассматриваются типичные ошибки при наладке устройств на микроконтроллерах. Книга предназначена для широкого круга радиолюбителей, а также может быть полезна студентам, изучающим программирование микроконтроллеров. Книги издательства “МК-Пресс” можно заказать: пр адресу: 02002, г.Киев, а/я 294, по телефону/факсу: (044) 362-04-38, по e-mail: info@mk-press.com Посетите наш Internet-магазин: http://www.mk-press.com
Издательство “МК-Пресс” представляет Кравченко А.В. 10 практических устройств на. AVR-микроконтроллерах. Книга 2 (+CD) ISBN 978-5-7931-0532-3 320 стр., мягкая обложка Это вторая книга из серии сборников с практическими примерами применения микрокон- троллеров AVR. В ней подробно рассмотрены десять завершенных устройств на базе микрокон- троллеров AVR, которые можно легко собрать в домашних условиях и применять в быту или профессиональной деятельности: генератор световых эффектов с помощью АЦП; схема управ- ления шаговым двигателем; автомат освещения шкафа-купе; схема управления вентилятором; простой термометр; световой эффект "Призма”; микроконтроллерный генератор; робот, который двигается на свет и умеет обходить преграды; система радиоуправления моделью автомобиля; схема цифрового управления паяльником. Каждому устройству посвящена отдельная глава, где подробно описаны все этапы создания микроконтроллерной модели и программ, начиная со структуры и блок-схемы, и заканчивая самой программой и готовым рабочим кодом. Иванов В.Б. Программирование микроконтроллеров для начинающих. Визуальное проектирование, язык С, ассемблер (+CD) ISBN 978-5-7931-0559-0 176 стр., мягкая обложка В этой книге автор проводит читателя по пути освоения программирования микрокон- троллеров от простого к сложному. Начав с краткого описания архитектуры и системы команд микроконтроллеров PIC, он переходит к визуальному проектированию в среде Flowcode, кото- рое позволяет получить выполняемый код без каких-либо навыков программирования на ас- семблере или языке высокого уровня. В завершающих двух главах представлены примеры про- граммирования микроконтроллеров PIC с помощью языка С в среде MikroC и ассемблера в сре- де MPLAB. Книги издательства “МК-Пресс” можно заказать: по адресу: 02002, г.Киев, а/я 294, по телефону/факсу: (044) 362-04-38, по e-mail: info@mk-press.com Посетите наш Internet-магазин: http://www.mk-press.com
ББК 32.973-04 Ш83 ( УДК 004.312 Ш83 Програмування на мов! С для AVR та PIC м!кроконтролер1в. Вид. 2-е, перероблене та доповнене./ Уклад. Ю.О. Шпак — К.: “МК- Пресс”, СПб.: “КОРОНА-ВЕК”, 2011. — 544 с., in. ISBN 978-5-7931-0842-3 (“КОРОНА-ВЕК") ISBN 978-966-8806-67-4 (“МК-Пресс”) У книз1 розглянуто програмування на MOBi С мжроконтролерв AVR з викорис- танням комтлятор!в WinAVR та CodeVisionAVR, а також м!кроконтролер1в PIC з використанням компшятортв CCS-PICC, mikroC та С30/32. Коротко розглянуто архпектуру та апаратне забезпечення як традиц|‘йних восьмирозрядних мжрокон- Tponepie AVR i PIC, так й нових амейств ATxmega, PIC24 та PIC32. Даний опис за- co6ie програмноТ розробки, включаючи емуляц!ю програм за допомогою AVR Stu- dio та MPLAB. Коротко розглянуто стандартний синтаксис моей С та директиви препроцесора, а також особливосл програмування на щй Moei для мжроконтроле- pie. Книга мгстить программ приклади на С, а також — довщник з описом системи асемблерних команд MixpoKOHTponepie AVR (включаючи ATxmega) та PIC (вклю- чаючи PIC24). ББК 32.973-04 ISBN 978-5-7931-0842-3 (“КОРОНА-ВЕК") ISBN 978-966-8806-67-4 (“МК-Пресс") ©“МК-Пресс”, 2011
2 ИЗДАНИЕ В книге рассмотрено программирование на языке С микро- контроллеров AVR с использованием компиляторов WinAVR и CodeVisionAVR, а также микроконтроллеров PIC с исполь- зованием компиляторов CCS-PICC, mikroC и С30/32. Кратко рассмотрена архитектура и аппаратное обеспечение как традиционных восьмиразрядных микроконтроллеров AVR и PIC, так и новых семейств ATxmega, PIC24 и PIC32. Дано описание средств программной разработки, включая эму- ляцию программ с помощью AVR Studio и MPLAB. Кратко рассмотрен стандартный синтаксис языка С и директивы препроцессора, а также особенности программирования на этом языке для микроконтроллеров. Книга содержит программные примеры на С, а также — справочник с описа- нием системы ассемблерных команд микроконтроллеров AVR (включая ATxmega) и PIC (включая PIC24). WWW.MK-PRESS.COM WWW.MK-PRESS.COM