Пример разработки программы с уходом в прерывания

Nbsp; Государственное образовательное учреждение высшего профессионального образования «Московский государственный технический университет имени Н.Э. Баумана» (МГТУ им. Н.Э. Баумана) Калужский филиал     Лабораторная работа №1 по курсу Ис САПР «Общие сведения о программировании PIC. От ASM к прошивке. Устройство микроконтроллера и принцип функционирования.»     Выполнил: Шестернин А.В. Группа: РПД-71 Принял: Драч В.Е.     Калуга, 2011

Семинар 4

«Прерывания. Стек. Правила.Обработка прерывания. Пример разработки программы с уходом в прерывания.»

Цель работы:Ознакомиться с прерываниями, принципом работы стека. Разработать программу с уходом в прерывание.

 

Теоретическая часть

Прерывания. Стек. Правила.

В принципе, в прерывания можно никогда не уходить (вообще их не использовать), так как все то, что можно сделать в подпрограммах прерываний, можно сделать и в "основном теле" программы, организовав периодическую (каждый полный цикл программы) проверку значений всех управляющих внешних сигналов.

Определимся с терминологией: при организации прерываний, рабочая часть программы включает в себя все подпрограммы (ПП) программы, включая и ПП прерываний.

Технология ухода в ПП прерывания следующая. Например, мы решили "прерываться" по входу INT. В "основном теле" программы обязательно нужно выделить группу команд, во время исполнения которых, при прохождении активного фронта управляющего сигнала по входу INT, могут происходить прерывания. В начале текста "основного тела" программы, обычно в начале ПП START (в подготовительных операциях), вставляется команда запрета всех прерываний clrfIntcon. Это объясняется тем, что "уход" в прерывания будет происходить позднее и, если изначально их не запретить, то этот "уход" может быть преждевременным, чего допустить нельзя (мы же не можем уйти в прерывания до окончания инициализации!). Далее программа исполняется до начала "зоны" действия прерываний. «Зона прерываний» - это группа команд "основного тела" программы, ограниченная "сверху" командой разрешения прерываний, а "снизу" - командой запрета прерываний.

Таким образом, в начале этой "зоны", действие прерываний по входу INT разрешается, после чего программа исполняется далее в режиме ожидания прерывания, а, затем прерывания опять запрещаются и программа исполняется далее.

При прохождении рабочей точкой программы «зоны прерываний», могут наступить 2 события: если прерывания нет, то программа исполняется обычным образом (в "основном теле" программы), а если произошло прерывание (прошел активный фронт по входу INT), то происходит переход рабочей точки программы, из "основного тела" программы в ПП прерываний INT (после нее могут следовать и другие ПП, входящие в состав ПП прерываний) по стеку.

Это означает, что в стек записывается адрес следующей (после команды, во время исполнения которой произошло прерывание) команды, для обеспечения последующего возврата рабочей точки программы, при выходе из ПП прерывания, именно на эту "следующую" команду.

Например, «зона прерываний» содержит 3 команды: A, B и С (сверху вниз по тексту программы). Пусть активный фронт сигнала прерывания по входу INT поступил во время исполнения команды А. Происходит переход рабочей точки программы на первую команду ПП прерывания INT. При этом, адрес команды В автоматически запишется в стек и будет в нем находиться, пока не исполнится последняя команда ПП прерываний, которой всегда должна быть команда retfie. По этой команде осуществляется возврат по стеку, что означает то, что из него извлекается адрес команды В и возврат рабочей точки программы произойдет именно на эту команду, после чего программа исполняется далее уже в "основном теле" программы. Если прерывание наступит во время исполнения команды В, то в стек запишется адрес команды С. Учтите, что программист, никак не может "повлиять" на стек и, по этой причине, он является "темной лошадкой", за которой можно только наблюдать, то есть, только констатировать факты либо выполнения команды условного перехода, либо возврата. Стек "подчиняется" только командам переходов и возвратов, а программиста он "ставит перед фактом" события, за что его многие стараются не использовать и стремятся обойтись без его привлечения (использование одних только команд безусловных переходов).

Но у стека есть одна замечательная особенность – он работает сам по себе, следовательно, программисту на надо задумываться над адресом возврата из ПП прерывания, этот адрес всегда «сам собой» попадает в стек. Программисту надо только использовать команду retfie.

При написании ПП прерываний, в любое их место (до команды retfie) должна быть, в обязательном порядке, вставлена команда сброса флага прерывания по выбранному входу (входам). В нашем случае, используется вход INT, и команда должна выглядеть так: bcf Intcon,1.

С точки зрения "наведения порядка" в тексте, ее лучше не вставлять между командами подпрограмм, а располагать либо, непосредственно перед командой retfie, либо где-то в начале ПП INT.

При отсутствии команды bcf Intcon,1, рабочая точка программы, "уйдя" первый раз из "основного тела" программы в ПП прерываний, будет "метаться" между ПП прерываний и "основным телом" программы (пока питание будет включено) при фактическом отсутствии прерываний (программа зависнет), то есть, если после возврата из ПП прерываний, флаг прерывания находится в поднятом состоянии (а это так и будет, так как, приисполнении ПП прерываний, он автоматически поднимается), то это "воспринимается" микроконтроллером как управляющий сигнал "ухода" в ПП прерываний.

Кроме того, специалисты Микрочипа рекомендуют, в начале ПП прерываний, сохранить содержимое регистров STATUS и W в специально созданных регистрах общего назначения (стандартные названия:Stat_Temp и W_Temp, но они могут быть и другими - по желанию программиста), а в конце ПП прерываний - восстановить их содержимое. Дело в том, что, по ходу исполнения ПП прерываний, содержимое регистров STATUS и W может измениться и, после возврата из ПП прерываний, это содержимое может негативным образом повлиять на исполнение программы в "основном теле" программы. Однако, есть и другой подход: заранее настроиться на то, что после любого прерывания содержимое STATUS и W может быть "испорчено", то есть не обращаться к этим регистрам на чтение.

Вывод. Для ухода в прерывания необходимо: в "шапке" программы определить вектор прерывания, определить активный фронт прерываний (OPTION), в "основном теле" программы назначить источник и «зону прерываний» (INTCON), в начале ПП прерываний сохранить, а в конце ПП прерываний - восстановить содержимое регистров STATUS и W, сбросить флаг прерывания по выбранному входу (входам) прерывания, а в самом конце ПП прерываний "вставить" команду retfie.

Пример разработки программы с уходом в прерывания.

Во-первых, при выполнении этого задания (и далее), соблюдем этикет программирования: шапку программы оформим в соответствии с рекомендациями разработчика. Подключаем стандартный конфигурационный файл директивой INCLUDE и прописываем конфигурацию с точки зрения повышения читаемости человеком.

LIST   p=16F84       ; Установка типа микроконтроллера.

__CONFIG _WDT_OFF & _HS_OSC ; Бит защиты выключен, WDT выключен, генератор внешний

#INCLUDE P16F84A.inc  ; Подключаем стандартную (фирменную) "шапку" для выбранного микроконтроллера

Далее, очевидно, в тексте программы придется применить директиву ORG (как минимум дважды). Начинаем программу с обычной связки

org    0       ;Расположить первую команду по адресу "0"

gotoStart   ; Переход в ПП Start

Затем следует директива ORG 0x04, указывающая на то, что с адреса 04 будет располагаться подпрограммаа обработки прерывания. Это стандарт для обработки переполнения TMR0 - обработчик должен находиться именно по этому адресу. Сразу за этой директивой начинаем описывать обработку прерывания. В нашем случае это следующая последовательность действий: передача в TMR0 значения длительности импульса (для будущего использования!), инверсия значения RA1 и сброс флага прерывания по переполнению TMR0 (иначе программа вечно будет "крутиться" в кольце). Из подпрограммы прерывания возвращаемся по команде retfie.

Теперь пишем текст рабочей части программы. Он во многом заимствован из предидущих примеров.

Startbsf    STATUS, RP0 ; Перейти в 1-й банк

movlw  .0       ; Записать константу 0 в аккумулятор (W).

movwf  TRISA    ; Скопировать 0 из W в регистр TrisA.

bcf    STATUS, RP0 ; Перейти в 0-й банк

clrf   PORTA    ; "Обнулить" порт А

bcf    INTCON, T0IF ; Флаг прерывания по переполнению TMR0 cбросить

bsf    INTCON, T0IE ; Разрешить прерывание по переполнению TMR0

Отличия от программы без прерываний (gnrtr.asm) следующие. Необходимо дополнить этот блок установкой в OPTION_REG битов, определяющих (а) выбор тактового сигнала для TMR0, (б) подключение предделителя и (в) коэффициент предделителя таймера. Затем передать в TMR0 значение длительности импульса. Кроме того, необходимо предусмотреть две команды, воздействующие на биты регистра INTCON, отвечающего за прерывания: сбросить флаг прерывания по переполнению TMR0 и разрешить прерывание по переполнению TMR0.

Далее следует основной цикл программы, который микроконтроллер будет пробегать многократно, "ожидая" наступления события, вызывающего прерывание. Это так называемая "зона прерываний". Например, она может выглядеть так:

Main_Loop                         ; Начало основного цикла программы

                                  ; т.е. начало зоны прерываний

       ...

gotoMain_Loop ; Переход в начало программы.

В общем случае вместо многоточия может стоять любой набор команд, которые должен циклически выполнять микроконтроллер. Только необходимость обработки прерывания вынудит его "выйти" за пределы этого набора команд.

Для данного технического задания можно вообще ничего не вставлять на место многоточия. Но можно вставить команду, разрешающую прерывания, так как мы этого еще не сделали нигде в теле программы.

bsf     INTCON, GIE ; разрешаем прерывание

Осталось не забыть про финальную строчку "end".

Встроенные инструменты MPLAB IDE позволяют оценить правильность функционирования программы путём наблюдения значений регистров МК. Например, при выполнении данной программы полезным будет видеть значение TMR0. В меню View выберите Watch (инструмент просмотра). По умолчанию окно должно быть пустым. Чтобы добавить регистр для наблюдения, необходимо раскрыть выпадающий список, указать регистр (в нашем случае TMR0) и нажать Add FSR (Добавить регистр).

 

Текст собственной программы

;*******************************************************************************

; GPI-2006.asm

; Генератор прямоугольных импульсов. Полупериоды согласно варианту 16.

; PIC16F84A     Частота 4 MГц.

;==========================================================================

 LIST   p=16F84A ; Установка типа микроконтроллера

;  __CONFIG   03FF1H ; Бит защиты выключен, WDT выключен, XT-генератор.

#include p16F84A.inc; ; Подключаем фирменную "шапку"

__CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC ;Битыконфигурации

;==========================================================================

org    0x00 ; Расположить первую команду по адресу 0.

gotoStart ; Переход в ПП Start.

       org  0x04 ; Начало ПП прерывания начинается с адреса 0х04.

movlw  .147; Записать константу 147 в аккумулятор (W)

movwf TMR0 ; Скопировать 147 из W в регистр TMR0.

movlw b'00000010' ; Записываем в аккумулятор маску по которой необходимо

                                          ; инвертировать уровни выходных сигналов.        

nop ; пропустить 1 машинный цикл.

XorwfPORTA, f    ; Инверсия по маске на всех ножках порта А только 2 линия

;поменяет состояние

bcf    INTCON, T0IF; Сбрасываем флаг прерывания по переполнению TMR0

retfie          ; Инструкция выхода из ПП прерываний

;*******************************************************************************

;                     Текст рабочей части программы

;*******************************************************************************

; Установка направления работы RA1 - "на выход".

;-------------------------------------------------------------------------------

Startbsf STATUS, 5 ; Перейти в 1-й банк (установить в "1"

       ; 5-й бит регистра Status).

       bcf  OPTION_REG, T0CS;Выбираем внутренний тактовый сигнала для TMR0        

movlw  .0    ; Записать константу 0 в аккумулятор (W).

movwf  TRISA; Скопировать 0 из W в регистр TrisA.

bcf STATUS, 5; Перейти в 0-й банк (установить в 0 5-й бит

; регистра Status).

clrfPORTA ; "Обнулить" порт А

bcf INTCON, T0IF ; Флаг прерывания по переполнению TMR0 cбросить

bsfINTCON, T0IE; Разрешить прерывание по переполнению TMR0

bsf  INTCON, GIE  ; Разрешаем глобальные прерывания.

movlw .163     ; Записать константу 163 в аккумулятор (W)

movwf TMR0   ; Скопировать 163 из W в регистр TMR0.

       nop             ; пропустить 1 машинный цикл.

       goto   $                      ; Переход на новый полный цикл программы.

;*******************************************************************************                       

end ; Директива конца программы (дальше

       ; можно писать что угодно).

 

 


                                                                                                   

 

 Рис.1. Импульс длительностью 116мкс

                               

Вывод:В результате выполненной лабораторной работы изучили принцип работы стека и прерывания, составили программу, работающую с прерываниями. Получили генератор меандра 116 мкс на базе TMR0. Получили новый рабочий файл *.hex.


Дата добавления: 2018-04-04; просмотров: 265; Мы поможем в написании вашей работы!

Поделиться с друзьями:




Мы поможем в написании ваших работ!