реклама на сайте
подробности

 
 
> Help! Timer0 в ATmega168PA отказывается повиноваться
DVF
сообщение Apr 23 2012, 06:41
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 630
Регистрация: 26-07-06
Из: Саратов
Пользователь №: 19 097



В расположенном ниже примере кода 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] для длинного кода!!!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 2)
Палыч
сообщение Apr 23 2012, 07:09
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(DVF @ Apr 23 2012, 10:41) *
if( OCF0A ) // Обнаружение флага компаратора OCF0A Timer0
.........
как-будто флаг Timer0, настроенного на 10мс опять установлен.

Чего же Вы хотели с таким-то условием?
Go to the top of the page
 
+Quote Post
DVF
сообщение Apr 23 2012, 09:42
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 630
Регистрация: 26-07-06
Из: Саратов
Пользователь №: 19 097



Виноват. Буду пробовать с if( TIFR0 & (1<<OCF0A) )
Действительно, так правильно. Теперь следующий шаг, на котором у меня опять затык - это перевод МК в режим ADC Noise Reduction: не уходит после строки SLEEP_MODE_EN(); в спячку.
CODE

void ADC_init()
{
ADCSRA = (1<<ADPS2) | (1<<ADPS1); // ADC отключен. Предделение тактовой 64 (время конвертации 104uS)
ADMUX = (1<<ADLAR); // Аналоговый вход 0, Выравнивание результатов ADC в лево
DIDR0 = (1<<ADC0D); // Отключение цифрового буфера от входа 0 ADC
ACSR = (1<<ACD); // Отключение питания от компаратора
ADCSRB = 0x00; // ADC: Free Running mode
}

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();
}

#pragma vector = ADC_vect
__interrupt void ADC_interrupt(void)
{
SLEEP_MODE_DIS(); // Запрет на "сон"
ADC_Data = ADCH;
}

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( TIFR0 & (1<<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;
}

POWER_ADC_SUP(); // Подаем питание на ADC (PRR &= ~(1<<PRADC))
ADC_EN(); // Разрешаем работу ADC (ADCSRA |= (1<<ADEN))
ADC_INTERRUPT_EN(); // Разрешаем прерывание от ADC (ADCSRA |= (1<<ADIE))
ADC_NOISE_REDUCTION_MODE(); // Устанавливаем режим ADC Noise Reduction (SMCR |= (1<<SM0))
SLEEP_MODE_EN(); // Запускаем режим сна (SMCR |= (1<<SE))

LED_LEVEL_SCAN_OFF(); // Выключение св.диода.

if( ADC_Data > 0x99 )
{
LED_NORM_ON();
}
else
{
LED_NORM_ERR_OFF();
}

}
}
}


Сообщение отредактировал DVF - Apr 23 2012, 19:26
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th July 2025 - 21:16
Рейтинг@Mail.ru


Страница сгенерированна за 0.01362 секунд с 7
ELECTRONIX ©2004-2016