Министерство образования Российской Федерации
Российский государственный профессионально-педагогический университет
Инженерно-педагогический институт
Лабораторная работа №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 |
;возврат из подпрограммы |
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.