Очередные разборки с ассемблером. Попытка организовать ШИМ на таймере 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 ничего не видит. Где я натупил?
С ассемблером не очень, поэтому наводящий вопрос: правильно ли я понимаю, что 'Temp1' это алиас одного из РОН? И Вы уровень ШИМ не в тот регистр записываете. Нужен OCR2, а не TCCR2 (последняя строка инициализации таймера). Касательно регистра флагов прерываний -- TIFR -- он сбрасывается записыванием единиц в соответствующие биты, а не нулей.
По порядку, как регистры идут в даташите: TCCR2: в биты WGM пишем обе единицы (FastPWM из таблицы 42), в биты COM пишем необходимый режим (таблица 44), по таблице 46 в биты CS пишем необходимое значение прескалера (он и только он определит частоту ШИМ). В остальные биты нули. Как только установится значение прескалера, таймер запустится. Чтобы остановить таймер, в прескалер пишем нули. При этом сам прескалер не остановится, а таймер не сбросится! TCNT2 - пишем ноль, если необходимо сбросить таймер. OCR2 - сюда заносим значение, пропорциональное необходимой скважности. Всё. Должны наблюдать ШИМ на выходе. ASSR2 - ничего не пишем. Там и так нули после сброса TIMSK2 - если не нужны прерывания - ничего не пишем TIFR2 - флаги сбрасываются чтением или записью единицы. Если отслеживать события таймера не нужно, то и не трогаем. SFIOR: бит PSR2 - пишем единицу для сброса прескалера, если нужен "ровный" (синхронизированный) старт таймера.
Вот это я лоханулся. Попутал TCCR2 и OCR2 и не заметил такой элементарной ошибки. Наверно старческий маразм. Спасибо, что ткнули носом.