|
Какой-то бред..., ...с прерыванием по таймеру |
|
|
|
Jan 2 2008, 10:34
|
Участник

Группа: Новичок
Сообщений: 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 секунд (определяю по взмаргиванию линии на осциллографе). И что это за бред...? Где моя ошибка?
Сообщение отредактировал HCHUNTER - Jan 2 2008, 10:37
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 22)
|
Jan 2 2008, 10:49
|
Участник

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

|
Работаю от кварца, это совершенно точно. Я такую простенькую программку написал уже от безысходности, чтобы выяснить где же я дурак...
Раньше с таймерами не работал, факт. А почему Вы пишете 8e6/1024/256 - 30 Гц ? отуда 256? Мастер мне пишет, что частота настроенная составляет 15625 Гц.
|
|
|
|
|
Jan 2 2008, 11:16
|
Участник

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

|
а как же мне тогда правильно таймер проинициализировать? Получается TCCR0=0x05; TCNT0=0xFF;
так?
|
|
|
|
|
Jan 2 2008, 11:37
|
Участник

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

|
Вобщем, сделал как сам же написал выше TCCR0=0x05; TCNT0=0xFF; вроде бы все заработало... щас буду думать дальше...
|
|
|
|
|
Jan 2 2008, 11:49
|
Участник

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

|
Да, конечно. В самой процедуре прерывания я тоже поправляю счетчик таймера.
В любом случае, огромное спасибо за наводку на мою ошибку! Пойду, попробую "прикрутить" полученное под свою конкретную задачу...
|
|
|
|
Guest_=AVR=_*
|
Jan 2 2008, 19:44
|
Guests

|
Эээ... это по какому такому АНСИ СИ порты "и так обнуляются", интересно узнать?
Сообщение отредактировал =AVR= - Jan 2 2008, 19:45
|
|
|
|
|
Jan 2 2008, 20:03
|

Местный
  
Группа: Свой
Сообщений: 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)  они [порты] по Атмелю и АНСИ СИ и так обнуляются
|
|
|
|
|
Jan 2 2008, 20:36
|
Участник

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

|
Цитата(Aesthete Animus @ Jan 2 2008, 23:03)  При этом не забудьте убрать цикл "while (1)" из мейна. А это для чего? что оно мне даст? куда же я тогда возвращаться-то буду... в "никуда" получается... Цитата Хочу заметить, что всякие задержки в прерываниях (наподобее delay_us) крайне не рекоммендуются, прерывание - это критическая часть кода, из которого следует выходить как можно скорее. Вот это мне тоже, кстати, не совсем понятно... Звучит как заученная фраза из книжек. А если мне нужно по возникновении прерывания выполнить массу всего? Что мне тогда делать...? Ведь мне никто не запрещает в прерывании остановить таймер, выполнить все что мне нужно, а по выходу из прерывания снова его запустить? С моей (ламерской) точки зрения процедура-обработчик может быть сколь угодно долгой. Главное, чтобы в это время я не наловил новых прерываний...
Сообщение отредактировал HCHUNTER - Jan 2 2008, 20:40
|
|
|
|
|
Jan 2 2008, 21:39
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(HCHUNTER @ Jan 2 2008, 23:36)  Ведь мне никто не запрещает в прерывании остановить таймер, выполнить все что мне нужно, а по выходу из прерывания снова его запустить? Никто не запрещает. С другой стороны, никто не запрещает также запустить таймер с одинаковыми интервалами времени. И пусть себе тикает. В обработчике прерывания таймера - взводить флажек, сигнализирующий, что некое событие наступило. И уже потом "в спокойной обстановке" тобиш в основном цикле программы проверить флажек и выполнить все, что требуется для обработки этого события.. Цитата С моей точки зрения процедура-обработчик может быть сколь угодно долгой. Конечно может, но меня например несколько раздражает когда жмешь CTRL-ALT-DEL, а системе "пофиг", т.к. некий программист решил сделать сколь угодно долгий обработчик. Если вам подходит такой стиль - то без проблем, пишите так ;> Цитата а как же мне тогда правильно таймер проинициализировать? Получается TCCR0=0x05; TCNT0=0xFF; Есть режим таймера CTC - очистка по сравнению. В этом режиме не надо трогать TCNT регистр, т.к. таймер сам будет сбрасываться тогда когда вы ему укажате. Правда в m8 этот режим есть только у таймера 1 и таймера 2. Если вам нужно отмерять один "тик", то на таймере 2 инициализация будет выглядеть так: #define WGM21 3 #define OCIE2 7 OCR2 = 1; TCCR2 = 0x07 | (1 << WGM21); TIMSK = (1 << OCIE2);
|
|
|
|
|
Jan 2 2008, 22:08
|
Участник

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

|
Цитата Если вам нужно отмерять один "тик", то на таймере 2 инициализация будет выглядеть так:
#define WGM21 3 #define OCIE2 7
OCR2 = 1; TCCR2 = 0x07 | (1 << WGM21); TIMSK = (1 << OCIE2); Да, я встречал подобную запись, когда разбирал чей-то код. Однако работаю в CVAVR, а там такое не прокатывает... не знает он что такое WGM и OCIE2...
|
|
|
|
Guest_=AVR=_*
|
Jan 2 2008, 22:13
|
Guests

|
Как не знает? Даже сразу после того, как ему сказали #define WGM21 и #define OCIE2?? Вот уж поистине ... - Новый год
|
|
|
|
|
Jan 4 2008, 17:59
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 28-09-07
Пользователь №: 30 914

|
Помогите плиз разобраться с таймерами Необходимо что бы Т0 и Т1 работали на переполнение с частотой ЦПУ (это не надо объяснять), а вот Т2 от часового кварца Подключаю часовой кварц к PC6, PC7 (ATmega16, 32), а инициализация будет, следующей?: Код #define TIMER_CLK_DIV8 0x02 ///< Timer clocked at 32.768KHz/8 #define TIMER_PRESCALE_MASK 0x07 ///< Timer Prescaler Bit-Mask #define TIMER2OVERFLOW_INT 5 volatile unsigned long Timer2Reg0;
void timer2Init(void) { // initialize timer 2 outb(TCCR2, (inb(TCCR2) & ~TIMER_PRESCALE_MASK) | TIMER_CLK_DIV8); // count 32.768KHz/8 outb(TCNT2, 0); // reset TCNT2 sbi(TIMSK, TOIE2); // enable TCNT2 overflow sbi(ASSR, AS2); // switch to asynchronous input (32KHz crystal) Timer2Reg0 = 0; // initialize time registers // attach service to real-time clock interrupt // rtcService() will be called at ((32768/8)/256) = 16Hz timerAttach(TIMER2OVERFLOW_INT, rtcService); sei(); }
|
|
|
|
|
Jan 4 2008, 22:20
|

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

|
Цитата(Dim_ON @ Jan 4 2008, 20:59)  Помогите плиз разобраться с таймерами Необходимо что бы Т0 и Т1 работали на переполнение с частотой ЦПУ (это не надо объяснять), а вот Т2 от часового кварца Подключаю часовой кварц к PC6, PC7 (ATmega16, 32), а инициализация будет, следующей?: Разрешите приведу код из doc2505 небольшими изменениями для иициализации часового кварца Код void init_Ex3(void) { ASSR= 1<<AS2; // Enable asynchronous // mode // Clear timer on compare match / Timer Clock = // system clock / 1024 TCCR2 = (1<<CTC2)|(1<<CS22)|(1<<CS21)|(1<<CS20); TIFR= 1<<OCF2; // Clear OCF2/ Clear // pending interrupts TIMSK= 1<<OCIE2; // Enable Timer2 Output // Compare Match Interrupt OCR2= 31; // Set Output Compare // Value to 32 DDRB= 0xFF; // Set Port B as output while (ASSR&(1<<OCR2UB)); // Wait for registers to update } В этом случае, прерывание по сравнению таймера №2 (SIG_OUTPUT_COMPARE2) будет вызываться раз в секунду. Хочу заметить, что в документации для регистра OCR2 задано неверное значение, у них вместо 31 написано 32.
|
|
|
|
|
Jan 5 2008, 09:04
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 28-09-07
Пользователь №: 30 914

|
Сори за офф, но решил не создавать новой темы, а спросить тут. Правильно ли я понимаю функционирование таймеров/счетчиков: Режим переполнения(overflow) - это когда таймеры считают синхроипульсы, и прерывание происходит когда MAX_COUNT-->0, при этом MAX_COUNT зависит от размерности таймера.
Режим совпадения(outcompare) - это когда в регистр OCR записывают MAX_COUNT, счетчик каждый такт сравнивает содержимое регистров OCR и TCNT, при равенстве происходит прерывание.
Режим захвата и сравнения - это когда состояние регистра TCNT сохраняется в регистре ICR по активному фронту ноги ICP, и для сравнения нам надо считывать ICR
Асинхронный режим - это когда источником синхроимпульсов является резонатор, подключенный к ногам TOSC1 и TOSC2
Режим генерации ШИМ - это отдельная тема
Режим подсчета внешних событий - это когда содержимое регистра TCNT увеличивается при...?? Не пойму, можно ли настраивать что бы работали на инкремент или декремент?
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|