Изучение программирования таймеров-счетчиков, измерение длительности включенного состояния тумблера SA4 (INT0)

Страницы работы

8 страниц (Word-файл)

Содержание работы

Министерство образования Российской Федерации

Российский государственный профессионально-педагогический университет

Инженерно-педагогический институт

Кафедра микропроцессорной управляющей вычислительной техники

Лабораторная работа №4

Изучение программирования таймеров-счетчиков

                                                                               Выполнили: Величко В.С.       

                                                                                                       Григоренко А.

                                                                                                     Крюков Д.В.

                                                                                   Проверил: Садовников М.Е.

Екатеринбург 2008

Цель работы:

Изучение функционирования таймеров/счетчиков микроконтроллеров АТ90S8535, получение практических навыков в их программировании.

Задача:

На основе таймеров организовать с дискретностью 1с измерение длительности включенного состояния тумблера SA4 (INT0). Допустимая длительность 9 секунд. Индикацию секунд организовать на семисегментном индикаторе HG2. При нажатии кнопки SB3 происходит обнуление индикатора.

Решение задачи в общем виде:

Признак начала включенности тумблера SA4 – внешнее прерывание INT0, происходящее по возрастающему фронту. Следовательно, счет должен запускаться программой обработки прерывания INT0. Для хранения текущего состояния счетчика секунд нужно выделить память в ОЗУ. Проще всего оперировать с ней будет, если она будет выделена в регистре, которому будет присвоено имя num в нашей программе.

Поскольку таймер-счетчик перебирает свои значения с определенной частотой, а минимальная частота изменения регистра состояния таймера-счетчика составляет CK/1024 (где CK=8MHz), чего явно недостаточна для нашей задачи, то необходимо программно организовать перебор секунд в регистре. Проведем соответствующие расчеты:

-Возьмем делитель частоты CK/256=8000000/256=31250 (CK/1024 нам не подойдет, наверно, т.к. 8000000/1024=7812,5 – не целое число).

- Будем инкрементировать наш счетчик секунд в момент совпадения регистра состояния таймера/счетчика(1 в нашем случае) с регистром сравнения. Это действие оформим в виде подпрограммы обработки прерывания по совпадению таймера/счетчика с регистром сравнения (в нашем случае это 16-разрядный регистр). В этой же подпрограмме будем сравнивать предыдущее состояние счетчика секунд: если оно равно 9, то обнулим его, иначе инкрементируем.

Признак выключения тумблера – логический ноль на соответствующем входе(pind,2). Таким образом работа таймера ограничена временем выполнения цикла, выход из которого возможен только если «0» на входе. Если тумблер включен более 9 секунд, то счетчик секунд обнуляется, а счет начинается заново. Ожидание очередного включения тумблера или сброса происходит в бесконечном цикле.

Блок схема:

Листинг программы:

.include "8535def.inc"

.def tmp=r16

;присвоить имена регистрам

.def tmp1=r17

.def num=r18

;текущая секунда

.dseg

.org $060

s7:

;выделяем память под семисегментные коды

 cod0:.byte 1

;по 1 байту под каждый код

 cod1:.byte 1

 cod2:.byte 1

 cod3:.byte 1

 cod4:.byte 1

 cod5:.byte 1

 cod6:.byte 1

 cod7:.byte 1

 cod8:.byte 1

 cod9:.byte 1

.cseg

;начало сегм. кода

.org $000

;вектор прерывания по сбросу

rjmp start

.org $001

;вектор прерывания INT0

rjmp pr000

.org $006

; вектор прерывания по совпадению таймера счетчика 1 с регистром

rjmp pr006

;сравнения A

.cseg

;начало сегм. кода

start:

ldi tmp,$3f

;записываем семисегментные коды в выделенные ячейки ОЗУ

sts cod0,tmp

;сначала число пишем в регистр

ldi tmp,$06

;потом из регистра записываем в ОЗУ

sts cod1,tmp

ldi tmp,$5b

sts cod2,tmp

ldi tmp,$4f

sts cod3,tmp

ldi tmp,$66

sts cod4,tmp

ldi tmp,$6d

sts cod5,tmp

ldi tmp,$7d

sts cod6,tmp

ldi tmp,$07

sts cod7,tmp

ldi tmp,$7f

sts cod8,tmp

ldi tmp,$6f

sts cod9,tmp

;конец записи 7-сегм. кодов

clr num

;очистить регистр секунд

ldi tmp,$00

;определяем стек с вершиной по адресу $00ff

out sph,tmp

;Sph – старший  байт указателя на вершину стека

ldi tmp,$0ff

;Spl - младший байт указателя на вершину стека

out spl,tmp

;НАСТРОЙКА ПОРТОВ

ldi tmp,$f0

;порт D: 0..3 на вход, остальные на выход

out DDRD,tmp

ldi tmp,$ff

;порт С на выход

out DDRC,tmp

sbi PORTB,3

;установить третий бит в порте B(подключить индикатор HG1)

;В регистр сравнения A загружаем число 31250=$7A12

ldi tmp,$7a

out OCR1AH,tmp

;старший байт 16-разр. регистра А

ldi tmp,$12

out OCR1AL,tmp

;младший байт 16-разр. регистра А

ldi tmp,0x03

;задаем характер сигнала прерывания по возрастающему фронту

out MCUCR,tmp

ldi tmp,0xff

;очищаем флаги внешних прерываний, записывая лог. «1»

out gifr,tmp

sei

;разрешаем глобальные прерывания

ldi tmp,0x40

out GIMSK,tmp

;разрешаем прерывания по INT0

rcall numout

;вызов подпрограммы вывода секунд на индикатор

loop3:

sbic pina,3

;ожидание нажатия кнопки SB3

rcall SB3event

;(бесконечный цикл)

rjmp loop3

pr000:

;подпрог. обработки прерывания INT0

in tmp,SREG

;сохраняем регистр статуса в стек

push tmp

ldi tmp,0

out TCNT1H,tmp

;обнуляем верхний и нижний байты регистра текущего состояния таймера

out TCNT1L,tmp

ldi tmp,0x00

;запрещаем

out GIMSK,tmp

;внешние прерывания

sei

;разрешаем глобальные прерывания

ldi tmp,$0c

;устанавливаем 2-й и 3-й биты регистра управления B таймером/счетчиком1

out TCCR1B,tmp

;3-й бит: обнуление таймера после прерывания по совпадению с регистром

;сравнения. 2,1,0 –й биты: выбор делителя тактовой частоты CK/256

ldi tmp,$10

out TIMSK,tmp

;Разрешение прерывания по совпадению регистра A с таймером/счетчиком1

m1:

;ожидание пока не будет выключен SA4

rcall numout

;вывод num на индикацию

sbic pind,2

rjmp m1

cli

;снять флаг всеобщего разрешения прерываний

ldi tmp,$00

out TCCR1B,tmp

;выключаем таймер/счетчик1

ldi tmp,$00

out TIMSK,tmp

;запрещаем прерывания по совпадению таймера с регистром

ldi tmp,0xff

out gifr,tmp

;снимаем флаги внешних прерываний, чтобы они не произошли случайно

ldi tmp,0x40

out GIMSK,tmp

;разрешаем внешнее прырыв. INT0

pop tmp

out SREG,tmp

;восстанавливаем регистр статуса

reti

;возврат из подпрограммы обработки прерывания INT0

pr006:

;подпрограмма обработки прерывания по совп. Т/С1 с рег. сранения

in tmp,SREG

;сохраняем регистр статуса в стек

push tmp

cpi num,9

;сравниваем текущее значение секунд с ограничением «9»

brne ne9

;если не равно то переход

 clr num

;иначе сбрасываем счетчик секунд num

 rjmp vv

ne9:

inc num

;увеличиваем на 1

vv:

pop tmp

;восстанавливаем регистр статуса

out SREG,tmp

reti

;возврат

SB3event:

;обработка нажатия кнопки SB3

ldi tmp,$3f

;на индикацию выводим «0»

out portc,tmp

clr num

;очищаем текущее количество секунд

ret

numout:

;подпрограмма вывода секунд на индикатор

ldi zl,s7

;настраиваем zl на начало 7-сегм. кодов

ldi zh,$00

push zl

;сохраняем zl в стек

add zl,num

;сложить zl и num

ld tmp,z

;загрузить содержимое байта, на кот. ссылается z, в рег. tmp

out portc,tmp

;вывод на индикацию

pop zl

;восстанавливаем из стека

ret

;возврат из подпрограммы

Похожие материалы

Информация о работе