• Добро пожаловать на компьютерный форум Tehnari.ru. Здесь разбираемся с проблемами ПК и ноутбуков: Windows, драйверы, «железо», сборка и апгрейд, софт и безопасность. Форум работает много лет, сейчас он переехал на новый движок, но старые темы и аккаунты мы постарались сохранить максимально аккуратно.

    Форум не связан с магазинами и сервисами – мы ничего не продаём и не даём «рекламу под видом совета». Отвечают обычные участники и модераторы, которые следят за порядком и качеством подсказок.

    Если вы у нас впервые, загляните на страницу о форуме и правила – там коротко описано, как задать вопрос так, чтобы быстро получить ответ. Чтобы создавать темы и писать сообщения, сначала зарегистрируйтесь, а затем войдите под своим логином.

    Не знаете, с чего начать? Создайте тему с описанием проблемы – подскажем и при необходимости перенесём её в подходящий раздел.
    Задать вопрос Новые сообщения Как правильно спросить
    Если пришли по старой ссылке со старого Tehnari.ru – вы на нужном месте, просто продолжайте обсуждение.

ATmega8 - плавное разгорание и затухание светодиода

Счастье

Не очень хороший человек
Регистрация
1 Дек 2012
Сообщения
6,155
Реакции
933
Баллы
0
ATmega8 - плавное разгорание и затухание светодиода

Всем привет!
Как же давно я не писала прошивку, а под рукой сейчас по этому вопросу нет примеров.
Может кто быстренько подскажет?
Есть микроконтроллер, в дип-корпусе
Arduino-To-Atmega8-Pins.png.webp
Задача такая:
например для порта B0 написать программу, чтобы светодиод плавно разгорался и затухал.
Хоть убей, не помню тонкости вопроса, вот шим-модуляцию.
Когда-то давно мне объясняли, на тренировочной плате такой код реализовывала
* Author: Who
*/

#define F_CPU 8000000UL
#include <Util/delay.h>
#include <avr/io.h>

int main(void)
{
DDRD=0b10000000;
TCCR2=0b01101100;

while(1)
{
OCR2=50;
_delay_ms(2000);
OCR2=205;
_delay_ms(2000);


//TODO:: Please write your application code
}
}
Вот после команды инициализации порта я смутно понимаю, почему именно такие значения.
Мне бы пояснений немножко))
 
Судя по тексту, на тренировочной плате был 40-ногий АВР, типа меги16, или 8535, у которой на PD7 выход ШИМа OC2

Для вашего случая на B0 можно организовать только программное переключение, аппаратный ШИМ не получится.

Программа в примере - переключает яркость светодиода на 2 сек, по заполнению 1/5 и 4/5 приблизительно, по яркости на глаз - думаю вполовину будет.
 
Ну да, это я поняла, а как хоть примерно это реализовать программно?
 
У меня получилось как-то так:
Код:
// winavr

#define F_CPU 8000000UL

#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>


volatile unsigned char pwm;             // шим
volatile unsigned char pwm_counter; // яркость
		 unsigned char rev;        // переключение режимов
		 

int main(void)
{

	DDRB = 0x01;
	
	TCCR0 |= (0<<CS02)|(1<<CS01)|(0<<CS00); // настройка тактирования таймера
	TIMSK |= (1<<TOIE0);                    // настройка прерывания по переполнению
	sei();	                                // включить глобальные прерывания
	
	
	while(1)
	{
		// плавное мигание светодиодом
		switch(rev)
		{
			case 0:	// плавное разгорание
				pwm_counter++;
				if(pwm_counter == 255)
				{
					rev = 1;
				};_delay_ms(4); // время разгорания
			break;
			case 1: // плавное затухание
				pwm_counter--;
				if(pwm_counter == 0)
				{
					rev = 0;
				};_delay_ms(6); // время затухания
			break;
		}
	}
}

SIGNAL(TIMER0_OVF_vect)
{
	TCNT0 = 200; // частота шим

	// программный  ШИМ
	if(pwm++ < pwm_counter)
	{
		PORTB|=_BV(0); // зажечь светодиод
	}else{
		PORTB&=~_BV(0);// погасить светодиод
	}
	
	
}
 
О боже, спасииииибо, человече!!!!!!
Раааботает!!))))
Ураа!!!
Можно , я код украду для своей Эйвы?)))
Ну пожалуйста!)))
 
Я добавила пару строк и для порта С и моргает сразу несколько, на старенькой отладочной платке проверила, спасиибо!)))
 
// winavr

#define F_CPU 8000000UL

#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>


volatile unsigned char pwm; // шим
volatile unsigned char pwm_counter; // яркость
unsigned char rev; // переключение режимов


int main(void)
{

DDRB = 0x01;
DDRC = 0b00111111;

TCCR0 |= (0<<CS02)|(1<<CS01)|(0<<CS00); // настройка тактирования таймера
TIMSK |= (1<<TOIE0); // настройка прерывания по переполнению
sei(); // включить глобальные прерывания


while(1)
{
// плавное мигание светодиодом
switch(rev)
{
case 0: // плавное разгорание
pwm_counter++;
if(pwm_counter == 255)
{
rev = 1;
};_delay_ms(4); // время разгорания
break;
case 1: // плавное затухание
pwm_counter--;
if(pwm_counter == 0)
{
rev = 0;
};_delay_ms(6); // время затухания
break;
}
}
}

SIGNAL(TIMER0_OVF_vect)
{
TCNT0 = 200; // частота шим

// программный ШИМ
if(pwm++ < pwm_counter)
{
PORTB|=_BV(0);
PORTC|=_BV(0);
PORTC|=_BV(1);
PORTC|=_BV(2);
PORTC|=_BV(3);
PORTC|=_BV(4);
PORTC|=_BV(5); // зажечь светодиод
}else{
PORTB&=~_BV(0);
PORTC&=~_BV(0);
PORTC&=~_BV(1);
PORTC&=~_BV(2);
PORTC&=~_BV(3);
PORTC&=~_BV(4);
PORTC&=~_BV(5);// погасить светодиод
}


}
Как индус, давно не практиковалась))) Исправлюсь)))
 
Назад
Сверху