;++++++++Set Timer 1
ldi temp,high(292 97)
out OCR1AH,temp
ldi temp,low(2 9297)
out OCR1AL,temp
ldi temp,0b00001101
out TCCR1B,temp ;1/1024; очистить после совпадения
ldi temp,(1<
;по совпадению для Timer 1 и переполнению Timer 0
out TIMSK,temp
Переключающий режим для вывода PDS-OC1A здесь мы не используем. Кроме этого, введем переменную count_min, с помощью которой будем считать интервалы в 7,5 с. В секции объявления переменных добавим:
def count_min = r23 ;счетчик 7,5-секундных интервалов
А в секции начальных установок его не забудем обнулить:
clr count_min
Далее введем специальный флаг sleep (пусть будет бит 7 в регистре Flag), который будет сигнализировать о режиме. Если этот бит установлен — пора «спать», если обнулен — работаем, как ни в чем не бывало. По умолчанию он обнулен (см. секцию «начальная установка переменных») и нам ничего не грозит, если мы вставим в основной цикл запуск режима энергосбережения по схеме, согласно листингу 17.2.
Gcykle:
sbrs Flag,7 ;если бит 7 установлен, то засыпаем
гjmp Gcykle ;иначе бесконечный цикл
cli ;на всякий случай запрещаем прерывания; все порты на вход, и нули в разряды, кроме PortD,6
clr temp
out DDRB,temp
out DDRC,temp
out DDRD,temp
out PortB,temp
out PortC,temp
ldi temp,0b01000000 ;выключение питания на всякий случай
out PortD,temp
ldi temp,0b11100000 ;разрешение Sleep, режим Standby прерывание по уровню
out MCUCR,temp
ldi temp,(1<
out GICR,temp
sei ;разрешаем прерывания
Sleep ;наконец, спим
cbr Flag, $80 ;по выходу из сна сбрасываем флаг sleep
clr count_min ;отсчет времени
;сначала установка портов вход-выход обратно
cli ;на всякий случай запрещаем прерывания
ldi temp,0b00111111 ; разряды out DDRB,temp
ldi temp,0b01111111 ; сегменты out DDRC,temp
ldi temp,0b11000000 ; знак минус и питание
out DDRD,temp
clr temp
out PortD,temp ;включить аналоговое питание
out MCUCR,temp ;запрещаем режим Sleep
out TCNT1H,temp ;очищаем счетные регистры таймера
out TCNT1L,temp
ldi temp,0b00001101 ; запускаем таймер
out TCCR1B,temp ;1/1024 очистить после совпадения
sei ;разрешаем прерывания
rjmp Gcykle ;бесконечный цикл
Теперь самое сложное: разобраться с прерываниями и установкой флага sleep. Не забудьте заменить reti на rjmp TIM1_COMPA в таблице прерываний, в строке для прерывания Timer1 Compare А (шестое сверху, не считая RESET). Прерывание таймера иллюстрирует листинг 17.3.
ТIМ1_СОМРА:
inc count_min
cpi count_min,1 ;через 7,5 с разрешаем INTO
brne schet_time
ldi temp,(1<
out GICR,temp ;GIMSK и GIGR — синонимы
schet_time: ;здесь отсчет времени
sbrs count_min,3 ;если бит 3=1, то прошло 8 интервалов =1 мин
reti ;иначе выходим
clr count_min ;в след, раз — сначала
sbr Flag,$80 ;устанавливаем бит sleep
clr temp ;останавливаем таймер
out TCCR1B,temp
reti ;выходим