Что не так с таймером3 у атмеги 1284р?

Тема в разделе "Микроконтроллеры AVR", создана пользователем SavvaRem, 2 окт 2018.

  1. SavvaRem

    SavvaRem Гик

    Приветствую, форумчане.

    Нужен дельный совет относительно работы таймера-счетчика 3 у атмеги1284р.
    Делаю сейчас на ней тахометр. Сигнал подается на пин INT0 и генерирует на нем прерывание, в котором инкрементируется переменная-счетчик COUNT. При достижении в счетном регистре TCNT3 значения определенного в регистре сравнения OCR3A должно произойти прерывание по "событию А" с обнулением COUNT, но оно не происходит. Я не уверен, что таймер вообще запускается и все ли я делаю правильно. Если не сложно, гуру, посмотрите, пожалуйста код. Что не так?

    С уважением,
    Савелий
     

    Вложения:

  2. parovoZZ

    parovoZZ Гуру

    А можно код сюда под спойлер?
    Вектор прерывания откуда взят?

    И ещё не понимаю - как в прерывании увеличивается значение счетчика CT3? Я бы понял, если бы тактирующий сигнал подавался на ногу T3. Но у данного МК ноги INT0 != T3.
     
  3. SavvaRem

    SavvaRem Гик

    Код (C++):
    /* circle-buffer averaging */
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <SPI.h>//SPI lib
    #include <PDQ_GFX.h>//PDQ: Core graphics library (bloody fast!!!! =)))))
    #include "PDQ_ST7735_config.h"//PDQ: pins and other setup for this sketch
    #include <PDQ_ST7735.h>//PDQ: Hardware-specific driver library


    #define TICK_TO_COMPARE 1953U // количество "тиков" таймера 3 для генерации прерывания
                                  // соответствует 1/1024*8MHz/4 = 0.25 секунд

    PDQ_ST7735 tft;// PDQ: create LCD object

    const int BacklightPIN = 12; // пин подсветки экрана ST7735
    const int SwitchOnButtonPIN = 0; //пин для включения девайса
    const int DeviceOnPIN = 1; //пин включающий питание ключем

    volatile unsigned int count=0;//переменная-счетчик

    void Timer3Init(void) {

       OCR3A=TICK_TO_COMPARE; // регистр сравнения для генерации прерывания раз в 0.25 сек
     
       TCCR3B|=(1<<CS32);//запуск таймера с предделителем на 1024
       TCCR3B|=(1<<CS30);
       TCCR3B|=(1<<WGM32);//регистр включения режима СТС (сброс при совпадении)
       TIMSK3|=(1<<OCIE3A);//флаг разрешения прерывания по "событию 3А"
       
       EICRA|=(1<<ISC01);   //прерывание по заднему фронту на пине INT0 (PD2)
       EIMSK|=(1<<INT0);  //разрешение внешнего прерывания INT0
         
       sei(); //глобальное разрешение прерываний
    }

    void setup() {

     
    /* SWITCH ON SECTION */
    pinMode(SwitchOnButtonPIN,INPUT_PULLUP); //Setup of Switch ON pin mode (for checking ON button pressed)
    pinMode(DeviceOnPIN,OUTPUT); //Setup of Switch OFF pin mode (for turn on device (to turn ON should be HIGH))
    pinMode(BacklightPIN,OUTPUT);//Setup of backlight PWM pin

    if (SwitchOnButtonPIN==LOW) {
    delay(2000);
       if (SwitchOnButtonPIN==LOW) {
       digitalWrite(DeviceOnPIN, HIGH);
       delay(10);
       }
    }

    // Setup the LCD
    #if defined(ST7735_RST_PIN)  // reset like Adafruit does
      FastPin<ST7735_RST_PIN>::setOutput();
      FastPin<ST7735_RST_PIN>::hi();
      FastPin<ST7735_RST_PIN>::lo();
      delay(1);
      FastPin<ST7735_RST_PIN>::hi();
    #endif

    //setup of LCD screen
      tft.begin();      // initialize LCD
      tft.setRotation(2);
      tft.fillScreen(ST7735_BLACK);
      tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
      digitalWrite(BacklightPIN, HIGH);


      Timer3Init(); // инициализация таймера-счетчика T3
    }

    void loop() {
       
        tft.setCursor(0, 0);
        tft.println(count);
    }


    ISR(INT0_vect)//вектор прерывания INT0 (инкрементирует счетчик)
    {
       count++;
    }


    ISR(TIMER3_COMPA_vect)//при TCNT3 == регистр сравнения OCR3A
    {                     //генерация прерывания и обнуление счетчика
       count=0;
    }
     
  4. SavvaRem

    SavvaRem Гик

    Вектор взят из инклудов AVR-GСС-Toolchain. А именно из файла iom1284p.h
    Полностью привести его не могу, так как у форума ограничение на длину сообщений.
     
  5. SavvaRem

    SavvaRem Гик

    Счетчик COUNT инкрементируется в векторе прерывания INT0, а при достижении счетным регистром TCNT3 значения в региcтре сравнения OCR3A он(счетчик) должен сбрасываться в ноль, но не сбрасывается. Грешу на запрет прерываний в векторе INT0 или на корявые побитовые сдвиги в настройках таймера... Не могу понять что не так ((((
     
  6. parovoZZ

    parovoZZ Гуру

    А как определил? Код вроде ровный.
    CT3 больше никто не использует?
     
    Последнее редактирование: 2 окт 2018
    SavvaRem нравится это.
  7. parovoZZ

    parovoZZ Гуру

    в даташите вот что написано
     
    SavvaRem нравится это.
  8. SavvaRem

    SavvaRem Гик

    Тобишь, нужно принудительно флаг OCF1A установить в единицу, правильно ли понимаю, что вот так:

    TIFR1|=(1<<OCF1A)?
     
  9. parovoZZ

    parovoZZ Гуру

    Не, не. Во флаг ничего не запишешь, только обнулишь.

    В дашике написан бит OCIEA, у тебя же OCIE3A. Если они определены одинаково, то пофигу. Я с этим МК не работал.
    И всё же
    как определил?
     
  10. SavvaRem

    SavvaRem Гик

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

    Идея была вот такая - как только таймер дотикает до регистра сравнения, в векторе обнулится глобальная
    count:

    ISR(TIMER3_COMPA_vect)//при TCNT3 == регистр сравнения OCR3A
    { //генерация прерывания и обнуление счетчика
    count=0;
    }
     
  11. parovoZZ

    parovoZZ Гуру

    там скорее всего не pico power, но утверждать не буду. У атмела надо аккуратно с этим - attiny2313 и attiny2313A по ногам отличаются.

    это понятно. Не понятно с TCNT3 - его показания никуда не выводятся. Я бы вывел на внешний вывод с блока сравнения и посмотрел бы осликом или ЛА. Ну или светиком - четверть секунды на глаз различима
     
  12. SavvaRem

    SavvaRem Гик

    И еще, спасибо за наводку, попробую глянуть обертки ардуиновские, может быть в них где-то используется Т3 для генерации ШИМ, что-то сразу не догадался...
     
  13. SavvaRem

    SavvaRem Гик

    Ок, спасибо, учту =)
     
  14. SavvaRem

    SavvaRem Гик

    Короче победа! Удалось обуздать таки таймер. Если кому интересно, приложу код и пояснения почему код был нерабочий, авось пригодится...
     
  15. parovoZZ

    parovoZZ Гуру

    давай рассказывай.
     
  16. b707

    b707 Гуру

    и пропал...
     
  17. SavvaRem

    SavvaRem Гик

    Привет, суть как и ожидалось оказалась в том, что таймер 3 использовали ардуиновские обертки для генерации ШИМ, естественно, если записывать единицы в отдельные разряды порта, то число записанное в порт управления таймером будет неправильное, поэтому нужно писать в порт не поразряно а-ля:

    TCCR3B|=(1<<CS32);
    TCCR3B|=(1<<CS30);

    а вот так:

    TCCR3A=0x00;
    TCCR3B=0b00000100;
    TCCR3C=0x00;

    что бы затереть, то, что осталось от <arduino.h>
     
  18. SavvaRem

    SavvaRem Гик

    одним сообщением выше отписался
     
  19. b707

    b707 Гуру

    ну молодец. что разобрался.
    Но, вообще-то, это общее правило - если до того конфигурировал таймер не ты - сначала обнули, прежде чем настраивать.
     
    SavvaRem, DetSimen и Mitrandir нравится это.
  20. SavvaRem

    SavvaRem Гик

    Ну вот с помощью этих граблей теперь и я в курсе