РЕШЕНО Atmega8, pwm на таймер 2

Тема в разделе "Микроконтроллеры AVR", создана пользователем a1000, 13 фев 2020.

  1. a1000

    a1000 Гуру

    Очередные разборки с ассемблером.
    Попытка организовать ШИМ на таймере 2. Светодиод подключён к OC2 (PB3).
    Для начала переводим PB3 на выход
    Код (C++):
    sbi DDRB, 3
    потом настройки таймера 2
    Код (C++):
         
        LDI         Temp1, 0b01101100
        OUT        TCCR2, Temp1
        CLR        Temp1
        OUT        ASSR, Temp1
        OUT        TIMSK, Temp1
        OUT        TIFR, Temp1
        OUT        SFIOR, Temp1
        OUT        TCNT2, Temp1
        LDI          Temp1, 150  ;уровень ШИМ
        OUT        TCCR2, Temp1
    Что куда заносим
    TCCR2
    бит 7 - FOC2. При FastPWM - 0
    биты 6 и 3 - WGM20 и WGM21 1 и 1 режим FastPWM
    биты 5 и 4 - COM21 и COM20 1 и 0 не инвертированный ШИМ
    биты 2, 1, 0 - CS02 - CS00 100. делитель на 64 (пробовал разные варианты, без разницы)
    ASSR - всё в 0 (асинхронный режим не используется)
    TIMSK и TIFR - всё в 0 (прерываний нет)
    SFIOR - тоже в 0 (сброс предделителя не нужен)
    TCNT2 - сбрасываем в 0 счётчик
    TCCR2 - регистр сравнения определяющий коэффициент заполнения ШИМ
    В цикле ничего не делаем, он пустой
    Код (C++):
    ; Основная программа (цикл)
    Main:
       
        ; Цикл выполняется сначала
        RJMP    Main
    Дальше самое интересное. ШИМ запускается при TCCR2 равном 255, 250, 150. Цифры получены случайно, может есть и другие значения. При значении 140, 160 ничего не работает. Светодиод не горит, логический анализатор на PB3 ничего не видит.
    Где я натупил?
     
  2. AlexU

    AlexU Гуру

    С ассемблером не очень, поэтому наводящий вопрос: правильно ли я понимаю, что 'Temp1' это алиас одного из РОН?
    И Вы уровень ШИМ не в тот регистр записываете. Нужен OCR2, а не TCCR2 (последняя строка инициализации таймера).
    Касательно регистра флагов прерываний -- TIFR -- он сбрасывается записыванием единиц в соответствующие биты, а не нулей.
     
    a1000 нравится это.
  3. parovoZZ

    parovoZZ Гуру

    По порядку, как регистры идут в даташите:
    TCCR2: в биты WGM пишем обе единицы (FastPWM из таблицы 42), в биты COM пишем необходимый режим (таблица 44), по таблице 46 в биты CS пишем необходимое значение прескалера (он и только он определит частоту ШИМ). В остальные биты нули. Как только установится значение прескалера, таймер запустится. Чтобы остановить таймер, в прескалер пишем нули. При этом сам прескалер не остановится, а таймер не сбросится!
    TCNT2 - пишем ноль, если необходимо сбросить таймер.
    OCR2 - сюда заносим значение, пропорциональное необходимой скважности.
    Всё. Должны наблюдать ШИМ на выходе.
    ASSR2 - ничего не пишем. Там и так нули после сброса
    TIMSK2 - если не нужны прерывания - ничего не пишем
    TIFR2 - флаги сбрасываются чтением или записью единицы. Если отслеживать события таймера не нужно, то и не трогаем.
    SFIOR: бит PSR2 - пишем единицу для сброса прескалера, если нужен "ровный" (синхронизированный) старт
    таймера.
     
    a1000 нравится это.
  4. a1000

    a1000 Гуру

    Вот это я лоханулся. Попутал TCCR2 и OCR2 и не заметил такой элементарной ошибки. Наверно старческий маразм. Спасибо, что ткнули носом.