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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Какой-то бред..., ...с прерыванием по таймеру
HCHUNTER
сообщение Jan 2 2008, 10:34
Сообщение #1


Участник
*

Группа: Новичок
Сообщений: 19
Регистрация: 29-12-07
Пользователь №: 33 732



AVR Mega8, 16МГц, среда разработки CVAVR v1.25.
Делаю все по шаблону, как предлагает мастер. Пытаюсь создать прерывание по таймеру №0 каждые 64 мкс (15625 Гц).

Вот текст программы:

Цитата
#include <mega8.h>
#include <delay.h>

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0x00; // сбросить счетчик таймера
PORTB.0=0; // выставить на ножке "0" на период ~3...4 мкс
delay_us (3);
}


void main(void)
{

PORTB=0x00;
DDRB=0xFF;

PORTC=0x00;
DDRC=0x7F;

PORTD=0x00;
DDRD=0xFF;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 15,625 kHz
TCCR0=0x05;
TCNT0=0x00;


// Timer/Counter 1 initialization
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x01;

// Analog Comparator initialization
ACSR=0x80;
SFIOR=0x00;


#asm("sei")

while (1)
{
PORTB.0=1; //на ножке постоянная "1", прерывать ее каждые 64 мкс
};

}


Результат смотрю на осциллографе - хрен два! Постоянная единица, ничего не прерывается.
Пробовал и так и эдак... И что я только не писал в обработчик прерывания - ничего не помогает. И запрещать прерывания там пробовал, и заново таймер реинициализировал...
Разве что проскакивает этот самый ожидаемый "0" каждые примерно 5 секунд (определяю по взмаргиванию линии на осциллографе).
И что это за бред...? cranky.gif
Где моя ошибка?

Сообщение отредактировал HCHUNTER - Jan 2 2008, 10:37
Go to the top of the page
 
+Quote Post
DASM
сообщение Jan 2 2008, 10:44
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



Откуда 64 мкс насчитали ? 8e6/1024/256 - 30 Гц. У вас фуз работы от кварца прошит ? Или от внутренного RC по умолчанию работаете ?
Go to the top of the page
 
+Quote Post
HCHUNTER
сообщение Jan 2 2008, 10:49
Сообщение #3


Участник
*

Группа: Новичок
Сообщений: 19
Регистрация: 29-12-07
Пользователь №: 33 732



Работаю от кварца, это совершенно точно.
Я такую простенькую программку написал уже от безысходности, чтобы выяснить где же я дурак...

Раньше с таймерами не работал, факт.
А почему Вы пишете 8e6/1024/256 - 30 Гц ? отуда 256? Мастер мне пишет, что частота настроенная составляет 15625 Гц.
Go to the top of the page
 
+Quote Post
DASM
сообщение Jan 2 2008, 10:52
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



там таймер0 - 8 битный, перполнение будет когда 255 превысит и сбросит в ноль, вот и 256 берется. 1024 - prescaler у Вас.
Кстати delay - я так понял библиотечная ? Я бы свою, попроще поставил вначале.
Go to the top of the page
 
+Quote Post
HCHUNTER
сообщение Jan 2 2008, 11:16
Сообщение #5


Участник
*

Группа: Новичок
Сообщений: 19
Регистрация: 29-12-07
Пользователь №: 33 732



а как же мне тогда правильно таймер проинициализировать?
Получается
TCCR0=0x05;
TCNT0=0xFF;

так?
Go to the top of the page
 
+Quote Post
DASM
сообщение Jan 2 2008, 11:20
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



нет, или надо тогда переписывать TCNT0 не нулем в прерывании а 256 - N , где N - коэфф деления или воспользваться чем-нибудь более продвинутым, типа Compare в 1-ом таймере.
256 - N - тут могу путать немного, не силен в арифметике и голова плохо варит.
Кстати TCNT0=0x00; // сбросить счетчик таймера - это Вы написали или мастер ? Предделитель тоже 1024 великоват, 8e6/1024 = 7812.5 Гц.
Попробуйте TCCR0 = 4 (делитель на 256), а в прерывании писать TCNT0 = 254. И уберите библиотечную задержку - и без нее нормальным осциллом все увидите
Go to the top of the page
 
+Quote Post
HCHUNTER
сообщение Jan 2 2008, 11:37
Сообщение #7


Участник
*

Группа: Новичок
Сообщений: 19
Регистрация: 29-12-07
Пользователь №: 33 732



Вобщем, сделал как сам же написал выше
TCCR0=0x05;
TCNT0=0xFF;
вроде бы все заработало...
щас буду думать дальше...
Go to the top of the page
 
+Quote Post
DASM
сообщение Jan 2 2008, 11:38
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



А ну да, у Вас же 16 Мгц, а не 8, что-то зациклился. Тогда правильно, только где Вы выше написали про = 0xFF ?
Go to the top of the page
 
+Quote Post
HCHUNTER
сообщение Jan 2 2008, 11:49
Сообщение #9


Участник
*

Группа: Новичок
Сообщений: 19
Регистрация: 29-12-07
Пользователь №: 33 732



Да, конечно. В самой процедуре прерывания я тоже поправляю счетчик таймера.

В любом случае, огромное спасибо за наводку на мою ошибку!
Пойду, попробую "прикрутить" полученное под свою конкретную задачу...
Go to the top of the page
 
+Quote Post
INT1
сообщение Jan 2 2008, 19:34
Сообщение #10


deleted
****

Группа: Свой
Сообщений: 555
Регистрация: 28-08-05
Пользователь №: 8 024



Кстати, писать столько нулей в инициализации портов и глобальных переменных, вроде как и смысла нет, они по Атмелю и АНСИ СИ и так обнуляются
Go to the top of the page
 
+Quote Post
Guest_=AVR=_*
сообщение Jan 2 2008, 19:44
Сообщение #11





Guests






Эээ... это по какому такому АНСИ СИ порты "и так обнуляются", интересно узнать?

Сообщение отредактировал =AVR= - Jan 2 2008, 19:45
Go to the top of the page
 
+Quote Post
Aesthete Animus
сообщение Jan 2 2008, 20:03
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 222
Регистрация: 9-06-07
Пользователь №: 28 317



Лучше инвертировать по прерыванию таймера ножку порта, то есть:
Код
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
    // Инвертировать быстрее xor`ом. Но т.к. я не знаю
    // специфики CV, то написал так:
    PORTB.0 = (PORTB.0 == 0 ? 1 : 0); // Инвертируем ножку
}


При этом не забудьте убрать цикл "while (1)" из мейна.

Хочу заметить, что всякие задержки в прерываниях (наподобее delay_us) крайне не рекоммендуются, прерывание - это критическая часть кода, из которого следует выходить как можно скорее.

=AVR=
Цитата(INT1 @ Jan 2 2008, 22:34) *
они [порты] по Атмелю и АНСИ СИ и так обнуляются

wink.gif
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Jan 2 2008, 20:07
Сообщение #13


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Цитата(=AVR= @ Jan 2 2008, 21:44) *
Эээ... это по какому такому АНСИ СИ порты "и так обнуляются", интересно узнать?

Для тех, кто читает не всё:
порты - по Atmel (default value);
глобальные переменные - по АНСИ СИ.
Go to the top of the page
 
+Quote Post
HCHUNTER
сообщение Jan 2 2008, 20:36
Сообщение #14


Участник
*

Группа: Новичок
Сообщений: 19
Регистрация: 29-12-07
Пользователь №: 33 732



Цитата(Aesthete Animus @ Jan 2 2008, 23:03) *
При этом не забудьте убрать цикл "while (1)" из мейна.

А это для чего? что оно мне даст?
куда же я тогда возвращаться-то буду... в "никуда" получается...


Цитата
Хочу заметить, что всякие задержки в прерываниях (наподобее delay_us) крайне не рекоммендуются, прерывание - это критическая часть кода, из которого следует выходить как можно скорее.

Вот это мне тоже, кстати, не совсем понятно... Звучит как заученная фраза из книжек.
А если мне нужно по возникновении прерывания выполнить массу всего? Что мне тогда делать...?

Ведь мне никто не запрещает в прерывании остановить таймер, выполнить все что мне нужно, а по выходу из прерывания снова его запустить?
С моей (ламерской) точки зрения процедура-обработчик может быть сколь угодно долгой. Главное, чтобы в это время я не наловил новых прерываний...

Сообщение отредактировал HCHUNTER - Jan 2 2008, 20:40
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Jan 2 2008, 21:28
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(HCHUNTER @ Jan 3 2008, 00:36) *
Вот это мне тоже, кстати, не совсем понятно... Звучит как заученная фраза из книжек.
А если мне нужно по возникновении прерывания выполнить массу всего? Что мне тогда делать...?


Мне кажется что в учебниках как раз про это не слова. Как правило это из опыта. Но тем не менее возможен и такой способ работы (как вы описали). Если у вас одно прерывание. Можно и с несколькими обойтись, таким же образом. Только надо чётко представлять что ты делаешь и какие проблемы могут возникнуть.

Если же в рамках общепринятого, то на вопрос "А если мне нужно по возникновении прерывания выполнить массу всего?" можно ответить таким образом. Выставить в прерывании флаг а в голове определить флаг и "выполнить массу всего".

В программировании любое действие можно сделать десятком способов. Выбирайте свой. Но мнение других всётаки желательно хотя бы послушать. Чтобы самому сделать свой выбор.
Go to the top of the page
 
+Quote Post

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

 


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


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