Шим atmega8

Тема в разделе "Микроконтроллеры AVR", создана пользователем Funny59, 6 май 2017.

Метки:
  1. Funny59

    Funny59 Нерд

    Нужно настроить ШИМ на 30КГц для dc-dc преобразователя на 180 вольт. Не получается его раскачать до нужной частоты.
    На arduin'е работал такой код:
    Код (C++):
    TCCR1B = TCCR1B & 0b11111000 | 0x01;
    analogWrite(10, 130);
    Набросал такой код:
    Код (C++):
    DDRB = 0x02;
    TCCR1A = (1<<COM1A1)|(1<<WGM10)|(1<<WGM12);
    TCCR1B = (1<<CS10);
    OCR1A = 128;
    Частота не та получается, в чем может быть проблема?
     
  2. mcureenab

    mcureenab Гуру

    Сам МК на какой частоте работает? Какой источник времени выбран?
     
  3. ostrov

    ostrov Гуру

    30КГц стандартным ШИМом не получится 8,8 потом сразу 65. Вот тут подробнее. Нужно запускать свой таймер на прерывание.

    Предделитель 1, OCRx = 0x0214 при 16,МГц
     
    Последнее редактирование: 6 май 2017
  4. Funny59

    Funny59 Нерд

    Работает на внешнем 16 МГц, если под "источником времени" вы подразумеваете источник тактирования, то это частота мк
     
  5. Funny59

    Funny59 Нерд

    Будет работать на меге8, регистр tccrb на atmega8 и atmega328 вроде бы не совпадают?(Попробовал как написано, не запустилось)
     
    Последнее редактирование: 6 май 2017
  6. ostrov

    ostrov Гуру

    Вы же пишите "на ардуине", откуда на ардуине atmega8.
     
  7. Funny59

    Funny59 Нерд

    в шапке написал atmega8, извиняюсь что не продублировал в посте
     
  8. Funny59

    Funny59 Нерд

    ну если что, есть arduino ng на atmega8
     
  9. mcureenab

    mcureenab Гуру

    (1<<WGM10)|(1<<WGM12) - это Fast PWM, 8-bit 0x00FF, т.е. частоту делим на 256.
     
  10. mcureenab

    mcureenab Гуру

    Чтобы из 16MHz получить 30kHz нужно делить на 533.
    Думаю, можно использовать
    (1<<WGM10)|(1<<WGM11)
    это 16000kHz / 512 = 31.25 kHz получается
     
  11. mcureenab

    mcureenab Гуру

    Но мне не понятно, зачем
    COM1A1 - Clear OC1A/OC1B on Compare Match (Set output to low level)
    Это же не генерация частоты, а просто отключение пина через время.
    COM1A0 - Toggle OC1A/OC1B on Compare Match

    и
    OCR1A = 256;
    чтобы 50% скважность была.
     
  12. ostrov

    ostrov Гуру

    Я написал что нужно для точного 30КГц, делитель и OCR от МК не зависит. Останется лишь добавить функцию с инверсией ножки в одну команду.
     
  13. mcureenab

    mcureenab Гуру

    Почему?

    16MHz / 533 = 30 018.8 Hz
     
  14. ostrov

    ostrov Гуру

    Как вы делить на 533 собрались то?

    Написать настройку для таймера Атмеги8 что ли уже?
     
  15. ostrov

    ostrov Гуру

    Не проверял, попробуйте сами:
    Код (C++):
    void setup() {
      cli();
      TCCR1A = 0x00;      // настройка таймера 1, канала А
      TCCR1B = 0x01;      // предделитель CLK/1;
      OCR1A = 0x0214;     // прерывание раз в 33мкс, если нужен полупериод то делим на два
      TIMSK = 0b00010000; // запуск таймера по совпадению 1А
      sei();              // разрешаем прерывания (запрещаем: cli(); )
    }

    void loop() {
    }


    ISR(TIMER1_COMPA_vect)  //обработчик прерывания по совпадению А
    {
      // тут инвертируем ногу
      TCNT1 = 0;            //обнуляем регистр TCNT1 (мб не обязательно в данном случае)
    }
     
  16. mcureenab

    mcureenab Гуру

    По формуле WGM 14 = Fast PWM mode :
    fOC1APWM = fclk_I/O / ( N * (1 + TOP))
    N = 1 - prescaler
    TOP = ICR1 = 532.

    Скважность в регистре OCR1A.
     
  17. mcureenab

    mcureenab Гуру

    Тестировал на Arduino LEONARDO. На осциллографе примерно 30 кГц получается.

    Код (C++):
    // Pins
    #define OC1A 9

    #ifdef PRR0
    #define TIMER1_PRTIM1 PRR0
    #else
    #define TIMER1_PRTIM1 PRR
    #endif

    class Timer1
    {
    public:
      enum CS : uint8_t { // Clock Select
        CS_STOP = 0,                              // No clock source. (Timer/Counter stopped), Initial
        CS_1 =                        _BV(CS10),  // clkI/O/1 (No prescaling)
        CS_8 =              _BV(CS11),            // clkI/O/8 (From prescaler)
        CS_64 =             _BV(CS11)|_BV(CS10),  // clkI/O/64 (From prescaler)
        CS_256 =  _BV(CS12),                      // clkI/O/256 (From prescaler)
        CS_1024 = _BV(CS12)          |_BV(CS10),  // clkI/O/1024 (From prescaler)
        CS_FALL = _BV(CS12)|_BV(CS11),            // External clock source on T1 pin. Clock on falling edge (PD6 (T1/OC4D/ADC9))
        CS_RISE = _BV(CS12)|_BV(CS11)|_BV(CS10)   // External clock source on T1 pin. Clock on rising edge  (PD6 (T1/OC4D/ADC9))
      };

      enum _WGM : uint8_t { // WGM internal bit mask
        _WGM__ = 0b0000,
        _WGM13 = 0b1000,
        _WGM12 = 0b0100,
        _WGM11 = 0b0010,
        _WGM10 = 0b0001,
      };

      enum WGM : uint8_t { // Waveform Generation Mode
        WGM_0  = _WGM__,                            // Normal, Initial
        WGM_1  =                            _WGM10, // PWM, Phase Correct, 8-bit
        WGM_2  =                   _WGM11,          // PWM, Phase Correct, 9-bit
        WGM_3  =                   _WGM11 | _WGM10, // PWM, Phase Correct, 10-bit
        WGM_4  =          _WGM12,                   // CTC, Clear Timer on Compare Match OCR1A
        WGM_5  =          _WGM12          | _WGM10, // Fast PWM, 8-bit, TOP=0xff
        WGM_6  =          _WGM12 | _WGM11,          // Fast PWM, 9-bit, TOP=0x1ff
        WGM_7  =          _WGM12 | _WGM11 | _WGM10, // Fast PWM, 10-bit, TOP=0x3ff
        WGM_8  = _WGM13,                            // PWM, Phase and Frequency Correct,  input capture ( IC ) function is disabled
        WGM_9  = _WGM13                   | _WGM10, // PWM, Phase and Frequency Correct
        WGM_10 = _WGM13          | _WGM11,          // PWM, Phase Correct,  input capture ( IC ) function is disabled
        WGM_11 = _WGM13          | _WGM11 | _WGM10, // PWM, Phase Correct
        WGM_12 = _WGM13 | _WGM12,                   // CTC, Clear Timer on Compare Match, ICR1,  input capture ( IC ) function is disabled
        WGM_14 = _WGM13 | _WGM12 | _WGM11,          // Fast PWM, input capture ( IC ) function is disabled, TOP=ICR1
        WGM_15 = _WGM13 | _WGM12 | _WGM11 | _WGM10, // Fast PWM, TOP=OCR1A
      };
      static inline Timer1& instance()
      {
        static Timer1 i;
        return i;
      }
      void inline start_timer()  { TIMER1_PRTIM1 &= ~(_BV(PRTIM1)); } // Initial
      void inline stop_timer()   { TIMER1_PRTIM1 |=   _BV(PRTIM1);  } // Shuts down the Timer/Counter1 module
      void set_CS(Timer1::CS mode);    // Clock Select
      void set_WGM(Timer1::WGM mode);  // Waveform Generation Mode
    protected:
    private:
      Timer1();
      ~Timer1();
      Timer1(Timer1 const&) = delete;
      Timer1& operator= (Timer1 const&) = delete;
    };


    Timer1::Timer1() { };

    Timer1::~Timer1(){ };

    void Timer1::set_CS(
      Timer1::CS mode
    ){
        TCCR1B = ( TCCR1B & ~( _BV(CS12)|_BV(CS11)|_BV(CS10) ) ) | mode;
    }

    void Timer1::set_WGM(
      Timer1::WGM mode
    ){
        TCCR1A = TCCR1A & ~( _BV(WGM11)|_BV(WGM10) ) | (_WGM11 & mode ? _BV(WGM11) : 0) | (_WGM10 & mode ? _BV(WGM10) : 0) ;
        TCCR1B = TCCR1B & ~( _BV(WGM13)|_BV(WGM12) ) | (_WGM13 & mode ? _BV(WGM13) : 0) | (_WGM12 & mode ? _BV(WGM12) : 0) ;
    }

    Timer1& tr1( Timer1::instance() );


    void setup() {
      // put your setup code here, to run once:
        pinMode(OC1A, OUTPUT); // Пин 9 аппаратно связан с таймером 1.
        tr1.set_WGM(Timer1::WGM_14); // Fast PWM, TOP = ICR1.
        tr1.set_CS(Timer1::CS_1); // Делитель частоты = 1.
        TCCR1A = TCCR1A & ~( _BV(COM1A1)|_BV(COM1A0) ) | _BV(COM1A1); // Режим пина OC1A "non-inverted PWM"
        ICR1 = 532;  // Частота 16000000 / CS_1 / (1 + ICR1) = 30018 Hz
        OCR1A = ICR1 / 5; // Скважность
        tr1.start_timer(); // Запускаем модуль Timer/Counter 1.
    }

    void loop() {
      //  if ( ! --OCR1A ) OCR1A = ICR1;  // Циклически меняем скважность
        delay(10);
    }
     
     
    Последнее редактирование: 7 май 2017
  18. mcureenab

    mcureenab Гуру

    Последнее редактирование: 7 май 2017
  19. ostrov

    ostrov Гуру

    Вот вы извращенцы то. Не поленюсь сделаю на 328 сегодня и покажу.
     
  20. mcureenab

    mcureenab Гуру

    Извращение - не пользоваться функциями МК специально для того предназначенными.
    А ШИМ на прерываниях, это грубо из-за джиттера.

    Автора может быть WGM_6 устроит на частоте 31кГц. Зато все ШИМ выходы таймера можно будет использовать.