Ю. С. Магда
Микроконтроллеры PIC: архитектура и программирование
Москва, 2009
УДК 621.396.6 ББК 32.872 *** ***
Магд...
30 downloads
505 Views
3MB Size
Report
This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Report copyright / DMCA form
Ю. С. Магда
Микроконтроллеры PIC: архитектура и программирование
Москва, 2009
УДК 621.396.6 ББК 32.872 *** ***
Магда Ю. С. Микроконтроллеры PIC: архитектура и программирование. – М.: ДМК Пресс, 2009. – 240 с.: ил.
СОДЕРЖАНИЕ
ISBN
В книге рассматривается широкий круг вопросов, связанных с прак тическим применением популярных 16битных микроконтроллеров PIC24 в системах обработки данных и управления оборудованием. При водятся многочисленные примеры программирования несложных аппа ратнопрограммных систем обработки аналоговой и цифровой ин формации с применением периферийных модулей микроконтроллеров PIC24F. В контексте разработанных примеров приводятся необходимые сведения из теории, что способствует лучшему пониманию материала книги. Все приведенные в книге аппаратнопрограммные проекты разра ботаны и проверены на отладочном модуле Explorer 16 Development Board фирмы Microchip и могут служить основой для создания собственных проектов.
УДК 621.396.6 ББК 32.872 Все права защищены. Любая часть этой книги не может быть воспроизведена в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Материал, изложенный в данной книге, многократно проверен. Но, поскольку вероятность технических ошибок все равно существует, издательство не может гарантировать абсолютную точность и правильность приводимых сведений. В связи с этим издательство не несет ответственности за возможные ошибки, связанные с использованием книги.
ISBN
© Магда Ю. С., 2009 © Оформление, ДМК Пресс, 2009
Введение ................................................................................................................... 5 Структура книги ...................................................................................................... 6 1. ОБЗОР 16БИТНЫХ PICМИКРОКОНТРОЛЛЕРОВ .................................... 8 2. АРХИТЕКТУРА МИКРОКОНТРОЛЛЕРОВ PIC24F ....................................... 10 3. СИСТЕМА КОМАНД И ОСНОВЫ ПРОГРАММИРОВАНИЯ МИКРОКОНТРОЛЛЕРОВ PIC24F .................................................................. 18 3.1. Программная модель микроконтроллеров PIC24F ....................................... 18 3.2. Режимы адресации и система команд ........................................................... 20 3.2.1. Команды перемещения и адресация данных ....................................... 23 3.2.2. Команды сравнения/выбора и условного перехода ............................ 28 3.2.3. Команды работы с битами .................................................................... 32 3.2.4. Команды сдвига и циклического сдвига .............................................. 35 3.2.5. Команды математических и логических операций ............................. 37 3.2.6. Команды условных/безусловных переходов ....................................... 44 3.3. Разработка и отладка программ на ассемблере в среде MPLAB IDE ........... 46 3.4. Особенности разработки и отладки программ на MPLAB C для PIC24 ...... 59 4. ПРОГРАММИРОВАНИЕ ПОРТОВ ВВОДА/ВЫВОДА ................................ 73 4.1. Аппаратнопрограммная архитектура портов ввода/вывода ........................ 73 4.2. Программирование портов ввода/вывода ..................................................... 77 4.3. Модуль регистрации событий ......................................................................... 81 5. ПРОГРАММИРОВАНИЕ ПРЕРЫВАНИЙ .................................................... 89 6. ПРОГРАММИРОВАНИЕ ТАЙМЕРОВ ......................................................... 100 6.1. Практическое использование 16битных таймеров ..................................... 104 6.2. Работа таймеров в 32битном режиме .......................................................... 114 6.3. Часы реального времени ............................................................................... 118
4
Содержание
7. ИНТЕРФЕЙС SPI МИКРОКОНТРОЛЛЕРОВ PIC24F ................................ 120 7.1. Аппаратнопрограммная реализация SPI в микроконтроллерах PIC24F .... 121 7.2. Практическое программирование обмена данными по SPI ....................... 127 8. ИНТЕРФЕЙС I2C МИКРОКОНТРОЛЛЕРОВ PIC24F ................................. 140 8.1. Принципы функционирования интерфейса I2C ......................................... 140 8.2. Модуль интерфейса I2C микроконтроллеров PIC24F ................................. 143 8.3. Практическое использование интерфейса I2C ............................................. 147 9. ПРОГРАММИРОВАНИЕ ИНТЕРФЕЙСА PMP ........................................... 159 9.1. Режимы работы PMP .................................................................................... 161 9.2. Практические примеры программирования интерфейса PMP .................. 164 10. ПОСЛЕДОВАТЕЛЬНЫЙ ИНТЕРФЕЙС МИКРОКОНТРОЛЛЕРОВ PIC24F .............................................................. 182 10.1. Аппаратнопрограммная архитектура UART ............................................ 183 10.2. Практическое использование последовательного порта ........................... 184 11. ОБРАБОТКА АНАЛОГОВЫХ СИГНАЛОВ В МИКРОКОНТРОЛЛЕРАХ PIC24F ............................................................ 198 11.1. Программная модель интегрированного АЦП .......................................... 201 11.2. Практическое использование модуля АЦП ............................................... 205 11.3. Использование внешнего АЦП .................................................................. 217 12. ГЕНЕРАЦИЯ АНАЛОГОВЫХ И ЦИФРОВЫХ СИГНАЛОВ ..................... 221 12.1. Модуль генерации цифровых сигналов ..................................................... 221 12.2. Аналоговые компараторы в микроконтроллерах PIC24F ......................... 229 Заключение ........................................................................................................... 239
ВВЕДЕНИЕ Системы управления и контроля на однокристальных микроконтроллерах в настоящее время используются практически во всех сферах человеческой деятельности, причем каждый день появляются все новые и новые области применения таких систем. В последнее время, в связи с бурным развитием электроники расширились возможности и самих микроконтроллеров, позво ляющих выполнять многие задачи, ранее недоступные для реализации, такие, например, как обработка и синтез аналоговых аудио и видеосигналов. Одним из наиболее популярных семейств микроконтроллеров являются устройства, выпускаемые фирмой Microchip и известные под аббревиатурой PIC. В послед ние годы были разработаны и запущены в производство 16 и 32битные модели, позволившие существенно расширить области применения систем на базе микроконтроллеров PIC. Для облегчения миграции от 8 к 16битным устройствам фирма Microchip обеспечила максимальный уровень совместимо сти аппаратнопрограммных функций этих микроконтроллеров. Эта книга посвящена практическим аспектам разработки систем на базе 16битных микроконтроллеров PIC24F. В книге приводятся основные сведения по аппаратнопрограммной архитектуре микроконтроллеров PIC24F, а также многочисленные проекты систем обработки данных на базе микроконтролле ров этого семейства. Все примеры, приведенные в книге, разработаны и про тестированы на плате «Explorer 16 Development Board» производства Microchip с установленным микроконтроллером PIC24FJ128GA010. Тем не менее, для те стирования приведенных примеров и разработки собственных проектов читатели могут использовать и более дешевую систему начального уровня «MPLAB Starter Kit for PIC24F» той же фирмы или отладочные платы других фирм. Для раз работки программного обеспечения проектов, представленных в книге, ис пользовалась интегрированная среда разработки MPLAB IDE версии 8.00 и бесплатная студенческая версия компилятора языка Си, известного под назва нием MPLAB C для PIC24. Кроме того, при изучении системы команд микро контроллера PIC24F, а также при анализе процесса отладки некоторых программ на языке Си используется довольно эффективный симулятор/отладчик MPLAB SIM. Книга рассчитана на широкий круг читателей — от начинающих до опытных разработчиков – и может оказаться полезной для всех, кто желает самостоя тельно изучить аппаратнопрограммную архитектуру 16битных микроконтрол леров PIC24F и применить эти знания на практике.
Структура книги
СТРУКТУРА КНИГИ Структура книги рассчитана на последовательное изучение материала, хотя опытные разработчики систем на базе микроконтроллеров PIC могут изучать материал выборочно. Теоретический материал большинства глав подкреплен практическими примерами, что позволяет существенно облегчить изучение. Книга состоит из 12 глав, краткие сведения о каждой из них приведены далее: • Глава 1. «Обзор 16битных PICмикроконтроллеров». В этой главе рас сматриваются общие характеристики 16битных микроконтроллеров фир мы Microchip и дается краткий обзор инструментальных средств разработ ки программного обеспечения. • Глава 2. «Архитектура микроконтроллеров PIC24F». Материал этой главы посвящен обзору аппаратной архитектуры микроконтроллеров PIC24F, организации памяти и функционирования периферийных модулей устрой ства. • Глава 3. «Система команд и основы программирования микроконтроллеров PIC24F». В этой главе детально проанализированы принципы реализации системы команд микроконтроллеров PIC24F и приведены многочисленные примеры программного кода на языке ассемблера. Значительная часть главы посвящена вопросам разработки и отладки программного обеспече ния в среде MPLAB IDE. • Глава 4. «Программирование портов ввода/вывода». Эта глава содержит материал по архитектуре и программированию цифровых портов ввода/ вывода микроконтроллеров PIC24F. Теоретический материал сопровожда ется примерами программ на языке Си с детальным анализом программ ного кода. • Глава 5. «Программирование прерываний». Материал главы посвящен ап паратнопрограммной реализации системы прерываний микроконтролле
7
ров PIC24F. На многочисленных примерах программного кода проанали зированы различные механизмы вызова и обработки пользовательских прерываний. • Глава 6. «Программирование таймеров». Глава содержит материал по ап паратнопрограммной архитектуре модулей таймеров микроконтроллеров PIC24F. Рассматриваются различные режимы работы таймеров и их на стройка. Теоретический материал сопровождается примерами программ на языке Си с детальным анализом программного кода. • Глава 7. «Интерфейс SPI микроконтроллеров PIC24F». В главе рассмот рены принципы функционирования и аппаратнопрограммная реализа ция модуля интерфейса SPI, а также приведены примеры программиро вания систем ввода/вывода дискретных данных с использованием данного интерфейса. Все примеры сопровождаются детальным анализом программ ного кода. • Глава 8. «Интерфейс I2C микроконтроллеров PIC24F». Материал главы посвящен рассмотрению принципов функционирования и аппаратнопро граммной конфигурации модуля интерфейса I2C в микроконтроллерах PIC24F. Теоретический материал сопровождается примерами программи рования обмена данными по шине I2C на языке Си с детальным анализом программного кода. • Глава 9. «Программирование интерфейса PMP». В главе рассматривается аппаратнопрограммная реализация 8битного параллельного интерфейса обмена данными PMP. Приводятся примеры разработки систем ввода/ вывода цифровых данных с использованием этого интерфейса. • Глава 10. «Последовательный интерфейс микроконтроллеров PIC24F». В этой главе рассматриваются принципы реализации и настройки модуля последовательного интерфейса микроконтроллеров PIC24F. Теоретиче ский материал сопровождается примерами программирования обмена данными с использованием этого модуля, разработанными на языке Си, с детальным анализом программного кода. • Глава 11. «Обработка аналоговых сигналов в микроконтроллерах PIC24F». Эта глава посвящена методам обработки аналоговых сигналов в микро контроллерах PIC24F. Здесь рассматривается широкий круг вопросов, связанных с настройкой и использованием модуля аналогоцифрового преобразователя, а также приводятся примеры программирования ввода данных посредством АЦП. • Глава 12. «Генерация аналоговых и цифровых сигналов». В этой главе рассматривается широкий круг вопросов, связанных с генерацией цифро вых и аналоговых сигналов в микроконтроллерах PIC24F. Теоретические аспекты иллюстрируются примерами программного кода на языке Си. Автор благодарит коллектив издательства «ДМК Пресс» за помощь при под готовке книги к изданию. Особую признательность автор выражает своей жене Юлии за поддержку и помощь при написании книги.
Глава 1. Обзор 16битных PICмикроконтроллеров
ГЛАВА
1
ОБЗОР 16$БИТНЫХ PIC$МИКРОКОНТРОЛЛЕРОВ
Разработанные фирмой Microchip 16битные микроконтроллеры являются очередным шагом на пути повышения производительности и эффективности встроенных и мобильных приложений. Эта 16битная архитектура изначально разрабатывалась как альтернатива 8битным решениям и призвана заменить в ближайшее время 8битные микроконтроллеры в большинстве приложений. Разработанная фирмой Microchip 16битная платформа реализована в двух семействах 16битных микроконтроллеров и в двух семействах цифровых сиг нальных контроллеров. Все эти семейства объединяет ряд общих характеристик: • совместимость по назначению выводов различных 16битных устройств; • возможность использования для всех устройств одних и тех же инструмен тальных средств разработки программного обеспечения; • аппаратнопрограммная совместимость всех одноименных периферийных модулей микроконтроллеров; • общая базовая система команд процессора, используемая во всех семействах. Выбор той или иной модели микроконтроллера или сигнального контроллера зависит от требований к разрабатываемому приложению. Для большинства не дорогих устройств средней производительности подходят микроконтроллеры PIC24F, максимальная производительность которых составляет 16 MIPS. Для устройств, требующих высокой производительности, можно использовать мик роконтроллеры PIC24H с максимальным быстродействием 40 MIPS. Микроконт роллеры семейств PIC24F и PIC24H работают с одним и тем же набором ин струкций процессора, включают одни и те же периферийные модули, имеют одну и ту же цоколевку, и для работы с ними используются одни и те же инст рументальные средства для разработки программного обеспечения. Если требуются дополнительные возможности по обработке сигналов, то вместо микроконтроллеров семейств PIC24F/H можно применить цифровые сигнальные контроллеры семейства dsPIC30F, которые могут помимо всего прочего работать при напряжении питания 5 В, или высокопроизводительные (40 MIPS) контроллеры dsPIC33F, которые имеют большой объем памяти и используют низковольтное (3.3 В) питание. В качестве инструментального
9
средства разработки программного обеспечения 16битных микроконтроллеров и цифровых сигнальных контроллеров используется свободно распространяе мая интегрированная среда разработки (ИСР) MPLAB IDE фирмы Microchip, которая позволяет разрабатывать и отлаживать 8, 16 и 32битные приложе ния. Программа MPLAB IDE работает под управлением операционных систем Windows 2000/XP/Vista и позволяет выполнить все этапы разработки и отладки программного обеспечения для целевой системы. Среда MPLAB IDE позволяет выполнять тестирование и отладку программ с использованием мощного про граммного симулятора MPLAB SIM. Кроме того, для разработки программного обеспечения для 16битных систем в среде MPLAB IDE можно использовать следующие инструментальные средства: • ассемблер ASM30 — полнофункциональный макроассемблер, в котором можно создавать пользовательские макросы и использовать условное ас семблирование. Многочисленные директивы языка делают макроассемб лер очень мощным средством разработки программ; • компилятор программ, написанных на языке Си, который называется MPLAB C для PIC24. Этот компилятор используется для компиляции и оптимизации программ, написанных для 16битных микроконтроллеров PIC24F/H и циф ровых сигнальных контроллеров dsPIC30/33. Он совместим со стандартом ANSI C и включает полную библиотеку стандартных функций ANSI C, в числе которых функции манипулирования строками, функции работы с ди намической памятью, функции преобразования даты/времени и математиче ские функции. В компиляторе MPLAB C для PIC24 имеется мощный оптими затор, позволяющий почти в 1,5 раза уменьшить размер программного кода по сравнению с компиляторами других фирмпроизводителей; • визуальный генератор кода инициализации MPLAB VDI, позволяющий значительно упростить процесс создания инициализационного кода про граммы. С помощью VDI можно в графическом виде сконфигурировать устройство и по завершении вставить сгенерированный программный код инициализации в программу на языке Си или ассемблере; • библиотеку периферийных модулей, включающую более чем 270 функций для работы с различными периферийными модулями; • библиотеку математических функций, совместимую со стандартом IEEE754, которая включает ряд функций для выполнения операций над обычными вещественными числами и вещественными числами с двойной точностью. Функции этой библиотеки могут использоваться как в программах на языке Си, так и на ассемблере. Кроме инструментальных средств разработки и отладки программного обес печения фирмыпроизводителя на рынке присутствуют и программные сред ства, выпускаемые многими известными фирмами (HiTech, CCS и т.д.). Из аппаратных средств разработки наиболее известна и популярна отладочная плата «Explorer 16 Development Board» фирмы Microchip, хотя другие фирмы также приступили к выпуску отладочных плат на базе 16битных микроконт роллеров.
Глава 2. Архитектура микроконтроллеров PIC24F
ГЛАВА
2
АРХИТЕКТУРА МИКРОКОНТРОЛЛЕРОВ PIC24F
Микроконтроллеры PIC24F были разработаны как недорогое аппаратно программное решение для перехода от 8битных микроконтроллеров семейства PIC18 к 16битной архитектуре, призванное обеспечить максимальную преем ственность как уже разработанных приложений для PIC18, так и вновь созда ваемых, более эффективных и недорогих 16битных решений. Выбор микроконтроллеров PIC24F оправдан в тех случаях, когда необходимо обеспечить среднюю производительность системы при относительно невысо кой стоимости конечного продукта. Для приложений, требующих более высо кой производительности (выше, чем 16 MIPS), можно использовать более до рогие микроконтроллеры семейства PIC24H. Микроконтроллеры PIC24F обладают следующими характеристиками: • высокая производительность (до 16 MIPS); • векторная система прерываний с 16 уровнями приоритетов; • наличие 16 рабочих регистров; • возможность выполнения 16битных математических операций; • возможность выполнения операций умножения с разрядностью 17 ґ 17 бит за один машинный цикл; • возможность выполнения сдвига на произвольное количество бит (до 16) за один машинный цикл; • аппаратнопрограммная архитектура, оптимизированная для разработки программ на языке Си; • мощная система команд, которая включает инструкцию повторения repeat для циклического выполнения команд, что особенно полезно при использовании команд пересылки данных. По сравнению с микроконтроллерами PIC18 микроконтроллеры PIC24F об ладают многими кардинальными улучшениями. Вопервых, в микроконтролле рах PIC24F расширен объем оперативной и флэшпамяти, что при прочих равных условиях позволяет оптимизировать обработку больших объемов дан ных и создавать более высокопроизводительные системы управления и обра ботки данных. Еще одним существенным улучшением стало включение в со став микроконтроллера дополнительных периферийных модулей.
11
В микроконтроллерах семейства имеется пять 16битных таймеров, четыре из которых можно каскадировать, получая два 32битных. Кроме того, на кри сталле микроконтроллера находится интегрированный 10битный аналого цифровой преобразователь последовательного приближения, который может выполнять преобразование аналоговых сигналов со скоростью до 500 тыс. вы борок в секунду. В микроконтроллерах семейства также реализован модуль JTAG, который позволяет выполнять тестирование и программирование мик роконтроллера в системе. Микроконтроллеры PIC24F могут взаимодействовать с различными внешни ми периферийными устройствами посредством интерфейсов I2C, SPI и UART. Для этого в состав устройства включены соответствующие модули, которые могут настраиваться и работать независимо друг от друга. Функциональность подсистемы асинхронной последовательной передачи данных улучшена за счет включения в UART аппаратнопрограммного субмодуля IrDA. Существенно улучшает рабочие характеристики модулей интерфейсов SPI и UART сериали зация данных в буфере FIFO, которая позволяет снизить непроизводительные траты процессорного времени на обработку передачи данных. В отличие от многих устройств семейства PIC18, в которых реализован порт параллельной передачи данных, работающий только в режиме «ведомого», в микроконтролле рах PIC24F имеется модуль параллельного обмена данными, который позволяет работать как в режиме «ведомого», так и в режиме «ведущего». Это существенно расширяет возможности PIC24F при обмене данными с периферийными устрой ствами, имеющими параллельный интерфейс (принтеры, сканеры, устройства внешней памяти и т. д.). Все устройства семейства PIC24F имеют один и тот же набор базовых пе риферийных модулей и отличаются объемом флэшпамяти. Обобщенная функ циональная схема микроконтроллеров семейства PIC24F показана на Рис. 2.1. Периферийные модули микроконтроллеров PIC24F позволяют создавать си стемы обработки данных и управления для широкого класса задач, решаемых в промышленности и в лабораторных исследованиях. Мы будем детально рас сматривать принципы функционирования большинства из этих периферийных модулей в последующих главах, а сейчас проведем краткий обзор и начнем с модуля аналогоцифрового преобразователя. В микроконтроллерах семейства Microchip используется 10битный аналого цифровой преобразователь последовательного приближения. Ниже приводятся отдельные характеристики этого преобразователя: • скорость преобразования — до 500 тыс. выборок/с; • количество каналов входных аналоговых сигналов — 16; • источник опорного напряжения — внешний или внутренний. Аналогоцифровой преобразователь может работать в режиме автоматиче ского сканирования входов и поддерживает различные режимы синхрони зации. Модуль АЦП допускает автономную работу при переходе процессора в «спящий» режим или режим «холостого хода». Аналогоцифровой преобра зователь может производить несколько последовательных выборок, накапливая
12
Глава 2. Архитектура микроконтроллеров PIC24F
Рис. 2.1. Обобщенная функциональная схема микроконтроллеров PIC24F
результат в 16уровневом буфере данных, и сохранять результат в одном из четырех форматов. Следующий периферийный модуль, который мы рассмотрим, — модуль ана логовых компараторов. Это устройство включает в себя два компаратора, ко торые используются при реализации широкого класса функциональных узлов, например детектора перехода через ноль в схеме синхронизации по пере менному току 50 Гц, или при создании более сложных устройств, таких, как 16битный сигмадельта аналогоцифровой преобразователь. Микроконтроллеры PIC24F включают 5 модулей таймеров общего назначе ния разрядностью 16 бит. Все пять таймеров обладают общими базовыми фун кциональными возможностями. Регистры периода всех таймеров могут исполь зоваться для генерации прерывания при совпадении содержимого такого регистра с текущим содержимым регистра таймера. Во всех таймерах преду смотрены режим запуска/останова по внешнему сигналу и генерация преры вания по спаду внешнего сигнала. Четыре из пяти таймеров могут объеди няться попарно для формирования 32битных таймеров. С модулями таймеров тесно связан 5канальный модуль захвата входных сигналов и 5канальный модуль генерации цифровых сигналов. Модуль захвата входных сигналов ис пользуется для измерения интервалов между событиями. Минимальная разре
Глава 2. Архитектура микроконтроллеров PIC24F
13
шающая способность при таком измерении равна длительности одного машин ного цикла. Для синхронизации временныêх меток модуль захвата входных сигналов использует в качестве базовых Таймеры 2 и 3. Модуль генерации цифровых сигналов используется для генерации одиноч ных импульсов и импульсных последовательностей и имеет пять каналов. Для отсчета интервалов времени при формировании таких сигналов модуль генера ции цифровых сигналов использует в качестве базовых Таймер 2 и Таймер 3. Выходные сигналы этого модуля могут использоваться для управления обыч ными (термоэлементы) и индуктивными (электродвигатели) нагрузками, а так же для синтеза голосовых сигналов. В микроконтроллерах семейства PIC24F имеется два модуля универсального асинхронного приемопередатчика (UART), которые позволяют реализовать об мен данными в соответствии со стандартами RS232 и RS485. Приемопередат чик обеспечивает обмен 8 или 9битными данными с контролем четности или без такового с одним или двумя стоповыми битами. Устройство поддерживает функцию аппаратного контроля обмена данными, что обеспечивает высокий уровень надежности и производительности, позволяя подключать к микрокон троллеру различные периферийные устройства, например модемы. Скорость передачи данных может изменяться от 15 бод до 1 Мбод. Повышение произво дительности операций обмена данными и разгрузка процессора обеспечивают ся за счет использования 4уровневых буферов входных/выходных данных и прерываний. Кроме того, модуль UART поддерживает передачу информации по протоколам IrDA и LIN. Для обмена данными между различными устройствам в настоящее время очень часто используются протоколы I2C и SPI. Микроконтроллеры PIC24F имеют интегрированные периферийные модули для поддержки этих протоко лов. В модуле I2C применяется аппаратнопрограммный алгоритм, позволяю щий выбрать режим «ведущего» или «ведомого». Модуль поддерживает как 7, так и 10битную адресацию устройств на шине I2C, при этом тактовая частота шины I2C может быть задана равной 100 или 400 кГц. Модули SPI микроконтроллеров PIC24F можно сконфигурировать для рабо ты с двумя, тремя или четырьмя сигнальными линиями. В режиме с двумя линиями (синхронизации и данных) интерфейс SPI можно использовать для приема сигналов датчиков. Для работы с аналогоцифровыми преобразовате лями, сдвиговыми регистрами и микросхемами памяти EEPROM используется, как правило, 3проводной интерфейс. Еще один периферийный модуль — модуль часов реального времени с ка лендарем (RTCC) — предназначен для точного отсчета времени в течение длительных интервалов и оперирует с датами и временем. Он может выполнять функцию будильника, включая внешнее устройство в определенный момент времени в будущем. Модуль RTCC синхронизируется непосредственно от внешнего источника тактового сигнала частотой 32 кГц. Из этого сигнала посредством предделителя формируется внутренний сигнал с периодом 0.5 с, который используется для синхронизации регистров модуля, содержащих эле
14
Глава 2. Архитектура микроконтроллеров PIC24F
менты даты (год, месяц, день; день недели, часы, минуты и секунды). Данные хранятся в регистрах в удобном BCDформате. Функция будильника может быть запрограммирована на определенный месяц, день; день недели, час, минуту и секунду. Кроме того, поскольку регистры модуля часов реального времени работают на очень низкой частоте, это позволяет минимизировать энергопотребление устройства. Часы реального времени могут функциониро вать и в том случае, если процессор находится в «спящем» режиме. Для управ ления внешними устройствами можно использовать выходной сигнал модуля частотой 1 Гц или сигнал, формируемый при срабатывании будильника. Модуль параллельного порта позволяет легко реализовывать аппаратнопро граммный 8битный интерфейс с внешними устройствами и модулями памяти. Модуль поддерживает мультиплексирование шин адреса/данных, позволяя пе редавать по 8битной шине 16битные данные. В модуле предусмотрена работа с 16 адресными линиями, что дает возможность адресовать до 64 Кбайт памяти, а при использовании дополнительных линий адреса, в качестве которых могут быть задействованы выводы портов общего назначения, — и большее простран ство адресов. В модуле предусмотрена функция автоинкремента/автодекремента адреса, что позволяет оптимизировать передачу больших блоков данных. Последнее периферийное устройство, на котором мы остановимся, — мо дуль контроля достоверности данных с использованием циклического избыточ ного кода (CRC). Этот модуль находит применение при контроле ошибок обмена данными с периферийным оборудованием и памятью, особенно при работе с коммуникационным оборудованием по протоколам CAN, USB и Ethernet. Микроконтроллеры семейства PIC24F имеют 16разрядную шину данных, что существенно повышает их функциональные возможности по сравнению с устройствами семейства PIC18. Длина инструкции (команды) процессора в микроконтроллерах серии PIC24 равна 24 битам, а частота выполнения команд процессора в 2 раза меньше, чем частота синхронизации устройства. Если использовать принятые в документации фирмы Microchip обозначения, то это соотношение можно выразить формулой: FCY = FOSC/2, где FOSC — тактовая частота синхронизации микроконтроллера, а FCY — такто вая частота процессора. Счетчик команд (Program Counter, PC) имеет разрядность 23 бита и позво ляет адресовать до 4 миллионов инструкций в памяти программ. Высокая про изводительность микроконтроллера обеспечивается за счет использования ме ханизма конвейеризации инструкций, при котором выборка и декодирование следующей инструкции процессора осуществляются на этапе выполнения пре дыдущей. При этом все инструкции выполняются за один машинный цикл, за исключением инструкций передачи управления, инструкций, оперирующих двой ными словами, и инструкций табличного чтения/записи. Кроме того, определен ную оптимизацию загрузки процессора можно осуществить за счет применения инструкции цикла repeat.
Глава 2. Архитектура микроконтроллеров PIC24F
15
Микроконтроллеры семейства PIC24F имеют 16 рабочих регистров, опери рующих данными размером в одно слово (16 бит). Каждый из этих регистров может выступать в роли регистра данных, адреса или смещения. Шестнадца тый по счету регистр (W15) используется в качестве указателя стека (SP, Stack Pointer) в операциях вызова процедур и обработчиков прерываний. В мик роконтроллерах PIC24F предусмотрена возможность отображения верхних 32 Кбайт памяти данных на адресное пространство памяти программ с вырав ниванием по границе слова, для чего используется 8битный регистр PSVPAG (Program Space Visibility Page). Разработчики семейства PIC24F предусмотрели обратную совместимость ин струкций и режимов адресации процессора с микроконтроллерами семейства PIC18 за счет прямого включения подмножества инструкций PIC18 в систему команд PIC24, а также посредством использования макросов. В микроконтроллерах семейства PIC24F реализована гарвардская архитектура, в которой память программ и память данных разделены, что позволяет осуще ствлять прямой доступ к памяти программ из памяти данных во время выпол нения программного кода. Организация памяти программ одной из наиболее распространенных линеек микроконтроллеров семейства PIC24FJ128GAxxx со 128 Кбайт флэшпамяти показана на Рис. 2.2. Пользовательским программам доступна область памяти в диапазоне адресов 0x000000…0x7FFFFF, за исключением области конфигурации устройства, дос туп к которой осуществляется посредством инструкций tblrd/tblwt. Память программ организована в виде блоков, адресуемых пословно. Хотя адрес памя ти является 24битным, более удобно рассматривать любой адрес в виде млад шего и старшего слова, при этом старший байт старшего слова не используется и равен 0. Младшее слово всегда располагается по четному адресу, а старшее — по нечетному. Следует сказать, что адреса памяти программ всегда выравни ваются по границе слова и при выполнении программного кода всегда инкре ментируются и декрементируются на 2. Область памяти программ между адресами 0х000000 и 0х000200 зарезервиро вана для векторов прерываний. По адресам 0x000000 и 0x000002 размещается команда перехода к фактическому началу программы, при этом по первому адресу располагается код операции инструкции goto, а по второму — соб ственно адрес точки входа в программу. Также в памяти программ размеща ются две таблицы векторов прерываний. Одна из них располагается в диапа зоне адресов 0x000004…0x0000FF, а вторая (альтернативная) — в диапазоне адресов 0x000100…0x0001FF. Адресное пространство памяти данных микроконтроллеров PIC24F пред ставляет собой непрерывную область 16битных адресов с линейной адресаци ей. Адрес для доступа к данным формируется двумя модулями генерации адресов, один из которых используется в операциях записи, а другой — в опе рациях чтения данных. Распределение памяти данных микроконтроллеров PIC24F1 показано на Рис. 2.3. 1
Моделей с 8 Кбайт ОЗУ. – Примеч. науч. ред.
16
Глава 2. Архитектура микроконтроллеров PIC24F
Рис. 2.2. Схема организации памяти программ микроконтроллеров PIC24FJ128GA
Глава 2. Архитектура микроконтроллеров PIC24F
Рис. 2.3. Схема распределения памяти данных
Все действующие адреса памяти данных (Effective Addresses, EA) имеют размер 16 бит, что позволяет адресовать 64 Кбайт памяти. Нижняя половина адресов памяти данных, для которых старший бит действующего адреса равен 0, используется для адресации данных, а старшая половина адресов, для ко торых старший бит адреса равен 1, — для отображения памяти программ на память данных (Program Space Visibility Area, PSVA). Микроконтроллеры PIC24FJ128GA010 имеют объем памяти данных 8 Кбайт; при обращении к памяти данных по адресу, лежащему за пределами этой области, возвраща ется нулевой байт или слово. Данные в памяти выравниваются по границе слова, при этом младшие бай ты имеют четные, а старшие — нечетные адреса. Для обратной совместимости с 8битными микроконтроллерами в систему команд PIC24F включены коман ды, поддерживающие операции как со словами, так и с отдельными байтами. При этом процессор распознает, когда выполняется операция над байтом, а когда – над словом, и генерирует соответствующий адрес. Например, если в команде используется косвенная адресация с постинкрементом, такая, как
17
[W1++], то для байтовой команды генерируется адрес, равный W1+1, а для команды, работающей со словом, — W1+2. При любых операциях со словами данные должны иметь четный адрес, поэтому компилятор будет выдавать ошибку при сборке программ, если в программном коде происходит обраще ние к слову по нечетному адресу. Если такая ситуация возникает при выпол нении программы, то генерируется ошибка адресации и вызывается обра ботчик этой исключительной ситуации. По этой причине следует соблюдать осторожность, если в программе одновременно присутствуют инструкции, ра ботающие с байтами и со словами. Для повышения эффективности работы программ в систему команд включен ряд инструкций, позволяющих преобразовывать байты данных в слова. Это инструкция расширения знака se (SignExtend), приводящая 8битное число со знаком к 16битному формату, и инструкция расширения нуля ze (Zero Extend), заполняющая старший байт беззнакового целого нулями. Большин ство инструкций процессора могут работать как с байтами, так и со словами, но некоторые инструкции оперируют только со словами. Первые два килобайта адресного пространства памяти данных (от 0x0000 до 0x7FF) выделяются для регистров специальных функций (Special Function Register, SFR), которые используются ядром и периферийными модулями мик роконтроллера PIC24F для выполнения различных операций. Эти регистры распределены между модулями, с которыми они связаны, и, как правило, группируются по принадлежности к тому или иному периферийному модулю. Большинство адресов, выделяемых под регистры специальных функций, на данный момент не задействованы и читаются как 0. Мы продолжим изучение особенностей аппаратнопрограммной архитекту ры микроконтроллеров PIC24F в следующей главе, в которой подробно рас смотрим особенности программирования этих устройств.
3.1. Программная модель микрокнтроллеров PIC24F
ГЛАВА
19
3
СИСТЕМА КОМАНД И ОСНОВЫ ПРОГРАММИРОВАНИЯ МИКРОКОНТРОЛЛЕРОВ PIC24F
Микроконтроллеры PIC24 представляют собой качественно новый тип устройств, разработанных фирмой Microchip. Программная архитектура этих микроконтроллеров существенно отличается от предыдущих семейств 8бит ных устройств, хотя разработчики сделали все возможное, чтобы обеспечить безболезненный переход от 8битной архитектуры к 16битной. В этой главе рассматривается базовая программная модель микроконтролле ров PIC24F без учета особенностей реализации периферийных модулей, кото рые детально анализируются в последующих главах.
3.1. Программная модель микроконтроллеров PIC24F Для разработчика программного обеспечения программную модель микро контроллеров PIC24F можно представить так, как показано на Рис. 3.1. В качестве рабочих используются 16 регистров процессора (W), которые могут функционировать как регистры данных или адресов. Функция, выпол няемая Wрегистром, определяется режимом адресации, который используется в данной инструкции. В регистре W15 содержится указатель стека (Stack Pointer, SP), который ав томатически модифицируется при обработке исключений, вызовов подпрог рамм и прерываний. Тем не менее, регистр W15 можно использовать в инст рукциях в качестве обычного рабочего регистра. Во многих случаях такое использование упрощает манипуляции с указателем стека. Бит 0 этого регистра всегда сброшен в 0 для выравнивания содержимого стека. При инициализации микроконтроллера в регистр W15 записывается значе ние 0x0800, и это обеспечивает установку указателя стека на начало области памяти, которая доступна пользователю. Программа пользователя может моди фицировать SP так, чтобы он указывал на любую требуемую область памяти. Указатель стека всегда указывает на первое доступное слово и смещается при заполнении от младших адресов к старшим. Указатель стека всегда декремен
Рис. 3.1. Программная модель микроконтроллера PIC24F
тируется перед извлечением значения из стека и инкрементируется после помещения значения в стек. Функционирование стека показано на Рис. 3.2. Когда содержимое счетчика команд помещается в стек, то биты 15…0 распо лагаются по первому доступному адресу в стеке, а биты 22…16 помещаются по следующему адресу, при этом старшие биты второго слова дополняются нулями.
Рис. 3.2. Функционирование стека
20
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
Процессор микроконтроллеров PIC24F имеет 16битный регистр состояния (Status Register, SR). Младшая часть регистра состояния (SRL) содержит флаги арифметических операций (нуля, переноса, переполнения и знака), а также 3 бита приоритета (IPL2…IPL0), в которых устанавливается текущий приоритет прерываний процессора (см. Рис. 3.1). Регистр управления процессором (Core Control Register, CORCON) имеет всего 2 бита, которые можно использовать при разработке программ. Бит 3 (Interrupt Priority Status Level, IPL3) задает уровень приоритета прерываний процессора. Если этот бит установлен, то уровень приоритета прерываний про цессора выше 7 — в этом случае пользовательские прерывания однозначно запрещены. Если этот бит сброшен, то уровень приоритета меньше или равен 7 — в этом случае прерывания пользователя могут быть разрешены. Бит 2 (Program Space Visibility, PSV) указывает на возможность доступа к памяти программ из памяти данных: если бит установлен, то заданная область памяти программ доступна из памяти данных, а если сброшен — недоступна. К программнодоступным регистрам ядра процессора микроконтроллеров PIC24F относятся еще два регистра, которые выполняют специальные функ ции и могут быть полезны при работе с блоками памяти и таблицами. Регистр TBLPAG используется для хранения старших 8 битов адреса памяти программ при операциях чтения/записи табличных данных. С помощью табличных ин струкций процессора можно перемещать данные из памяти программ в память данных. Регистр PSVPAG (Program Memory Visibility Page Address Pointer) по зволяет пользователю отобразить страницу памяти программ размером 2 Кбайт на верхние 32 Кбайт адресного пространства памяти данных. С помощью этого регистра можно получить доступ к секции констант программы.
3.2. Режимы адресации и система команд
гистровыми и адресными. Основное различие между этими типами инструкций состоит в том, что регистровые инструкции модифицируют содержимое регист ров1, в то время как адресные инструкции используют содержимое рабочих реги стров для доступа к данным, находящимся в памяти. В свою очередь адресные инструкции могут быть как с прямой регистровой адресацией (register direct addressing), так и с косвенной регистровой адресацией (register indirect addressing). Прямая регистровая адресация используется для доступа к содержимому 16 рабочих регистров W0…W15, причем обращение возможно как к целому слову (16 бит), так и к байту. Косвенная регистровая адресация применяется для доступа к любой ячейке памяти данных посредством формирования исполнительного адреса данных по содержимому одного или нескольких рабочих регистров. Таким образом, содер жимое рабочего регистра или регистров является указателем на область памяти данных. Дополнительные возможности такого метода адресации обеспечиваются механизмами пред и постинкремента содержимого регистра, что позволяет последовательно обрабатывать непрерывный диапазон адресов в памяти данных. Методы формирования эффективного адреса (ЕА) с помощью косвенной регистровой адресации показаны в Табл. 3.1. Таблица 3.1. Формирование эффективного адреса методом косвенной регистровой адресации Режим адресации
Байтовая адресация
Адресация слова
Описание
Косвенная без модификации Косвенная с пост" инкрементом
EA = [Wn]
EA = [Wn]
EA = [Wn]+=1
EA = [Wn]+=2
Косвенная с пост" декрементом
EA = [Wn]–=1
EA = [Wn]–=2
Косвенная с пред" инкрементом
EA = [Wn+=1]
EA = [Wn+=2]
Косвенная с пред" декрементом
EA = [Wn–=1]
EA = [Wn–=2]
Эффективный адрес формируется по содержимому регистра Wn Эффективный адрес формируется по содержимому регистра Wn, затем содержимое Wn инкремен" тируется Эффективный адрес формируется по содержимому регистра Wn, затем содержимое Wn декремен" тируется Перед формированием эффектив" ного адреса содержимое Wn инкрементируется Перед формированием эффектив" ного адреса содержимое Wn декрементируется Эффективный адрес формируется как сумма Wn и Wb
3.2. Режимы адресации и система команд Систему инструкций (команд) микроконтроллеров PIC24F можно разделить на несколько групп: • команды перемещения; • команды математических операций; • команды логических операций; • команды сдвига и циклического сдвига; • команды работы с битами; • команды сравнения/выбора; • команды условных переходов; • команды работы со стеком; • команды управления. Мы не будем подробно описывать функционирование каждой команды, а остановимся лишь на общих принципах реализации команд и используемых ими методах адресации. В этом разделе мы рассмотрим многочисленные приме ры использования команд микроконтроллеров семейства PIC24F с применением различных методов адресации. Инструкции процессора в PIC24F могут быть ре
21
Косвенная со сме" EA = [Wn + Wb] EA = [Wn + Wb] щением, заданным в регистре Косвенная со сме" EA = [Wn + EA = [Wn + Эффективный адрес формируется щением, заданным + Slit5] + 2*Slit5] как сумма Wn и константы Slit5 константой (значение в диапазоне от –16 до +15)
1
Точнее, области памяти в диапазоне адресов 0x0000…0x1FFF (команда mov — в диапазоне адресов 0x0000…0xFFFE). – Примеч. науч. ред.
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
22
Регистр W0 является особым регистром, поскольку это единственный из рабочих регистров, который можно использовать в регистровых инструкциях. Регистровые инструкции оперируют с адресами памяти и содержимым регист ра W0. Рабочие регистры W1…W15 в таких инструкциях в качестве приемника использовать нельзя. Регистровые инструкции обратно совместимы с инструк циями, которые входят в систему команд микроконтроллеров предыдущих семейств и работают только с одним Wрегистром. Синтаксис ассемблера включает обозначение «WREG», призванное подчеркнуть, что регистр W0 ис пользуется в регистровой инструкции. Ниже приводятся примеры регистровых инструкций: mov add
WREG,0x0100 0x0100,WREG
Первая инструкция помещает содержимое регистра W0 по адресу 0x0100, а вторая складывает значение по адресу 0x0100 с содержимым регистра WREG и помещает результат в WREG. Все рабочие регистры отображены на адресное пространство памяти данных, поэтому их можно использовать в таких, например, инструкциях: mov
0x0004,W10
Здесь 0х0004 — адрес регистра W2. Эта инструкция эквивалентна следующей: mov
W2,W10
Для более глубокого изучения различных режимов адресации и функциони рования команд микроконтроллеров PIC24F мы рассмотрим многочисленные примеры программного кода, написанного на языке ассемблера MPLAB ASM30. В качестве целевого устройства будем использовать микроконтроллер PIC24FJ128GA010, хотя программы будут работать и с другими моделями се мейства PIC24F. Изучение функционирования микроконтроллера на уровне команд ассемб лера обязательно, если вы намерены стать высококвалифицированным разра ботчиком программного обеспечения. Даже если в дальнейшем вам придется разрабатывать программы на одном из языков высокого уровня (Си, Бейсик или Паскаль), знание языка ассемблера и программной архитектуры окажет неоценимую помощь при отладке программ. Зачастую, как показывает прак тика, без знания ассемблера бывает крайне сложно отладить программу, осо бенно сложную, до требуемого уровня функциональности. Очень часто знание ассемблера помогает решить те или иные проблемы, которые на языке высо кого уровня решить довольно трудно (особенно это касается работы с внешни ми устройствами и интерфейсами). Разумное сочетание языка высокого уровня и ассемблера позволяет решить любую задачу в пределах аппаратных возмож ностей самого устройства. Компиляцию тестовых программ на ассемблере мы будем проводить в среде MPLAB IDE, а отладку проводить с помощью программного симулятора MPLAB SIM. Все тестовые программы на ассемблере разработаны с использо ванием шаблона, который показан далее:
3.2. Режимы адресации и система команд #include
23
"P24FJ128GA010.inc"
.data .text .global __reset:
reset
.end
Все примеры из этой книги тестируются на микроконтроллере PIC24FJ128GA010, поэтому в шаблон включен заголовочный файл P24FJ128GA010.inc. Кроме того, во многих примерах используются инициализированные данные, которые объявляются в секции .data. Команды размещаются в секции программного кода .text. Исходный текст программы на ассемблере следует сохранить в файле с расширением .s, а сам файл включить в проект, созданный с помо щью мастера проектов среды MPLAB IDE. Мы рассмотрим не все команды процессора, поскольку это заняло бы не сколько сот страниц, а только часть из них. Детальную информацию обо всех инструкциях процессора читатели смогут найти в технической документации на микроконтроллеры PIC24F фирмы Microchip. 3.2.1. Команды перемещения и адресация данных В командах перемещения, большинство из которых имеет мнемоническое обозначение mov, используется хотя бы один регистр. Регистровые инструкции могут использовать Wрегистр как регистр данных или регистр, в который помещается смещение адреса. Рассмотрим несколько примеров. Пример 1 mov mov
#0x19C7,W0 W0,W1
В первой инструкции константа 0x19C7 командой mov помещается в регистр W0. Затем содержимое регистра W0 пересылается в регистр W1. Таким обра зом, после выполнения второй инструкции в регистре W1 будет содержаться значение 0x19C7. Пример 2 .data d1: .word 0x0800 .text .global __reset __reset: mov #0x1234,W0 mov #d1,W1 mov W0,[W1] L1: goto L1 .end
В этой короткой программе переменная d1 из секции инициализированных данных (директива .data) размещается по адресу 0x0800. В секции программы
24
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
.text, которая начинается с метки main, первая команда mov помещает в регистр W0 константу 0x1234. Вторая команда mov помещает адрес перемен ной d1 (равный 0x0800) в регистр W1. Третья команда помещает содержимое регистра W0 по адресу, находящемуся в W1. Таким образом, после выполнения третьей команды mov в переменной d1 будет содержаться значение 0x1234. Пример 3 .data d1: .word 0x0800 d2: .word 0x0802 .text .global __reset __reset: mov #0x1234, W0 mov #d1, W1 mov W0, [W1++] add #0x3, W0 mov W0, [W1] L1: goto L1 .end
Здесь показана методика использования постинкрементной адресации. В области данных проинициализированы две переменные – d1 и d2 с адресами 0х0800 и 0х802 соответственно. Как и в предыдущем примере, в регистр W0 помещается значение 0х1234, а в регистр W1 — адрес d1. В третьей команде mov в переменную d1, чей адрес содержится в регистре W1, помещается зна чение 0х1234, после чего содержимое W1 увеличивается на 2 (команда опери рует словами). Таким образом после выполнения команды регистр W1 будет содержать значение 0х0802, что соответствует адресу переменной d2. Команда add прибавляет значение 0х3 к содержимому регистра W0, так что перед последней командой mov регистр W0 будет содержать значение 0х1237. Наконец, следующая за add команда помещает это значение по адресу 0х0802, находящемуся в регистре W1. Пример 4 .data d1: .word 0x0800 d2: .word 0x0802 .text .global __reset __reset: mov #0x1234,W0 mov #d2,W1 mov W0,[W1—] add #0x3,W0 mov W0,[W1] L1: goto L1 .end
Пример демонстрирует постдекрементную адресацию. В регистр W1 коман дой mov заносится адрес переменной d2 (0x0802), по которому записывается
3.2. Режимы адресации и система команд
25
значение 0х1234, затем содержимое W1 декрементируется, указывая на пере менную d1 (адрес 0х0800). По этому адресу записывается значение 0х1237 из регистра W0. Пример 5 .data d1: .word 0x0800 d2: .word 0x0802 d3: .word 0x0804 .text .global __reset __reset: mov #0x1234,W0 mov #d2,W1 mov W0,[++W1] add #0x7,W0 mov W0,[W1] L1: goto L1 .end
В этой программе показано использование прединкрементной адресации. В регистр W1 командой mov заносится адрес переменной d2 (0x0802). Сле дующая команда предварительно увеличивает содержимое W1 на 2 (команда оперирует со словами), после чего помещает значение 0x123B из регистра W0 по адресу 0х0804. Пример 6 .data d1: .word 0x0800 d2: .word 0x0802 d3: .word 0x0804 .text .global __reset __reset: mov #0x1234,W0 mov #d2,W1 mov W0,[—W1] L1: goto L1 .end
В этом примере показано использование преддекрементной адресации. Вто рая команда mov помещает в регистр W1 адрес переменной d2. Следующая команда вначале декрементирует содержимое регистра W1, после чего помеща ет по адресу 0x0800, содержащемуся в этом регистре, значение 0х1234. Пример 7 .data d1: .word d2: .word d3: .word .text
0x0800 0x0802 0x0804
26
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
.global __reset __reset: mov #0x4321,W0 mov #d1,W1 mov #4,W2 mov W0,[W1+W2] L1: goto L1 .end
Программа демонстрирует применение косвенной адресации со смещением, заданным в одном из рабочих регистров. В качестве базового в данном случае выступает регистр W1, в который помещается адрес переменной d1, равный 0х0800 (вторая команда mov). Затем в регистр W2 заносится смещение 4. Наконец, последняя команда mov помещает содержимое регистра W0 по эф фективному адресу, который формируется как сумма содержимого базового регистра W1 и регистра W2. Таким образом, эффективный адрес, по которому будет записано значение 0х4321, получается равным 0х0804, что соответствует переменной d2. Пример 8 .data d1: .word 0x0800 d2: .word 0x0802 d3: .word 0x0804 .text .global __reset __reset: mov #0x4321,W0 mov #d1,W1 mov W0,[W1+2] L1: goto L1 .end
Данный пример демонстрирует использование косвенной адресации со сме щением, заданным константой. Базовый адрес, равный адресу переменной d1, загружается в регистр W1. Последняя команда mov помещает содержимое ре гистра W0 по адресу, который формируется как сумма содержимого регистра W1 и константы 2 и будет равен 0x0802. Таким образом, эта команда запишет значение 0х4321 в переменную d2. В ряде случаев необходимо манипулировать с отдельными байтами слова или двойного слова. Для этого в командах перемещения используется суффикс b или q. В следующем примере показано, как записать байт в переменную, рас положенную в памяти данных. Пример 9 .data d1: .word d2: .word .text
0x0800 0x0802
3.2. Режимы адресации и система команд
27
.global __reset __reset: mov #0x4321,W0 mov #d2,W1 mov.b W0,[W1] L1: goto L1 .end
Замечу, что во всех командах, манипулирующих с байтами, по умолчанию изменяется младший байт. В этом примере для записи младшего байта (0x21) в младший байт переменной d2 используется инструкция mov.b, в которой применяется косвенная регистровая адресация посредством регистра W1. В следующем примере в переменную последовательно записываются млад ший и старший байты значения. Пример 10 .data d1: .word 0x0800 d2: .word 0x0802 .text .global __reset __reset: mov #0x1ACE,W0 mov W0,d1 mov #d2,W1 mov mov.b mov.b
#d1,W0 [W0++],[W1++] [W0],[W1]
goto
L1
L1: .end
Первые две команды программы записывают значение 0х1ACE в перемен ную d1. Затем адрес переменной d1 помещается в регистр W0, а адрес пере менной d2 — в регистр W1. В последних двух командах mov.b используется постинкрементная адресация для записи старшего байта переменной d1 в стар ший байт переменной d2. К командам перемещения данных относится и команда перестановки стар шего и младшего байтов или полубайтов, которая эффективно используется в математических вычислениях. Следующий пример демонстрирует переста новку старшего и младшего байтов слова. Пример 11 .text .global __reset __reset: mov #0x4,W1 mov #0x9,W2 add W1, W2,W0 swap W0
28
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
Loop1: bra .end
Loop1
Здесь содержимое регистров W1 (0x4) и W2 (0x9) складывается командой add W1, W2, W0 и результат (0xD) записывается в регистр W0. В 16битном регистре W0 старший байт будет равен 0х0, а младший — 0xD. После выполнения коман ды swap W0 старший байт станет равным 0x0D, а младший — 0x0. Эту же про грамму можно модифицировать так, чтобы менять местами значения старшего и младшего полубайта младшего байта регистра W0, применив инструкцию swap.b. Исходный текст программы в этом случае будет выглядеть так: Пример 12 .text .global __reset __reset: mov #0x4,W1 mov #0x9,W2 add W1,W2,W0 swap.b W0 Loop1: bra Loop1 .end
Перед выполнением команды swap.b в регистре W0 содержится значение 0x000D. После выполнения этой команды в регистре W0 будет содержаться значение 0x00D0. Аналогичным образом можно обменять и содержимое двух 16битных рабо чих регистров с помощью инструкции exch. Исходный текст простейшей про граммы, выполняющей обмен содержимым регистров W0 и W1, приведен ниже. Пример 13 .text .global __reset __reset: mov #0x4,W1 mov #0x9,W2 exch W1,W2 Loop1: bra Loop1 .end
В этой программе содержимое регистра W1 (0x4) пересылается в регистр W2, а содержимое регистра W2 (0x9) пересылается в регистр W1. 3.2.2. Команды сравнения/выбора и условного перехода К этой группе команд относятся команды вида BTxx и CPxx, где аббреви атура BT означает «Bit Test», CP означает «Compare», а символы xx — одно из условий. О функциях команд легко догадаться по их названию. Команды BTxx проверяют состояние указанного бита (0 или 1) и по результатам проверки
3.2. Режимы адресации и система команд
29
выполняют определенное действие. Команды CPxx выполняют сравнение зна чений операндов, в результате чего устанавливаются флаги в регистре состо яния SR процессора. Дальнейшие действия выполняются с помощью команд условных переходов bra xx, где хх — условие выполнения перехода (с этими командами мы познакомимся при изучении примеров). Рассмотрим практические примеры использования этих команд. Пример 1 .data d1: .word 0x0800 .text .global __reset __reset: mov #d1,W0 mov #0xAAAA,W2 mov W2,[W0] mov btss Loop1: bra mov mov Loop2: bra .end
#0xFFFF,W1 W1,#0 Loop1 #0xFFFF, W2,[W0]
W2
Loop2
В этой программе в переменную d1 записывается значение 0хАААА, если бит 0 регистра W1 сброшен в 0, и значение 0хFFFF, если бит установлен в 1. В данном примере в регистр W1 заносится значение 0xFFFF, т.е. бит 0 будет установлен. Следовательно, в переменную d1 будет записано значение 0xFFFF. Если в регистр W1 поместить, например, значение 0xFFFE, то результат про граммы изменится и в переменную d1 будет записано 0xAAAA. Команда btss выполняет проверку бита 0 в регистре W1: если он равен 0, то выполняется следующая за btss команда, а если он равен 1, то следующая за btss инст рукция пропускается. В этой программе команда bra выполняет безусловный переход на указанную в ней метку, образуя «вечный» цикл. Противоположным образом ведет себя инструкция btsc. В следующем при мере показан модифицированный исходный текст программы из Примера 1, в котором вместо btss применяется инструкция btsc. Пример 2 .data d1: .word 0x0800 .text .global __reset __reset: mov #d1,W0 mov #0xFFFF,W2 mov W2,[W0] mov
#0xFFFF,W1
30
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
btsc Loop1: bra mov mov Loop2: bra .end
31
Loop1 #0xAAAA,W2 W2,[W0]
В нашем случае инструкция bra анализирует биты состояния, установленные предыдущей командой cp. Команда cp имеет различные модификации, позволяющие организовывать циклы оптимальным образом.
Loop2
Пример 4
W1,#0
В этой программе инструкция btsc проверяет на равенство нулю нулевой бит регистра W1. Если он равен 0, то следующая команда пропускается и в переменную d1 записывается значение 0xAAAA; если бит установлен в 1, программа уходит на «вечный» цикл по метке Loop1, реализованный инструк цией безусловного перехода bra, при этом в переменной d1 остается значение 0xFFFF, как в данном конкретном случае. Пример 3 .data d1: .word 0x0800 .text .global __reset __reset: mov #d1,W0 mov #0xF,W2 mov W2,[W0] mov again: dec cp bra Loop1: bra .end
3.2. Режимы адресации и система команд
#9,W0 d1 d1 ge,again Loop1
В этой программе показан простой цикл по метке again, выполненный с применением команд dec, cp и bra ge, again. В начале каждой итерации цикла происходит декремент значения переменной d1, после чего команда cp сравнивает значение, записанное в рабочий регистр по умолчанию W0 (9), со значением в переменной d1. Команда cp изменяет, в зависимости от результата сравнения, младшие биты в регистре состояния процессора SR. Само сравне ние выполняется методом вычитания содержимого рабочего регистра из содер жимого переменной d1 во внутреннем цикле команды cp, так что значения операндов не меняются. Следующая за командой cp инструкция bra проверяет условие «большеравно». Пока содержимое переменной d1 остается большим либо равным значению в W0, цикл повторяется. Как только значение в пере менной d1 станет равным 8, произойдет выход из цикла. В этом примере у нас появилась команда условного перехода bra ge, again. Обратите внимание на синтаксис этой команды. После мнемоники инструкции (bra) следует условие в форме аббревиатуры (ge, Great than or Equal) и ука зывается метка перехода к программе, в случае если условие выполнено.
.data d1: .word 0x0800 .text .global __reset __reset: mov #d1,W0 mov #15,W2 mov W2,[W0] again: dec d1 cp0 d1 bra gt,again Loop1: bra Loop1 .end
Здесь для реализации цикла используется инструкция cp0, которая выпол няет сравнение значения переменной с нулем и устанавливает соответствую щим образом биты регистра состояния SR. В переменную d1 помещается зна чение 15, после чего ее содержимое декрементируется в цикле again, пока не станет равным 0. Инструкция bra gt, again анализирует флаг нуля регистра SR и после его установки завершает цикл. Пример 5 .data d1: .word 0x0800 .text .global __reset __reset: mov #d1,W0 mov #15,W2 mov W2,[W0] repeat #11 dec d1 Loop1: bra Loop1 .end
В этой программе демонстрируется использование еще одной весьма полез ной инструкции условного перехода процессора repeat. Команда repeat имеет всего один операнд, представляющий собой число в диапазоне 0…16383, которое определяет, сколько раз выполнится следующая за командой repeat инструкция. В данном случае команда repeat будет выполнять следующую за ней инструкцию dec d1 11 раз. После выполнения команды repeat в перемен ной d1 будет содержаться значение 4, но инструкция dec d1 должна выпол ниться еще один раз, поскольку является очередной командой после repeat.
32
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
3.2. Режимы адресации и система команд
33
В результате перед выполнением последней команды bra программы перемен ная d1 будет содержать значение 3. Подобные нюансы следует учитывать как при написании кода, так и при анализе дизассемблированных листингов.
bclr.b Loop1: bra .end
Пример 6
Здесь в переменную d1 с адресом 0x0800 записывается значение 32 (0x20), затем команда bset.b [W0], #0 устанавливает бит 0 этой переменной, в ре зультате чего содержимое d1 становится равным 33 (0x21). Следующая за ней инструкция bclr.b [W0], #5 сбрасывает бит 5 переменной d1, в результате чего окончательное значение переменной d1 будет равно 1. В этих командах была использована косвенная регистровая адресация посредством регистра W0, в котором хранится адрес переменной d1. Для быстрого анализа состояния отдельных битов переменной в систему команд микроконтроллеров PIC24F включены инструкции fbcl, ff1l и ff1r. Эти инструкции очень полезны в системах сбора данных при сканировании, например, сигнальных выводов периферийных устройств. Вот краткое описа ние этих инструкций: • fbcl — определяет изменение состояния битов от младшего к старшему (слева направо); • ff1l — находит первый ненулевой бит при проходе слева направо; • ff1r — находит первый ненулевой бит при проходе справа налево. Далее приведен пример использования инструкции ff1r.
.data d1: .word 0x0800 .text .global __reset __reset: mov #d1,W0 mov #32,W2 mov W2,[W0] call Increment Loop1: bra Loop1 Increment: repeat #7 inc d1 return .end
К инструкциям условных/безусловных переходов относят и команду вызова процедуры call. При вызове команда помещает адрес следующей за ней ин струкции в стек, а команда return, которая должна быть последней в проце дуре, извлекает это значение из стека в счетчик команд. В этом примере вызывается процедура Increment, которая увеличивает значение переменной d1 на 8. В программе на языке ассемблера точка входа в процедуру определя ется меткой (в данном случае Increment), а выход из процедуры происходит по команде return. 3.2.3. Команды работы с битами Команды работы с битами микроконтроллеров PIC24F, как следует из назва ния, предназначены для манипуляций с отдельными битами операндов. Такая возможность является весьма востребованной, поскольку в большинстве случаев системы на базе микроконтроллеров должны работать с отдельными сигнальны ми битами внешних устройств. Битовые команды позволяют анализировать со стояние отдельных битов, что дает возможность организовать ветвления и пе реходы в программе, а также устанавливать или сбрасывать отдельные биты операнда. Пример 1 .data d1: .word 0x0800 .text .global __reset __reset: mov #d1,W0 mov #32,W2 mov W2,[W0] bset.b [W0],#0
[W0],#5 Loop1
Пример 2 .text .global __reset __reset: mov #8,W2 ff1r W2,W3 Loop1: bra Loop1 .end
В этой программе в регистр W2 заносится значение 8. Инструкция ff1r обнаруживает первый единичный бит в регистре W2 на позиции 4 (отсчет ведется от 1) и записывает это значение в регистр W3. Таким образом, регистр W3 будет содержать значение 4. Пример 3 .text .global __reset __reset: mov #d1,W0 mov #8,W2 mov W2,[W0] ff1l W2,W3 Loop1: bra Loop1 .end
В этой программе, в отличие от предыдущей, сканирование первого нену левого бита в регистре W2 выполняется слева направо инструкцией ff1l.
34
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
В этом случае позиция этого бита относительно старшего значащего бита будет равна 13 (0xD). Это значение и будет помещено в регистр W3. Среди команд битовых операций часто используются инструкции установки (bset, bset.b), сброса (bclr, bclr.b) и переключения (btg, btg.b) битов. Как правило, эти команды применяются для управления внешними исполнитель ными устройствами, подключенными к портам вывода микроконтроллера. Рассмотрим учебный пример генератора прямоугольных импульсов на выво де 0 порта A. Пример 4 .text .global __reset __reset: mov #0x0,W0 mov W0,TRISA clr PORTA again: btg PORTA,#0 call Delay bra again Delay: clr mov mov next: mov cp bra mov mov return Loop1: bra .end
TMR1 #0x8010,W0 W0,T1CON TMR1,W1 W1,#0xAFFF le,next #0,W0 W0,T1CON
Loop1
В этой программе бит 0 порта А переключается в противоположное состо яние с интервалом времени, определяемым функцией задержки Delay. Таким образом, на выводе 0 порта А генерируются прямоугольные импульсы с пери одом, равным Delay * 2. Эти операции выполняются в цикле again: . . bra
. again
Собственно переключение бита 0 порта А выполняет инструкция btg PORTA, #0. Для того чтобы это работало, порт А или, по крайней мере, его младший бит должен быть настроен как выход, что достигается сбросом соответствую щих битов регистразащелки TRISA в начале программы. Для реализации задержки в функции Delay используется 16битный Таймер 1, который запус кается на определенное время, определяемое константой в инструкции cp W1, #0xAFFF. Запуск Таймера 1 осуществляется посредством регистра T1CON.
3.2. Режимы адресации и система команд
35
3.2.4. Команды сдвига и циклического сдвига Эта группа команд часто используется для преобразования последовательно го потока битов в параллельный двоичный код и обратно, а также для опера ций быстрого целочисленного умножения и деления на степень двойки. Рас смотрим несколько примеров. Пример 1 .data d1: .word 0x0800 .text .global __reset __reset: mov #d1,W1 mov #0x8888,W2 mov W2,[W1] mov #0x2,W0 lsr d1 Loop1: bra Loop1 .end
В этой программе в переменную d1 записывается значение 0x8888. Затем в регистр W0 помещается число, которое определяет количество сдвигов. Со ответственно команда lsr d1 выполняет сдвиг вправо на 2 позиции, в резуль тате чего в переменной d1 окажется число 0x2222. Пример 2 .text .global __reset __reset: mov #0x17,W0 lsr W0, #2,W1 Loop1: bra Loop1 .end
В этом примере выполняется сдвиг содержимого регистра W0, которое равно 0x17, на 2 позиции вправо, а результат сохраняется в регистре W1. Таким образом, после выполнения команды lsr W0, #2, W1 в регистре W1 будет со держаться значение 0x5. В качестве демонстрационного примера рассмотрим реализацию операций целочисленного быстрого умножения при помощи команд сдвига и сложения. Такая возможность продемонстрирована в следующем примере. Пример 3 .text .global __reset __reset: mov #0x4,W0 mov W0,W2 sl W0,#2,W1 add W2,W1,W0
36
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
Loop1: bra .end
Loop1
Нам нужно число 4, находящееся в регистре W0, умножить на 5 и результат записать в этот же регистр. Умножение на 5 можно представить в форме 2 ґ 2 + 1. Иными словами, можно выполнить два сдвига числа 4 влево, в результате чего получим 16, а затем прибавить число 4 к полученному резуль тату. Команда сдвига sl W0, #2, W1 сдвигает число в регистре W0 на 2 позиции влево и записывает результат в регистр W1. Команда сложения add W2, W1, W0 складывает содержимое регистров W2 и W1 и записывает результат в регистр W0. В следующем примере содержимое порта А сдвигается влево, при этом анали зируется бит 6 на равенство 1. Если в потоке битов, проходящих через 6ю по зицию, обнаруживается 1, то программа останавливается. Пример 4 .text .global __reset __reset: mov #0x0,W0 mov W0,TRISA mov W0,PORTA bset.b PORTA, #0 again: mov #1,W0 sl PORTA btsc PORTA,#6 forever: bra forever call Delay bra again Delay: clr mov mov next: mov cp bra mov mov return Loop1: bra .end
TMR1 #0x8010,W0 W0,T1CON TMR1,W1 W1,#0x5 lt,next #0,W0 W0,T1CON
3.2. Режимы адресации и система команд
бита 6 порта А: если он равен 1, то сдвиг влево прекращается, и программа входит в «вечный» цикл по метке forever. Если сдвигаемый бит не достиг 6й позиции, то вызывается функция задержки Delay, после чего начинается следующая итерация цикла again. Таким образом, в программе будет выпол нено 6 сдвигов, после которых в регистрезащелке порта А окажется значение 0х040. 3.2.5. Команды математических и логических операций Микроконтроллеры семейства PIC24F обладают обширным набором инст рукций для выполнения математических и логических действий над операн дами. В АЛУ процессора предусмотрено выполнение 4 основных математиче ских действий над целыми знаковыми и беззнаковыми числами: сложения, вычитания, умножения и деления. Для каждого из этих действий предусмотрен ряд инструкций, в которых используются различные типы адресации, делаю щие выполнение таких операций весьма эффективным. Все математические инструкции оперируют с целыми числами, знаковыми или беззнаковыми. Далее приведено несколько примеров использования этих инструкций. Пример 1 .data d1: .word 0x0800 .text .global __reset __reset: mov #d1,W0 mov #67,W1 mov W1,[W0] mov add Loop1: bra .end
#34,W0 d1 Loop1
В этой программе используется одна из версий команды сложения, когда к содержимому ячейки памяти прибавляется содержимое рабочего регистра по умолчанию (W0). Сначала в переменную d1 записывается значение 67. Затем в регистр W0 заносится значение 34. Команда сложения add d1 к содержимому d1 прибавляет содержимое регистра W0, что дает в результате значение 101 (0x65). Пример 2
Loop1
В цикле again с помощью команды sl PORTA выполняется сдвиг влево на 1 бит содержимого порта А. Для команды sl величина сдвига задается в ра бочем регистре W0 и в данном случае равна 1. Затем анализируется состояние
37
.text .global __reset __reset: mov #14,W0 add W0,#7,W1 Loop1: bra Loop1 .end
38
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
В этой программе команда add имеет 3 операнда. К содержимому регистра W0 прибавляется 7, и результат записывается в регистр W1. После выполнения операции там будет находиться значение 21 (0x15). Команды математических операций, как и рассмотренные нами команды перемещения, допускают использование прямой и косвенной регистровой адресации. В предыдущем при мере в команде add была использована прямая регистровая адресация. Следую щий пример демонстрирует использование косвенной регистровой адресации. Пример 3 .data d1: .word 0x0800 .text .global __reset __reset: mov #d1,W0 mov #7,W1 add W1,#5,[W0] Loop1: bra Loop1 .end
В данном случае команда add складывает содержимое регистра W1 (0х7) с константой 5 и помещает результат по адресу, находящемуся в регистре W0, т.е. в переменную d1. После выполнения операции в d1 будет находиться значение 12 (0xC). Пример 4 .data d1: .word 0x0800 d2: .word 0x0802 .text .global __reset __reset: mov #d1,W0 mov #7,W1 mov #19,W2 add W1,W2,[++W0] Loop1: bra Loop1 .end
В этом примере продемонстрировано применение косвенной регистровой адресации с прединкрементом при сложении содержимого двух регистров W1 и W2. В регистр W0 помещается адрес переменной d1 из секции .data, кото рый перед выполнением сложения командой add инкрементируется. Таким образом, результат сложения, выполненного командой add, будет записан по адресу, следующему за адресом d1, т. е. в переменную d2. После выполнения операции в переменной d2 будет содержаться значение 26 (0x1A). В сочетании с командами условных/безусловных переходов, при помощи математических команд можно реализовать гибкие алгоритмы обработки дан ных, как это показано в следующих нескольких примерах.
3.2. Режимы адресации и система команд
39
Пример 5 .data d1: .word 0x0800 d2: .word 0x0802 d3: .word 0x0804 .text .global __reset __reset: mov #d1,W0 mov #7,W1 mov #19,W2 repeat #2 sub W1,W2,[W0++] Loop1: bra Loop1 .end
В этой программе в ячейки памяти d1…d3 помещается результат вычитания содержимого регистра W2 из содержимого регистра W1, которое равно –12 (0xFFF4). Для последовательного доступа к переменным d1…d3 применяется постинкрементная адресация с помощью регистра W0 в команде вычитания sub. Инструкция repeat обеспечивает выполнение следующей за ней инструк ции вычитания sub 2 раза. Всего команда sub будет выполнена 3 раза. В результате выполнения этой программы в переменных d1…d3 окажется зна чение 0xFFF4. Подобный алгоритм при небольшой модификации можно ис пользовать для заполнения области памяти какимлибо значением, например нулем. Несложно реализовать и алгоритм нахождения суммы элементов какойлибо области памяти, как это показано в следующем примере. Пример 6 .data d1: .word 0x0800 d2: .word 0x0802 d3: .word 0x0804 cnt: .word 0x0806 .text .global __reset __reset: mov #d1,W0 push W0 mov #7,W1 mov W1,[W0++] mov #20,W1 mov W1,[W0++] mov #10,W1 mov W1,[W0] mov #cnt,W3 mov #3,W0 mov W0,[W3] pop
W0
; cnt = 3 ; àäðåñ d1 -> W0
40
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F clr
W4
; ðåçóëüòàò íàêàïëèâàåì â W4
next: mov add dec cp0 bra Loop1: bra .end
[W0++],W1 W1, W4,W4 cnt cnt nz,next Loop1
В этой программе выполняется сложение содержимого ячеек памяти d1…d3, а результат сложения помещается в регистр W4. Переменная cnt выполняет функцию счетчика цикла next, в котором и выполняется операция сложения. В начале программы переменные d1…d3 инициируются следующими значени ями: в d1 помещается число 7, в d2 — 20 и в d3 — 10. Инструкция push W0 сохраняет в стеке адрес переменной d1, который далее будет использоваться в качестве базового адреса при доступе к области памяти. Перед выполнением цикла next в счетчик cnt, адресуемый регистром W3, помещается количество итераций, равное 3, а регистр W4, в котором будет накапливаться результат, обнуляется командой clr W4. Кроме того, перед началом цикла next нам нужно восстановить содержимое регистра W0, а именно адрес переменной d1, что и выполняет команда извлечения из стека pop W0. Сложение чисел, содержащихся в переменных d1…d3, выполняется инструк цией add W1, W4, W4, при этом к предыдущему значению регистра W4 прибав ляется содержимое регистра W1. Регистр W1 содержит значение текущей ячей ки памяти, которое помещается в него командой mov [W0++], W1. Цикл выполняется до тех пор, пока значение счетчика cnt не станет нулевым. Это условие отслеживается командами cp0 bra
cnt nz,next
После выполнения цикла next в регистре W4 будет содержаться значение 37 (0x25). Два следующих примера посвящены операциям умножения и их реали зации посредством инструкций процессора. Пример 7 .data d1: .word 0x0800 d2: .word 0x0802 .text .global __reset __reset: mov #d1, W0 push W0 mov #73, W1 mov W1, [W0++] mov #20, W1 mov W1, [W0]
3.2. Режимы адресации и система команд pop mov mov mul.uu Loop1: bra .end
41
W0 [W0++], W1 [W0], W2 W1, W2, W4 Loop1
В этой программе выполняется умножение чисел, содержащихся в перемен ных d1 и d2. Для умножения беззнаковых чисел используется инструкция mul.uu. В качестве операндов этой инструкции в данной программе выступают регистры W1 и W2, каждый из которых содержит сомножители, извлеченные из переменных d1 и d2 соответственно. В качестве приемника результата ум ножения выступает пара регистров W4…W5. Первым регистром приемника должен быть обязательно регистр c четным номером (в данном случае W4), в который помещается младший байт результата. Второй регистр приемника в команде явно не указывается, но его номер по умолчанию на 1 больше. В нашем случае это регистр W5, в который помещается старший байт резуль тата. Если бы в качестве младшего регистра приемника использовался регистр W6, то старшим регистром в этом случае был бы W7 и т.д. В начале программы переменные d1 и d2 инициализируются значениями 73 и 20 соответственно. Для адресации этих переменных используется регистр W0. При указанных значениях переменных после выполнения операции умноже ния регистр W4 будет содержать значение 1460 (0x5B4). Для выполнения операций над числами со знаком необходимо использовать другую версию команды умножения, а именно mul.ss. Модифицируем преды дущий пример так, чтобы его можно было использовать для перемножения целых чисел со знаком. Пример 8 .data d1: .word 0x0800 d2: .word 0x0802 .text .global __reset __reset: mov #d1,W0 push W0 mov #73,W1 mov W1,[W0++] mov #-10,W1 mov W1,[W0] pop W0 mov [W0++],W1 mov [W0],W2 mul.ss W1,W2,W4 Loop1: bra Loop1 .end
В этой программе перемножаются положительное число 73 (переменная d1) и отрицательное число –10 (переменная d2). Для умножения используется
42
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
команда mul.ss, параметры которой имеют тот же смысл, что и в рассмотрен ной ранее инструкции mul.uu из предыдущего примера. Результат операции помещается в регистры W4 и W5, при этом в W5 будет содержаться 0, а W4 будет содержать значение 0xFD26, что соответствует отрицательному числу – 730, представленному в дополнительном коде. Группа математических команд содержит инструкции, позволяющие рабо тать с многобайтовыми данными. Эти команды при выполнении операций учитывают флаг переноса, который мог быть установлен как следствие пере носа или заема в результате операции с предыдущими словами. К таким ин струкциям относятся addc и subb. При желании читатели смогут самостоятель но исследовать работу этих команд с помощью отладчика. Рассмотрим примеры использования группы команд логических операций. Эти команды позволяют выполнять булевые одноместные и двуместные опе рации. К таким операциям относятся хорошо известные двуместные операции логическое «И», логическое «ИЛИ», исключающее «ИЛИ» и одноместная опе рация отрицания «НЕ». В эту группу команд включены инструкции очистки (обнуления) операнда и установки, когда все биты операнда устанавливаются в 1. Инструкции, выполняющие операцию логического «И», имеют мнемони ческое обозначение and, логического «ИЛИ» — ior, исключающего «ИЛИ» — xor. Что же касается операции отрицания «НЕ», то она реализована посред ством инструкции com. Кроме того, в эту группу команд включена команда neg, позволяющая инвертировать знак числа. Инструкции логических опера ций весьма полезны при выделении и анализе отдельных битов операндов. Применение этих команд показано в следующих примерах. Пример 1 .text .global __reset __reset: mov mov and Loop1: bra .end
#0xFC,W0 #0x13,W1 W0,W1,W2 Loop1
Здесь выполняется операция логического «И» над операндами, помещенны ми в регистры W0 и W1. Команда and помещает результат операции в регистр W2. При указанных значениях операндов W0 и W1 итоговое значение в регист ре W2 будет равно 0x10. Если инструкцию and
W0,
W1,
W2
заменить инструкцией ior W0, W1, W2 (логическое «ИЛИ»), то итоговое зна чение в регистре W2 станет равным 0xFF. При использовании в программе команды xor (исключающее «ИЛИ») в регистре W2 после выполнения опера ции будет содержаться значение 0xEF.
3.2. Режимы адресации и система команд
43
Пример 2 .text .global __reset __reset: mov #0xC, W0 com W0, W1 Loop1: bra Loop1 .end
В этом примере показано применение инструкции com. Эта инструкция ин вертирует все биты исходного операнда. В данном случае инвертируется содер жимое регистра W0 (0x000C), а результат, который будет равен 0xFFF3, поме щается в W1. Пример 3 .text .global __reset __reset: mov #0xFFF4, neg W0, W1 Loop1: bra Loop1 .end
W0
Программа инвертирует знак числа при помощи команды neg. Команда neg использует стандартный алгоритм получения инверсии числа: сначала все биты операнда инвертируются, затем к младшему биту прибавляется 1. В нашем примере при исходном значении операнда в регистре W0, равном 0xFFF4 (до полнительный код отрицательного числа –12), результат выполнения команды neg, помещенный в регистр W1, будет равен 0x000C, что соответствует поло жительному числу 12. Инструкцию neg можно использовать в программе для получения абсолют ного значения (модуля) числа, как это показано в следующем примере. Пример 4 .text .global __reset __reset: mov #0x81F4,W0 mov W0,W1 btsc W0,#15 neg W0,W1 Loop1: bra Loop1 .end
В этой программе с помощью инструкции btsc W0, #15 проверяется значе ние старшего бита числа. Если бит равен 0, то число в регистре W0 положи тельное и не нуждается в преобразовании. В этом случае следующая за btsc инструкция пропускается. Если же число в W0 отрицательное (старший бит установлен в 1), то команда neg преобразует его в положительное. В нашем
44
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
случае число 0x81F4 — отрицательное, поэтому оно преобразуется командой neg к положительному значению 0x7E0C. 3.2.6. Команды условных/безусловных переходов Команды этой группы предназначены для управления ходом вычислитель ного процесса и осуществляют переход к различным секциям программы по результатам проверки флагов состояния процессора. В предыдущих примерах программного кода мы уже использовали некоторые из этих команд, сейчас же остановимся на них более подробно. Наиболее широко при разработке программного обеспечения используются инструкции bra xx (xx — код условия), call и goto. Команда bra xx осуще ствляет переход по адресу программы, содержащемуся в теле инструкции, при выполнении условия xx. В общей сложности эта команда может проверять выполнение следующих условий: • C — установлен флаг переноса; • GE — больше или равно; • GEU — больше или равно для операций без знака; • GT — больше; • GTU — больше для операций без знака; • LE — меньше или равно; • LEU — меньше или равно для операций без знака; • LT — меньше; • LTU — меньше для операций без знака; • N — результат предыдущей операции отрицательный; • NC — перенос (заем) отсутствует; • NN — результат предыдущей операции неотрицательный; • NOV — переполнения нет; • NZ — результат предыдущей операции ненулевой; • OV — возникло переполнение; • Z — установлен бит нуля в регистре состояния. Например, команда bra z, label1 выполнит переход на метку label1 про граммы, если установлен бит Z в регистре состояния процессора. Кроме того, команда bra имеет две модификации, позволяющие выполнять безусловный переход: • bra ìåòêà, где метка должна находиться в пределах от –32768 до +32767 слов памяти программ относительно команды bra; • bra Wn, где Wn — рабочий регистр. К командам переходов относятся и команды вызова процедур call и безуслов ного перехода goto. Инструкции call и goto в качестве операнда могут исполь зовать либо метку, либо один из рабочих регистров. Если в качестве адреса пе рехода использовать содержимое какоголибо из рабочих регистров, то с помощью одной инструкции bra или call можно организовать несколько ветвлений в про грамме, например, по принципу оператора switch…case языка Си. Рассмотрим несколько примеров подобного использования команд bra и call.
3.2. Режимы адресации и система команд
45
Пример 1 .text .global __reset __reset: mov #0x1,W0 mov #handle(Sub1),W2 btss W0,#0 mov #handle(Sub2),W2 call W2 Loop1: bra Loop1 Sub1: mov #0x1111,W1 return Sub2: mov #0xFFFF,W1 return .end
Программа работает следующим образом: с помощью команды btss W0, #0 анализируется бит 0 регистра W0 и по результату анализа выбирается вариант продолжения. Если бит 0 установлен, то вызывается процедура Sub1, если же бит 0 сброшен, вызывается Sub2. Для того чтобы вызвать процедуру посред ством адреса, содержащегося в рабочем регистре W2, выполняется команда call
W2
Значение стартового адреса одной из процедур (Sub1 или Sub2) записыва ется в регистр с помощью специального оператора handle в одной из команд mov mov
#handle(Sub1),W2 #handle(Sub2),W2
В нашем случае бит 0 регистра W0 принудительно устанавливается в 1, поэтому вызывается процедура Sub1. Пример 2 .text .global __reset __reset: mov #0x0,W0 mov #handle(J1),W2 btss W0,#0 mov #handle(J2),W2 goto W2 J1: mov #0x1111,W1 Loop1: bra Loop1 J2: mov #0xFFFF,W1 Loop2: bra Loop2 .end
46
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
Это модифицированный вариант предыдущего примера. Здесь вместо вызо вов процедур используются команды безусловного перехода bra и goto. Прин цип формирования адреса остался прежним: адрес перехода формируется из меток J1 и J2 с помощью оператора handle и записывается в регистр W2. Переход на нужную ветвь программы выполняет команда goto W2.
3.3. Разработка и отладка программ на ассамблере в среде MPLAB IDE
47
PIC24FJ128GA010, поэтому в раскрывающемся списке следует выбрать именно это устройство (Рис. 3.4).
3.3. Разработка и отладка программ на ассемблере в среде MPLAB IDE Для тестирования всех наших программ на ассемблере мы будем использо вать возможности среды разработки MPLAB IDE. На данном этапе нам пона добится ассемблер MPLAB ASM30 и отладчик (симулятор) MPLAB SIM. Все этапы разработки и отладки ассемблерных программ в среде MPLAB будут показаны на примере проекта, в котором будет использован исходный текст последнего примера из предыдущего раздела. В этом примере мы рассматри вали использование команд передачи управления bra и goto. Разработаем новый проект с помощью мастера проектов среды MPLAB IDE. Для этого запустим приложение MPLAB IDE и в меню Project выберем опцию Project Wizard… (Рис. 3.3). Затем на Шаге 1 следует выбрать модель микроконтроллера, для которого будет разработан данный проект. В данном случае мы будем использовать
Рис. 3.4. Выбор микроконтроллера
На Шаге 2 мастер проектов предложит выбрать требуемый пакет инструмен тальных средств. Мы будем использовать ассемблер MPLAB ASM30, поэтому вы бираем в раскрывающемся списке пункт «Microchip ASM30 Toolsuite» (Рис. 3.5).
Рис. 3.3. Создание нового проекта в среде MPLAB IDE
Рис. 3.5. Выбор компилятора MPLAB ASM30
48
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
3.3. Разработка и отладка программ на ассамблере в среде MPLAB IDE
49
На Шаге 3 следует выбрать имя проекта и каталог, в котором он будет располагаться (Рис. 3.6).
Рис. 3.8. Окно диалога после создания проекта Project1
Рис. 3.6. Выбор имени и каталога проекта
Для выбора каталога и имени следует нажать верхнюю на рисунке кнопку Browse и, выбрав каталог, ввести имя проекта. В данном случае дадим проекту имя Project1 (Рис. 3.7).
Еще раз убедимся, что имя проекта и каталог размещения нас устраивают, и нажмем кнопку Далее. Созданный проект не содержит ни файлов с исход ными текстами программ, ни файлов с библиотеками функций. На следующем, 4м шаге мастер предложит включить в проект дополнительные файлы (Рис. 3.9).
Рис. 3.7. Выбор имени и каталога сохраняемого проекта
После нажатия кнопки Сохранить файл проекта с расширением .mcp будет сохранен под именем Project1 и высветится в окне выбранного проекта (Рис. 3.8).
Рис. 3.9. Окно включения дополнительных файлов в проект
50
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
3.3. Разработка и отладка программ на ассамблере в среде MPLAB IDE
Для нашего проекта мы пока не создали ни одного файла и ничего включать не собираемся, поэтому пропустим этот шаг, нажав кнопку Далее. После этого в следующем окне, если параметры проекта нас устраивают, нажмем кнопку Готово (Рис. 3.10).
Рис. 3.10. Завершение создания проекта
Рис. 3.11. Окно созданного проекта
В окне приложения MPLAB IDE, куда мы возвращаемся после создания проекта, в меню View выберем опцию Project и посмотрим, что включено в состав проекта (Рис. 3.11). Кроме файла проекта Project1.mcp рабочее пространство пока не содержит файлов. Создадим новый файл, в который включим исходный текст програм мы на ассемблере. Для этого в меню File выберем опцию New (Рис. 3.12). В появившемся окне редактирования наберем исходный текст, который со храним в каталоге проекта в файле project1.s (Рис. 3.13). Для того чтобы включить файл project1.s в проект, нужно установить отметку Add File To Project. Хотя, даже если забудете это сделать, сохраненный файл в любой момент можно будет включить в проект, выбрав опцию Add New File To Project из меню File. В исходный текст программы с помощью директивы include обязательно нужно включить заголовочный файл для данной модели: #include
"P24FJ128GA010.inc"
Кроме того, в проект нужно включить файл сценария компоновщика для данной модели микроконтроллера. Файл имеет имя, совпадающее с обозначе нием модели, и расширение .gld, а располагается в каталоге \...\Program Files\ Microchip\MPLAB ASM30 Suite\Support\gld. После включения файлов в проект окно проекта должно выглядеть так, как показано на Рис. 3.14.
Рис. 3.12. Создание нового файла в среде MPLAB IDE
51
52
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
3.3. Разработка и отладка программ на ассамблере в среде MPLAB IDE
53
Сохраним проект и выполним сборку двоичного образа программы. После успешной компиляции и последующей компоновки в каталоге проекта должны появиться файлы с расширением .cof (elf) и .hex. HEXфайл представляет собой готовый к загрузке в память программ целевой системы двоичный образ программы, а COFFфайл представляет собой исполняемый файл, который можно использовать при отладке программы в среде MPLAB IDE. Для сборки приложения в меню Project нужно выбрать опцию Build All. Если сборка при ложения прошла успешно, то можно посмотреть работу программы в отлад чике. Для этого нужно выполнить несколько подготовительных действий. Вопервых, необходимо установить опцию Debug (Рис. 3.15).
Рис. 3.13. Сохранение исходного текста на ассемблере
Рис. 3.15. Установка режима компиляции
Рис. 3.14. Окно проекта после включения файлов
Если эта опция была установлена до компиляции, можно перейти к сле дующему шагу. Если нет, то следует выполнить повторную сборку программы. Далее следует выбрать отладчик из меню Debugger (Рис. 3.16). Выберем стандартный отладчик MPLAB SIM. После выбора отладчика по явится дополнительная панель инструментов для отладки программы с кноп ками управления процессом отладки (Рис. 3.17). Теперь все готово для проверки работоспособности программного кода микроконтроллера. Прежде чем мы запустим приложение в отладчике, необ ходимо сделать одно важное замечание, которое касается достоверности ре зультатов отладки. Программный отладчик (симулятор) никогда полностью не заменит тестирование программы в реальном устройстве, поскольку точно смоделировать работу электроники и обеспечить требуемые временные зависи мости между сигналами схемы ни один симулятор никогда не сможет. Тем не менее с проверкой работоспособности программного алгоритма и обнаружени ем возможных ошибок в программе такой симулятор вполне справится. При
54
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
3.3. Разработка и отладка программ на ассамблере в среде MPLAB IDE
55
Перед запуском процесса отладки нужно определить, что именно нас инте ресует в конкретной программе. Для этого обратимся к исходному тексту, который показан ниже: #include
Рис. 3.16. Выбор отладчика
"P24FJ128GA010.inc"
.text .global __reset __reset: mov #0x0,W0 mov #handle(J1),W2 btss W0,#0 mov #handle(J2),W2 goto W2 J1: mov #0x1111,W1 Loop1: bra Loop1 J2: mov #0xFFFF,W1 Loop2: bra Loop2 .end
В программе задействованы 3 рабочих регистра W0…W2, поэтому интересно будет отследить, как меняется их содержимое в процессе выполнения програм мы. Для наблюдения за состоянием регистров выберем опцию Watch в меню View (Рис. 3.18). После выбора опции появится окно просмотра переменных, в котором можно выбрать регистры и переменные программы, состояние которых нужно отслеживать (Рис. 3.19).
Рис. 3.17. Вид дополнительной панели инструментов отладчика
определенном опыте создания программ и их отладки симулятор сможет стать весьма эффективным средством улучшения качества программы. Запуск на отладку программы можно выполнить по команде Run в меню Debugger либо воспользоваться «быстрой» клавишей F9. Можно выполнить от ладку в режиме Animate — это позволяет визуально отслеживать изменения при выполнении команд программы. В дальнейшем при отладке программ мы будем использовать оба этих режима. Отладку программы можно проводить также в пошаговом режиме и с установкой точек прерывания — эти режимы мы рассматривать не будем, а читатели, интересующиеся деталями механизма отладки, могут обратиться к документации фирмы Microchip.
Рис. 3.18. Выбор опции Watch
56
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
3.3. Разработка и отладка программ на ассамблере в среде MPLAB IDE
57
Рис. 3.19. Окно просмотра переменных
Рис. 3.20. Меню «перезагрузки» микроконтроллера
Для выбора регистра нужно открыть список в левой верхней части окна и, выбрав нужный регистр, щелкнуть на кнопке Add SFR. Под областью меню тут же появится строка состояния, в которой отображается информация о данном регистре. Рабочие регистры в окне просмотра имеют обозначения WREGx (x = 0, 1, 2…) и соответствуют регистрам Wx программы. Перед отладкой программы желательно всегда делать «аппаратную» переза грузку симулируемого микроконтроллера, поэтому выберем опцию MCLR Reset (Рис. 3.20). После «перезагрузки» рабочие регистры сбросятся в 0. Теперь можно запу стить программу на отладку, выбрав режим Run или Animate. Разница между этими режимами состоит в следующем: в режиме Run все команды программы выполняются по возможности с учетом временных параметров устройства, а в режиме Animate такая жесткая привязка по времени не делается, зато ото бражается проход по командам (операторам) программы. Анализ содержимого регистров и переменных программы, выполняющейся в режиме Run, можно провести, остановив программу либо установив специальные опции отладки (с этим способом мы познакомимся при изучении процесса отладки программ на языке Си). В режиме Animate изменения состояния переменных и регистров можно наблюдать в окне просмотра переменных в процессе выполнения про граммы, однако следует помнить, что в этом случае программа будет выпол няться далеко не в режиме реального времени. Промежуточные состояния пе
ременных можно наблюдать, установив в определенных местах программы точки прерывания или же перейдя в пошаговый режим работы. Еще одно замечание: точность временных интервалов в режиме Run зависит от производительности процессора персонального компьютера, его загрузки и вы бранной в окне настройки тактовой частоты микроконтроллера (Рис. 3.21, 3.22). Тем не менее, не следует полагать, что если в отладчике установить опре деленную частоту процессора (например, 8 МГц, как показано на Рис. 3.22), то все команды программы и временные зависимости будут точно соответствовать этой частоте. Но в любом случае, временные соотношения между интервалами выполнения команд, вызовы и обработка прерываний и т.д. будут выполняться по возможности максимально точно. Если процессор персонального компью тера загружен выполнением других программ, то отклонения от реального режима при отладке программы в режиме Run будут больше. Вернемся к отладке нашей программы. Программа выполнится довольно быстро и войдет в «вечный» цикл по метке Loop2, а содержимое рабочих регистров будет таким, как показано на Рис. 3.23. Как видно по результатам отладки, регистры W0 и W1 содержат значения, которые мы и должны были получить при запуске программы. Что же касается регистра W3, то в него помещается адрес метки J2, который зависит от настро ек компилятора и компоновщика, выполняющего сборку программы.
58
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
3.4. Особенности разработки и отладки программ на MPLAB C для PIC24
59
Рис. 3.21. Выбор опции настроек отладчика
Рис. 3.23. Состояние рабочих регистров после отладки
3.4. Особенности разработки и отладки программ на MPLAB C для PIC24
Рис. 3.22. Установка тактовой частоты микроконтроллера в отладчике
Для разработки сложных программ намного больше возможностей предос тавляет компилятор языка Си фирмы Microchip, известный под названием MPLAB C для PIC24. Весь последующий материал этой книги будет опираться на методы разработки и отладки программного обеспечения на языке Си. В следующем разделе мы коснемся основных методов разработки и отладки программного обеспечения с использованием данного компилятора.
Компилятор MPLAB C для PIC24 представляет собой эффективный про граммный инструмент разработки приложений для 16битных микроконтрол леров фирмы Microchip, базирующийся на стандарте ANSI C. Компилятор MPLAB C для PIC24 выполняет компиляцию файлов исходных текстов, создавая промежуточные ассемблерные и объектные файлы. Получен ные объектные файлы затем компонуются с другими объектными файлами и библиотеками и собираются компоновщиком (линкером) в исполняемый файл программы. Кроме того, объектные файлы в формате COFF или ELF можно использовать при создании библиотек, либо загрузить в отладчик среды MPLAB IDE для дальнейшего тестирования и отладки. С помощью утилиты преобразования форматов можно преобразовать COFF или ELFфайл в фор мат HEXфайла, пригодный для загрузки в память программ целевой систе мы. На Рис. 3.24 показаны все этапы разработки программы с использовани ем MPLAB C для PIC24.
60
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
3.4. Особенности разработки и отладки программ на MPLAB C для PIC24
61
практической стороне разработки. Везде, где это нужно, будет даваться краткое пояснение работы того или иного элемента языка. Практическое знакомство с MPLAB C для PIC24 начнем с разработки и отладки простого приложения на Си для микроконтроллера PIC24FJ128GA010. Для этого с помощью мастера приложений создадим новый проект точно так же, как это делали для программы на ассемблере. Единственное отличие состоит в том, что на Шаге 2 теперь следует выбрать пакет «Microchip C30 Toolsuite» (Рис. 3.25).
Рис. 3.25. Выбор компилятора проекта Рис. 3.24. Этапы сборки программы
Компилятор MPLAB C для PIC24 включает средства оптимизации программ при трансляции стандартных ANSI C программ в ассемблерный код микрокон троллера PIC24. В компилятор включены многочисленные расширения, позво ляющие эффективно работать с периферийными модулями микроконтролле ров, а также дополнительные библиотеки с готовыми функциями для работы с периферией. При разработке демонстрационных программ этой книги мы будем исполь зовать среду разработки MPLAB IDE фирмы Microchip и студенческую версию компилятора С30. В этом разделе мы коснемся практических аспектов разра ботки программ для PIC24, в частности, отладки программ с помощью симу лятора MPLAB SIM. Отладчик MPLAB SIM предоставляет намного больше возможностей для отладки и трассировки Сипрограмм по сравнению с при ложениями на ассемблере, что позволяет успешно разрабатывать и тестировать довольно сложные приложения, написанные на языке Си. Мы не будем касать ся особенностей синтаксиса языка C30, поскольку он подробно описан в фирменной технической документации, а уделим основное внимание именно
В созданный проект необходимо добавить два файла: файл с исходным текстом на Си и файл сценария компоновщика с расширением .gld, который для данного устройства называется p24fj128ga010.gld и находится в каталоге \...\Program Files\Microchip\MPLAB C30\support\PIC24F1. Наше первое прило жение будет периодически переключать вывод 0 (бит 0) порта А в противопо ложное состояние. Создадим и включим в проект файл с расширением .с и следующим исходным текстом: #include
void Delay(void) { unsigned long cnt while (cnt != 0) }
1
= 10000; cnt—;
В принципе, файл сценария компоновщика можно и не включать в проект — в этом случае на этапе сборки программы будет автоматически использован файл сценария, соответствую щий выбранной модели. – Примеч. науч. ред.
62
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
void main(void) { TRISA = 0xfffe; PORTAbits.RA0 = 1; while(1) { PORTAbits.RA0 Delay(); }
=
~PORTAbits.RA0;
}
Бит 0 порта А здесь переключается в цикле while(1) с помощью оператора PORTAbits.RA0 = ~PORTAbits.RA0. Задержка между переключениями форми руется функцией Delay, а величина этой задержки определяется значением счетчика cnt в самой функции. Поскольку мы будем выполнять отладку в программном симуляторе MPLAB SIM, то начальное значение cnt можно выбрать достаточно большим, чтобы можно было наблюдать изменения состо яния бита 0 порта А визуально. Компиляцию программы нужно выполнить в режиме Debug, а для наблю дением за состоянием порта А, вернее, его младшего бита в раскрывающемся списке окна просмотра переменных следует выбрать PORTA (Рис. 3.26).
3.4. Особенности разработки и отладки программ на MPLAB C для PIC24
пользовать пошаговое выполнение программы, хотя это потребует больше времени. Это далеко не самая сложная программа, поэтому процесс отладки довольно очевиден. Намного сложнее протестировать программу, которая должна рабо тать с внешними прерываниями или, например, с точными временными ин тервалами. Методы тестирования и отладки подобных программ предполагают хорошие знания аппаратнопрограммной архитектуры микроконтроллера и возможно стей программного симулятора MPLAB SIM. Создадим в MPLAB IDE проект, в котором приложение будет переключать тот же бит 0 порта А, но уже в обработчике прерывания Таймера 1. Таймеры и их применение мы будем детально рассматривать в следующих главах, здесь для демонстрации нам будет достаточно основных сведений. В микроконтроллерах PIC24F имеется несколько таймеров, но мы будем ис пользовать 16битный Таймер 1 (его часто называют таймером Атипа). Интер вал срабатывания Таймера 1 в режиме таймера при заданной тактовой частоте процессора определяется двумя параметрами: значением, содержащимся в реги стре периода PR1, до которого регистр таймера TMR1 инкрементируется, и ко эффициентом деления предделителя, который может быть равен 1, 8, 64 или 256. Интуитивно понятно, что, чем больше значение регистра PR1 и коэффициент предделения, тем больше интервал срабатывания Таймера 1. При превышении значения PR1 устанавливается флаг прерывания _T1IF, и если разрешено пре рывание Таймера 1, то вызывается функцияобработчик этого прерывания. Вот исходный текст программы, в которой используется Таймер 1: #include
_CONFIG2(FCKSM_CSDCMD&OSCIOFNC_ON&POSCMOD_HS&FNOSC_PRI) void __attribute__ ((__interrupt__)) { _T1IF = 0; PORTAbits.RA0 = ~ PORTAbits.RA0; } void main(void) { TRISA = 0xfffe; PORTAbits.RA0 = 1; _T1IF _T1IE
= =
0; 1;
PR1 = 15625 * 3; TMR1 = 0; T1CON = 0x8030;
Рис. 3.26. Выбор порта А для просмотра
Изменения состояния бита 0 лучше всего наблюдать в режиме Animate от ладчика, хотя можно запустить программу и в режиме Run, а затем остановить и запустить ее несколько раз для анализа состояния бита. Также можно ис
63
while(1) { } }
_T1Interrupt(void)
64
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
В начало этой программы включен макрос _CONFIG2, который определяет параметры источника тактового сигнала микроконтроллера. При отладке про граммы в симуляторе MPLAB SIM этот макрос можно не использовать, по скольку все необходимые настройки производятся в самом симуляторе. При работе с реальным оборудованием, в зависимости от аппаратного решения, выбранного для тактирования устройства, следует правильно указать констан ты этого макроса. Смысл констант, используемых для настройки источника тактового сигнала, описан в заголовочном файле устройства. Программа должна переключать бит 0 порта А в противоположное состояние каждые 3 с, для чего мы используем прерывание Таймера 1 микроконтроллера PIC24FJ128GA010. Более подробно прерывания описаны в последующих гла вах, но понять, как происходит обработка прерывания в этом конкретном примере, несложно. Каждые 3 с инициируется прерывание Таймера 1, и управ ление передается функцииобработчику _T1Interrupt. В MPLAB C для PIC24 предопределены прототипы функцийобработчиков прерываний для каждого из возможных источников прерывания, поэтому можно воспользоваться таким обработчиком для Таймера 1. Все, что делает функцияобработчик в нашем случае, — это сбрасывает флаг прерывания _T1IF и переключает бит 0 порта А в противоположное состояние. В основной программе мы должны настроить вывод 0 (бит 0) порта А как выход, что выполняется установкой соответствующего бита в регистре TRISA. Кроме того, нужно разрешить работу прерывания Таймера 1, что выполняет оператор _T1IE = 1. Флаг прерывания перед установкой разрешения прерыва ния должен быть сброшен (оператор _T1IF = 0). Операторы
3.4. Особенности разработки и отладки программ на MPLAB C для PIC24
65
Рис. 3.27. Настройка тактовой частоты микроконтроллера
Кроме того, нужно настроить интервал обновления данных в окне просмот ра переменных в режиме Animate. Для этого в окне Simulator Settings выберем закладку Animation/Realtime Updates и установим параметры обновления так, как показано на Рис. 3.28.
PR1 = 15625 * 3; TMR1 = 0; T1CON = 0x8030;
устанавливают параметры Таймера 1. При отладке программы в симуляторе MPLAB SIM мы будем использовать тактовую частоту микроконтроллера 8 МГц. Кроме того, зададим коэффициент деления предделителя Таймера 1, равный 256. В этом случае регистр периода PR1 должен содержать значение 15625 ґ 3, что соответствует интервалу срабатывания 3 с. Перед запуском Тай мера 1 очистим регистр таймера, а для запуска установим соответствующие биты в регистре управления T1CON. Так работает эта программа. Для проверки работоспособности программы в отладчике необходимо выполнить сборку приложения в режиме Debug, вы брать в меню Debugger симулятор MPLAB SIM и, кроме того, выполнить не сколько предварительных настроек в самом отладчике. Поскольку мы собираемся симулировать работу программы в режиме, при ближенном к режиму «реального» времени, то необходимо установить тактовую частоту микроконтроллера, равную 8 МГц, выбрав в меню Debugger опцию Simulator Settings и установив соответствующее значение в окне Processor Fre quency (Рис. 3.27).
Рис. 3.28. Настройка параметров обновления
В данном случае мы выбрали интервал обновления данных, равный 0.3 с, хотя можно выбрать и другое разумное значение. Не следует выбирать значение интервала слишком малым, поскольку для вывода обновленной информации в окно просмотра требуется определенное время, к тому же процессор персо нального компьютера может оказаться перегруженным, что само по себе замед лит работу всей системы и ни о каком «реальном» масштабе времени в этом случае говорить будет нельзя.
66
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
В данной программе нас будут интересовать изменения состояния Таймера 1 и порта А, поэтому в новом окне просмотра выберем из списка эти объекты для наблюдения (Рис. 3.29).
3.4. Особенности разработки и отладки программ на MPLAB C для PIC24
67
void main(void) { TRISA = 0xfffe; PORTAbits.RA0 = 1; _INT3IF _INT3IE
= =
0; 1;
while(1) { } }
Эта программа переключает бит 0 порта А при возникновении прерывания INT3 (вывод RA14 порта А). Прерывание инициируется перепадом сигнала на выводе INT3 из НИЗКОГО уровня в ВЫСОКИЙ. Как и в предыдущем примере, в программе используется функцияобработчик прерывания, но с предопреде ленным именем _INT3Interrupt. В нее включены два оператора, первый из которых (_INT3IF = 0) сбрасывает флаг прерывания, а второй инвертирует бит 0 порта А. В основной программе с помощью оператора TRISA = 0xfffe бит 0 конфи гурируется как выход, а остальные (и среди них RA14) – как входы. Затем выход 0 порта А устанавливается в начальное состояние с высоким уровнем сигнала. Операторы _INT3IF _INT3IE
Рис. 3.29. Выбор объектов в окне просмотра
Теперь можно запустить программу в режиме Animate и наблюдать за изме нениями значений регистра таймера TMR1 и порта А во времени. До сих пор мы рассматривали примеры программ, в которых не было об работки внешних сигналов, например сигналов прерываний, поступающих на входы микроконтроллера. Подавляющее большинство приложений реального времени в процессе функционирования как раз и должны обрабатывать подоб ные события. Для тестирования таких программ в отладчике MPLAB SIM предусмотрены специальные средства, позволяющие промоделировать появле ние и обработку внешних событий. Как это делается, я покажу в следующем примере. Создадим новый проект в среде MPLAB IDE, в который включим файл на Си со следующим исходным текстом: #include
_CONFIG2(FCKSM_CSDCMD&OSCIOFNC_ON&POSCMOD_HS&FNOSC_PRI) void __attribute__ ((__interrupt__)) { _INT3IF = 0; PORTAbits.RA0 = ~ PORTAbits.RA0; }
_INT3Interrupt(void)
= =
0; 1;
инициализируют прерывание INT3. Компиляцию и сборку программы нужно выполнить в режиме Debug и вы брать отладчик MPLAB SIM. Для моделирования внешних событий в отладчи ке MPLAB SIM можно настроить стимулирующие воздействия, выбрав в меню Debugger опцию Stimulus (Рис. 3.30). При выборе этой опции появится окно стимулятора, в котором можно вы полнить настройку стимулирующих воздействий. Все настройки можно сохра нить в файле стимуляции с расширением .sbs и использовать при повторной отладке. Выберем закладку Asynch и из раскрывающегося списка под заголов ком Pin/SFR выберем INT3 (Рис. 3.31). Во второй колонке (Action) выберем опцию Pulse High — это означает, что на вывод INT3 (RA14) будет подан кратковременный перепад сигнала 0—1—0, длительностью 1 машинный цикл. Этого достаточно, чтобы сигнал прерывания был зафиксирован микроконтроллером и впоследствии обработан. Для генера ции стимулирующего воздействия следует запустить приложение в режиме Run или Animate и нажать стрелку под заголовком Fire в окне стимулятора. Для наблюдения за состоянием порта А при стимуляции INT3 в окне просмотра переменных программы должна присутствовать строка PORTA. В качестве стимулирующего воздействия можно задать и синхронный сигнал с определенной частотой (стимуляция синхронным сигналом). Это позволяет промоделировать, например, работу программы измерения временных пара
68
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
3.4. Особенности разработки и отладки программ на MPLAB C для PIC24
69
метров внешних сигналов. Можно выбрать и довольно изощренный алгоритм стимуляции, позволяющий отлаживать намного более сложные программы. Мы рассмотрим еще одно, очень полезное во многих случаях, свойство сти мулятора — возможность вывода и отображения данных программы в «вирту альном» окне. Вывод данных можно осуществить в любой точке программы, используя хорошо знакомую всем программистам библиотечную функцию printf. Чтобы это сделать, нужно выбрать опцию Settings… меню Debugger и в окне Simulator Settings перейти к закладке Uart1 IO (Рис. 3.32).
Рис. 3.30. Задание стимулирующих воздействий
Рис. 3.32. Настройка виртуального терминала
В этом окне нужно установить опцию Enable Uart1 IO, а под заголовком Output отметить опцию Window. После установки этих опций в окно Output будут вы водиться данные, присутствующие в функции printf гделибо в отлаживаемой программе. В самом окне Output после установки «виртуального» вывода по явится закладка SIM Uart1 (Рис. 3.33). Для демонстрации «виртуального» вывода данных создадим новый проект и включим в него Сифайл с исходным текстом из предыдущего примера, кото рый немного модифицируем, так, чтобы в виртуальное окно можно было вы водить количество вызовов прерывания INT3. Исходный текст нашей новой программы будет выглядеть следующим обра зом: #include #include
<stdio.h>
_CONFIG2(FCKSM_CSDCMD&OSCIOFNC_ON&POSCMOD_HS&FNOSC_PRI) int
Рис. 3.31. Выбор асинхронного во времени сигнала стимуляции
void {
cnt
=
0;
__attribute__
((__interrupt__))
_INT3Interrupt(void)
70
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
Рис. 3.33. Установка дополнительного окна вывода данных программы _INT3IF = 0; PORTAbits.RA0 = ~ PORTAbits.RA0; cnt++; printf("INT3 occured %d times!\n",
cnt);
} void main(void) { TRISA = 0xfffe; PORTAbits.RA0 = 1; _INT3IF _INT3IE
= =
0; 1;
while(1) { } }
Для использования библиотечной функции printf в исходный текст нужно включить заголовочный файл stdio.h. Все изменения в тексте программы ка саются только функцииобработчика _INT3Interrupt. При каждом вызове пре рывания в «виртуальное» окно с помощью функции printf посылается строка, в которой отображается количество вызовов INT3 (переменная cnt). Использо
3.4. Особенности разработки и отладки программ на MPLAB C для PIC24
71
Рис. 3.34. Выбор настроек текущего проекта
вание функций ANSI C (в данном случае – printf) требует выделения неини циализированной области памяти, для чего перед компиляцией и сборкой про граммы необходимо выбрать опцию Build Options… в меню Project (Рис. 3.34). Затем на странице Build Options For Project… нужно выбрать закладку MPLAB LINK30 и установить подходящее значение в окне Heap size. В нашем случае большого объема памяти не требуется, поэтому установим размер «кучи», рав ный 512 байтам (Рис. 3.35). После выполнения остальных необходимых настроек запустим программу на симуляцию. Окно работающего приложения может выглядеть так, как показа но на Рис. 3.36. Каждый раз при вызове прерывания INT3 (кнопка Fire) окна стимуляции в окне Output будет отображаться очередная строка. Мы рассмотрели далеко не все возможности компилятора MPLAB C для PIC24 и отладчика MPLAB SIM. Но из приведенных примеров видно, что эти инструменты разработки являются весьма эффективными на первых этапах создания и тестирования программ. Обширная информация по применению инструментальных средств собрана в технической документации фирмы Microchip, к которой можно обратиться для более детального изучения данной темы.
72
Глава 3. Система команд и основы программирования микроконтроллеров PIC24F
ГЛАВА
4
ПРОГРАММИРОВАНИЕ ПОРТОВ ВВОДА/ВЫВОДА
Практически ни один проект с микроконтроллерами не обходится без опера ций ввода/вывода через цифровые порты. Микроконтроллеры семейства PIC24F предоставляют разработчику широкие возможности по работе с дискретными сигналами благодаря наличию достаточного количества портов ввода/вывода и некоторым функциям, расширяющим функциональность самих портов.
4.1. Аппаратно$программная архитектура портов ввода/вывода Рис. 3.35. Установка размера «кучи»
Рис. 3.36. Окно работающего приложения
Порты ввода/вывода общего назначения — это простейшие периферийные устройства, с помощью которых PICмикроконтроллер может получать цифро вые данные и управлять другими устройствами. Дополнительную гибкость при работе с портами ввода/вывода обеспечивает и то, что их можно настроить для выполнения альтернативных функций. В общем виде функциональную схему стандартного порта ввода/вывода, ко торый не используется периферийными модулями, можно представить так, как показано на Рис. 4.1. Эта схема довольно точно отображает функционирование стандартного пор та ввода/вывода. Порт может быть настроен на ввод или вывод цифрового сигнала с помощью защелки TRIS, которая представляет собой Dтриггер. Если порт должен работать как выход, то на вход D защелки TRIS подается сигнал лог. 0, который по тактовому импульсу записывается в триггер. В этом случае инверсный выход TRISзащелки разрешает работу схемы «И» и откры вает тристабильный буфер, через который сигнал с выхода защелки данных (см. Рис. 4.1) проходит на вывод порта. Если на вход D защелки TRIS подать сигнал лог. 1, то на инверсном выходе триггера появится 0, который запрещает прохождение сигнала с защелки дан ных на выход порта. В этом случае данные с вывода порта можно будет только читать. Здесь не следует смешивать чтение выходных данных порта и чтение вывода порта. Для чтения бита данных, записанного в порт, нужно прочитать содержимое защелки данных.
74
Глава 4. Программирование портов ввода/вывода
4.1. Аппаратнопрограммная архитектура портов ввода/вывода
75
содержимое регистраоперанда (в данном случае регистра порта) вначале счи тывается, полученное значение модифицируется и затем обратно записывается в регистр. Если вывод порта сконфигурирован как выход (на запись), то ни каких проблем не возникает. Однако если выводы порта сконфигурированы как входы, то здесь нужно соблюдать осторожность и записывать данные в порт до того, как направление обмена данными изменится с чтения на запись. У каждого порта имеется регистр LATx, использование которого позволяет исключить проблемы, связанные с выполнением операций типа «чтение–мо дификация–запись». При чтении этого регистра возвращается значение бита, записанного в защелку порта, а не значение на выводе порта. Операции типа «чтение–модификация–запись», выполненные над регистрами LAT, дают пра вильный результат. Вкратце все вышеизложенное можно резюмировать следу ющим образом: • • • • Рис. 4.1. Схема порта ввода/вывода
Каждый порт ввода/вывода управляется с помощью четырех регистров: • TRISx — установка режима работы (чтение или запись) для порта PORTx (здесь x = A, B, C и т. д. и обозначает конкретный порт); • PORTx — регистр ввода/вывода порта; • LATx — регистрзащелка данных порта PORTx; • ODCx — регистр режима работы с открытым стоком. Каждому выводу порта ввода/вывода соответствует отдельный бит в регис трах TRISx, PORTx, LATx и ODCx. Общее количество портов ввода/вывода и количество выводов зависит от конкретной модели микроконтроллера. Вполне возможно и то, что отдельные биты портов ввода/вывода в конкретном устройстве задействованы не будут. В любом случае лучше обратиться к технической документации на микроконт роллер. Рассмотрим назначение каждого из регистров порта ввода/вывода. Регистр TRISx позволяет сконфигурировать направление обмена данными для каждого вывода порта. Если для какоголибо вывода порта в регистре TRIS на соответствующей позиции установлен 0, то вывод будет работать на пере дачу данных. Если же соответствующий бит в регистре TRIS установлен в 1, то вывод порта будет работать на прием (чтение). Доступ к данным порта осуществляется посредством регистра PORTx. При чтении этого регистра считываются значения сигналов, присутствующих на выводах порта, а при записи этого регистра данные заносятся в защелку дан ных порта. Многие команды микроконтроллера, такие, например, как BSET и BCLR, выполняют операции, известные как «чтение–модификация–запись». При этом
при при при при
записи записи чтении чтении
в регистр PORTx данные записываются в защелку порта; в регистр LATx данные записываются в защелку порта; регистра PORTx данные читаются с вывода порта; регистра LATx данные читаются с защелки порта.
Каждый вывод порта может работать как в обычном режиме, так и в режиме с «открытым стоком». Для переключения выводов в этот режим используются регистры ODCx (Open Drain Control). Если соответствующий бит регистра ODCx установлен в 1, то вывод порта работает как выход с открытым стоком. Если же данный бит сброшен в 0, то вывод работает как обычный цифровой выход. При сбросе микроконтроллера все биты регистра ODCx сбрасываются в 0. Конфигурация с «открытым стоком» применяется в случаях, когда к выводу порта требуется подключить нагрузку, которая должна питаться от напряже ния, большего или меньшего напряжения питания микроконтроллера. Следует соблюдать осторожность при подключении устройств к «открытому стоку» с повышенным напряжением питания, поскольку это может повредить кристалл микроконтроллера. В таких случаях следует обращаться к документа ции на микроконтроллер. Выводы портов микроконтроллеров семейства PIC24F можно сконфигури ровать для работы как с цифровыми, так и с аналоговыми сигналами. При использовании порта для ввода цифровых данных входной сигнал поступает на TTLбуфер или триггер Шмита. При настройке порта на выход для передачи выходного сигнала используется буферный усилитель или же применяется конфигурация с «открытым стоком». Один и тот же вывод порта ввода/вывода может использоваться и при работе периферийных модулей микроконтроллера, при этом он не может работать как обычный вывод порта. При этом в большинстве случаев вывод должен конфи гурироваться как обычный вывод порта ввода/вывода, хотя некоторые перифе рийные устройства могут переопределять содержимое регистра TRIS. На Рис. 4.2 показана функциональная схема такого «разделяемого» порта ввода/вывода, который используется периферийными модулями.
76
Глава 4. Программирование портов ввода/вывода
4.2. Программирование портов ввода/вывода
77
При работе порта ввода/вывода c модулем аналогоцифрового преобразова ния установки регистра TRIS не влияют на состояние порта. Для того чтобы использовать порт, используемый аналогоцифровым преобразователем, в каче стве стандартного цифрового порта ввода/вывода, соответствующий бит в реги стре AD1PCFG должен быть установлен в 1, независимо от того, включен модуль АЦП или выключен. Следует сказать, что некоторые дополнительные функции, присвоенные портам ввода/вывода, не требуют перехвата управления выводом порта, как, например, в случае с модулем аналогоцифрового преобразователя. Если порт ввода/вывода должен работать как вход прерывания, вход синхронизации тай мера или вход регистрации события, то достаточно установить соответствую щий бит в регистре TRISx. При этом модули прерывания, таймера и регист рации событий не берут управление портом на себя. Другие периферийные модули (SPI, I2C и UART) при функционировании полностью перехватывают управление портом ввода/вывода, так что конфигу рирование такого порта посредством регистров PORTx и TRISx не требуется.
4.2. Программирование портов ввода/вывода
Рис. 4.2. Схема разделяемого порта ввода/вывода
При чтении разделяемого порта ввода/вывода нужно помнить несколько правил. Вопервых, если порт управляется периферийным модулем (Рис. 4.2), то состояние его вывода можно определить, прочитав регистр PORTx. Вовто рых, периферийный модуль может прочитать состояние вывода независимо от цифрового модуля ввода/вывода. При разделении порта ввода/вывода, настроенного на передачу (запись) сиг нала, между разными модулями следует помнить, что: • если выход управляется периферийным устройством, то запись данных в регистр PORTx не возымеет никакого эффекта; • данные можно прочитать из порта при помощи регистра PORTX; • параметры выходного сигнала порта (токи нагрузки, скорость нарастания выходного сигнала и т. д.) определяются настройками периферийного мо дуля, который использует этот порт; • для конфигурирования вывода порта в качестве выхода необходимо сбра сывать соответствующий бит в регистре TRISx; • если выход порта может устанавливаться в тристабильное состояние, то это осуществляет сам периферийный модуль.
В этом разделе мы рассмотрим несколько проектов, в которых будут проде монстрированы характерные особенности программирования портов ввода/ вывода, работающих в стандартном режиме обмена цифровыми данными. Аппаратная часть первого проекта показана на Рис. 4.3. В этой схеме к выводу RA0 (бит 0 порта PORTA) подключен светодиод, который должен включаться/отключаться при ВЫСОКОМ уровне напряжения на выводе RA7 (бит 7 порта PORTA). В исходном состоянии порт RA0 настроен как вход. Программная часть проекта разработана в среде MPLAB IDE с помощью мастера проектов. Для большей наглядности при разработке мы будем использовать язык ас семблера, поэтому в окне выбора инстру ментальных средств мастера проектов сле дует выбрать ассемблер MPLAB ASM30 (Рис. 4.4). В пустой проект следует добавить файл с расширением .s (стандартное расширение для ASMфайла), поместив в него следую щий исходный текст: .include "p24fj128ga010.inc" .bss cnt : .space 2 cnt1: .space 2 .text .global __ reset
Рис. 4.3. Аппаратная часть проекта
78
Глава 4. Программирование портов ввода/вывода
4.2. Программирование портов ввода/вывода
79
ВЫСОКОГО уровня сигнала. Обе переменные имеют размер в одно слово (2 байта) и при запуске программы получают максимальные значения 0xffff. Впоследствии эти переменные декрементируются в циклах Loop и Main_Loop, формируя тем самым определенный интервал времени задержки. Микроконт роллер работает на частоте 8 МГц, так что задержка получается достаточно ощутимой, чтобы увидеть результат работы программы. В начале программы все выводы порта А конфигурируются как входы: mov mov
#0xffff,w0 w0,TRISA
В этом случае запись в бит 0 любого значения не изменит состояния выхода, поскольку инверсный выход защелки TRIS (см. Рис. 4.1) сброшен в 0 и бло кирует выходной буфер. Таким образом, команда bclr.b
Рис. 4.4. Окно выбора компилятора __reset: mov mov mov mov bclr.b wait: btss goto btsc bclr
#0xffff,w0 w0,cnt #0xffff,w0 w0,TRISA PORTA,#0
PORTA,#7 wait TRISA,#0 TRISA,#0
#0xffff,w0 w0,cnt
Loop: dec bra dec bra
cnt NZ,Loop cnt1 NZ,Main_Loop
goto .end
хоть и сбрасывает бит 0 защелки данных порта А, но на выход эти данные не попадают. По этой причине светодиод на выходе RA0 не включается, посколь ку падение напряжения на нем практически равно 0. Далее в цикле wait программа ожидает поступления сигнала ВЫСОКОГО уровня на вывод RA7 (бит 7 порта А): wait: btss goto . . .
PORTA,#7 wait
При поступлении сигнала ВЫСОКОГО уровня на этот вывод бит 0 регистра TRISA сбрасывается:
mov mov Main_Loop: mov mov
btg.b
PORTA,#0
#2,0 w0,cnt1
PORTA,#0 wait
В этой программе переменные cnt и cnt1 используются для формирования небольшой задержки переключения светодиода при удержании на входе RA7
bclr
TRISA,#0
Это означает, что выходной буфер бита 0 порта А разблокируется, и на выход поступает сигнал с выхода защелки данных (LAT) (Рис. 4.1), который был ранее установлен в 0 командой bclr.b PORTA, #0. Это вызывает вклю чение светодиода D1. Далее, с определенной задержкой, выход RA0 периоди чески переключается, до тех пор, пока на входе RA7 присутствует ВЫСОКИЙ уровень. Эта программа демонстрирует, как работает порт ввода/вывода в режиме передачи цифровых данных при изменении конфигурации. Многие функции микроконтроллера, такие, как вызов прерывания, синхро низация таймера и т. д., работают со стандартными настройками портов ввода/ вывода. Это означает, например, что если вывод INT3 настроен как вход, то сигнал, поступающий на этот вход, будет вызывать соответствующее прерыва ние (если это прерывание разрешено). В следующем проекте демонстрируется работа с прерыванием INT3, вход которого использует вывод RA14 (бит 14 порта А). Светодиод D1 переключа ется каждый раз при вызове обработчика прерывания. Аппаратная часть про екта показана на Рис. 4.5.
80
Глава 4. Программирование портов ввода/вывода
4.3. Модуль регистрации событий _RA0
=
81
0x1;
_INT3IF _INT3IE
= =
0; 1;
while(1); }
Это очень простой пример. Обработчик прерывания _INT3Interrupt сбрасы вает флаг прерывания _INT3IF, а затем инвертирует бит 0 порта А. Поскольку при инициализации микроконтроллер настраивает порты на чтение, то нам нужно переключить бит 0 порта А на запись: TRISAbits.TRISA0
=
0x0;
Кроме того, нужно разрешить внешнее прерывание INT3: _INT3IF _INT3IE
Рис. 4.5. Схема прерывания INT3 на порту вводавывода
Напомню, что порты ввода/вывода во многих случаях можно задействовать и для реализации альтернативных функций микроконтроллера. На Рис. 4.5 как раз и показано использование вывода 14 порта A для приема сигнала преры вания. В такой конфигурации вывод порта должен быть настроен для чтения входного сигнала с помощью установки соответствующего бита в регистре TRISA. При желании или необходимости можно создать и такую аппаратно программную конфигурацию, в которой, допустим, в определенные моменты времени бит 14 будет принимать сигнал прерывания, а остальную часть вре мени работать как выходной для управления какойлибо нагрузкой. Программная часть проекта реализована с помощью мастера проектов MPLAB IDE, но исходный текст написан уже на Си: #include
_CONFIG2(FCKSM_CSDCMD&OSCIOFNC_ON&POSCMOD_HS&FNOSC_PRI) void __attribute__ { _INT3IF = 0; _RA0 = ~_RA0; } void main(void) { TRISAbits.TRISA0
((interrupt))
=
0x0;
_INT3Interrupt(void)
= =
0; 1;
В данном примере мы работаем с портом А, который не используется пе риферийными модулями. Если, например, светодиод был бы подключен к порту В, который используется модулем аналогоцифрового преобразователя, то си туация была бы иной. При инициализации микроконтроллера порт В сразу настраивается для использования модулем АЦП, поэтому, чтобы задействовать все или отдельные выводы порта для ввода/вывода цифровых сигналов, в основ ной программе пришлось бы вначале выполнить оператор AD1PCFG
=
0xffff;
В любом случае перед использованием в проекте того или иного порта следует ознакомиться с документацией на конкретный микроконтроллер.
4.3. Модуль регистрации событий В микроконтроллерах PIC24F предусмотрена еще одна полезная функция, которая позволяет программе реагировать определенным образом на измене ния уровней сигналов на входах портов. Эта функция основана на исполь зовании механизма «захвата» или регистрации событий. В данном контексте под событием понимают любое изменение сигнала на входе порта ввода/ вывода. Этот механизм используется при работе с выводами портов, для которых предусмотрен специальный вариант обработки событий при изменении состо яния сигнала на входе порта. Такие выводы микроконтроллера имеют допол нительное обозначение CNx (Change Notification) и реализованы посредством отдельного аппаратного модуля в микроконтроллере. При возникновении со бытия задействуется механизм прерываний, при этом обработчик прерывания позволяет оперативно обработать событие. Количество таких выводов зависит от конкретной модели микроконтроллера, поэтому за более подробной инфор мацией следует обращаться к технической документации на устройство.
82
Глава 4. Программирование портов ввода/вывода
С CNмодулем связаны три группы регистров управления: • регистр CNENn — содержит биты разрешения прерывания от соответству ющих выводов, которые обозначаются как CNxIE, где x обозначает номер CNвывода; • регистры CNPUn/CNPDn — содержат биты управления CNxPUE/ CNxPDE. Эти биты разрешают/запрещают подтяжку выводов к питанию (CNPUn) и общему проводу (CNPDn). Это позволяет отказаться от ис пользования внешних подтягивающих резисторов при подключении таких узлов, как кнопки (клавиатура). Функциональная схема одного из каналов CNмодуля показана на Рис. 4.6.
4.3. Модуль регистрации событий
83
Рассмотрим пример проекта, в котором показаны основные принципы об работки событий на цифровых входах микроконтроллера. Аппаратная часть проекта показана на Рис. 4.7.
Рис. 4.7. Аппаратная часть проекта Рис. 4.6. Схема CNмодуля
На этом рисунке изображена функциональная схема канала 0 CNмодуля. При любом изменении сигнала на выводе CN0 схема исключающего ИЛИ будет формировать сигнал ВЫСОКОГО уровня, который, попадая на один из входов оконечного элемента ИЛИ, приведет к генерации прерывания. Точно так же работают и другие входы CN1…CNx. Программирование обработчиков событий на входах CNx включает несколь ко шагов: 1. Требуемый вывод CNx переключается в режим цифрового входа посред ством установки соответствующего бита в регистре TRISx. 2. Разрешается при необходимости подключение внутренней подтяжки пу тем установки соответствующих битов регистров CNPUx. 3. Сбрасывается флаг прерывания CNxIF. 4. Устанавливается требуемый уровень приоритета от CNмодуля путем ус тановки CNxIP. 5. Разрешаются прерывания от CNвходов путем установки соответствую щих битов CNxIE. Программа пользователя при необходимости должна сама определить, какое событие произошло (перепад 0—1 или 1—0), и выполнить требуемые действия.
В этой схеме контролируемые сигналы поступают на входы CN7 и CN20 микроконтроллера PIC24FJ128GA010. Программная часть проекта обеспечива ет синхронное переключение светодиодов при одновременном присутствии сигналов ВЫСОКОГО уровня на входах CN7 и CN20. Например, переключе ние светодиодов будет осуществляться при ВЫСОКОМ уровне сигнала на входе CN7 и изменении уровня с НИЗКОГО на ВЫСОКИЙ на входе CN20. Тактовая частота схемы равна 8 МГц. Программная часть проекта разработана в среде MPLAB IDE с помощью мастера проектов. Исходный текст программы на языке Си приведен далее: #include
_CONFIG2(FCKSM_CSDCMD&OSCIOFNC_ON&POSCMOD_HS&FNOSC_PRI) #define #define
TRISB_5 TRISBbits.TRISB5 TRISD_14 TRISDbits.TRISD14
#define #define
TRISB_0 TRISB_1
#define #define
CN7 CNEN1bits.CN7IE CN20 CNEN2bits.CN20IE
#define
SYSCLK
TRISBbits.TRISB0 TRISBbits.TRISB1
8000000
Глава 4. Программирование портов ввода/вывода
84
void __attribute__ ((interrupt)) _CNInterrupt(void) { _CNIF = 0; if (_RB5 == 1 && _RD14 == 1) { _RB0 = ~_RB0; _RB1 = ~_RB1; } }
4.3. Модуль регистрации событий
85
Аппаратная часть проекта представлена схемой на Рис. 4.8.
void main(void) { TRISB_0 = 0; TRISB_1 = 0; TRISB_5 = 1; TRISD_14 = 1; _CNIF _CNIP CN7 CN20 _CNIE
= = =
0; 0x4; 1; = 1; = 1;
while(1); }
Переключение светодиодов, подключенных к выводам 0 и 1 порта B, выпол няется в обработчике прерывания _CNInterrupt. Для инициализации выводов прерывания CN7 и CN20 в основной программе устанавливаются соответст вующие биты в регистрах CNEN1 и CNEN2: CN7 = 1; CN20 = 1;
Кроме того, необходимо, как и в случае других источников прерываний, разрешить прерывания от CNмодуля: _CNIE
=
Рис. 4.8. Аппаратная часть устройства
1;
Программный код должен настроить также выводы RB5(CN7) и RD14(CN20) на ввод цифровых сигналов, что выполняется операторами: TRISB_5 = 1; TRISD_14 = 1;
В остальном программный код, думаю, понятен. Возможность регистрации событий позволяет создавать системы сигнализа ции и оповещения различной степени сложности. В нашем следующем проекте мы рассмотрим простейшую систему регистрации нескольких событий и ин дикации источника события. Мы проанализируем взаимосвязь аппаратной и программной частей, а также возможные модификации этого проекта. Разра ботчики встраиваемых устройств часто сталкиваются с дилеммой: решить за дачу с максимальным использованием аппаратных средств или использовать большей частью программный вариант решения. На этом примере мы проана лизируем преимущества и недостатки обоих подходов.
В данном проекте используется микроконтроллер PIC24FJ128GA010 с так товой частотой 8 МГц. На входы 1…4 RSтриггера 74HC279 (DD1) могут под ключаться источники сигналов (дискретные датчики, переключатели и т. д.), НИЗКИЙ уровень напряжения которых приводит к появлению сигнала лог. 1 на одном из входов логического элемента ИЛИНЕ (микросхема DD3). Логи ческий элемент DD3 переключается из состояния НИЗКОГО уровня в состо яние ВЫСОКОГО уровня при наличии напряжения логической единицы на любом из 4 входов, изменяя тем самым состояние входа CN7, что приводит к генерации прерывания. Далее программа считывает состояние выходов Q1…Q4 триггера DD1 и вы водит его в биты 0…3 порта B, к которым подключены светодиоды D1…D4. Триггеры Шмита (микросхема DD2) выполняют функцию автоматического сброса состояния входов через определенное время задержки, определяемое RCцепочкой R5C1. Эта задержка нужна для того, чтобы функцияобработчик прерывания успевала считать состояние выходов Q1…Q4.
Глава 4. Программирование портов ввода/вывода
86
4.3. Модуль регистрации событий
87
В программную часть проекта, разработанную в MPLAB IDE, нужно вклю чить Сифайл со следующим исходным текстом: #include
_CONFIG2(FCKSM_CSDCMD&OSCIOFNC_ON&POSCMOD_HS&FNOSC_PRI) char
c1;
void __attribute__ ((interrupt)) { _CNIF = 0; c1 = PORTA & 0xf; PORTB = c1; }
_CNInterrupt(void)
void main(void) { AD1PCFG = 0xffff; TRISB = 0xfff0; TRISA = 0x7fff; _CNIF = 0; _CNIP = 0x4; _CN7IE = 1; _CNIE = 1; while(1); }
Программа очень проста. Обработка входных сигналов осуществляется в функцииобработчике прерывания _CNInterrupt. Здесь в переменную c1 счи тываются 4 бита порта А, которые тут же передаются в младшие биты порта В. В основной программе выполняется инициализация портов А и В, а также настройка прерывания обработки событий. Обработка одних и тех же внешних сигналов может осуществляться и с по мощью других аппаратнопрограммных решений. В каждом конкретном случае нужно определить оптимальную конфигурацию. Если в системе необходимо добиться использования минимального количества внешних компонентов, то основной упор должен делаться на программную часть микроконтроллера (firmware). Однако здесь могут возникнуть ограничения, связанные с быстро действием системы. Если сравнивать один и тот же алгоритм, реализованный оптимальным образом внешними элементами и аппаратнопрограммными средствами микроконтроллера, то вариант с внешними элементами будет ра ботать быстрее. Тем не менее, для многих систем с невысоким или средним быстродействием упор на программную реализацию алгоритмов вполне оправ дан. Например, наш предыдущий проект почти целиком можно реализовать с помощью одного микроконтроллера, оставив в системе минимум внешних компонентов. Модифицированная аппаратная часть предыдущего проекта представлена на Рис. 4.9.
Рис. 4.9. Аппаратная часть модифицированного проекта
В этой схеме для считывания данных мы оставили одну внешнюю микро схему DD1. Выходы Q1…Q4 триггера в этой схеме соединены со входами ре гистрации событий CN2…CN5 микроконтроллера. Такое упрощение схемы требует модификации программной части проекта, поскольку нужно разрешить обработку событий по входам CN2…CN5. Вот исходный текст основной про граммы для данной аппаратной конфигурации: #include
_CONFIG2(FCKSM_CSDCMD&OSCIOFNC_ON&POSCMOD_HS&FNOSC_PRI) char
c1;
void __attribute__ ((interrupt)) { _CNIF = 0; c1 = PORTB & 0xf; PORTA = c1; } void {
main(void)
_CNInterrupt(void)
88
Глава 4. Программирование портов ввода/вывода AD1PCFG = 0xffff; TRISB = 0xffff; TRISA = 0x0; _CNIF _CNIP
= =
_CN2IE _CN3IE _CN4IE _CN5IE
0; 0x4; = = = =
_CNIE
=
ПРОГРАММИРОВАНИЕ ПРЕРЫВАНИЙ
1;
}
Здесь нужно установить выводы порта В для работы в качестве цифровых портов, что выполняется двумя операторами: AD1PCFG = 0xffff; TRISB = 0xffff;
Кроме того, нужно установить разрешение прерывания при возникновении изменений сигналов на входах CN2…CN5: = = = =
5
1; 1; 1; 1;
while(1);
_CN2IE _CN3IE _CN4IE _CN5IE
ГЛАВА
1; 1; 1; 1;
В принципе, если нет жестких ограничений по количеству задействованных сигнальных выводов, то удобно реализовать большую часть проекта (если это не какойто специальный случай) программным способом. Если необходима повышенная производительность, то в этом случае можно взять более быстро действующий микроконтроллер, например, семейства PIC24H.
Микроконтроллеры PIC24F имеют развитую систему прерываний, позволя ющую использовать это устройство в приложениях реального времени различ ной степени сложности. Модуль прерываний микроконтроллеров PIC24F об ладает следующими характеристиками: • обеспечивает обработку 8 немаскируемых системных прерываний; • позволяет задавать до семи уровней приоритетов пользовательских преры ваний; • позволяет задавать до 118 векторов прерываний в таблице векторов пре рываний IVT. При этом каждому прерыванию назначается уникальный вектор; • позволяет настроить дополнительную таблицу векторов прерываний (AIVT), которую можно использовать при отладке программ. Таблица векторов прерываний IVT размещается в памяти программ, начиная с адреса 0x000004, и содержит 126 векторов прерываний, из которых 8 исполь зуются системными прерываниями, а остальные 118 могут использоваться пери ферийными модулями. Системные прерывания позволяют выполнить обработку серьезных аппаратнопрограммных сбоев в системе, поэтому их нельзя запретить или замаскировать. Векторы системных прерываний описаны в Табл. 5.1. Таблица 5.1. Векторы немаскируемых ловушек Номер вектора прерывания
Адрес в таблице IVT
Источник ошибки
0 1 2 3 4
0x000004 0x000006 0x000008 0x00000A 0x00000C
5 6 7
0x00000E 0x000010 0x000012
Зарезервирован Сбой генератора тактовой частоты Ошибка адресации Ошибка обращения к стеку Ошибка математических вычислений (как правило, деление на 0) Зарезервирован Зарезервирован Зарезервирован
Каждый вектор прерывания содержит 24битный адрес, по которому распо лагается соответствующая функцияобработчик прерывания (Interrupt Service Routine, ISR).
Глава 5. Программирование прерываний
90
Глава 5. Программирование прерываний
Любое пользовательское прерывание может быть разрешено или запрещено посредством установки или сброса соответствующего бита в одном из регист ров разрешения прерываний IECn. Установка бита соответствующего преры вания в 1 разрешает прерывание, а сброс этого бита — запрещает. В микро контроллерах PIC24F предусмотрен ряд механизмов, позволяющих разрешить или запретить все прерывания одновременно (кроме, естественно, немаскиру емых прерываний). При сбросе микроконтроллера все биты разрешения прерываний сбрасыва ются в 0, запрещая генерацию прерываний, поэтому программа пользователя должна сама устанавливать необходимые разрешения. При разработке приложений было бы очень неудобно изменять биты разре шения прерываний, явно указывая регистры IECn, поскольку каждый раз при шлось бы просматривать все эти регистры в поисках соответствующего бита. К счастью, в компиляторе MPLAB С предусмотрен очень удобный механизм работы с битами разрешения прерываний посредством макросов, определенных в заголовочных файлах. Например, для разрешения/запрета прерывания Таймера 1 используется макрос _T1IE, для INT3 используется _INT3IE и т. д. Так, раз решить прерывание Таймера 1 в программе на Си можно с помощью оператора _T1IE
=
1;
Каждому пользовательскому прерыванию может быть присвоен тот или иной уровень приоритета. Биты управления приоритетом располагаются на трех младших позициях каждой тетрады регистров IPCn. Биты 3 тетрад не используются и читаются как 0. Соответственно уровень приоритета каждого прерывания может изменяться от 1 (самый низкий приоритет) до 7 (наивыс ший приоритет). Если все биты приоритета прерывания сброшены в 0, то прерывание запрещено. Как и в случае с битами разрешения прерываний, в заголовочных файлах описаны макросы, облегчающие программные манипу ляции при установке приоритетов. Например, для установки приоритета 4 пре рывания Таймера 1 можно использовать оператор _T1IP
=
4;
Для установки приоритета 2 прерывания INT4 можно использовать оператор _INT4IP
=
2;
По умолчанию (после сброса микроконтроллера) приоритеты пользователь ских прерываний устанавливаются равными 4. Для более подробной информа ции читатели могут обратиться к соответствующим заголовочным файлам. Рассмотрим несколько проектов, в которых демонстрируются различные ва рианты реализации прерываний в системах с микроконтроллерами PIC24F. Вначале вкратце рассмотрим, каким образом организуется обработка прерыва ний в компиляторе MPLAB С. Каждое прерывание, используемое в программе, должно иметь соответст вующую функциюобработчик, прототип которой в MPLAB C для PIC24 мож но представить следующим образом: void
__attribute__
((__interrupt__))
isr0(void);
91
Из объявления прототипа функцииобработчика прерывания isr0 видно, что она не принимает никаких параметров и не возвращает никаких значе ний. При вызове функцииобработчика компилятор автоматически сохраняет в стеке все рабочие регистры, а также регистр состояния процессора SR. Остальные переменные можно сохранить, перечислив их в поле атрибутов. Например, для того чтобы компилятор автоматически сохранял и восстанав ливал переменные var1 и var2, можно использовать такой прототип функ цииобработчика: void
__attribute__((__interrupt__(__save__(var1,
var2))))
isr0(void);
Обратите внимание, что в объявлении функцииобработчика используется двойное подчеркивание. Компилятор MPLAB С «понимает» и слегка упрощен ный вариант объявления: void
__attribute__
((interrupt))
isr0(void);
Если функцияобработчик не требует указания дополнительных параметров, для ее объявления можно применить упрощенный синтаксис. Это делается с помощью макросов, которые объявлены в заголовочных файлах устройств. Вот пример такого объявления: #define
ISR
__attribute__((interrupt))
Тогда функцияобработчик прерывания Таймера 1 может быть объявлена в программе следующим образом: #include void _ISR _INT1Interrupt(void);
Дополнительные аспекты обработки прерываний мы рассмотрим в контек сте последующих практических примеров. В первом примере демонстрируется техника обработки прерываний с раз личным уровнем приоритетов. Аппаратная часть проекта показана на Рис. 5.1. В этой схеме сигнал прерывания (перепад 0—1 на выходе инвертора) пода ется одновременно на два входа внешних прерываний INT3 и INT4, имеющих разные приоритеты. Функцияобработчик прерывания INT3 инвертирует вы ход 0 порта А, а обработчик прерывания INT3 то же самое делает с выходом 7 того же порта. В каждый из обработчиков включена небольшая задержка, реализованная на Таймере 1. Присваивая разные приоритеты прерываниям INT3 и INT4, можно наблюдать за изменениями последовательности переклю чения светодиодов на выходах 0 и 7. Если приоритет прерывания INT3 выше приоритета INT4, то светодиод, подключенный к выходу 0 порта А, переклю чится раньше, чем светодиод на выходе 7. Если же установить приоритет прерывания INT3 ниже приоритета INT4, то можно будет наблюдать обратную картину: светодиод на выходе 7 при подаче сигнала прерывания будет пере ключаться раньше, чем светодиод на выходе 0. Программная часть проекта разработана в среде MPLAB IDE на языке Си и включает файл со следующим исходным текстом:
92
Глава 5. Программирование прерываний
Глава 5. Программирование прерываний TRISAbits.TRISA14 TRISAbits.TRISA15 _INT3IF _INT3IP _INT3IE
= = =
0; 7; 1;
_INT4IF _INT4IP _INT4IE
= = =
0; 3; 1;
= =
93
1; 1;
while(1); }
Рис. 5.1. Аппаратная часть проекта
#include
_INT3IF _INT3IP _INT3IE
_CONFIG2(FCKSM_CSDCMD&OSCIOFNC_ON&POSCMOD_HS&FNOSC_PRI) void Delay(void) { TMR1 = 0; T1CON = 0x8030; while (TMR1 < 30000); T1CON = 0x0; } void __attribute__ { _INT3IF = 0; _RA0 = ~_RA0; Delay(); }
((interrupt))
_INT3Interrupt(void)
void __attribute__ { _INT4IF = 0; _RA7 = ~ _RA7; Delay(); }
((interrupt))
_INT4Interrupt(void)
void main(void) { TRISA = 0;
В программе определены два обработчика прерываний: _INT3Interrupt (пре рывание INT3) и _INT4Interrupt (прерывание INT4). В обработчиках прерыва ний биты 0 (прерывание INT3) и 7 (прерывание INT4) порта A инвертируются каждый раз при генерации прерываний. В каждом из обработчиков присутству ет функция Delay, реализующая посредством Таймера 1 микроконтроллера не большую задержку. Первый оператор обоих обработчиков прерываний сбрасы вает флаги прерывания (_INT3IF и _INT4IF соответственно). Инициализация прерывания INT3 выполняется в основной программе с по мощью операторов = = =
0; 7; 1;
Вначале сбрасывается флаг прерывания (первый оператор), затем прерыва нию присваивается уровень приоритета, равный 7, после чего устанавливается флаг разрешения прерывания. Точно та же последовательность действий вы полняется и для инициализации прерывания INT4, только уровень приоритета для этого прерывания устанавливается равным 3, т. е. ниже, чем для INT3. Таким образом, при возникновении ситуации, когда сигналы прерывания поступают на оба входа одновременно, обработчик прерывания INT3 выпол нится первым. Эта ситуация как раз и моделируется схемой, показанной на Рис. 5.1. Выводы прерываний должны быть сконфигурированы как входы, поэтому соответствующие биты регистра TRIS порта А устанавливаются в 1 с помощью операторов TRISAbits.TRISA14 TRISAbits.TRISA15
= =
1; 1;
Задавая разные уровни приоритетов прерываниям INT3 и INT4, можно на блюдать различную очередность переключения светодиодов, подключенных к выходам порта А. Микроконтроллеры PIC24F позволяют генерировать прерывания программ но, устанавливая флаг соответствующего прерывания в регистре IFSn. Напри мер, можно разработать приложение, в котором функцияобработчик преры вания Таймера 1 вызывала бы прерывание INT3. В этом случае прерывание
94
Глава 5. Программирование прерываний
INT3 будет вложенным по отношению к прерыванию Таймера 1. Микрокон троллеры PIC24F позволяют использовать вложенные прерывания, при этом вложенные прерывания должны иметь более высокий приоритет по сравнению с текущим прерыванием. Это означает, что прерывание INT3, вызванное из обработчика прерывания Таймера 1, будет обработано раньше только в том случае, если его приоритет будет выше, чем у текущего прерывания. Если приоритет прерывания INT3 будет ниже, чем у прерывания Таймера 1, то обработчик INT3 будет вызван по завершении обработчика прерывания Тай мера 1. В нашем следующем проекте будет продемон стрирована последовательность обработки вло женных прерываний. Аппаратная часть проекта показана на Рис. 5.2. В этой схеме светодиод, подключенный к выво ду RA0 порта А, будет переключаться каждый раз при вызове прерывания INT3. Светодиод, подклю ченный к выводу RA7, будет переключаться при вызове прерывания Таймера 1. Визуально очеред ность переключения светодиодов будет зависеть от приоритета вложенного прерывания INT3. Программная часть демонстрационного проек та разработана в MPLAB IDE и включает файл Рис. 5.2. Аппаратная часть с программой, исходный текст которой приводит проекта ся далее: #include
_CONFIG2(FCKSM_CSDCMD&OSCIOFNC_ON&POSCMOD_HS&FNOSC_PRI) #define #define #define
SYSCLK t1 1 PREG
8000000 SYSCLK/2/256*t1
void Delay(void) { long cnt = 100000; while (cnt != 0)cnt—; } void __attribute__ { _T1IF = 0; _INT3IF = 1; _RA7 = ~_RA7; Delay(); }
((interrupt))
_T1Interrupt(void)
void __attribute__ { _INT3IF = 0;
((interrupt))
_INT3Interrupt(void)
Глава 5. Программирование прерываний
95
_RA0 = ~_RA0; Delay(); } void main(void) { TRISA = 0; TRISAbits.TRISA14
=
1;
PR1 = PREG; TMR1 = 0; IFS0bits.T1IF = 0; _T1IP = 5; _T1IE = 1; T1CON = 0x8030; _INT3IF _INT3IP _INT3IE
= = =
0; 3; 1;
while(1); }
В этой программе определены две функцииобработчики прерываний. Фун кция _T1Interrupt обрабатывает прерывание таймера, которое при тактовой частоте микроконтроллера 8 МГц, указанных настройках регистра периода PR1 и предделителя будет вызываться с интервалом в 1 с. Функция _INT3Interrupt вызывается из обработчика _T1Interrupt путем установки флага прерывания _INT3IF. Функция Delay() реализует временную задержку и используется для того, чтобы пользователь мог визуально отследить очередность переключения светодиодов при различных настройках параметров прерываний. Исходный уровень приоритета для прерывания Таймера 1 устанавливается равным 5, а уро вень приоритета для прерывания INT3 — равным 3. Поскольку приоритет INT3 ниже, чем приоритет Таймера 1, то, несмотря на установку флага прерывания _INT3IF в функцииобработчике _T1Interrupt, обработчик INT3 не сможет выполниться, пока не завершится обработка прерывания Таймера 1. Визуально светодиод на выводе 7 порта А будет переключаться первым, и только затем, с определенной задержкой, переключится светодиод на выводе 0. Если теперь изменить приоритеты прерываний так, чтобы INT3 имело высший приоритет, например 6, то картина изменится. Первым будет пере ключаться светодиод на выводе 0 порта А, поскольку вначале будет выполнять ся обработчик вложенного прерывания INT3, и только затем продолжит вы полнение обработчик прерывания Таймера 1. Еще несколько слов о программе. Параметры Таймера 1 настраиваются с по мощью операторов PR1 = PREG; TMR1 = 0; T1CON = 0x8030;
96
Глава 5. Программирование прерываний
В регистр периода PR1 Таймера 1 записывается значение, соответствующее времени срабатывания Таймера 1 и равное 1 с. Здесь учитывается то, что так товая частота микроконтроллера, равная 8 МГц, делится на 2 и на коэффици ент деления предделителя, равный 256. В результате получаем необходимое значение для регистра периода (оно равно константе PREG). Таймер 1 запус кается при установке бита 15 (TON) регистра управления T1CON и битов 5 и 4 предделителя (отношение 1:256). Настройки прерывания Таймера 1 выпол няются по стандартной схеме с помощью операторов IFS0bits.T1IF _T1IP = 5; _T1IE = 1;
=
Глава 5. Программирование прерываний
97
Рассмотрим практический пример, иллюстрирующий запрещение/разреше ние прерываний. Аппаратная часть проекта показана на Рис. 5.3.
0;
Здесь уровень приоритета прерывания Таймера 1 устанавливается равным 5. Обработку вложенных прерываний можно запретить, если установить бит15 (NSTDIS) регистра управления INTCON1. В этом случае пользовательские ус тановки приоритетов будут игнорироваться. Если, например, в исходный текст нашей программы включить оператор INTCON1bits.NSTDIS
=
1;
то все прерывания будут работать с одинаковым приоритетом, а вложенные прерывания работать не будут. В нашем случае установка флага прерывания _INT3IF в обработчике Таймера 1 не вызовет прерывания его выполнения, т. е. обработчик прерывания INT3 всегда будет выполняться после обработчика Таймера 1. В ряде случаев возникает необходимость запретить на некоторое время пользовательские прерывания, например при выполнении критических участ ков программного кода. Можно применить один из двух способов. Простей ший вариант — использовать инструкцию disi микроконтроллера, которая позволяет на определенный интервал времени запретить прерывания с приори тетами 1…6. Прерывания с приоритетом 7 и выше с помощью этой инструкции запретить нельзя. Второй способ, более эффективный, позволяет запретить все прерывания без какихлибо ограничений по времени. Для этого можно использовать следую щую последовательность операций: • сохранить регистр состояния микроконтроллера в стеке с помощью инст рукции push SR; • записать в биты приоритета IPL2…IPL0 процессора (биты 7…5 регистра состояния процессора SR) значение , что позволит установить уро вень 7 приоритета процессора и запретить все пользовательские прерыва ния. Для установки этих битов можно выполнить, например, инструкцию ior (логическое ИЛИ) над содержимым младшего байта (SRL) регистра состояния SR и значения 0xE0. Если критический участок программного кода пройден, можно восстановить состояние процессора и разрешить прерывания инструкцией pop SR.
Рис. 5.3. Аппаратная часть проекта
Работа схемы во многом напоминает функционирование аппаратной части из предыдущего проекта, но имеется и существенное отличие: при нажатии на кнопку разблокируется работа прерываний Таймера 1 и INT3. Прерывание INT3 вызывается из обработчика _T1Interrupt. При запуске программы все прерывания блокируются, поэтому никакого изменения состояния светодиодов наблюдаться не будет. При нажатии на кнопку все пользовательские прерыва ния разблокируются, и светодиоды начнут мигать. Исходный текст программы, написанной на языке Си, показан далее: #include
_CONFIG2(FCKSM_CSDCMD&OSCIOFNC_ON&POSCMOD_HS&FNOSC_PRI) #define #define #define
SYSCLK t1 1 PREG
8000000 SYSCLK/2/256*t1
void Delay(void) { long cnt = 100000; while (cnt != 0)cnt—; } void __attribute__ { _T1IF = 0; _INT3IF = 1;
((interrupt))
_T1Interrupt(void)
Глава 5. Программирование прерываний
98
Глава 5. Программирование прерываний
_RA7 = ~_RA7; Delay(); } void __attribute__ { _INT3IF = 0; _RA0 = ~_RA0; Delay(); }
((interrupt))
void main(void) { AD1PCFG = 0xffff; TRISB = 0xffff; TRISA = 0; TRISAbits.TRISA14 =
_INT3Interrupt(void)
= = =
asm
.
1;
// //
SR" mov #0xE0, w0" ior SR"); ïîìåñòèòü êðèòè÷åñêèé êîäà
while (_RB0 != asm("pop SR"); while(1);
.
Переменная current_cpu_ipl будет содержать текущее на момент обраще ния значение приоритета процессора. Установка уровня приоритета равным 7 выполняется макросом SET_AND_SAVE_CPU_IPL, а восстановление предыду щего уровня приоритета и разблокирование пользовательских прерываний осу ществляется макросом RESTORE_CPU_IPL.
ó÷àñòîê
1);
}
Большую часть этого программного кода мы уже анализировали, поэтому остановлюсь только на сделанных изменениях. Для запрещения/разрешения пользовательских прерываний используются две ассемблерные вставки. Группа команд push SR mov #0xE0, ior SR
.
current_cpu_ipl;
SET_AND_SAVE_CPU_IPL(current_cpu_ipl, 7); // Ñþäà ìîæíî ïîìåñòèòü êðèòè÷åñêèé ó÷àñòîê // ïðîãðàììíîãî êîäà while (_RB0 != 1); RESTORE_CPU_IPL(current_cpu_ipl);
0; 6; 1;
("push "\n "\n Ñþäà ìîæíî ïðîãðàììíîãî
состояния SR (pop SR). Это произойдет при нажатии на кнопку (см. Рис. 5.3), инициирующую подачу сигнала ВЫСОКОГО уровня на вывод 0 порта В. После этого можно будет наблюдать выполнение обработчиков прерываний по смене состояния светодиодов. Вместо ассемблерной вставки можно воспользоваться макросами, специаль но предусмотренными для запрещения/разрешения всех прерываний. Тогда ту часть программного кода, в которой используются команды ассемблера, можно переписать следующим образом: int
PR1 = PREG; TMR1 = 0; _T1IF = 0; _T1IP = 5; _T1IE = 1; T1CON = 0x8030; _INT3IF _INT3IP _INT3IE
99
w0
выполняет сохранение в стеке содержимого регистра состояния (push SR), ус танавливает уровень приоритета 7 для процессора, запрещая тем самым пользовательские прерывания (mov #0xE0, w0 и ior SR). Таким образом, при запуске программы никакие прерывания обрабатываться не будут. Для разре шения прерываний нужно просто извлечь из стека старое содержимое регистра
101
ГЛАВА
6
ПРОГРАММИРОВАНИЕ ТАЙМЕРОВ
Микроконтроллеры семейства PIC24F, в зависимости от исполнения, могут иметь несколько 16битных таймеров, которые принято обозначать как Таймер 1, Таймер 2, Таймер 3 и т. д. Аппаратнопрограммная архитектура каждого 16бит ного таймера включает несколько регистров, доступных для чтения/записи. К ним относятся: • TMRx — 16битный регистрсчетчик (х = 1, 2, 3, …); • PRx — 16битный регистр периода; • TxCON — 16битный регистр управления Таймера х. Каждый модуль таймера может генерировать прерывание, поэтому ему на значены следующие программные ресурсы: • бит TxIE — флаг разрешения прерывания Таймера х; • бит TxIF — флаг состояния прерывания Таймера х; • биты TxIP — установка приоритета Таймера х. Для 16битных таймеров предусмотрено три основных режима (хотя не каждый таймер может работать во всех режимах): • режим «таймера», когда таймер синхронизируется внутренним или вне шним тактовым сигналом и инкрементируется до значения, установлен ного в регистре периода PRx; • режим запуска/остановки внешним сигналом (Gated Time Accumulation), при котором запуск таймера осуществляется перепадом 0—1 внешнего сигнала, а остановка осуществляется по перепаду 1—0 этого же источника; • асинхронный режим работы от внешнего источника тактового сигнала. В зависимости от режима работы 16битного таймера прерывание генериру ется или по превышению значения регистра периода PRx (если таймер не работает в режиме внешнего запуска/останова), или по спадающему фронту внешнего сигнала запуска/останова. Вне зависимости от того, разрешено пре рывание таймера или нет, при возникновении любой из этих ситуаций будет установлен флаг прерывания TxIF, который должен сбрасываться программой. Если необходимо работать с прерываниями таймера, то соответствующий флаг разрешения прерывания TxIF должен быть установлен. Биты приоритетов TxIP
устанавливаются в соответствии с требованиями к приложению (по умолчанию это значение равно 4). Кроме указанных режимов работы, существуют и определенные отличия функциональных возможностей 16битных таймеров, поэтому все таймеры разделены на три базовых типа: A, B и C. Таймер базового типа A, который присутствует во всех микроконтроллерах PIC24F, может работать в режиме «таймера» и внешнего запуска/останова, а к особенностям таймеров типа B и C следует отнести возможность их конфигурирования для работы в 32битном режиме. К таймеру типа А относится Таймер 1, функциональная схема кото рого показана на Рис. 6.1.
Рис. 6.1. Функциональная схема 16битного таймера (базовый тип А)
Из Рис. 6.1 довольно легко понять работу таймера в зависимости от устано вок отдельных битов регистра управления TxCON. Рассмотрим более подробно, какие биты регистра управления используются при различных режимах работы таймера типа A. Сразу оговорюсь: функциональная схема с элементами циф ровой логики, показанная на Рис. 6.1, далеко не полностью соответствует принципиальной схеме модуля Таймера 1, скорее это достаточно хорошее приближение к реальной схеме. Тем не менее, такая функциональная схема в точности отображает поведение таймера, поэтому мы рассмотрим ее более
102
Глава 6. Программирование таймеров
подробно — это значительно облегчит понимание принципов программирова ния таймера. Предположим, что Таймер 1 типа А работает в режиме «таймера» с коэффици ентом деления тактовой частоты 1:8. В этом случае бит TGATE = 0, TCS = 0 и мультиплексор MUX 1 пропускает на свой выход тактовый сигнал TCY, частота которого равна половине частоты тактового генератора микроконтроллера. Для дальнейшего прохождения сигнала бит TON регистра управления должен быть установлен в 1. В этом случае сигнал попадает на предделитель, коэффициент деления которого определяется значениями пары битов TCKPS1:TCKPS0. Если, например, требуется поделить частоту сигнала TCY на 8, то TCKPS1:TCKPS0 = 01. Поскольку бит TCS = 0, то значение бита синхронизации от внешнего ис точника TSYNC игнорируется, и сигнал через мультиплексор приходит на схему инкремента регистра таймера TMR1. Содержимое регистра таймера TMR1 постоянно сравнивается с содержимым регистра периода PR1, и если значения равны, то регистр таймера вместо инкрементирования сбрасывается в 0, а на выходе компаратора формируется сигнал, который, проходя через мультиплексор MUX 2, вызывает установку флага прерывания T1IF. Второй режим, который мы рассмотрим, — режим запуска/остановки Тай мера 1 внешним сигналом с вывода T1CK. При работе в этом режиме таймер, как и в только что рассмотренном режиме «таймера», синхронизируется им пульсами тактового сигнала TCY, но запуск и остановка таймера выполняются внешним сигналом: запуск таймера осуществляется по фронту (перепад 0—1) сигнала, а остановка — по спаду (перепад 1—0). Для работы в этом режиме бит TGATE должен быть установлен в 1, а бит TCS должен быть равен 0 (работа от внутреннего источника тактового сигнала). При этой комбинации сигнал TCY проходит логику совпадения и через муль типлексор MUX 1 поступает на предделитель и далее с коэффициентом деле ния 1:8 — на логику управления регистром таймера TMR1. В данном режиме флаг прерывания устанавливается по спаду внешнего сигнала, который пере ключает Dтриггер T1, работа которого разрешается ВЫСОКИМ уровнем вследствие установки бита TGATE. Сигнал с выхода Q триггера T1 инициирует установку флага прерывания T1IF. В этом режиме установка флага прерывания вызывается не переполнением Таймера 2, а только перепадом 1—0 внешнего сигнала. Третий режим — работа от внешнего источника тактового сигнала. В каче стве источника может быть использован генератор (выделен пунктирной лини ей), к выводам SOSC0 и SOSC1 которого подключается кварцевый резонатор. Как альтернатива, к выводу SOSC0 можно подключить внешний тактовый генератор. В любом случае биты конфигурации микроконтроллера должны быть установлены соответствующим образом. В этом режиме бит TCS должен быть установлен в 1, тогда внешний тактовый сигнал проходит через мульти плексор MUX 1 и предделитель на логику управления регистром таймера. Если дополнительно установлен бит синхронизации TSYNC, то внешний сигнал будет синхронизирован внутренним тактовым сигналом. Логика формирования сигнала прерывания будет работать так же, как и в режиме «таймера».
Глава 6. Программирование таймеров
103
Назначение битов регистра управления T1CON Таймера 1 (тип А) приводит ся в Табл. 6.1. Таблица 6.1. Назначение битов регистра T1CON Позиция бита
Обозначение Описание
15
TON
14 13
12–7 6
5–4
3 2
1
0
Запуск/остановка таймера: 1 – запуск таймера; 0 – остановка таймера Читается как 0 TSIDL Режим остановки в режиме «холостого хода» микроконтроллера: 1 – работа таймера прекращается в режиме «холостого хода»; 0 – таймер продолжает работать Читается как 0 TGATE Разрешение запуска/остановки таймера внешним сигна" лом. При установленном бите TCS значение этого бита игнорируется. Если TCS = 0, то установка бита в 1 разрешает запуск/остановку таймера, а сброс в 0 запрещает работу в этом режиме TCKPS1–TCKPS0 Биты установки предделителя: 11 – соотношение 1:256 10 – соотношение 1:64 01 – соотношение 1:8 00 – соотношение 1:1 Читается как 0 TSYNC Если TCS = 1, то: 1 – выполняется синхронизация внешнего сигнала; 0 – не выполняется синхронизация внешнего сигнала. Если TCS = 0 (используется внутренний источник тактовой частоты), то бит игнорируется и читается как 0 TCS Выбор источника тактовой частоты: 1 – используется сигнал на выводе T1CK; 0 – используется внутренний генератор тактовой частоты (FOSC/2) Читается как 0
Кроме Таймера 1, который относится к типу А, в большинстве микрокон троллеров PIC24F есть Таймер 2 и Таймер 4, которые относятся к типу В. Таймер типа B позволяет (вместе с таймером типа С) организовать 32битный таймер. Для этого в таймерах типа В предусмотрен бит Т32 (бит 3 регистра TxCON), который, будучи установлен, разрешает функционирование в 32бит ном режиме. В большинстве микроконтроллеров PIC24F имеются также и таймеры типа С (Таймер 3 и Таймер 5). Таймер типа С имеет следующие специальные воз можности: • вместе с таймером типа В может образовывать 32битный таймер; • как минимум один таймер типа C может управлять процессом преобра зования АЦП.
104
Глава 6. Программирование таймеров
Формирование 32битного таймера выполняется с помощью либо Таймера 2 типа B и Таймера 3 типа C, либо Таймера 4 типа B и Таймера 5 типа C. За исключением бита T32 в регистре управления таймера типа B, все остальные биты таймеров типов В и С идентичны по назначению битам регистра управ ления таймера типа A. Остановимся на некоторых практических аспектах программирования тай меров микроконтроллеров PIC24F.
6.1. Практическое использование 16$битных таймеров
6.1. Практическое использование 16битных таймеров #define #define
t1 PREG
0.5 SYSCLK/2*t1/256
#define #define
DELAY PORTB_0
20 PORTBbits.RB0
105
void main(void) { int cnt = 0; AD1PCFG = 0xffff; TRISB = 0xfffe; PR1 = PREG; TMR1 = 0; T1CON = 0x8030;
Рассмотрим несколько практических примеров программирования таймеров микроконтроллеров PIC24F. В нашем первом проекте мы будем переключать светодиод, подключенный к выводу 0 порта B, каждые 10 секунд, используя метод опроса Таймера 1. В этом проекте тактовая частота микроконтроллера выбрана равной 8 МГц. Аппаратная часть проекта показана на Рис. 6.2.
while {
(1) if
(_T1IF
==
1)
{ _T1IF
=
0;
if (cnt == DELAY) { cnt = 0; PORTB_0 = ~PORTB_0; } cnt++; } } }
Для установки временных интервалов в программе нам нужно просчитать некоторые константы. Мы приняли, что светодиод должен переключаться каждые 10 секунд. Если выбрать интервал срабатывания таймера t1 равным 0.5 с, то программе понадобится 20 циклов опроса, прежде чем светодиод переключится. Таким образом, мы определяем в программе две константы: #define #define
Рис. 6.2. Аппаратная часть проекта
Программную часть нашего проекта создадим с помощью среды MPLAB IDE. В созданный проект включим исходный текст программы на языке Си, приведенный далее: #include
_CONFIG2(FCKSM_CSDCMD&OSCIOFNC_ON&POSCMOD_HS&FNOSC_PRI) #define
SYSCLK
8000000
t1 DELAY
0.5 20
Здесь t1 определяет время срабатывания Таймера 1, а DELAY определяет общий интервал задержки, равный 20 * 0.5 = 10 с. Далее нам нужно определить число, которое следует записать в регистр периода Таймера 1, чтобы получить интервал перезагрузки, равный 0.1 с (константа t1). Значение регистра периода (обозначим его PREG) по известному интервалу времени t1 можно вычислить из формулы: PREG = (t1 ґ Fosc/2)/Prescaler, где PREG — значение регистра периода; t1 — заданный интервал времени; Fosc — тактовая частота (во всех наших примерах Fosc = 8 МГц); Prescaler — значение предделителя (выберем значение, равное 256).
Глава 6. Программирование таймеров
106
6.1. Практическое использование 16битных таймеров
После того, как значение регистра периода определено, мы можем запустить таймер: PR1 = PREG; TMR1 = 0; T1CON = 0x8030;
=
while (TMR1 < DELAY); TMR1 = 0; PORTB_0 = ~PORTB_0; }
0xffff;
переводит порт B в режим ввода/вывода цифровых сигналов, а команда
Здесь мы указываем значение интервала времени прямо в переменной t1 (2), а для константы DELAY устанавливаем значение 31250, что соответствует зна чению регистра периода PR1 для 2секундного интервала. В этом случае ожи дание реализуется в цикле while
(TMR1
=
_CONFIG2(FCKSM_CSDCMD&OSCIOFNC_ON&POSCMOD_HS&FNOSC_PRI) #define #define #define
SYSCLK t1 PREG
#define #define
DELAY 31250 PORTB_0 PORTBbits.RB0
void {
DELAY)
0xfffe;
переключает вывод 0 на выход. Данная программа позволяет работать с относительно большими интервала ми времени. Если требуются интервалы времени порядка единиц секунд, то предыдущий листинг исходного текста можно значительно упростить. Напри мер, если требуется временная задержка 2 с, то можно использовать такую программу: #include
1; dat &= 0xfff; return dat;
13;
cnt++)
}
void main() { unsigned int float res; int temp;
binData;
TRISA = 0x0f01; while (1) { if (_INT3IF == 1) { _INT3IF = 0; binData = getBinary(); res = 5.0 / 4096.0 * binData; temp = res * 100 – 273.16; } } }
Преобразование аналогового сигнала выполняется при НИЗКОМ уровне сигнала . После фазы выборки, которая завершается в момент второго спада на линии CLK, начинается фаза преобразования. Данные на линии Dout ста новятся действительными по спаду синхроимпульсов CLK, а по фронту CLK их можно считывать в микроконтроллер. По окончании преобразования сле дует установить сигнал в ВЫСОКИЙ уровень. Временная диаграмма одного преобразования формируется в функции getBinary. Эта временная диаграмма является типичной для большинства аналого цифровых преобразователей последовательного приближения, поэтому, по няв принцип работы какоголибо одного устройства, можно успешно приме нять и другие микросхемы этого типа. Само преобразование запускается при перепаде сигнала на входе прерывания INT3 из НИЗКОГО уровня в ВЫСО КИЙ. В этой программе используется тот факт, что при возникновении за проса на прерывание флаг прерывания _INT3IF будет установлен в любом случае, независимо от того, разрешено конкретное прерывание или нет. Двоичный результат преобразования помещается в переменную binData, а окончательный результат в формате вещественного числа с плавающей точ кой помещается в переменную res. На базе этого проекта можно реализовать несложный измеритель темпера туры, в котором используется прецизионный аналоговый датчик температуры LM335. Аппаратная часть проекта представлена на Рис. 11.7. В этой схеме используется прецизионный датчик температуры LM335, вы ходное напряжение которого пропорционально температуре измеряемого объекта или среды с коэффициентом пропорциональности 10 мВ/К°. Напри мер, при температуре 0°С выходное напряжение датчика будет равно 2.73 В. Принципиальная схема, думаю, в объяснениях не нуждается. Что же касается программной части, то практически весь код позаимствован из предыдущей программы, поэтому я остановлюсь только на изменениях. Их два: в основную
220
Глава 11. Обработка аналоговых сигналов в микроконтроллерах PIC24F
ГЛАВА
12
ГЕНЕРАЦИЯ АНАЛОГОВЫХ И ЦИФРОВЫХ СИГНАЛОВ
Рис. 11.7. Схема измерителя температуры
программу включена целочисленная переменная temp, в которой будет хра ниться значение температуры, а также добавлен оператор temp
=
res
*
100
–
273.16;
В качестве упражнения читатели могут попробовать реализовать такой изме ритель температуры на интегрированном АЦП микроконтроллера.
В микроконтроллерах PIC24F предусмотрена возможность генерации раз личных цифровых и аналоговых сигналов, которые можно использовать для управления внешними устройствами. На кристалле микроконтроллеров PIC24F имеется несколько модулей, выполняющих подобные функции: модуль анало говых компараторов, модуль формирования опорных напряжений аналоговых компараторов, а также модуль генерации цифровых сигналов. Модули, отно сящиеся к обработке аналоговых сигналов, в процессе функционирования оперируют только с аналоговыми напряжениями и являются, по сути, простей шими преобразователями «цифра–аналог–цифра». С помощью модуля генера ции цифровых сигналов формируются последовательности цифровых сигналов на основе временных параметров, задаваемых Таймером 2 или 3. Все перечис ленные периферийные модули очень полезны при разработке внешних анало говых и цифровых интерфейсов, создании различного рода преобразователей сигналов, в измерительных и управляющих схемах. Вначале рассмотрим модуль генерации цифровых сигналов.
12.1. Модуль генерации цифровых сигналов Модуль генерации цифровых сигналов содержит несколько каналов. Каждый из каналов функционирует следующим образом: в регистры данных (один или оба, в зависимости от выбранного режима работы) заносится значение интервала времени, которое затем будет сравниваться с текущим значением, находящимся в регистре одного из таймеров (Таймера 2 или Таймера 3). При совпадении значений в регистрах данных и регистре таймера на опре деленных выходах микроконтроллера будет генерироваться либо одиночный цифровой импульс, либо их последовательность. Параметры импульсов опре деляются содержимым регистров данных и настройками Таймера 2 или Тай мера 3. Характеристики выходных сигналов модуля генерации цифровых сиг налов могут варьироваться в очень широком диапазоне, что дает возможность получить импульсные сигналы с различной скважностью и частотой. Такие импульсные последовательности легко преобразовать в аналоговые гармони
222
Глава 12. Генерация аналоговых и цифровых сигналов
ческие (синус/косинус) сигналы и их комбинации с помощью несложных аналоговых фильтров. Подобная методика используется при синтезе анало говых сигналов звуковых частот. Как и все периферийные модули микроконт роллера PIC24F, модуль генерации цифровых сигналов представляет собой ав тономное устройство, которое может настраиваться и функционировать независимо от других модулей. Его можно настроить для работы с использо ванием прерывания, что позволит разгрузить процессор. Функциональная схема одного канала модуля показана на Рис. 12.1.
12.1. Модуль генерации цифровых сигналов
периода Таймера 2 или Таймера 3. Таким образом, содержимое регистра OCxR определяет интервал задержки между очередной перезагрузкой таймера и из менением уровня сигнала на выводе OCx. В режимах двойного сравнения дополнительно задействуется регистр OCxRS, содержимое которого определяет момент второго перепада импульсного сигна ла. Фактически содержимое регистров OCxR и OCxRS будет определять дли тельность импульсного сигнала в этих режимах. Выбор режима (однократного или двойного сравнения), а также дополнитель ные характеристики импульсных сигналов определяются битами OCM ре гистра управления модуля OCxCON. Бит 3 (OCTSEL) этого же регистра опре деляет источник базового сигнала (0 — Таймер 2, 1 — Таймер 3). Количество каналов модуля генератора цифровых сигналов определяется моделью микро контроллера, поэтому для получения детальной информации нужно обращать ся к технической документации на данный микроконтроллер. Конфигурирова ние прерываний ничем не отличается от настройки прерываний для других модулей, только здесь нужно использовать соответствующие флаги разрешения и приоритета прерываний. Далее рассмотрим практический пример программирования модуля генера ции цифровых сигналов для микроконтроллера PIC24FJ128GA010. Отладку и анализ результатов выполним в среде программирования MPLAB IDE с помо щью симулятора MPLAB SIM. Разработаем генератор импульсов, выход кото рого будет переключаться каждые 3 с, для чего выберем режим однократного сравнения с использованием только регистра OC1R. Выходной сигнал будет генерироваться на выходе OC1 (RD0) микроконтроллера. Создадим с помощью мастера проектов MPLAB IDE новый проект и вклю чим в него файл со следующим исходным текстом: #include #include #define #define #define
Каждый канал модуля содержит два регистра данных – OCxR и OCxRS. В одних режимах работы используется только регистр OCxR, а в других режимах — оба регистра. Например, в режимах однократного сравнения в регистр OCxR по мещается значение, которое будет сравниваться с содержимым регистра одного из таймеров. При совпадении значений будет генерироваться единичный им пульс или последовательность импульсов. В этом случае длительность такого сигнала будет определяться разностью содержимого регистра OCxR и регистра
<stdio.h> SYSCLK 8000000 t1 3 PREG2 SYSCLK/2/256*t1
unsigned
Рис. 12.1. Функциональная схема одного канала модуля генерации цифровых сигналов
223
int
cnt
=
0;
void __attribute__ ((__interrupt__)) _OC1Interrupt(void) { _OC1IF = 0; printf("OC1 toggled %d times\n", ++cnt); } void {
main(void)
PR2 = OC1CON OC1CON
PREG2; = 0x0000; = 0x0003;
224 OC1R
Глава 12. Генерация аналоговых и цифровых сигналов =
PR2;
IFS0bits.OC1IF IEC0bits.OC1IE
= =
0; 1;
TMR2 = 0; T2CON = 0x8030; while(1) { } }
Анализ исходного текста программы начнем с переменных и констант, объявленных в программе. Константа SYSCLK содержит значение тактовой частоты микроконтроллера (8 МГц). Константа t1 равна 3 и обозначает интер вал времени срабатывания таймера, а константа PREG2 определяет значение, которое будет загружено в регистр периода Таймера 2, который мы намерены использовать в этом проекте. Эта константа соответствует времени срабатыва ния Таймера 2, равному 3 с. В программе объявлена также целочисленная переменная cnt, которая будет равна количеству перепадов импульсного сиг нала на выходе OC1. В программе используется прерывание первого канала модуля с функцией обработчиком _OC1Interrupt. Эта функция сбрасывает флаг прерывания и выводит содержимое счетчика cnt на «виртуальную» консоль функцией printf. В основной программе мы определяем две настройки: канала 1 модуля гене рации цифровых сигналов и Таймера 2. Конфигурирование канала 1 выпол няется операторами OC1CON = 0x0000; OC1CON = 0x0003; OC1R = PR2;
12.1. Модуль генерации цифровых сигналов
выполняют инициализацию прерывания канала 1 модуля, для чего вначале сбрасывается флаг прерывания OC1IF, а затем устанавливается флаг разреше ния прерывания OC1IE. Для отладки нашей программы скомпилируем ее в режиме Debug, затем выберем отладчик MPLAB SIM и выполним некоторые дополнительные дей ствия. В окне настройки отладчика установим значение тактовой частоты устройства, равное 8 МГц (Рис. 12.2).
Рис. 12.2. Установка тактовой частоты
Кроме того, установим опцию вывода данных в «виртуальное» окно отлад чика, для чего выберем закладку UART1 IO и установим опции так, как пока зано на Рис. 12.3.
Первый оператор сбрасывает текущие настройки канала 1 модуля (эту про цедуру желательно выполнять каждый раз при перенастройке каналов модуля генерации цифровых сигналов). В регистр управления OC1CON заносится значение 3, т. е. выбирается режим переключения выхода OC1 при каждом срабатывании Таймера 2, который выбран в качестве базового для этой про граммы. Переключение выхода OC1 должно выполняться всякий раз при пе резагрузке Таймера 2, поэтому в регистр данных OC1R помещаем значение регистра периода PR2 Таймера 2. Настройка Таймера 2 выполняется стандартным образом. Вначале в регистр периода PR2 помещается значение перезагрузки (оно определяется константой PREG2), регистр Таймера 2 TMR2 обнуляется, а в регистр управления T2CON заносится значение 0x8030. Коэффициент деления частоты тактового сигнала Таймера 2 здесь выбран равным 256. Операторы IFS0bits.OC1IF IEC0bits.OC1IE
= =
0; 1;
225
Рис. 12.3. Установка опций вывода в «виртуальное» окно
226
Глава 12. Генерация аналоговых и цифровых сигналов
12.1. Модуль генерации цифровых сигналов
227
Напомню, что установка опции «виртуального» вывода позволит выводить данные программы в окно Output при отладке. И последняя операция — в настройках проекта нужно выбрать закладку MPLAB LINK30 и выделить па мять для «кучи», указав объем выделяемой памяти в окне Heap size (Рис. 12.4). Эта настройка необходима для использования библиотечных функций ANSI C.
Рис. 12.5. Окно просмотра переменных
Рис. 12.4. Выделение памяти для «кучи»
Для отладки приложения в окно просмотра переменных нужно вывести пе ременные TMR2, PORTD (бит 0 соответствует выводу OC1) и cnt (Рис. 12.5). После выполнения этих настроек можно запустить программу в режиме Animate и наблюдать за изменениями значений переменных в окне Watch. Функционирование канала 1 модуля генерации цифровых сигналов в режи ме двойного сравнения я покажу на следующем примере. Для этого разрабо таем проект, аппаратная часть которого показана на Рис. 12.6. Схема работает следующим образом: на выводе OC1 микроконтроллера каж дые 3 с появляется короткий импульс положительной полярности, который пе реключает защелку DD1 в противоположное состояние. В результате светодиод D1 будет периодически включаться/выключаться. Длительность импульса будет определяться программными настройками канала 1. Микроконтроллер работает на тактовой частоте 8 МГц (частота выполнения команд равна 4 МГц).
Рис. 12.6. Аппаратная часть проекта
Программная часть проекта разработана в среде MPLAB IDE и содержит файл программы со следующим исходным текстом: #include
_CONFIG2(FCKSM_CSDCMD&OSCIOFNC_ON&POSCMOD_HS&FNOSC_PRI) #define #define #define
SYSCLK 8000000 t1 3 PREG2 SYSCLK/2/256*t1
void __attribute__ { _OC1IF = 0;
((__interrupt__))
_OC1Interrupt(void)
228
Глава 12. Генерация аналоговых и цифровых сигналов
} void {
main(void)
OC1CON = 0x0000; OC1CON = 0x0005; OC1R = 3000; OC1RS = 10000; _OC1IF _OC1IE
= =
0; 1;
PR2 = PREG2; TMR2 = 0; T2CON = 0x8030; while(1) { }
12.2. Аналоговые компараторы в микропроцессорах PIC24F
229
фронта импульса на выходе OC1. Содержимое второго регистра данных OC1RS определяет момент формирования спадающего фронта импульса. Оба значения в данном примере выбраны произвольно, поэтому читатели могут при желании поэкспериментировать с этой программой, записывая в регистры данных раз личные значения и наблюдая результат. Функцияобработчик прерывания канала 1 модуля _OC1Interrupt используется для сброса флага прерывания _OC1IF, установленного после перепада 1—0 импульса. Из прямоугольной последовательности импульсов можно синтезировать не прерывный аналоговый сигнал требуемой частоты. Более того, поскольку мик роконтроллеры PIC24F включают, как правило, несколько каналов в одном модуле генерации цифровых сигналов, то можно получить непрерывный ана логовый сигнал, используя микширование различных сигналов в смесителях. В простейшем случае для получения, например, синусоидального сигнала ча стотой 1000 Гц на выходе OC1 можно установить полосовой фильтр со средней частотой 1000 Гц (Рис. 12.7).
}
Здесь используются те же константы, что и в предыдущей программе, по этому останавливаться на них мы не будем. В качестве базового таймера для канала 1 модуля генерации цифровых сигналов используется Таймер 2. На стройки Таймера 2 соответствуют интервалу его перезагрузки, равному 3 с. В течение этого интервала времени на выводе OC1 будет генерироваться им пульс, длительность которого определяется разностью содержимого регистров данных OC1RS и OC1R. Регистр OC1R определяет смещение фронта импульса относительно момента перезагрузки Таймера 1. Как только содержимое регистра таймера TMR2 превысит содержимое OC1R, сигнал на выводе OC1 перейдет в состояние ВЫСОКОГО уровня. Этот уровень будет удерживаться до того момента, пока содержимое TMR2 не пре высит значение во втором регистре данных OC1RS. После этого сигнал на выводе OC1 перейдет в состояние НИЗКОГО уровня. Таким образом, в каждом периоде перезагрузки Таймера 2 на выводе OC1 будет генерироваться импуль сный сигнал, положительный фронт которого будет переключать защелку DD1. Настройка режима двойного сравнения выполняется операторами OC1CON = 0x0000; OC1CON = 0x0005; OC1R = 3000; OC1RS = 10000;
Как обычно, перед настройкой нового режима канал 1 следует отключить, что и выполняет первый оператор. Затем в регистр управления канала 1 модуля записывается число 5, которое и определяет выбранный режим работы. Бит 3 регистра OC1CON сброшен в 0, поэтому в качестве базового источника будет использоваться Таймер 2. В регистр OC1R записывается значение смещения относительно начала пе резагрузки таймера, которое определяет момент формирования нарастающего
Рис. 12.7. Схема формирования синусоидального сигнала частотой 1000 Гц
В этой схеме используется аналоговый полосовой фильтр Баттерворта 2го по рядка с центральной частотой 1000 Гц и коэффициентом усиления сигнала, равным 1. Входной импульсный сигнал фильтра поступает с выхода OC1 мик роконтроллера PIC24FJ128GA010. Операционный усилитель для такого филь тра должен иметь высокую скорость нарастания входного сигнала (slew rate), чтобы избежать появления нелинейных искажений. Используя несколько таких полосовых фильтров для разных выходных сигналов и смеситель, можно по лучить непрерывный сигнал произвольной формы и частоты.
12.2. Аналоговые компараторы в микроконтроллерах PIC24F Модуль компараторов аналоговых сигналов и модуль формирования опор ного напряжения микроконтроллеров PIC24F часто используются при созда нии аналогоцифровых интерфейсов различных измерительных и управляю щих схем. Модуль формирования опорного напряжения обычно используется в качестве источника смещения (опорного напряжения) для модуля аналоговых
230
Глава 12. Генерация аналоговых и цифровых сигналов
компараторов, хотя его вполне успешно можно применить в качестве управ ляемого цифроаналогового преобразователя. Функциональная схема модуля формирования опорного напряжения пока зана на Рис. 12.8.
12.2. Аналоговые компараторы в микропроцессорах PIC24F
231
при этом шаг составляет CVRSRC/24 (здесь CVRSRC — выбранное напряжение питания модуля). При CVRR = 0 выходное напряжение модуля формирования опорного напряжения изменяется от 0.25CV до 0.75CVRSRC с шагом CVRSRC/32. Биты 3:0 (CVR3:CVR0) регистра управления CVRCON определяют выходное напряжение модуля. При этом значение выходного напряжения определяется выбранным с помощью бита CVRR рабочим диапазоном. Если CVRR = 1, то напряжение на выходе модуля CVREF определяется по формуле CVREF = (CVR/24) ґ CVRSRC. Если бит CVRR = 0, то выходное напряжение вычисляется следующим об разом: CVREF = 0.25CVRSRC + (CVR/32) ґ CVRSRC. Кроме этих битов, на функционирование модуля формирования опорного напряжения оказывает влияние бит 6 (CVROE) регистра CVRCON. Если он установлен, то выходное напряжение появляется на выводе CVREF микрокон троллера, если сброшен — выходной каскад вывода CVREF отключается от схем формирования. Далее рассмотрим пример применения модуля формирования опорного напряжения в простой схеме контроля температуры на микроконтроллере PIC24FJ128GA010. Аппаратная часть проекта показана на Рис. 12.9.
Рис. 12.8. Модуль формирования опорного напряжения
Вкратце рассмотрим работу этого модуля. На схеме обозначены биты реги стра управления CVRCON данного модуля, соответствующие тем или иным установкам. Бит 4 (CVRSS) регистра CVRCON определяет источник входного напряжения для модуля формирования опорного напряжения. Если бит уста новлен, то используется внешний источник напряжения, если же CVRSS = 0, то используется напряжение питания микроконтроллера. Бит 7 (CVREN) включает (1) или отключает (0) модуль. Бит 5 (CVRR) оп ределяет диапазон изменения и шаг выходного напряжения модуля. Если CVRR = 1, то выходное напряжение изменяется от 0 до значения 0.75CVRSRC,
Рис. 12.9. Аппаратная часть проекта
В этой схеме сигнал с датчика температуры LM335 подается на неиверти рующий вход операционного усилителя DA1, который здесь работает в каче стве компаратора. На инвертирующий вход DA1 подается напряжение смещения с выхода модуля формирования опорного напряжения CVREF, соответствую щее напряжению на выходе датчика температуры при температуре окружаю щей среды приблизительно 25°С. Величина напряжения на выходе CVREF устанавливается программно. Так, для переключения компаратора при темпе
232
Глава 12. Генерация аналоговых и цифровых сигналов
ратуре, превышающей 25°С, напряжение CVREF должно быть равным пример но 2.98 В. При превышении температурой этого значения напряжение на выходе дат чика D1 станет выше напряжения на инвертирующем входе и на выходе ком паратора DA1 появится ВЫСОКИЙ уровень, что приведет к генерации преры вания INT3. Программная часть проекта разработана в среде MPLAB IDE и включает файл со следующим исходным текстом: #include
_CONFIG2(FCKSM_CSDCMD&OSCIOFNC_ON&POSCMOD_HS&FNOSC_PRI) #define #define #define
SYSCLK t1 PRG1
unsigned
long
8000000 3 SYSCLK/2/256*t1 del
void __attribute__ { _INT3IF = 0; _RA0 = 1; del = 0; TMR1 = 0; T1CON = 0x8030; }
=
0;
((__interrupt__))
void __attribute__ ((__interrupt__)) { _T1IF = 0; del++; if (del == 5) { _RA0 = 0; T1CON = 0x0; } }
_INT3Interrupt(void)
12.2. Аналоговые компараторы в микропроцессорах PIC24F CVRCONbits.CVREN = CVRCONbits.CVROE = CVRCON |= 0x000B;
_INT3IF _INT3IE _T1IF _T1IP _T1IE PR1
=
CVRCON
= = = = =
0; 1; 0; 1; 5;
PRG1; =
0;
1; 1;
while(1) { } }
В процессе функционирования программа обрабатывает два прерывания: внешнее прерывание INT3 и прерывание Таймера 1. Прерывание INT3 вызы вается переходом сигнала на выходе компаратора DA1 из НИЗКОГО уровня в ВЫСОКИЙ. Функцияобработчик прерывания _INT3Interrupt включает светодиод на выводе 0 порта А и запускает Таймер 1, который предназначен для отсчета времени (15 с) нахождения светодиода во включенном состоянии. По прошествии этого интервала светодиод выключается, а Таймер 1 отключа ется. Формирование задержки и отключение Таймера 1 выполняется в обра ботчике прерывания _T1Interrupt Таймера 1. Временные параметры рассчи таны для тактовой частоты микроконтроллера, равной 8 МГц. Конфигурирование модуля формирования опорного напряжения выполняет ся в основной программе. Оператор CVRCONbits.CVREN
=
1;
включает модуль (см. Рис. 12.8), а оператор CVRCONbits.CVROE
_T1Interrupt(void)
=
1;
подключает выход модуля к выводу CVREF микроконтроллера. Кроме того, по умолчанию, в качестве источника питания модуля используется источник пи тания устройства (бит CVRSS равен 0) и выбирается диапазон выходных на пряжений с начальным значением 0.25CVRSRC (бит CVRR = 0). Чтобы при таких установках на выходе CVREF появилось напряжение порядка 2.98 В, необходимо в младшие 4 бита регистра управления CVRCON записать код, соответствующий аналоговому напряжению 2.98 – 1.25 = 1.72 В. Это соответ ствует десятичному значению 11 или шестнадцатеричному 0x000B. Это значение следует записать в регистр CVRCON, что выполняется с помощью оператора CVRCON
void main(void) { TRISA = 0xfffe; _RA0 = 0;
233
|=
0x000B;
Инициализация прерывания INT3 выполняется операторами _INT3IF _INT3IE
= =
0; 1;
а инициализация прерывания Таймера 1 — с помощью операторов _T1IF _T1IP _T1IE
= = =
0; 1; 5;
Запуск Таймера 1 осуществляется в функцииобработчике прерывания INT3 обычным способом с использованием операторов TMR1 = 0; T1CON = 0x8030;
234
Глава 12. Генерация аналоговых и цифровых сигналов
Загрузку регистра периода Таймера 1 требуемым значением мы выполняем в основной программе. Перейдем к анализу работы модуля аналоговых компа раторов. В микроконтроллере PIC24FJ128GA010 реализовано два канала ана логовых компараторов (Рис. 12.10).
Рис. 12.10. Функциональная схема двухканального модуля аналоговых компараторов
Оба канала модуля содержат аппаратно реализованные компараторы (C1 и C2), которые настраиваются с помощью одного регистра управления CMCON. Настройка каждого из компараторов заключается в выборе нескольких опций, которые устанавливаются с помощью соответствующих битов регистра управ ления и состояния CMCON. Вот назначение отдельных битов этого регистра: • биты C1EVT и C2EVT (12, 13) — устанавливаются при изменении состоя ния (переключении) компаратора C1 или C2 соответственно. Биты дос тупны для чтения и могут быть сброшены программно; • биты C1EN и C2EN (10, 11) — установка этих битов разрешает работу компараторов C1 или C2 соответственно, сброс бита запрещает работу соответствующего канала модуля; • биты C1OUTEN и C2OUTEN (8, 9) — установка этих битов разрешает прохождение выходных сигналов компараторов C1 и C2 на соответствую щие выводы микроконтроллера; • биты C1OUT и C2OUT (6, 7) — доступны для чтения и отражают состо яние выходов компараторов C1 и C2 соответственно. Значение этих битов определяется установками битов C1INV и C2INV; • биты C1INV и C2INV (4, 5) — установка этих битов приводит к инверсии сигнала на выходах компараторов C1 и C2 соответственно. Если биты сброшены в 0, то при условии VIN+ > VIN на выходе компараторов будет
12.2. Аналоговые компараторы в микропроцессорах PIC24F
235
ВЫСОКИЙ уровень. Если биты установлены в 1, то при этих же условиях на выходе компараторов будет НИЗКИЙ уровень; • биты C2POS и C2NEG (2, 3) — определяют источники входных сигналов для компаратора C2. Если C2POS = 1, то вход VIN+ компаратора С2 под ключается к выводу C2IN+, если же C2POS = 0, то вход VIN+ подключается к выходу модуля формирования опорного напряжения CVREF. Если C2NEG = 1, то вход VIN– компаратора C2 подключается к выводу C2IN+, если же C2NEG = 0, то вход VIN– компаратора С2 подключается к выводу C2IN– микроконтроллера; • биты C1POS и C1NEG (0,1) — определяют источники входных сигналов для компаратора C1. Если C1POS = 1, то вход VIN+ компаратора С1 под ключается к выводу C1IN+, если же C1POS = 0, то вход VIN+ подключается к выходу модуля формирования опорного напряжения CVREF. Если C1NEG = 1, то вход VIN– компаратора C1 подключается к выводу C1IN+, если же C1NEG = 0, то вход VIN– компаратора С1 подключается к выводу C1IN– микроконтроллера. Для определения момента переключения компараторов и выполнения соот ветствующих действий можно задействовать прерывание компаратора, по скольку при изменении состояния выходного сигнала любого из компараторов устанавливается флаг прерывания CMIF (бит 2 регистра IFS1 микроконтрол лера). Функцияобработчик прерывания компараторов может прочитать биты C1EVT и C2EVT, чтобы определить, какие именно изменения состояния про изошли. Даже если бит разрешения прерывания компараторов CMIE (бит 2 регистра IEC1 микроконтроллера) сброшен, т. е. прерывание запрещено, флаг прерывания CMIF все равно будет устанавливаться при изменениях состояний компараторов. Рассмотрим применение канала 1 модуля аналоговых компараторов на при мере схемы сигнализации превышения температуры с датчиком LM335. Аппа ратная часть проекта показана на Рис. 12.11.
Рис. 12.11. Аппаратная часть проекта
236
Глава 12. Генерация аналоговых и цифровых сигналов
Здесь сигнал с датчика температуры D1 поступает на вход C1IN– модуля аналогового компаратора 1. При превышении температуры среды 54°С срабо тает внутренний компаратор C1 и на его выходе установится ВЫСОКИЙ уровень, который, поступая на вывод C1OUT микроконтроллера, включит светодиод. Программно вход C1IN– подключается ко входу VIN– компаратора C1, а на вход VIN+ подается напряжение CVREF с модуля формирования опорного на пряжения. При таких настройках для получения ВЫСОКОГО уровня на вы ходе компаратора C1 при превышении порогового значения необходимо ин вертировать выход установкой бита C1INV. Программная часть проекта разработана в среде MPLAB IDE. Исходный текст программы приводится далее: #include
12.2. Аналоговые компараторы в микропроцессорах PIC24F
237
использовать бит 0 порта А (вывод RA0 микроконтроллера PIC24FJ128GA010), к которому подключим светодиод, а схему подключения датчика оставим пре жней (Рис. 12.12).
_CONFIG2(FCKSM_CSDCMD&OSCIOFNC_ON&POSCMOD_HS&FNOSC_PRI)
void {
main(void)
CVRCON = 0; CVRCONbits.CVREN = CVRCONbits.CVROE = CVRCON |= 0x000D;
Рис. 12.12. Аппаратная часть проекта
1; 1;
Исходный текст программы на языке Си для данного проекта показан ниже: #include
_CONFIG2(FCKSM_CSDCMD&OSCIOFNC_ON&POSCMOD_HS&FNOSC_PRI) CMCON
=
0x0F10;
while(1) { } }
Программа очень проста. Поскольку на вход VIN+ компаратора 1 мы подаем опорное напряжение CVREF с выхода модуля формирования опорного напря жения, то первые четыре оператора программы выполняют соответствующие настройки. Для получения напряжения CVREF, равного приблизительно 3.278 В (это соответствует температуре датчика 54°С) при напряжении питания +5 В, в младшие 4 бита регистра управления CVRCON записывается значение 0xD: CVRCON
|=
0x000D;
Настройка компаратора 1 выполняется в регистре управления CMCON с по мощью оператора CMCON
=
0x0F10;
Обратите внимание, что для инвертирования выходного сигнала компарато ра С1 бит 4 регистра CMCON (C1INV) установлен. Для демонстрации работы прерывания модуля аналогового компаратора немно го модифицируем наш проект. Для сигнализации превышения температуры будем
void __attribute__ ((__interrupt__)) { _CMIF = 0; _C1EVT = 0; _RA0 = CMCONbits.C1OUT; } void main(void) { TRISA = 0xfffe; _RA0 = 0; CVRCON = 0; CVRCONbits.CVREN = CVRCONbits.CVROE = CVRCON |= 0x000D; CMCON _CMIF _CMIP _CMIE
= = = =
while(1) { } }
0x0F10; 0; 5; 1;
1; 1;
_CompInterrupt(void)
238
Глава 12. Генерация аналоговых и цифровых сигналов
Большая часть исходного текста программы нам уже знакома, поэтому рас смотрим только внесенные изменения. Поскольку компаратор 1 модуля теперь работает в режиме прерывания, то в нашей программе объявлена функция обработчик прерывания с предопределенным в файле p24fj128ga010.gld именем _CompInterrupt. Функция сбрасывает флаг прерывания _CMIF и флаг собы тия _C1EVT. В защелку 0 порта А записывается значение флага состояния C1OUT компаратора 1, при этом на вывод RA0 подается соответствующий уровень. Операторы _CMIF _CMIP _CMIE
= = =
0; 5; 1;
позволяют настроить параметры прерывания модуля аналоговых компараторов, при этом прерыванию присваивается приоритет 5. Последний оператор разре шает работу прерывания. Для функционирования вывода 0 порта А в режиме выхода защелка TRIS этого вывода сбрасывается в 0. Мы рассмотрели только часть функций, которые могут выполняться моду лями компараторов. Обширная информация по функциям этих модулей и их применению содержится в документации фирмы Microchip.
ЗАКЛЮЧЕНИЕ В этой книге автор старался охватить как можно более широкий круг во просов, касающихся программирования систем на базе 16битных микрокон троллеров PIC. Хотя довольно сложно проанализировать все аспекты проекти рования таких систем в одной книге, особенно с учетом бурного развития технологий, тем не менее, автор надеется, что анализ основных принципов разработки и программирования устройств с 16битными микроконтроллерами фирмы Microchip окажет несомненную пользу и при решении тех задач, ко торые не были рассмотрены. Хочется надеяться, что даже в таком объеме книга принесет пользу читателю и станет настольной для многих разработчиков, как опытных, так и начинающих.
Книги издательства «ДМК Пресс» можно заказать в торговоиздательском холдинге «АЛЬЯНСКНИГА» наложенным платежом, выслав открытку или письмо по почтовому адресу: 123242, Москва, а/я 20 или по электронному ад ресу: orders@alianskniga.ru. При оформлении заказа следует указать адрес (полностью), по которо му должны быть высланы книги; фамилию, имя и отчество получателя. Же лательно также указать свой телефон и электронный адрес. Эти книги вы можете заказать и в Internetмагазине: www.alianskniga.ru. Оптовые закупки: тел. (495) 2589194, 2589195; электронный адрес books@alianskniga.ru.
Магда Ю. С.
Микроконтроллеры PIC: архитектура и программирование
Главный редактор
Мовчан Д. А.
dm@dmk"press.ru
Перевод Верстка Дизайн обложки
Слинкин А. А. Чаннова А. А. Мовчан А. Г.
Подписано в печать 13.05.2008. Формат 70ґ100 1/16 . Гарнитура «Ньютон». Печать офсетная. Усл. печ. л. 45. Тираж 1000 экз. № Издательство ДМК Пресс Webсайт издательства: www.dmkpress.ru Internetмагазин: www.alianskniga.ru