В расположенном ниже примере кода Timer0, настроенный на режим компаратора по OCR0A не генерит прерывание, как и было задумано. Для этого в цикле мониторится флаг прерывания этого компаратора с последующим его сбросом. Но не пашет чего-это.
CODE
///--- TIMER0 initialize - prescale:1024 --------------
///--- quartz 8MHz
///--- WGM: CTC
///--- desired value: 10mSec
///--- actual value: 10,048mSec (-0,5%)
void timer0_init()
{
STOP_TIMER0(); //stop
//TCNT0 = 0x32; //set count
OCR0A = 0x4E; //set count limite
OCR0B = 0x4E; //set count limite
TCCR0A = 0x02; // WGM: CTC
}
void devices_init()
{
CLI();
ports_init();
ADC_init();
timer0_init();
MCUCR = 0x00;
EICRA = 0x00; // Extended ext ints
EIMSK = 0x00;
PCMSK0 = 0x00;
PCMSK1 = 0x00;
PCMSK2 = 0x00;
PCICR = 0x00;
PRR = 0xEF; // отключение питания от всей периферии
SEI();
}
void main()
{
devices_init(); // Инициализация контроллера (здесь спрятан и вызов инициализации timer0)
POWER_TIMER0_EN(); // Разрешаем питание на Timer0 (PRR &= ~(1<<PRTIM0))
INT_TIMER0_CTCA_DISBL(); // Запрет прерываний от Timer0 (TIMSK0 &= ~(1<<OCIE0A))
START_TIMER0_PRSCL1024(); // Запустк Timer0 (TCCR0B |= (1<<CS02) | (1<<CS00))
while( 1 )
{
if( OCF0A ) // Обнаружение флага компаратора OCF0A Timer0
{
FLAG_TIMER0_CLINE(); // Сбрасываем флаг Timer0 (TIFR0 |= (1<<OCF0A))
switch( LED_Level ) // Включение св.диода с необходимой интенсивностью
{
case 1:
LED_1LEVEL_SCAN_ON();
break;
case 2:
LED_2LEVEL_SCAN_ON();
break;
case 3:
LED_3LEVEL_SCAN_ON();
break;
}
Data_ADSC = 1; // Значение бита ADSC регистра для дальнейшего слежения в while( Data_ADSC ).
// В обработчике прерывания от ADC переменная Data_ADSC обнуляется
POWER_ADC_SUP(); // Подаем питание на ADC (PRR &= ~(1<<PRADC))
ADC_EN(); // Разрешаем работу ADC (ADCSRA |= (1<<ADEN))
ADC_INTERRUPT_EN(); // Разрешаем прерывание от ADC (ADCSRA |= (1<<ADIE))
ADC_START_CONV(); // Запуск измерения (ADCSRA |= (1<<ADSC))
while( Data_ADSC )
{
;
}
LED_LEVEL_SCAN_OFF(); // Выключение св.диода.
if( ADC_Data > 0x99 )
{
LED_NORM_ON();
}
else
{
LED_NORM_ERR_OFF();
}
}
}
}
Само прерывание ADC не примечательно:
Код
#pragma vector = ADC_vect
__interrupt void ADC_interrupt(void)
{
ADC_Data = ADCH;
Data_ADSC = 0;
}
На строки подачи питания на АЦП и т.п. просьба не обращать внимание - в будущем планируется вести измерение в режиме ADC Noise Reduction.
На скриншоте видно, что св.диод практически постоянно во включенном состоянии (низкий уровень Digital1). Получается, что светит он на время измерения, далее гашение на короткий отрезок и опять вход в измерение, как-будто флаг Timer0, настроенного на 10мс опять установлен.
Сообщение отредактировал IgorKossak - Apr 23 2012, 06:44
Причина редактирования: [codebox] для длинного кода!!!