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

Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 17:14:16
king-live
Доброго времени соток. Изучаю таймеры и прерывания и начал с таймера T/C0. И вот вопрос. в функции White() вместо while(TCNT0<250) хочу использовать флаг прерывания TOV0, для выхода из цикла по переполнению TCNT0. Но как это написать не знаю. Вернее много написал. но ничего не работает. Спасибо.

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

#include <avr/io.h>
#define F_CPU 4000000UL
#include <avr/interrupt.h>

White()
{
TCNT0=0;
while(TCNT0<250){}
}

int main(void) 
{
TIMSK=0b01000001;
SREG=0b10000000;
DDRD=0xff;  
TCCR0=5;
while(1)
	{

PORTD |= _BV(PD0);
White();
PORTD &=~_BV(PD0);
White();
	}
}

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 17:22:54
codenamehawk
Надежней, да и проще использовать прерывания.

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 17:25:45
king-live
Прерывания это надёжно, но как этот код написать или подправить на моём примере?

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 17:27:22
ibiza11

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

while(!(TOV0)){}
TOV0 = 0;

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 17:32:49
king-live
AVRStudio ругается на строчку TOV0=0;

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

#include <avr/io.h>
#define F_CPU 4000000UL
#include <avr/interrupt.h>


White()
{
TCNT0=0;
//while(TCNT0<250){}
while(!(TOV0)){}
TOV0=0;
}

int main(void) 
{
TIMSK=0b01000001;
SREG=0b10000000;
DDRD=0xff;  
TCCR0=1;
while(1)
	{

PORTD |= _BV(PD0);
White();
PORTD &=~_BV(PD0);
White();
	}
}


Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 17:57:40
YS
Так ясен пень, TOV0 это константа-номер бита, расположенного в TIFR.

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

//while(TCNT0<250){}
while(!(TOV0)){}
TOV0=0;
- дико.

Вот:

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

while (!(TIFR & (1<<TOV0)));
А присваивать в TOV0 вообще бессмысленно. Можно очистить этот бит:

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

TIFR&=~(1<<TOV0);

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 18:11:11
Мастер Ломастер
YS писал(а): Можно очистить этот бит:

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

TIFR&=~(1<<TOV0);
очистка битов в регистре TIFR осуществляется ЗАПИСЬЮ ЕДИНИЦ в соответствующие биты, поэтому это неправильный код, правильно будет так: TIFR = (1<<TOV0);

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 18:17:52
king-live

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

[b]while(!(TIFR & (1<<TOV0)))[/b]
Можете мне расписать по подробнее эту строчку? Мне нужно разбить эту строку на части на последовательность операции. Иначе не понятно, и буду опять возвращаться к теме. Спасибо.

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 18:26:01
king-live
Код аппаратно, и программно не работает. После выхода из цикла программа начинает работать с самого начало.

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

#include <avr/io.h>
#define F_CPU 4000000UL
#include <avr/interrupt.h>


White()
{
TCNT0=0;
//while(TCNT0<250){}
while(!(TIFR & (1<<TOV0))){}
//TIFR=(1<<TOV0);
}

int main(void) 
{
TIMSK=0b01000001;
SREG=0b10000000;
DDRD=0xff;  
TCCR0=1;
while(1)
	{

PORTD |= _BV(PD0);
White();
PORTD &=~_BV(PD0);
White();
	}
}

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 18:39:16
ibiza11
YS писал(а):... - дико.
Если уж начали про дикости, то прошу заметить, что дикости начались с начала темы с проверки флага прерывания вместо написания обработчика прерывания.

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 18:42:49
king-live
Как правильно написать обработчик прерывания? Я ни разу не писал и это тема у меня первая с таймерами и прерываниями.

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 20:36:31
YS
После выхода из цикла программа начинает работать с самого начало.
Ибо Вы включили прерывание, и не описали обработчик. По умолчанию AVR-GCC генерирует код, перезагружающий МК при возникновении неописанного прерывания.
очистка битов в регистре TIFR осуществляется ЗАПИСЬЮ ЕДИНИЦ
Фу блин, точно. Тогда

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

TIFR|=(1<<TOV0);
Можете мне расписать по подробнее эту строчку?
Курите битовые операции.
Как правильно написать обработчик прерывания?

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

ISR (<vector>)
{
}
Названия векторов можно найти в документации. Например,

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

ISR (TIM0_COMPA_vect)
{
}

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 21:12:47
king-live
спасибо, попробую поработать с обработчиком прерываний. А на счёт строчки я так понял while(!(TIFR & (1<<TOV0))) цикл работает пока TIFR не равно единице. Это правильно я понял?

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 21:32:44
YS
А на счёт строчки я так понял while(!(TIFR & (1<<TOV0))) цикл работает пока TIFR не равно единице.
Именно.

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 21:52:40
king-live
А для чего нужно TIFR обнулять. Я так понял это происходит аппаратно. или только после вызова обработчика прерывания он может обнулиться?

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 22:02:39
Мастер Ломастер
YS писал(а):Фу блин, точно. Тогда

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

TIFR|=(1<<TOV0);
так тоже можно, но по объему кода и скорости неоптимально. самый эффективный вариант я привел ранее.

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 22:03:48
Мастер Ломастер
king-live писал(а):А для чего нужно TIFR обнулять. Я так понял это происходит аппаратно. или только после вызова обработчика прерывания он может обнулиться?
обнулять его нужно, если вы его опрашиваете без работы с прерываниями - раз нет обработчика, некому аппаратно его сбрасывать, надо вручную.

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Вс мар 25, 2012 22:10:02
king-live
Спасибо! Понял. осталось понять как вызывать прерывания.

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Пн мар 26, 2012 00:14:22
YS
так тоже можно, но по объему кода и скорости неоптимально.
Зато не затрагивает остальные биты.

Re: Работа с таймерами и прерываниями в Mega8

Добавлено: Пн мар 26, 2012 05:37:37
Совесть
Мастер Ломастер писал(а):очистка битов в регистре TIFR осуществляется ЗАПИСЬЮ ЕДИНИЦ в соответствующие биты, поэтому это неправильный код, правильно будет так: TIFR = (1<<TOV0);
Это верно.
YS : Фу блин, точно. Тогда TIFR|=(1<<TOV0);
Мастер Ломастер: так тоже можно, но по объему кода и скорости неоптимально. самый эффективный вариант я привел ранее.
YS: Зато не затрагивает остальные биты.
Диалог опытных программистов :facepalm: Если сбрасываете конкретный флаг, ответ выше. А если хотите сбросить все активные флаги в данном регистре, то не мудрите, делайте проще

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

TIFR = TIFR;