Таймер 0 используется в режиме сброса при совпадении и генерирует нужный сигнал , таймер 1 в нормальном режиме и используется для опроса кнопок.
По нажатию на кнопку на пине PD3 происходит смена предделителя таймера 0. Однако, при выполнении программы , делитель меняется только один раз с 256 до 1024 , больше смена почему то не происходит. проверял в протеусе и на контролере, все абсолютно одинаково - "по нажатию" на PD3 один раз устанавливается больший предделитель и больше чип на кнопку не реагирует, частота сигнала понижается. Контроллер работает от внешнего кварца на 16 МГц.
CODE
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
volatile uint8_t flags;
#define KeysF 2
#define StopS 3
void init_timers(void){
cli();
// TCCR0A : com0A1 com0A0 com0B1 com0B0 - - WGM01 WGM00
// TCCR0B : FOC0A FOC0B - - WGM02 CS02 CS01 CS00
// TCCR1A : COM1A1 COM1A0 COM1B1 COM1B0 – – WGM11 WGM10
// TCCR1B : ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10
// TCCR1C : FOC1A FOC1B – – – – – –
// TIMSK : TOIE1 OCIE1A OCIE1B - ICIE1 OCIE0B TOIE0 OCIE0A
// TIFR : TOV1 OCF1A OCF1B – ICF1 OCF0B TOV0 OCF0A
TCCR0A = (1<<WGM01);
TCCR0B = (1<<CS02);
OCR0A = 254;
TCCR1A = 0;
TCCR1B = (1<<CS12);
TIMSK = (1<<OCIE0A) | (1<<TOIE1) ;
sei();
}
/*
Table 41. Clock Select Bit Description
CS02 CS01 CS00 Description
0 0 0 No clock source (Timer/Counter stopped)
0 0 1 clkI/O/(No prescaling)
0 1 0 clkI/O/8 (From prescaler)
0 1 1 clkI/O/64 (From prescaler)
1 0 0 clkI/O/256 (From prescaler)
1 0 1 clkI/O/1024 (From prescaler)
1 1 0 External clock source on T0 pin. Clock on falling edge.
1 1 1 External clock source on T0 pin. Clock on rising edge.
*/
ISR(TIMER0_COMPA_vect){
flags |= 1;
}
ISR(TIMER1_OVF_vect){
flags |= (1<<KeysF);
TCNT1 = 65536 - 31250;
}
int main(void){
DDRB = 0;
PORTB = 0;
DDRD = 1<<PD6;
PORTD = (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) ;
init_timers();
sleep_enable();
while(1){
sleep_cpu();
if ((flags & 1) && !(flags & (1<<StopS))) {
PORTD |= 1<<PD6 ;
asm("nop");
asm("nop");
PORTD &= ~(1<<PD6) ;
flags &= ~1 ;
}
if (flags & (1<<KeysF)) { // 2 раза в секунду опрашиваем кнопки
flags &= ~(1<<KeysF) ;
// увеличиваем частоту таймер 0
if (bit_is_clear(PIND,PD0) && OCR0A > 2)
OCR0A --;
// уменьшаем частоту таймер 0
if (bit_is_clear(PIND,PD1) && OCR0A < 255)
OCR0A ++;
if (bit_is_clear(PIND,PD2)){
if ( flags & (1<<StopS) )
flags &= ~(1<<StopS) ;
else
flags |= (1<<StopS) ;
}
if (bit_is_clear(PIND,PD3)){
cli();
if (TCCR0B & (1<CS00))
TCCR0B = (1<<CS02);
else
TCCR0B = (1<<CS02) | (1<<CS00);
sei();
}
}
}
}