Подключаем кнопку и настраиваем ШИМ на микроконтроллере ATmega8

В этом уроке подключим кнопку к выводу PB0, светодиод — к выводу PB3, а затем настроим аппаратный ШИМ микроконтроллера ATmega8. При нажатии кнопки яркость светодиода будет плавно увеличиваться и уменьшаться.

Подключение кнопки и светодиода

Для работы программы кнопку подключаем к выводу PB0, а светодиод — к выводу PB3.

Подключение кнопки и светодиода к ATmega8
Схема подключения кнопки и светодиода

Регистр TCCR2

Перед настройкой ШИМ необходимо рассмотреть регистр TCCR2, который задаёт режим работы таймера/счётчика 2.

Регистр TCCR2 микроконтроллера ATmega8
Биты регистра TCCR2
  • FOC2 — отвечает за принудительное изменение состояния выхода OC2. В нашей программе этот режим не используется.
  • CS22, CS21, CS20 — выбирают источник тактирования и коэффициент деления частоты таймера.
  • WGM20, WGM21 — определяют режим работы таймера/счётчика.
  • COM21, COM20 — определяют поведение выхода OC2.

Делитель частоты Timer2

CS22 CS21 CS20 AS2 = 0 AS2 = 1
0 0 0 Стоп Стоп
0 0 1 clk clkt
0 1 0 clk / 8 clkt / 8
0 1 1 clk / 32 clkt / 32
1 0 0 clk / 64 clkt / 64
1 0 1 clk / 128 clkt / 128
1 1 0 clk / 256 clkt / 256
1 1 1 clk / 1024 clkt / 1024

clk — системный тактовый сигнал.

clkt — тактовый сигнал от внешнего источника, используемого асинхронным Timer2.

Выбор режима Timer2

WGM21 WGM20 Режим работы
0 0 Normal
0 1 Phase Correct PWM
1 0 CTC
1 1 Fast PWM

Настройка выхода OC2

COM21 COM20 Режим работы
0 0 Таймер/счётчик отключён от выхода OC2
0 1 Состояние выхода меняется на противоположное в соответствующих режимах
1 0 Выход сбрасывается
1 1 Выход устанавливается

Основная программа — main.c

#include <avr/io.h>
#include <util/delay.h>
#include "pwr.h"

void init(void);
void init_PWR(void);


int main(void)
{
    init();
    init_PWR();

    while (1)
    {
        if (B_PB0 == 0)
        {
            /* Кнопка нажата */

            while (OCR2 < 0xff)
            {
                OCR2 = OCR2 + 0x01;
                _delay_ms(15);
            }

            while (OCR2 > 0x00)
            {
                OCR2 = OCR2 - 0x01;
                _delay_ms(15);
            }
        }
        else
        {
            /* Кнопка не нажата */

            OCR2 = 0x00;
        }
    }
}


void init(void)
{
    /*
        PB0 — вход.
        Включаем внутреннюю подтяжку к питанию.
    */
    PORTB = 0b00000001;

    /*
        PB3 — выход
    */
    DDRB = 0b00001000;
}


void init_PWR(void)
{
    /*
        Источник тактирования Timer2
    */
    ASSR = 0x00;

    /*
        Fast PWM
        OC2 сбрасывается при совпадении
        делитель частоты = 64
    */
    TCCR2 = 0b01101100;

    /*
        Счётчик начинает работу с нуля
    */
    TCNT2 = 0x00;

    /*
        Начальное значение регистра сравнения
    */
    OCR2 = 0x00;
}

Заголовочный файл pwr.h

#ifndef PWR_H_
#define PWR_H_

#define F_CPU 1000000

/*
    Считываем состояние входа PB0
*/
#define B_PB0 (PINB & (1 << PB0))

#endif /* PWR_H_ */

Результат работы

После загрузки программы при нажатии кнопки значение регистра OCR2 постепенно увеличивается от 0 до 255, а затем уменьшается обратно до 0. За счёт изменения коэффициента заполнения ШИМ яркость светодиода плавно изменяется. Если кнопку отпустить, в регистр OCR2 записывается 0.