atmega8a + таймер

Тема в разделе "Микроконтроллеры AVR", создана пользователем alexxx86, 3 авг 2016.

  1. alexxx86

    alexxx86 Гик

    Добрый вечер!
    Столкнулся с проблемой работы 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
    миллисекунды.
    Вот скрин осциллограммы.
    скрин.png

    Подскажите что не так? Может я туплю и не вижу очевидной ошибки.
     
  2. ostrov

    ostrov Гуру

    Если нужно каждые полсекунды, то:
    OCR1A = 0x3D08

    И вот это место не понятно:
    Код (C++):
         PORTD|=(1<<PORTD1);
         PORTD&=~(1<<PORTD1);
    Дернуть ножкой на 60 наносеунд достаточно?
     
  3. alexxx86

    alexxx86 Гик

    На код не обращайте внимание, создан чтобы сдель осциллограмму.
    Извиняюсь, 0x7A12 это для интервала в 1сек. но сути это не меняет.
    А разве в регистор сравнения не записывается сначало старший байт а потом младший?
    По крайней мере на 168атмеги а именно так и делал.
     
    Последнее редактирование: 3 авг 2016
  4. ostrov

    ostrov Гуру

    Можно сразу в оба байта, работает. А как код проверять если не смотреть? Что не нравится на осциллограмме?
     
  5. alexxx86

    alexxx86 Гик

    На осциллограмме прерывание срабатывает каждые 4 миллисекунды а не каждую секунду.
     
  6. Alex19

    Alex19 Гуру

    Бросается в глаза строка:
    Код (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);
     
    Последнее редактирование: 3 авг 2016
  7. ostrov

    ostrov Гуру

    Кстати, да. Вот это деление, а не логическая операция, то есть ошибка:
    Код (C++):
    TCCR1B|=(1<<WGM12)/(1<<CS12);
    Ну так и почему не смотреть код, если он не правильный? И OCR и настройки.
     
  8. alexxx86

    alexxx86 Гик

    На ошибки не обращайте внимание))) Накосячил пока здесь редактировал код))) значение регитров H и L действительно перепутаны, но опять же только здесь))) Я работаю в атмел студио, и вот что получается если в регистор сравнения записать целиком то все работает а если сначало старший байт а потом младший то уже не работает. Возможно косяк в самой студии. Спасибо вам за помощь!
     
  9. ostrov

    ostrov Гуру

    Странный вы человек. Выложил код который написан неправильно, говорит не смотрите там все не так как надо, только вот не работает, объясните в чем дело!
     
  10. alexxx86

    alexxx86 Гик

    Вот код который не работает:
    Код (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);
    }
     
  11. alexxx86

    alexxx86 Гик

    А этот уже работает:
    Код (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);
    }