Добрый вечер! Столкнулся с проблемой работы 16-разрядного таймера1 в режиме СТС (сброс при совпадении) на атмеги8а. Банальный код, который должен дергать ножкой каждые по секунды. Частота 8mHz, делитель 256 Код (C++): #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> int main(void) { DDRD|=(1<<PORTD1); TCCR1A = 0; TCCR1B|=(1<<WGM12)/(1<<CS12); // Режим CTC (сброс при совпадении). делитель 256 TIMSK|=(1<<OCIE1A); OCR1AL = 0x7A; OCR1AH = 0x12; sei(); while (1) { } } ISR(TIMER1_COMPA_vect) { PORTD|=(1<<PORTD1); PORTD&=~(1<<PORTD1); } Но в результате прерывание по таймеру срабатывает почти каждые 4 миллисекунды. Вот скрин осциллограммы. Подскажите что не так? Может я туплю и не вижу очевидной ошибки.
Если нужно каждые полсекунды, то: OCR1A = 0x3D08 И вот это место не понятно: Код (C++): PORTD|=(1<<PORTD1); PORTD&=~(1<<PORTD1); Дернуть ножкой на 60 наносеунд достаточно?
На код не обращайте внимание, создан чтобы сдель осциллограмму. Извиняюсь, 0x7A12 это для интервала в 1сек. но сути это не меняет. А разве в регистор сравнения не записывается сначало старший байт а потом младший? По крайней мере на 168атмеги а именно так и делал.
Можно сразу в оба байта, работает. А как код проверять если не смотреть? Что не нравится на осциллограмме?
Бросается в глаза строка: Код (C++): TCCR1B|=(1<<WGM12)/(1<<CS12); // Режим CTC (сброс при совпадении). делитель 256 Возможно это ошибка вставки, так более корректно. TCCR1B|=(1<<WGM12)|(1<<CS12); Не очень понятно данная строка Код (C++): OCR1AL = 0x7A; OCR1AH = 0x12; Возможно тоже описка, для 1 секунды, перепутаны L и H регистры. Код (C++): OCR1AH=0x7A; OCR1AL=0x12; Можно писать OCR1A = 31250, мне так нагляднее. У меня нет Atmega8a. Поэтому так же проверил в СodeVisionAVR, рекомендую скачать, вот код. Код (C++): // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 31,250 kHz // Mode: CTC top=OCR1A // OC1A output: Disconnected // OC1B output: Disconnected // Noise Canceler: Off // Input Capture on Falling Edge // Timer Period: 1 s // Timer1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: On // Compare B Match Interrupt: Off TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10); TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (1<<CS12) | (0<<CS11) | (0<<CS10); TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x7A; OCR1AL=0x11; OCR1BH=0x00; OCR1BL=0x00; UPD. И еще блок, забыл Код (C++): // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (1<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<TOIE0);
Кстати, да. Вот это деление, а не логическая операция, то есть ошибка: Код (C++): TCCR1B|=(1<<WGM12)/(1<<CS12); Ну так и почему не смотреть код, если он не правильный? И OCR и настройки.
На ошибки не обращайте внимание))) Накосячил пока здесь редактировал код))) значение регитров H и L действительно перепутаны, но опять же только здесь))) Я работаю в атмел студио, и вот что получается если в регистор сравнения записать целиком то все работает а если сначало старший байт а потом младший то уже не работает. Возможно косяк в самой студии. Спасибо вам за помощь!
Странный вы человек. Выложил код который написан неправильно, говорит не смотрите там все не так как надо, только вот не работает, объясните в чем дело!
Вот код который не работает: Код (C++): #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> int main(void) { DDRD|=(1<<PORTD1); TCCR1B|=(1<<WGM12)|(1<<CS12); TIMSK|=(1<<OCIE1A); OCR1AH = 0x7A; OCR1AL = 0x12; sei(); while (1) { } } ISR(TIMER1_COMPA_vect) { PORTD|=(1<<PORTD1); PORTD&=~(1<<PORTD1); }
А этот уже работает: Код (C++): #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> int main(void) { DDRD|=(1<<PORTD1); TCCR1B|=(1<<WGM12)|(1<<CS12); TIMSK|=(1<<OCIE1A); OCR1A = 0x7A12; sei(); while (1) { } } ISR(TIMER1_COMPA_vect) { PORTD|=(1<<PORTD1); PORTD&=~(1<<PORTD1); }