Пример №1. Управление яркостью светодиода с помощью ШИМ
Пояснения к схеме
Программа
//************************************************************
//
// Учебный курс. Программирование микроконтроллеров AVR на Си
// Управление нагрузкой с помощью
// широтно-импульсной модуляции (ШИМ, PWM)
//
//************************************************************
#include
#include
int main(void)
{
//инициализация портов
PORTB = 0;
DDRB = 0xff;
//инициализация таймера Т0
TIMSK = 0;
//реж. - fast pwm, вывод OC0 - неинверт. шим, clk/64
TCCR0 = (1<<WGM01)|(1<<WGM00)|(1<<COM01)|(0<<COM00)|(0<<CS02)|(1<<CS01)|(1<<CS00);
TCNT0 = 0;
OCR0 = 0;
//ион - напряжение питания, выравнивание влево, нулевой канал
ADMUX = (0<<REFS1)|(1<<REFS0)|(1<<ADLAR)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0);
//вкл. ацп, реж. непрерывн. преобр., разр. прерывания, частота преобр. = FCPU/128
ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
//режим непрерывного преобразования
SFIOR = 0;
__enable_interrupt();
while(1);
return 0;
}
//********************************
//прерывание АЦП
#pragma vector=ADC_vect
__interrupt void adc_my(void)
{
Пояснения к коду
Логика работы
Инициализация периферии - таймера Т0, модуля АЦП. Разрешение прерываний. Бесконечный цикл. В прерывании АЦП напряжение считанное с переменного резистора записывается в регистр сравнения OCR0. В микроконтроллере AVR для этого регистра организован буфер , и на самом деле запись происходит сначала в него. Из буфера же значение переписывается в OCR0, только когда происходит переполнение счетного регистра TCNT0. Параллельно циклу while и модулю АЦП, работает таймер Т0 и генерит на выводе OC0(PB2) ШИМ сигнал. Когда счетный регистр TCNT0 переполняется OC0 устанавливается в 1, когда значение счетного регистра совпадает с регистром сравнения OCR0, вывод устанавливается в 0.
Инициализация таймера
Пример №2. Генерация синусоидального сигнала с помощью ШИМ
Пояснение к схемe
Резистор R2 просто забыл выкинуть из схемы. R3 и C8 интегратор.
Программа
#include
#include
#include "TableSin.h"
int main(void)
{
//инициализация портов
PORTB = 0;
DDRB = 0xff;
TIMSK = (1<<OCIE0);
//реж. - fast pwm, вывод OC0 - неинверт. шим, предделитель - на 8
TCCR0 = (1<<WGM01)|(1<<WGM00)|(1<<COM01)|(0<<COM00)|(0<<CS02)|(1<<CS01)|(0<<CS00);
//обнуляем счетный регистр и регистр сравнения
TCNT0 = 0;
OCR0 = 0;
__enable_interrupt();
while(1);
return 0;
}
Пояснения к коду
Таблица значений синуса
TableSin.h - хедер, в котором прописан константный массив, содержащий 32 значения синуса.
Инициализация таймера Т0
В программе используется прерывание таймера Т0 по событию совпадение.Для разрешения прерывания устанавливается бит OCIE0 регистра TIMSK. Остальная часть инициализации таймера, как и в предыдущей программе.
Обработчик прерывания таймера Т0
В прерывании таймера микроконтроллер считывает из массива очередное значение синуса и записывает его в регистр сравнения OCR0. Действительная перезапись этого регистра происходит когда счетный регистр таймера Т0 переполняется. Для доступа к элементам массива используется статическая переменная, значение которой увеличивается на 1, пока не дойдет до 32.