Понедельник, 15 октября 2012 04:44

Программирование c нуля в AVRStudio 5 (ч.9) Featured

Written by
Rate this item
(0 votes)

altПерейдем к изучению встроенных таймеров.

Изучение прерываний и особенно таймеров в микроконтроллерах представляет определенную сложность из за их многофункциональности. Сегодня постараемся разобраться в терминах и названиях.

В микроконтроллерах AVR могут быть от одного до 4-х таймеров, восьмиразрядные или шестнадцатиразрядные.

Упрощенно таймеры обозначаются буквой T, и номером от нуля до трех. Обычно четные Т0 и Т2 являются восьмиразрядными, а нечетные Т1 и Т3 шестнадцатиразрядными.

 

 

При программировании упрощенный вариант используется только в комментариях, а в программах прописывается полное название таймера – регистр TCNT.

Ниже показаны обозначения таймеров:

Таймеры.

T0, T2 – (TCNT0, TCNT2) восьмиразрядные счетчики (четные)

TCNTn - счетный регистр 8 разрядного счетчика

где; n-номер счетчика

T1, T3 – (TCNT1Н и TCNT1L, TCNT3H и TCNT3L) шестнадцатиразрядные счетчики (нечетные)

TCNTny - счетный регистр 16 разрядного счетчика

где; n-номер счетчика

y-старший (H) или младший (L) разряд

Т1 состоит из двух восьмиразрядных регистров TCNT1Н и TCNT1L, а

Т3 из двух регистров TCNT3H и TCNT3L. Буквой H обозначается старший разряд, а L младший.

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

Приняты определенные правила записи и чтения в таймеры TCNT1Н и TCNT1L.

  1. Программы записи и чтения данных таймера должны быть атомарными, т.е. перед чтением или записью мы запрещаем прерывания, а по окончании процесса вновь разрешаем.
  2. При записи сначала записывается старший байт H а затем младший L.
  3. При чтении сначала считывается младший байт L затем старший H.

Например:

Запись данных в счетный регистр.

CLI                     ; Запрещаем прерывания
OUT     TCNT1H,R16      ; Запись старшего байта
OUT     TCNT1L,R17      ; Запись младшего байта
SEI                     ; Разрешаем прерывания

Чтение данных из счетного регистра

CLI                     ; Запрещаем прерывания
IN      TCNT1L,R16      ; Считывание младшего байта
IN      TCNT1H,R17      ; Считывание старшего байта
SEI                     ; Разрешаем прерывания

Почему такие правила? А все для того, чтобы не исказились данные за то время, которое уйдет на процесс считывания из каждого регистра.

Если использовать прямое чтение 8-битных регистров TCNT1H и TCNT1L, то нельзя быть уверенным, что эти регистры прочитались одновременно. Может произойти следующая ситуация: Счетчик содержал значение $01FF, Вы считали TCNT1H (содержащий значение 01 в какую-то переменную). За это время пришел счетный импульс, и содержимое TCNT1L стало равно $00, а в TCNT1H записалось значение $02. Теперь Вы читаете значение TCNT1L в другую переменную, получаете в этой переменной значение $00 (ведь таймер/счетчик уже произвел счет). 16-битное значение этих переменных получилось $0100, но на момент считывания старшего байта содержимое счетчика было $01FF, и младший байт у Вас должен был прочитаться как FF. Для предотвращения такой ситуации служит временный регистр, содержащийся в блоке таймера/счетчика. Этот регистр прозрачный, т.е. действует автоматически. При считывании значения регистра TCNT1L в переменную, содержимое TCNT1H попадает в этот регистр. Затем при чтении старшего байта в переменную, считывается значение временного регистра. Временный регистр абсолютно прозрачен для пользователя, но для его корректной работы необходимо соблюдать указанную выше последовательность действий. Обращение к регистрам через дополнительный (буферный) регистр называется двойной буферизацией

Таймеры связаны с счетными импульсами, которые могут быть внешними и поступать на специальный вход микросхемы или формироваться собственным генератором. В свою очередь частота собственного генератора может синхронизироваться внешним кварцевым резонатором, а может определяться внутренней RC – схемой. После этого, внешняя частота или частота собственного генератора, проходят предделитель, управляемый регистром CLKPR.Частоту генератора после предделителя (прескалера) CLKPR нередко называют тактовым сигналом (тактовой частотой) процессора (CPU).

Частота, подаваемая на вход таймера обозначается как CLKTn Эта частота соответствует тактовому сигналу процессора.

Один счетный импульс увеличивает значение таймера на единицу, поэтому регистры TCNT являются счетными, и называются таймером/счетчиком (ТС).

Для правильной работы таймера/счетчика по внешнему тактовому сигналу минимальное время между двумя переключениями внешнего тактового сигнала должно быть не менее одного периода тактового сигнала CPU. Синхронизируется внешний тактовый сигнал нарастающим фронтом внутреннего тактового сигнала CPU. (Это нужно помнить при построении частотомеров).

Управляющим регистром для таймера/счетчика TCNT является регистр TCCR.

Маской прерывания для таймера/счетчика TCNT служит регистр TIMSK (регистр управления прерываниями таймера).

Регистром флагов маски прерывания TIMSK - является регистр TIFR. Запомните, что эти 3 регистра (TCCR, TIMSK, TIFR) при работе таймера/счетчика TCNT используются почти всегда.

Прерывания могут вызываться по переполнению регистра TCNT, сравнению значения регистра TCNT со значением специальных регистров сравнения OCR, захвату – по значениям специальных регистров захвата ICR и определяются режимом работы таймера/счетчика. Кроме этого запрос прерывания может происходить по срабатыванию сторожевого таймера (Watchdog Timer) WDT.

Таймеры/счетчики могут работать в разных режимах и соответственно выполнять разные функции.

Режим работы, то есть, поведение таймера/счетчика и выхода сигнала совпадения, определяется как режимом работы генератора сигналов, управляемого регистрами WGM02; WGM01; WGM00 (сокращенная запись WGM02:0), так и режимом вывода сигнала совпадения, управляемых регистрами СОМ0х1; СОМ0х0 (сокращенная запись СОМ0х1:0). Состояние битов, от которых зависит  режим вывода сигнала совпадения, не влияет на последовательность подсчета, которая определяется только состоянием битов конфигурации генератора сигналов.

Биты СОМ0х1:0 определяют, должен ли выходной сигнал ШИМ быть инвертирован или нет (инвертированный или не инвертированный ШИМ). (ШИМ) Широтно-импульсная модуляция или Pulse-width modulation (PWM). Для не-ШИМ-режимов содержимое битов СОМ0х1:0 определяет, должен ли сигнал на выходе быть установлен в единицу, сброшен в ноль либо переключен в противоположное состояние в момент совпадения

Выделяют следующие режимы работы таймеров:

Normal – подсчет и прерывание по переполнению. В этом режиме, при выставленном бите TOIE регистра TIMSK возникает запрос на прерывание. Условием для прерывания будет обнуление регистра таймера TCNT, которое происходит после заполнения всех ячеек (после числа 0xFF) и фиксируется аппаратным поднятием флага переполнения TOV в регистре TIFR.

Флаг TOV0 в этом случае ведет себя как девятый бит, за тем исключением, что он только устанавливается, но не сбрасывается.

Используя прерывание по переполнению таймера, которое автоматически очищает флаг TOV0, можно увеличить коэффициент пересчета программным путем. Режим Normal не имеет других функций и считается наиболее простым.

Capture – (захват) запоминание значения счетчика в специальном регистре захвата ICRx по управляющему сигналу (от специального входа микроконтроллера (ICP) или от выхода встроенного компаратора), где x- соответствует номеру счетчика. Одновременно с захватом происходит запрос на прерывание и переход на векторы прерывания - CAPT. Устанавливается прерывание в этом режиме битом ICIE или TICIE в регистре TIMSK, и фиксируется поднятием флага ICF в регистре TIFR.

CTC – (Clear Timer on Compare) сброс при совпадении – сравнение со значением специальных регистров совпадения OCR, которые используется для того, чтобы управлять коэффициентом пересчета счетчика.

Происходит запрос на прерывание и переход на векторы прерывания - COMP. Регистры совпадения обозначаются как OCRnxy

где; n - номер счетчика,

x –регистр А или B (если регистров совпадения 2, то обозначают первый как как регистр A, а второй как регистр B, каждый из них может быть 16 разрядным)

y - старший (H) или младший (L) разряд регистров совпадения.

В большинстве моделей микроконтроллеров одному восьмиразрядному таймеру соответствуют два восьмиразрядных регистра сравнения OCR, регистр А и регистр В. Например, таймеру TCNT0 соответствуют два регистра сравнения OCR0A и OCR0B.

Если таймер шестнадцатиразрядный, то ему соответствуют четыре восьмиразрядных регистра сравнения, например, таймеру TCNT1 соответствуют OCR1AH и OCR1AL, OCR1BH и OCR1BL.

В режиме СТС возникает запрос прерывания, сброс таймеров (при совпадении с OCR1 и OCR1A) или изменяется состояние выводов микроконтроллера, которые зависят от установленных настоек таймера.

Значения ячеек регистров TIMSK и TIFR в разных моделях микроконтроллеров имеют похожие функции и названия, но могут отличаться расположением, и при переходе с одного контроллера на другой трудностей не вызывают.

 

Tiny

alt

 

Бит 0 - OCIE0A: прерывание по совпадению таймера-счетчика T0A

Бит 1 - TOIE0: прерывание по переполнению Т0

Бит 2 - OCIE0B: прерывание по совпадению таймера-счетчика T0B

Бит 3 - ICIE1: Разрешение прерывания по входу захвата (вход ICP)

Бит 4 - Зарезервировано

Бит 5 – OCIE1B: прерывание по совпадению таймера-счетчика T1B

Бит 6 – OCIE1A: прерывание по совпадению таймера-счетчика T1A

Бит 7 – TOIE1: прерывание по переполнению Т1

 

alt

 

Флаги соответствуют прерываниям в регистре TIMSK. Устанавливаются в "1" при выполнении условий соответствующего прерывания.

 

Mega8

alt

alt

 

Mega16

alt

 

Бит 7 - OCIE2: прерывание по совпадению Т2

Бит 6 - TOIE2: прерывание по переполнению Т2

Бит 5 - TICIE1: прерывание по захвату Т1

Бит 4 - OCIE1A: прерывание по совпадению A Т1

Бит 3 - OCIE1B: прерывание по совпадению В Т1

Бит 2 - TOIE1: прерывание по переполнению Т1

Бит 1 - OCIE0: прерывание по совпадению таймера-счетчика T0 (В Mega8 этот бит зарезервирован)

Бит 0 - TOIE0: прерывание по переполнению Т0

Если соответствующий бит установлен в "1" и бит I (7-й бит) регистра состояний SREG установлен в "1", тогда соответствующее прерывание будет срабатывать.

alt

 

Флаги соответствуют прерываниям в регистре TIMSK. Устанавливаются в "1" при выполнении условий соответствующего прерывания.

Теперь рассмотрим механизмы управления функциями таймеров.

За установку различных режимов и функций таймеров отвечает регистр TCCR

TCCRnx - восьмиразрядные регистры управления таймерами

где; n-номер счетчика

х-буквенное обозначение регистра управления

Например в микроконтроллере ATtiny2313 простому восьмиразрядному таймеру/счетчику T0 будет соответствовать регистры - TCCR0А и TCCR0B, a шестнадцатиразрядному таймеру/счетчику T1 – восьмиразрядные регистры TCCR1A, TCCR1B, TCCR1C. В других моделях микроконтроллеров управляющих регистров может быть больше, которые обозначаются буквами латинского алфавита – A,B,C,D и т.д.

Для того, чтобы упорядочить типы таймеров/счетчиков по их функциональному назначению, их тоже принято обозначать в виде заглавных букв латинского алфавита:

A – Восьмиразрядный таймер-счетчик без дополнительных функций

B – Восьмиразрядный таймер-счетчик с функциями сравнения/ШИМ

C – Восьмиразрядный таймер-счетчик с функциями сравнения/ШИМ и функцией счета реального времени

D – Шестнадцатиразрядный таймер-счетчик с функциями захвата и сравнения/ШИМ

E – Шестнадцатиразрядный таймер-счетчик с функцией захвата и двумя каналами для выполнения функций сравнения/ШИМ.

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

При описании счетчиков используются специальные обозначения для всех его важных состояний.

BOTTOM – счетчик достигает значения BOTTOM (начало), когда его содержимое равно 0х0000

MAX - счетчик достигает значения MAX (максимум), когда его содержимое равно 0хFF для восьмибитных таймеров/счетчиков и 0xFFFF для шестнадцатибитных таймеров/счетчиков.

TOP - Счетчик достигает значения ТОР (вершина), когда его содержимое достигает самого высокого значения в данном режиме работы. В зависимости от режима значение ТОР может быть равно либо OxFF (МАХ) для восьмибитных таймеров/счетчиков или 0x00FF, 0x01FF, 0x03FF для шестнадцатибитных таймеров/счетчиков либо значению, записанному в регистре OCR0A (режим сброса по совпадению - CTC)

Напомню, что в ATtiny2313 один 8- разрядный таймер/счетчик с отдельным предделителем и один 16-разрядный таймер/счетчик с отдельным предделителем, схемой сравнения, схемой захвата и двумя каналами широтно-импульсной модуляции (ШИМ).

Или по другому - один таймер/счетчик типа A и один таймер/счетчик типа D с регистрами управления TCCR0А, TCCR0B и TCCR1A, TCCR1B, TCCR1С.

 

ATtiny2313

T0, таймер/счетчик типа A, регистры управления TCCR0А, TCCR0B

 

alt

alt

 

T1, таймер/счетчик типа B, регистры управления TCCR1А, TCCR1B, TCCR1C

 

alt

alt

alt

 

Рассмотрим назначение битов регистров TCCR:

CS02:CS01:C00 - Разряды, определяющие источник тактового сигнала таймера/счетчика Т0.

CS12:CS11:C10 - Разряды, определяющие источник тактового сигнала таймера/счетчика Т1.

 

alt

 

где n - номер счетчика

В зависимости от установленных бит CS, мы можем получить прямой, инверсный или поделенный на 8,64, 256, 1024 счетный импульс, а так же полностью остановить счет.

Для практического программирования нужно просто запомнить эту таблицу с назначением битов CS.

COM0A1:COM0A0:COM0B1:COM0B0 - Эти разряды определяют поведение вывода OC1A:OC1B при совпадении значения счетного регистра TCNT0 и регистра сравнения OCR0A:OCR0B

COM1A1:COM1A0:COM1B1:COM1B0 - Эти разряды определяют поведение вывода OC1A:OC1B при совпадении значения счетного регистра TCNT1 и регистра сравнения OCR1A:OCR1B

ICNC1 - Разряд управления схемой помех, если бит равен "0" захват будет по первому активному фронту, если "1" захват будет после четвертой одинаковой выборки сигнала захвата.

ICES1 - Разряд выбора активного фронта сигнала, если его значение равно "0", сохранение счетного регистра TCNT1 в регистре захвата OCR1 будет по спадающему фронту сигнала, если "1" по нарастающему.

WGM02: WGM01: WGM00 - Эти разряды определяют режим работы таймера/счетчика Т0

 

alt

 

WGM13:WGM12:WGM11:WGM10 - Эти разряды определяют режим работы таймера/счетчика Т1

 

alt

 

FOC1A:FOC1B - Эти разряды служат для принудительного изменения состояния вывода OC1A:OC1B

(Регистр TCCR1C и его биты FOC1A:FOC1B не прописаны в файле 2313def.inc поэтому при необходимости можно программно их назначить

.equ    TCCR1С  = 0x22  ; TCCR1C - Timer/Counter1 Control Register C

.equ    FOC1B   = 6     ; изменение состояния вывода OC1B

.equ    FOC1A   = 7     ; изменение состояния вывода OC1A

Посмотрите карту регистров ввода-вывода для ATtiny2313. Там есть регистр TCCR1С под адресом $0x22, но работает этот регистр или нет, я не проверял. (По технической документации должен работать.)

Рассмотрим еще два регистра:

GTCCR – главный регистр управления таймерами

 

alt

 

В этом регистре всего один бит PSR10 – выполняет сброс предварительных делителей всех таймеров. После сброса предделителей таймеров бит PSR10 немедленно очищается (переводится в 0).

Есть еще один регистр, который управляет делителем тактовой частоты процессора CLKPR. Нередко начинающий программист путает биты регистра TCCR, определяющие источник тактового сигнала таймера/счетчика с битами управления предделителя CLKPR. Дело в том, что регистр CLKPR изменяет тактовую частоту процессора. Например, если в наличии имеется кварцевый резонатор на 64 МГц, а нам нужно 8 МГц то мы можем использовать этот резонатор, подключив через прескалер (предделитель), разделив исходную частоту на 8. Прескаллер (предделитель) регистра TCCR (биты CS), управляет частотой, которая попадает на входы счетчиков/таймеров и ни как не влияет на тактовую частоту процессора.

Регистр CLKPR (Clock Prescale Register)

Изменяя его биты можно менять значение предделителя тактового сигнала

Для управления предделителем тактового сигнала предназначен регистр CLKPR, расположенный по адресу (0х46) в пространстве дополнительных регистров ввода/вывода. Формат этого регистра:

 

alt

 

Старший бит (СLKРСЕ) служит для разрешения изменения частоты тактового сигнала, а биты CLKPS3...CLKPS0 задают коэффициент деления предделителя

Выбор коэффициента деления предделителя (прескалера) тактового сигнала

 

alt

 

Для изменения содержимого битов CLKPS3...0 следует выполнить следующие действия:

  1. Записать в бит СРСЕ лог. 1, а в биты CLKPS3...0 — лог. 0.
  2. В течение следующих четырех тактов занести требуемое значение в биты CLKPS3...0, при этом бит СРСЕ будет сброшен в 0. В противном случае бит СРСЕ буден сброшен аппаратно по истечении четырех тактов, запрещая дальнейшее изменение битов CLKPS3...0.

Начальное состояние битов CLKPS3...0 определяется конфигурационной ячейкой CKDIV8. Если она не запрограммирована (1), то при запуске микроконтроллера в битах CLKPS3...0 будет находиться значение 0000. Если же ячейка CKDIV8 запрограммирована (0), стартовым значением битов CLKPS3...0 является 0011 (коэффициент деления — 8).

В микроконтроллере ATtiny2313 по умолчанию установлена частота встроенного тактового генератора 8 МГц, с коэффициентом деления прескалера 8, т.е. тактовая частота процессора равна 1 МГц. Биты регистра CLKPR доступны при прошивке кристалла программатором в виде фьюзов. О них мы еще поговорим отдельно.

Перепишем программу бегущих огней :

{showhide title="Развернуть код" template="strong" changetitle="Свернуть код" mousetitleistitle=true closeonclick=true titleasspan=true}


 

; ****************************************
; Автор:                                 *
; Дата:                                  *
; Версия:                                *
; Название файла:                        *
; Для AVR:  ATtiny2313                   *
; Тактовая частота:  8мГц                *
; ****************************************
; Выполняемые функции:  Реверсивные бегущие огни с задержкой от встроенного таймера
; в режиме сравнения, с управлением от 2-х кнопок по  внешним прерываниям INT1 и INT0
; ==================================================
      ; .device                          ;
      ; .nolist                          ;
      ; .include                         ; Присоединение файла описаний
      ; .list                            ; Включение листинга

; =================================================== Псевдокоманды управления
       .def     temp = r16               ; Определение основного рабочего регистра temp
       .def     temp1 = r17              ; Определение дополнительного рабочего регистра temp1
       .def     temp2 = r18              ; Определение дополнительного рабочего регистра temp2
       .def     temp3 = r19              ; Определение дополнительного рабочего регистра temp4
       .equ     time = 3024              ; Присвоение перменой time значения 3024 (время задержки)

; =================================================== Начало программного кода
            .cseg                        ; Выбор сегмента программного кода
            .org    0                    ; Установка текущего адреса на ноль

; =================================================== Векторы прерываний
        rjmp    init                     ; Переход на начало программы
                rjmp    INT_0
                rjmp    INT_1
                reti                     ; Прерывание по захвату таймера T1
                rjmp    pr_tim           ; Прерывание по совпадению T1
                reti                     ; Прерывание по переполнению T1
                reti                     ; Прерывание по переполнению T0
                reti                     ; Прерывание UART прием завершен
                reti                     ; Прерывание UART регистр данных пуст
                reti                     ; Прерывание UART передача завершена
                reti                     ; Прерывание по компаратору
                reti                     ; Прерывание по изменению на любом контакте
                reti                     ; Таймер/счетчик 1. Совпадение B
                reti                     ; Таймер/счетчик 0. Совпадение B
                reti                     ; Таймер/счетчик 0. Совпадение A
                reti                     ; USI Стартовая готовность
                reti                     ; USI Переполнение
                reti                     ; EEPROM Готовность
                reti                     ; Переполнение сторожевого таймера

; =================================================== Начало программы
init:                                                                   

; =================================================== Инициализация стека
                ldi temp,low(RAMEND)     ; Устанавливаем младший бит из значения RAMEND прописанного по
                out SPL,temp             ; умолчанию в файле tn2313def.inc
                .if (RAMEND)>=0x0100     ; Если значение опреративной памяти превышает число 256 то,
                ldi temp,high(RAMEND)    ; Устанавливаем старший бит из значения RAMEND прописанного по
                out SPH,temp             ; умолчанию в файле tn2313def.inc
                .endif                   ; Конец условия

; =================================================== Инициализация Оперативной памяти
                ldi     ZL,low(SRAM_START)        ; Устанавливаем адрес начала ОЗУ прописанного по
                ldi     ZH,high(SRAM_START)       ; умолчанию в файле tn2313def.inc
                clr     temp                      ; Очищаем r16
flush:         
                st      Z+,temp                   ; Обнуляем ячейку памяти
                cpi     ZH,high(RAMEND+1)         ; Если не достигли конца старшего байта оперативной памяти
                brne    flush                     ; то продолжаем обнулять
                cpi     ZL,low(RAMEND+1)          ; Если не достигли конца младшего байта оперативной памяти
                brne    flush                     ; то продолжаем обнулять
                clr     ZL                        ; Очищаем индексы младшего
                clr     ZH                        ; и старшего байтов памяти

; =================================================== Инициализация регистров общего назначения
                ldi     ZL, 30                    ; Адрес самого старшего регистра       
                clr     ZH                        ; Обнуляем
                dec     ZL                        ; Уменьшаем адрес на единицу
                st      Z, ZH                     ; Записываем в регистр 0
                brne    PC-2                      ; Зацикливаемся до полного обнуления

; =================================================== Инициализация Главного предделителя
                ldi     temp,(1<
                out     CLKPR, temp               ; регистр CLKPR
                ldi     temp, 0                   ; Обнуляем регистр temp
                out     CLKPR, temp               ; Деление  тактовой частоты  в регистре CLKPR равно 1

; =================================================== Инициализация портов
                ser     temp                      ; устанавливает все биты регистра temp  в 1
                clr     temp1                     ; обнуляет регистр temp1 - все биты регистра temp1 в 0
                ldi     temp2,(1< 
                out     DDRB,temp                 ; переводит все биты порта B на вывод 
                out     DDRD,temp1                ; перевод битов PD3 и PD2 на ввод     
                out     PortB,temp1               ; отключает подтягивающие резисторы портов B
                out     PortD,temp2               ; подключение подтягивающих резисторов на PD3 и PD2

; =================================================== Инициализация таймера T1
                ldi     temp,(1<                  
                out     TCCR1B, temp 
                ldi     temp, high(time)          ; Старший полубайт кода совпадения
                out     OCR1AH, temp              ; Запись в регистр совпадения старш.
                ldi     temp, low(time)           ; Младший полубайт кода совпадения
                out     OCR1AL, temp              ; Запись в регистр совпадения младш.

; =================================================== Запись в регистр маски прерываний
                ldi     temp,(1<
                out     TIMSK, temp

; =================================================== Инициализация прерываний
                ldi     temp,(1

 

                out     GIMSK,temp                ; инициализация внешних входов INT1 и INT0
                ldi     temp,(1< 
                out     MCUCR,temp                ; инициализация прерываний по спадающему фронту входного сигнала
                SEI                               ; разрешение прерываний
; =================================================== Рисунок бегущего огонька

                ldi     temp, 0b10000000          ; Запись начального значения
; =================================================== Глобальное разрешение прерываний и зацикливание

                sei                               ; Разрешение прерываний
Loop:           rjmp    Loop                      ; Пустой бесконечный цикл
; =================================================== Подпрограмма обработки прерываний таймера

pr_tim:
                SBRC    temp3,0                   ; если 0 бит регистра temp4 равен 1,
                rjmp    left                      ; то переход на метку left
                SBRC    temp3,1                   ; если 1 бит регистра temp4 равен 1,
                rjmp    right                     ; то переход на метку right

left:           rol     temp                      ; циклический сдвиг влево через флаг C
                brcc    led                       ; если перенос очищен, то перейти на метку led
                ldi     temp1,0b00000001          ; если C=1, то записываем
                add     temp, temp1               ; в 0 бит единицу
                rjmp    led                       ; и переходим на метку led

right:          ror     temp                      ; циклический сдвиг вправо через флаг C
                brcc    led                       ; если перенос очищен, то перейти на метку led
                ldi     temp1,0b10000000          ; если C=1, то записываем   
                add     temp, temp1               ; в 7 бит единицу

led:            out     PortB,temp                ; вывод в порт D значения регистра temp
                reti
; =================================================== Подпрограммы прерываний кнопок

INT_0:
                ldi temp3,1                       ; Запись состояния кнопки PD2
                reti

INT_1:
                ldi temp3,2                       ; Запись состояния конпки PD3
                reti
В этой программе мы добавили еще одну кнопку, нажатие на которую позволяет менять направление огонька. Направление меняется по прерыванию от внешнего сигнала (от кнопок). В практических конструкциях обычно так не делают, но демонстрация внешних прерываний представлена весьма наглядно.

 

Схема в протеусе будет выглядеть как на рисунке:

 

alt

Read 8997 times Last modified on Среда, 03 сентября 2014 11:49

Все права принадлежат ChipMK.ru. При копировании материала ссылка обязательна. 2011-2017 © ChipMK.ru

ChipMk.ru Яндекс.Метрика
PRCY.ru