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