Страница 1 из 1

Функция прерывания AtMega 8

Добавлено: Пн ноя 21, 2011 01:36:05
petrovich1285
Здравствуйте.
Недавно начал осваивать прерывания микроконтроллера. Освоение двигалось нормально, но вот когда дошол до внутренних прерываний - прерывание по совпадению, то тут столкнулся с проблемкой.
В функции прерывания нужно увеличивать переменную на единицу и в фуннкции main выводить значение на 7-ми сегментном индикаторе (что-то похожее на часы - подсчет количества временных интервалов). Но значение переменной (time) не увеличивается, не пойму почему.
Может кто-то подскажет в чем проблема. Заранее благодарен.

P.S. испытания проводил на макетной плате

#include <avr/io.h>
#include <avr/interrupt.h>

int time=0;

ISR (TIMER1_COMPA_vect)
{
TCNT1H=0x00;
TCNT1L=0x00;
time++;

}

int main (void)
{
TCCR1A=1<<6;
TCCR1B=5;
TIMSK=1<<4;
OCR1AH=0x1F;
OCR1AL=0x40;
sei();

while (1)
{
//код программы индикации

}
}

Re: Функция прерывания AtMega 8

Добавлено: Пн ноя 21, 2011 03:03:47
woosterstring
Может быть заработает

Код: Выделить всё

volatile int time = 0;
если в регистрах настройка правильная. Это особенности компилятора.

Re: Функция прерывания AtMega 8

Добавлено: Пн ноя 21, 2011 06:11:57
BerZerK-ku
Ошибка в том, что вместо установки СТС режима, вы настроили управление портом.

Код: Выделить всё

TCCR1A = 0;
TIMSK = (1 << OCIE1A);
OCR1AH = 0x1F;
OCR1AL = 0x40;
TCCR1B = (1 << WGM12) | (1 << CS12) | (1 << CS10);
В прерывании обнулять регистр TCNT1 не надо, лишняя трата времени.
+ как выше написано, для переменных изменяемых в прерывании привыкайте использовать volatile.

Re: Функция прерывания AtMega 8

Добавлено: Пн ноя 21, 2011 12:12:42
petrovich1285

Код: Выделить всё

volatile int time = 0;
Урааа!!! заработало!!!
Большое спасибо! А где можно почитать об volatile? А то я об этом первый раз слышу. Перерыл не один форум, сайт и в книгах не встречал такого объявления переменных.

А управление портом мне как раз и надо. К ШИМ режимам я еще не дошол... практически, только теорию почитал.

Re: Функция прерывания AtMega 8

Добавлено: Пн ноя 21, 2011 13:15:50
BCluster
А че тут читать) volatile запрещает компилятору оптимизировать переменную. То есть например есть код

Код: Выделить всё

bool flag=false;
while(flag)
{
...
}
тут цикл скорее всего выполняться не будет, ибо значение переменной flag не поменятеся в процессе выполнения программы.
если же ее объявить как volatile цикл честно выполнится.

В вашем случае тоже самое - компилятор не просматривает обработчики прерываний, считает что переменная не используюется и оптимизирует ее. ИМХО ибо я в winavr не работаю

Re: Функция прерывания AtMega 8

Добавлено: Пн ноя 21, 2011 13:24:31
Мастер Ломастер
petrovich1285 писал(а):А где можно почитать об volatile? А то я об этом первый раз слышу. Перерыл не один форум, сайт и в книгах не встречал такого объявления переменных.
извините, а вы где искали и в каких книгах рылись? не в "сказках народов мира" случайно? просто ну никак не верится вашим словам! если вас в гугле не забанили, посмотрите повнимательнее

Re: Функция прерывания AtMega 8

Добавлено: Пн ноя 21, 2011 13:44:34
petrovich1285
В одной из ссылок, автор сам пишет, что встречался с этим всего 2 раза!
Я, перед открытием этой темы, перерыл форумы, смотрел готовые прошивки електронных часов... в прерываниях использовались переменные, которие там же изменяли свое значение и использовались в бругих местах и не мог понять, почему у них все работает, а у меня нет!
Я так понял, что это и еще зависит и от компилятора, потому как с бодобным уже встречался при изучении прерываний внешних.

Re: Функция прерывания AtMega 8

Добавлено: Пн ноя 21, 2011 15:45:23
woosterstring
Вот выдержка из разела справки FAQ WinAVR (v. 20100110). Этот вопрос часто всплывает у них на форуме.
My program doesn't recognize a variable updated within an interrupt routine.
When using the optimizer, in a loop like the following one:

Код: Выделить всё

uint8_t flag;
...
ISR(SOME_vect) {
  flag = 1;
}
...

        while (flag == 0) {
                ...
        }
the compiler will typically access flag only once, and optimize further accesses completely away, since its code path analysis shows that nothing inside the loop could change the value of flag anyway. To tell the compiler that this variable could be changed outside the scope of its code path analysis (e. g. from within an interrupt routine), the variable needs to be declared like:

Код: Выделить всё

volatile uint8_t flag;