AVR и аппаратный ШИМ

Модератор: boogyman

Ответить
Аватара пользователя
boogyman
Модератор
Сообщения: 183
Зарегистрирован: 25 дек 2011, 22:48
Откуда: Москва

AVR и аппаратный ШИМ

#1

Сообщение boogyman »

Чем аппаратный ШИМ отличается от программного? В программном мы просто переключаем ножку контроллера с нуля на единицу с большой частотой и меняем задержку между переключениями. В аппаратном ШИМе мы снимаем сигнал с ножек контроллера OC1A, OC1B, OC2 которые напрямую подключены к таймерам/счетчикам, тут остается лишь настроить сами таймеры и менять верхний предел счета для изменения коэффициента заполнения ШИМ. Ниже представлен код проекта управления RGB светодиодом на atmega8.

Код: Выделить всё

/*** Управление RGB светодиодом. Аппаратный ШИМ ***/
#include <avr/io.h>
#include <util/delay.h>

#define pwm_r OCR1A // канал для красного цвета
#define pwm_g OCR1B // канал для зеленого цвета
#define pwm_b OCR2 // канал для синего цвета

/*** красный цвет ***/
void red (unsigned int time)
	{
        for (char a = 0; a<254; a++)
		{
            pwm_r = 255 - a; //увеличение
			pwm_g = 0;
			pwm_b = 0;
			_delay_ms(time);
		}     
        for (char a = 0; a<254; a++)
		{
            pwm_r = a; //уменьшение
			pwm_g = 0;
			pwm_b = 0;
			_delay_ms(time);
		}
	}

/*** зеленый цвет ***/
void green (unsigned int time)
	{
        for (char a = 0; a<254; a++)
		{
 			pwm_g = 255 - a;
			pwm_r = 0;
			pwm_b = 0;
			_delay_ms(time);
		}     
        
		for (char a = 0; a<254; a++)
		{
			pwm_g = a;
			pwm_r = 0;
			pwm_b = 0;
			_delay_ms(time);
		}

	}
/*** синий цвет ***/
void blue (unsigned int time)
	{
        for (char a = 0; a<254; a++)
		{
            pwm_b = 255 - a;
			pwm_g = 0;
			pwm_r = 0; 
			_delay_ms(time);
		}     
        for (char a = 0; a<254; a++)
		{
			pwm_b = a;
			pwm_g = 0;
			pwm_r = 0; 
			_delay_ms(time);
		}
	}
/*** белый цвет ***/
void white (unsigned int time)
	{
        for (char a = 0; a<254; a++)
		{
            pwm_r = 255 - a;
			pwm_g = 255 - a;
            pwm_b = 255 - a;
			_delay_ms(time);
		}     
        for (char a = 0; a<254; a++)
		{
            pwm_r = a;
			pwm_g = a;
			pwm_b = a; 
			_delay_ms(time);
		}
	}

/*** переход цветов ***/
void rgb (unsigned int time)
	{
	    for (char a = 0; a<254; a++)
		{
			pwm_r = a;
			pwm_b = 255 - a;
			pwm_g = 0;
			_delay_ms(time);
		}

		for (char a = 0; a<254; a++)
		{
			pwm_b = a;
			pwm_g = 255 - a;
			pwm_r = 0;
			_delay_ms(time);
		}
		
		for (char a = 0; a<254; a++)
		{
			pwm_g = a;
			pwm_r = 255 - a;
			pwm_b = 0;
			_delay_ms(time);
		}
	}

int main (void) 
{
	DDRB |= (1 << PB3)|(1 << PB2)|(1 << PB1); // PB3,2,1 - выходы
    
    TCCR1A |= (1<<COM1A1)|(1<<COM1B1)|(1<<WGM10); // сброс OC1A/OC1B при достижении верхнего предела счета
    TCCR1B |= (1<<CS10); // без предделителя
    TCCR2 |= (1<<CS20)|(1<<COM21)|(1<<WGM20); // без предделителя, сброс OC2 при достижении верхнего предела счета
	
	pwm_r = 0; // начальные установки ШИМ
	pwm_g = 0;
	pwm_b = 0;

    while(1)
	{ 	
	red(5);
    green(5);		
    blue(5);
	white(5);
	for(;;) 
	{rgb(100);}
	}
}
Аватара пользователя
Hamito
Новичок
Сообщения: 3
Зарегистрирован: 29 фев 2012, 11:30

Re: AVR и аппаратный ШИМ

#2

Сообщение Hamito »

Прогонял в Avrstudio 4 и 5, у меня ошибки
Вложения
errors.png
errors.png (43.95 КБ) 34776 просмотров
Аватара пользователя
boogyman
Модератор
Сообщения: 183
Зарегистрирован: 25 дек 2011, 22:48
Откуда: Москва

Re: AVR и аппаратный ШИМ

#3

Сообщение boogyman »

Ошибки скорей всего синтаксические, в коде ничего не менял?
Аватара пользователя
Hamito
Новичок
Сообщения: 3
Зарегистрирован: 29 фев 2012, 11:30

Re: AVR и аппаратный ШИМ

#4

Сообщение Hamito »

Нет, просто скопировал и вставил. Если посмотреть, то выдает одни и те же ошибки
Аватара пользователя
boogyman
Модератор
Сообщения: 183
Зарегистрирован: 25 дек 2011, 22:48
Откуда: Москва

Re: AVR и аппаратный ШИМ

#5

Сообщение boogyman »

WINAVR нормально установлена?
Аватара пользователя
Hamito
Новичок
Сообщения: 3
Зарегистрирован: 29 фев 2012, 11:30

Re: AVR и аппаратный ШИМ

#6

Сообщение Hamito »

Обновил 4 версию проги, поставил AVR Toolchain 3.3.0 Это тот же винавр, только сейчас по-другому называется. Несколько ошибок осталось, но их удалось исправить. Спасибо за помощь
Аватара пользователя
Vlad1m1r
Новичок
Сообщения: 3
Зарегистрирован: 10 окт 2013, 12:46

Re: AVR и аппаратный ШИМ

#7

Сообщение Vlad1m1r »

boogyman писал(а):Чем аппаратный ШИМ отличается от программного? В программном мы просто переключаем ножку контроллера с нуля на единицу с большой частотой и меняем задержку между переключениями. В аппаратном ШИМе мы снимаем сигнал с ножек контроллера OC1A, OC1B, OC2 которые напрямую подключены к таймерам/счетчикам, тут остается лишь настроить сами таймеры и менять верхний предел счета для изменения коэффициента заполнения ШИМ. Ниже представлен код проекта управления RGB светодиодом на atmega8.

Код: Выделить всё

/*** Управление RGB светодиодом. Аппаратный ШИМ ***/
#include <avr/io.h>
#include <util/delay.h>

#define pwm_r OCR1A // канал для красного цвета
#define pwm_g OCR1B // канал для зеленого цвета
#define pwm_b OCR2 // канал для синего цвета

/*** красный цвет ***/
void red (unsigned int time)
	{
        for (char a = 0; a<254; a++)
		{
            pwm_r = 255 - a; //увеличение
			pwm_g = 0;
			pwm_b = 0;
			_delay_ms(time);
		}     
        for (char a = 0; a<254; a++)
		{
            pwm_r = a; //уменьшение
			pwm_g = 0;
			pwm_b = 0;
			_delay_ms(time);
		}
	}

/*** зеленый цвет ***/
void green (unsigned int time)
	{
        for (char a = 0; a<254; a++)
		{
 			pwm_g = 255 - a;
			pwm_r = 0;
			pwm_b = 0;
			_delay_ms(time);
		}     
        
		for (char a = 0; a<254; a++)
		{
			pwm_g = a;
			pwm_r = 0;
			pwm_b = 0;
			_delay_ms(time);
		}

	}
/*** синий цвет ***/
void blue (unsigned int time)
	{
        for (char a = 0; a<254; a++)
		{
            pwm_b = 255 - a;
			pwm_g = 0;
			pwm_r = 0; 
			_delay_ms(time);
		}     
        for (char a = 0; a<254; a++)
		{
			pwm_b = a;
			pwm_g = 0;
			pwm_r = 0; 
			_delay_ms(time);
		}
	}
/*** белый цвет ***/
void white (unsigned int time)
	{
        for (char a = 0; a<254; a++)
		{
            pwm_r = 255 - a;
			pwm_g = 255 - a;
            pwm_b = 255 - a;
			_delay_ms(time);
		}     
        for (char a = 0; a<254; a++)
		{
            pwm_r = a;
			pwm_g = a;
			pwm_b = a; 
			_delay_ms(time);
		}
	}

/*** переход цветов ***/
void rgb (unsigned int time)
	{
	    for (char a = 0; a<254; a++)
		{
			pwm_r = a;
			pwm_b = 255 - a;
			pwm_g = 0;
			_delay_ms(time);
		}

		for (char a = 0; a<254; a++)
		{
			pwm_b = a;
			pwm_g = 255 - a;
			pwm_r = 0;
			_delay_ms(time);
		}
		
		for (char a = 0; a<254; a++)
		{
			pwm_g = a;
			pwm_r = 255 - a;
			pwm_b = 0;
			_delay_ms(time);
		}
	}

int main (void) 
{
	DDRB |= (1 << PB3)|(1 << PB2)|(1 << PB1); // PB3,2,1 - выходы
    
    TCCR1A |= (1<<COM1A1)|(1<<COM1B1)|(1<<WGM10); // сброс OC1A/OC1B при достижении верхнего предела счета
    TCCR1B |= (1<<CS10); // без предделителя
    TCCR2 |= (1<<CS20)|(1<<COM21)|(1<<WGM20); // без предделителя, сброс OC2 при достижении верхнего предела счета
	
	pwm_r = 0; // начальные установки ШИМ
	pwm_g = 0;
	pwm_b = 0;

    while(1)
	{ 	
	red(5);
    green(5);		
    blue(5);
	white(5);
	for(;;) 
	{rgb(100);}
	}
}
Здравствуйте, а как нужно этот код поменять чтоб он заработал на attiny2313! :-)
Как я понимаю у 2313 4 аппаратных шим, и два таймер счетчика по два канала пврада один 8 а второй 16 разрядный!
Ножки на которых есть таймер счетчик это oc0b/PD5, это нога стоит как то омобнеком, а три остальные вместе это oc0a/PB2, oc1a/PB3, oc1b/PB4, вот как на них правильно включить шим? И вообще я правильно понял что только на них есть шим и таймер счетчики?
Аватара пользователя
boogyman
Модератор
Сообщения: 183
Зарегистрирован: 25 дек 2011, 22:48
Откуда: Москва

Re: AVR и аппаратный ШИМ

#8

Сообщение boogyman »

В attiny2313 настройки 8-ми и 16 - ти разрядных таймеров похожи:

Код: Выделить всё

TCCR1A |= (1 << COM1A1)|(1 << COM1B1)|(1 << WGM10); // сброс OC1A/OC1B при достижении верхнего предела счета
TCCR1B |= (1 << CS10); // без предделителя
TCCR0A |= (1 << COM0A1)|(1 << WGM00); // сброс OC0A при достижении верхнего предела счета
TCCR0B |= (1 << CS00); // без предделителя
В начале кода надо еще заменить канал OCR2 на OCR0A
Аватара пользователя
Vlad1m1r
Новичок
Сообщения: 3
Зарегистрирован: 10 окт 2013, 12:46

Re: AVR и аппаратный ШИМ

#9

Сообщение Vlad1m1r »

boogyman писал(а):В начале кода надо еще заменить канал OCR2 на OCR0A
Большое спасибо за отзывчивость!!! :-)

Ну как я понял еще и входы нужно не забыть поменять :-)

Код: Выделить всё

DDRB |= (1 << PB4)|(1 << PB3)|(1 << PB2); // PB4,3,2 - выходы
Аватара пользователя
boogyman
Модератор
Сообщения: 183
Зарегистрирован: 25 дек 2011, 22:48
Откуда: Москва

Re: AVR и аппаратный ШИМ

#10

Сообщение boogyman »

Да, выходы надо обязательно поменять
Аватара пользователя
Vlad1m1r
Новичок
Сообщения: 3
Зарегистрирован: 10 окт 2013, 12:46

Re: AVR и аппаратный ШИМ

#11

Сообщение Vlad1m1r »

boogyman писал(а):В attiny2313 настройки 8-ми и 16 - ти разрядных таймеров похожи:
Хм... Странно, но работает в точности да наоборот. Сразу загорается цвет максимальной яркости, убавляется постепенно, а потом загорается так же медленно!! :) Что-то похоже я еще не разобрался как работает аппаратный шим)))
Аватара пользователя
uuu000
Любитель
Сообщения: 17
Зарегистрирован: 08 апр 2019, 00:15

Re: AVR и аппаратный ШИМ

#12

Сообщение uuu000 »

При попытке компиляции нашел11 ошибок в файле delay.h
"__builtin_avr_delay_cycles expects a compile time integer constant pwm 2 c:\program files (x86)\atmel\studio\7.0\toolchain\avr8\avr8-gnu-toolchain\avr\include\util\delay.h 187"
Что обозначает эта ошибка?
Ответить