Перейти к содержанию
    

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:

Где моя ошибка?

Изменено пользователем HCHUNTER

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Откуда 64 мкс насчитали ? 8e6/1024/256 - 30 Гц. У вас фуз работы от кварца прошит ? Или от внутренного RC по умолчанию работаете ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Работаю от кварца, это совершенно точно.

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

 

Раньше с таймерами не работал, факт.

А почему Вы пишете 8e6/1024/256 - 30 Гц ? отуда 256? Мастер мне пишет, что частота настроенная составляет 15625 Гц.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

там таймер0 - 8 битный, перполнение будет когда 255 превысит и сбросит в ноль, вот и 256 берется. 1024 - prescaler у Вас.

Кстати delay - я так понял библиотечная ? Я бы свою, попроще поставил вначале.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а как же мне тогда правильно таймер проинициализировать?

Получается

TCCR0=0x05;

TCNT0=0xFF;

 

так?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

нет, или надо тогда переписывать TCNT0 не нулем в прерывании а 256 - N , где N - коэфф деления или воспользваться чем-нибудь более продвинутым, типа Compare в 1-ом таймере.

256 - N - тут могу путать немного, не силен в арифметике и голова плохо варит.

Кстати TCNT0=0x00; // сбросить счетчик таймера - это Вы написали или мастер ? Предделитель тоже 1024 великоват, 8e6/1024 = 7812.5 Гц.

Попробуйте TCCR0 = 4 (делитель на 256), а в прерывании писать TCNT0 = 254. И уберите библиотечную задержку - и без нее нормальным осциллом все увидите

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вобщем, сделал как сам же написал выше

TCCR0=0x05;

TCNT0=0xFF;

вроде бы все заработало...

щас буду думать дальше...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А ну да, у Вас же 16 Мгц, а не 8, что-то зациклился. Тогда правильно, только где Вы выше написали про = 0xFF ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

В любом случае, огромное спасибо за наводку на мою ошибку!

Пойду, попробую "прикрутить" полученное под свою конкретную задачу...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати, писать столько нулей в инициализации портов и глобальных переменных, вроде как и смысла нет, они по Атмелю и АНСИ СИ и так обнуляются

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость =AVR=

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

Изменено пользователем =AVR=

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Лучше инвертировать по прерыванию таймера ножку порта, то есть:

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

 

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

 

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

 

=AVR=

они [порты] по Атмелю и АНСИ СИ и так обнуляются

;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Для тех, кто читает не всё:

порты - по Atmel (default value);

глобальные переменные - по АНСИ СИ.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

А это для чего? что оно мне даст?

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

 

 

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

Вот это мне тоже, кстати, не совсем понятно... Звучит как заученная фраза из книжек.

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

 

Ведь мне никто не запрещает в прерывании остановить таймер, выполнить все что мне нужно, а по выходу из прерывания снова его запустить?

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

Изменено пользователем HCHUNTER

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот это мне тоже, кстати, не совсем понятно... Звучит как заученная фраза из книжек.

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

 

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

 

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

 

В программировании любое действие можно сделать десятком способов. Выбирайте свой. Но мнение других всётаки желательно хотя бы послушать. Чтобы самому сделать свой выбор.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...