|
||||
Меню:
Главная
Форум
Литература: Программирование и ремонт Импульсные блоки питания Неисправности и замена Радиоэлектронная аппаратура Микросхема в ТА Рубрикатор ТА Кабельные линии Обмотки и изоляция Радиоаппаратура Гибкие диски часть 2 часть 3 часть 4 часть 5 Ремонт компьютера часть 2 Аналитика: Монтаж Справочник Электроника Мощные высокочастотные транзисторы 200 микросхем Полупроводники ч.1 Часть 2 Алгоритмические проблемы 500 микросхем 500 микросхем Сортировка и поиск Монады Передача сигнала Электроника Прием сигнала Телевидиние Проектирование Эвм Оптимизация Автомобильная электроника Поляковтрансиверы Форт Тензодатчик Силовые полевые транзисторы Распределение частот Резисторные и термопарные Оберон Открытые системы шифрования Удк |
[5] 5 Особенности реализации 5.1 Поддержка прерываний Компилятор PICC полностью поддерживает прерывания контроллера. Таким образом вам не придется писать ни строчки ассемблерного кода при написании полноценных обработчиков прерываний. Для описания функции, которая и будет являться обработчиком, необходимо воспользоваться квалификатором interrupt. Эта функция будет напрямую вызвана в случае возникновения прерывания. Но компилятор оформит эту функцию специальным образом. Прежде всего будут сохранены и восстановлены все регистры, которые были задействованы в обработчике и, кроме того, для выхода из функции бкдет использоваться оператор retfie. Функция обработчик прерываний должна возвращать значение типа void и не должна иметь аргументов. Ее нельзя вызывать непосредственно из программы, но она может обращаться к другим функциям, с чем надо проявлять особую осторожность. Опуская поддержку прерываний в контроллерах базового класс, сразу переходим к контроллерам среднего класса. Вот пример простейшего обработчика прерываний: long tick count; void interrupt tc int(void) { ++tick count; Поскольку в контроллерах этого класса реализован только один вектор прерываний, то и функцию обработчик можно описать только одну, что звучит вполне логично. В самой функции вы можите анализировать какое именно прерывание имело место и выполнять соответствующие действия. Код реализующий эту функцию будет автоматически расположен в положенном месте. Должен обратить ваше внимание, насколько удобный и простой код получается в этом случае. Конечно при профессиональном подходе и ассемблерный код можно оформить вполне читабельно, но такой прозрачности, пожалуй, добиться будет трудно. Следует отдельно остановиться на сохранении контекста при выполнении обработчика прерывания. Все знают, что при возникновении прерывания контроллер автоматически сохраняет только регистр PC, чего явно недостаточно для работы нормальной программы. Поэтому программист должен сам позаботиться о сохранении всех важных регистров и объектов. Поскольку система прерываний контроллеров среднего класс не поддерживает приоритеты, то особых проблем с сохранением контекста не возникает. Более того, компилятор PICC сам отслеживает какие переменные и объекты были использованы в обработчике прерываний и сохраняет их. Это очень удобно при написании тривиальных обработчиков прерываний. Когда требуется тонкое управление процедурой сохранения-восстановления контекста, то можно, к примеру, воспользоваться встроенным ассемблером, так как фрагменты ассемблерного кода, которые компилятор встречает в обработчике прерываний, не сканируются на предмет выявления переменных, нуждающихся в сохранении. Думаю на этом можно закончить рассмотрение вопроса сохранения контекста при обработке прерываний, хотя здесь много тонких вопросов, но они вызывают интерес только при необходимости вмешаться в процесс сохранения-восстановления переменных. В заключении хочется рассказать, как собственно управлять прерываниями (разрешать и запрещать). С PICC это делается очень просто: ADIE = 1; Разрешитьпрерывание от АЦП PEIE = 1; Разрешитьвсе прерывания от периферийных устройств ei(); Разрешитьвсе прерывания di(); Запретитьвсе прерывания 5.2Совмещение кода C и Assembler Конечно, вы можите включать фрагменты ассемблерного кода непосредственно в свою программу на С. Для этого воспользоваться следующими механизмами: оформить ассемблерный код как внешнюю функцию или включить фрагмент в программу. В первом случае, определенная функция может быть написана полностью на ассемблере как внешний файл с расширением .as, скомпилирована с помощью ASPIC и включена в двоичный образ с помощью компоновщика. Эта технология позволяет передавать аргументы и принимать результат между С и ассемблерной программами. Для этого, прежде всего, необходимо включить адекватное описание внешней функции в С-программе. Допустим, нам необходима функция сдвига в лево через флаг переноса, и мы решили реализовать ее на ассемблере: extern char rotateleft(char); В примере, приведенном выше, мы описали внешнюю функцию под названием rotate left ( ), которая получает в качестве аргумента символ (char) и, соответственно, возвращает символ, только сдвинутый влево в соответствии с условим задачи. Текст этой архи-сложной функции поставляется в виде отдельного файла (.as), который, к тому же, и компилируется отдельно с помощью ASPIC. Вот вам возможная реализация этой функции: processor 16C84 psect text0,class=CODE,local,delta=2 globalrotate left signatrotate left,4201 rotate left ; Аргумент передается через регистр W movwf?a rotate left ; Результат сдвига помещаем опять в W rlf?a rotate left,w ; Результат должен находиться в W return FNSIZE rotate left,1,0 global?a rotate left Название ассемблерной функции должно совпадать с именем, упомянутым в С-программе, но с добавленным лидирующим знаком подчеркивания. Директива global является аналогом extern, а signat - необходима для проверки соответствия на этапе сборки. Подробнее этот вопрос будет рассмотрен далее. ВНИМАНИЕ! Чтобы все работало правильно ассемблерная функция должна брать аргументы из правильного места и правильно оформлять результат. Механизм выделения памяти под локальные переменные (через fnsize), аргументы и результат детально обсуждается в руководстве и его таки надо хорошо понимать, прежде чем лезть со своим ассемблером в С-программу!!! 5.3Передача аргументов в функцию Метод передачи функции аргументов определяется их размерами и количеством. Если передается только один аргумент типа char, то используется регистр W. Если передается один аргумент, но большего размера, то он помещается в "область аргументов" вызываемой функции. Если имеются еще аргументы, то они отправляются туда же. Если передается несколько аргументов, но первый из них однобайтный, то он помещается в авто-переменную, а все остальные аргументы - в область аргументов вызываемой функции. В случае передачи списка аргументов, создает временный список аргументов и передает указатель на него. Для примера рассмотрим простой вызов функции: void test(int a, int b, int c) Очевидно, что эта функция получит все аргументы в свою область аргументов. В случае вызова test( 0x65af, 0x7288, 0x080c) будет получен следующий код: movlw 0AFh movwf (((? test))&7fh) movlw 065h movwf (((? test+1))&7fh) movlw 088h movwf ((0+((? test)+02h))&7fh) movlw 072h movwf ((1+((? test)+02h))&7fh) movlw 0Ch movwf ((0+((? test)+04h))&7fh) movlw 08h movwf ((1+((? test)+04h))&7fh) lcall ( test) Начало области аргументов определяется меткой состоящей из знака вопроса, знака подчеркивания и названия функции (? test). Эта величина принимается за базу, к которой прибавляется смещение для доступа ко всем аргументам. Таким образом первый аргумент будет доступен по адресам ? test и ? test+1. Бывает полезно создавать пустые функции с заданными аргументами, компилировать программу с включенным флагом -S для контроля генерируемого кода. 5.4 Возвращение результата из функции Передача результата из функции осуществляется следующим образом: Значения размером 8-бит В микроконтроллерах среднего класса, байтовые значения возвращаются через рабочий регистр W. Пример: char return 8(void) return 0; В результате компиляции будет получен следующий код: movlw 0 return Значения размером 16-бит Значения размером 16 и 32 бита возвращаются через память. Пример: int return 16(void) return 0x1234; В результате компиляции будет получен следующий код: |
Среды: Smalltalk80 MicroCap Local bus Bios Pci 12С ML Микроконтроллеры: Atmel Intel Holtek AVR MSP430 Microchip Книги: Емкостный датчик 500 схем для радиолюбителей часть 2 (4) Структура компьютерных программ Автоматическая коммутация Кондиционирование и вентиляция Ошибки при монтаже Схемы звуковоспроизведения Дроссели для питания Блоки питания Детекторы перемещения Теория электропривода Адаптивное управление Измерение параметров Печатная плата pcad pcb Физика цвета Управлении софтверными проектами Математический аппарат Битовые строки Микроконтроллер nios Команды управления выполнением программы Перехода от ahdl к vhdl Холодный спай Усилители hi-fi Электронные часы Сердечники из распылённого железа Анализ алгоритмов 8-разрядные КМОП Классификация МПК История Устройства автоматики Системы и сети Частотность Справочник микросхем Вторичного электропитания Типы видеомониторов Радиобиблиотека Электронные системы Бесконтекстный язык Управление техническими системами Монтаж печатных плат Работа с коммуникациями Создание библиотечного компонента Нейрокомпьютерная техника Parser Пи-регулятор ч.1 ПИ-регулятор ч.2 Обработка списков Интегральные схемы Шина ISAВ Шина PCI Прикладная криптография Нетематическое: Взрывной автогидролиз Нечеткая логика Бытовые установки (укр) Автоматизация проектирования Сбор и защита Дискретная математика Kb радиостанция Энергетика Ретро: Прием в автомобиле Управление шаговым двигателем Магнитная запись Ремонт микроволновки Дискретные системы часть 2 | ||