Изменение яркости светодиода кнопкой

Обсуждаем контроллеры компании Atmel.
Ответить
Открыл глаза
Сообщения: 55
Зарегистрирован: Пн сен 11, 2017 10:49:54

Сообщение kot2004 »

Здравствуйте! Решил сделать небольшой rgb контроллер для светодиодной ленты. Задача такая: имеется 3 кнопки (одна уменьшает яркость, другая увеличивает, а третья переключает между каналами светодиодов r => g => b). Сейчас пытаюсь сделать регулировку яркости для одного светодиода. Главное условие использовать программный шим! Вот написал подобное:

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

/*
 * GccApplication7.c
 *
 * Created: 20.04.2019 01:28:45
 * Author : Timofey
 */ 

#include <util/delay.h>
#define F_CPU 10000000UL
#include <avr/interrupt.h>
#include <stdlib.h>
#define BitIsSet(reg,bit) ((reg&(1<<bit)) !=0)
#define BitIsClear(reg,bit) ((reg&(1<<bit)) ==0)


#define nop() {asm("nop");} 
unsigned int i, p, a, b, c, ms, x;

void delay_ms(int ms){ 
for (x=ms; x>0; x--) nop ();}


void led0(int led, int i, int p){
	PORTB &= ~_BV(led);   delay_ms(i);
	PORTB |= _BV(led);   delay_ms(p);}

SIGNAL(INT1_vect){
	a = a - 500;
	b = b + 500;
}

SIGNAL(INT0_vect){
	a = a + 500;
	b =  b - 500;
}

int main(void){

	DDRB |= _BV(PB0);
	DDRB |= _BV(PB1);
	DDRB |= _BV(PB2);
	
	PORTB = 0x00;
	GIMSK=0b11000000;
	MCUCR=0b00001111;
	DDRD = 0x00;
	sei();
	
	while(1){
		for(;;){
			led0(PB0, a, b);
			//led0(PB1, a, b);
			//led0(PB2, a, b);
		}
		
	}
}
Но проблема в том, что светодиод горит не плавно, а быстро-быстро мигает. Можно ли программно как-то исправить это (про другой кварц не надо)? Или существует более оптимальный программный способ решить мою задачу?
Вложения
attiny2313%20rgb%20led_schem.png
Это схема (для одного rgb светодиода)
(119.08 КБ) 451 скачивание
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

kot2004 писал(а):Можно ли программно как-то исправить это
можно. для этого надо сделать правильно программный ШИМ.
а правильный - это тот, который работает не в главном цикле, а по прерываниям.
настраиваете прерывание таймера на частоту, предположим 100 Гц.
в обработчике прерывания ведете счет в переменной-счетчике, и после каждого изменения счетчика сравниваете его значение со значением величин "каналов ШИМ" (тоже переменные). как только счетчик стал больше переменной канала, канал отключаете, пока счетчик меньше - канал включаете.

далее, по вашему коду:
1. SIGNAL - это устаревший макрос для обработчика прерываний, применяйте ISR
2. ваша функция delay_ms работать не будет. вы же подключили "библиотечный" модуль delay.h, так пользуйтесь "фирменными" функциями _delay_ms и _delay_us, где надо!
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Открыл глаза
Сообщения: 55
Зарегистрирован: Пн сен 11, 2017 10:49:54

Сообщение kot2004 »

А можете пример кода привести? (Простите, что так наглею!)
далее, по вашему коду:
1. SIGNAL - это устаревший макрос для обработчика прерываний, применяйте ISR
2. ваша функция delay_ms работать не будет. вы же подключили "библиотечный" модуль delay.h, так пользуйтесь "фирменными" функциями _delay_ms и _delay_us, где надо!
Спасибо большое!
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

kot2004 писал(а):А можете пример кода привести?
могу

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

volatile uint8_t pwm1; // первый канал
volatile uint8_t pwm2; // второй канал

ISR(TIMER0_OVF_vect){
   static uint8_t counter;
   
   counter++;
   if(counter < pwm1){
      // выключаем канал 1
   } else {
      // включаем канал 1
   }
   if(counter < pwm2){
      // выключаем канал 2
   } else {
      // включаем канал 2
   }
}
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Открыл глаза
Сообщения: 55
Зарегистрирован: Пн сен 11, 2017 10:49:54

Сообщение kot2004 »

Написал такой код:

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

/*
 * GccApplication7.c
 *
 * Created: 20.04.2019 01:28:45
 * Author : Timofey
 */ 

#define F_CPU 10000000 //fuse LOW=0x7a
#include <avr/interrupt.h>
#include <util/delay.h>
#define BitIsClear(reg,bit) ((reg&(1<<bit)) ==0)

volatile uint8_t pwm1; // первый канал


ISR(TIMER0_OVF_vect)
{
	static uint8_t counter;
	
	counter++;
	if(counter < pwm1){
		// выключаем канал 1
		PORTB &=~(1<<PB0);
		} else {
		// включаем канал 1
		PORTB |= (1<<PB0);
	}
}

ISR(INT1_vect){
	pwm1--;
}

ISR(INT0_vect){
	pwm1++;
}


int main(void)
{
	DDRB=0b00000111; // установка PortB пины 0,1,2 выходы
	DDRD = 0;
	TIMSK = 0b00000010; // включить прерывание по переполнению таймера
	TCCR0B = 0b00000001; // настройка таймера, делитель выкл
	GIMSK=0b11000000;
	MCUCR=0b00001111;
	PORTB = 0;
	sei();               // разрешить прерывания

	while (1)       //бесконечная шарманка
	{

	}

}
Вопрос такой можно ли как-то изменить "разрешение" светодиода (сколько кликов нужно сделать кнопкой, чтобы светодиод загорелся на полную мощь)?
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

на сколько вы за 1 клик увеличите pwm1, настолько и яркость увеличится. надо еще контролировать "потолок" и "пол", ибо иначе все пойдет по кругу после перехода через край
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Открыл глаза
Сообщения: 55
Зарегистрирован: Пн сен 11, 2017 10:49:54

Сообщение kot2004 »

Потолок и пол контролирую! Все работает, дело в том, что при минимальной яркости светодиоды на каналах не погашены, а тускло горят. Как можно решить эту проблему?
Друг Кота
Аватара пользователя
Сообщения: 39197
Зарегистрирован: Сб сен 13, 2014 16:27:32
Откуда: СпиртоГонск созвездия Омега

Сообщение musor »

выключателем питания
ZМудрость(Опыт и выдержка) приходит с годами.
Все Ваши беды и проблемы, от недостатка знаний.
Умный и у дурака научится, а дураку и ..
Алберт Ейнштейн не поможет и ВВП не спасет.и МЧС опаздает
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Смотришь на современных новичков и жалко мне вас, и грустно. Засилие интернета отняло память. Зачем, если в любой момент можно кликнуть мышкой и получить информацию. Засилие игровых приставок, компьютеров, смартфонов отняло стимул к поиску нужной информации. Нажатие кнопок и кликание кнопой мышки отняло мелкую моторику. Суммируя все это - отняло интеллект. Моторика, поиск информации, осознанные действия формируют и тренируют синапсы. Взаимосвязи синапсов, память, умение оперировать полученной информацией, объектами - это и есть интеллект. Труд сделал из примата человека. Физический и умственный.
Контактная информация:
Открыл глаза
Сообщения: 55
Зарегистрирован: Пн сен 11, 2017 10:49:54

Сообщение kot2004 »

[uquote="musor",url="/forum/viewtopic.php?p=3623279#p3623279"]выключателем питания[/uquote] Я имел ввиду программно!
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Смотрим в даташит микроконтроллера и видим, что у AVR есть баг. При значении ШИМ равным нулю на выходе будут иголки, импульсы. Значит, если значение ШИМ равно нулю, отключаем бит ШИМ-а. Либо порт определяем как ВХОД. DDRX. X = 0, PORTX. X = 0.
Именно это я и имел в виду. Изучаете, соизвольте заглянуть в книжки, даташит. Поиск информации. Нашёл, получил результат. Получил удовлетворение. Заметьте никаких наркотиков даже не нужно. Поработал, получил удовлетворение от процесса, результата.
Контактная информация:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Demiurg писал(а):у AVR есть баг
не баг, а фича :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

[uquote="ARV",url="/forum/viewtopic.php?p=3623555#p3623555"]
Demiurg писал(а):у AVR есть баг
не баг, а фича :)[/uquote]Вы же ему программный написали, при чем тут аппаратный?
kot2004 писал(а):Я имел ввиду программно!
Спойлер

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

#define F_CPU 10000000 //fuse LOW=0x7a
#include <avr/interrupt.h>
#include <util/delay.h>
#define BitIsClear(reg,bit) ((reg&(1<<bit)) ==0)

volatile uint8_t pwm1; // первый канал


ISR(TIMER0_COMPA_vect)
{
   static uint8_t counter;
   
   counter++;
   if(counter < pwm1){
      // включаем канал 1
      PORTB |= (1<<PB0);
      } else {
      // выключаем канал 1
      PORTB &=~(1<<PB0); 
   }
}

ISR(INT1_vect){
   if(--pwm1 == 255) pwm1=0;
}

ISR(INT0_vect){
   if(++pwm1 == 0) pwm1=255;
}


int main(void)
{
// Crystal Oscillator division factor: 1

CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);

// Input/Output Ports initialization
// Port A initialization
// Function: Bit2=In Bit1=In Bit0=In 
DDRA=(0<<DDRA2) | (0<<DDRA1) | (0<<DDRA0);
// State: Bit2=T Bit1=T Bit0=T 
PORTA=(0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);

// Port B initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=Out Bit1=Out Bit0=Out 
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (1<<DDB2) | (1<<DDB1) | (1<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=0 Bit1=0 Bit0=0 
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Port D initialization
// Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRD=(0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit6=T Bit5=T Bit4=T Bit3=P Bit2=P Bit1=T Bit0=T 
PORTD=(0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (1<<PORTD3) | (1<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 1000,000 kHz
// Mode: CTC top=OCR0A
// OC0A output: Disconnected
// OC0B output: Disconnected
// Timer Period: 1 us
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (0<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<TOIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<ICIE1) | (0<<OCIE0B) | (0<<TOIE0) | (1<<OCIE0A);

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Low level
// INT1: On
// INT1 Mode: Low level
// Interrupt on any change on pins PCINT0-7: Off
GIMSK=(1<<INT1) | (1<<INT0) | (0<<PCIE);
MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
EIFR=(1<<INTF1) | (1<<INTF0) | (0<<PCIF);

// USI initialization
// Mode: Disabled
// Clock source: Register & Counter=no clk.
// USI Counter Overflow Interrupt: Off
USICR=(0<<USISIE) | (0<<USIOIE) | (0<<USIWM1) | (0<<USIWM0) | (0<<USICS1) | (0<<USICS0) | (0<<USICLK) | (0<<USITC);

// USART initialization
// USART disabled
UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (0<<RXEN) | (0<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);

// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);
// Digital input buffer on AIN0: On
// Digital input buffer on AIN1: On
DIDR=(0<<AIN0D) | (0<<AIN1D);
   sei();               // разрешить прерывания

   while (1)       //бесконечная шарманка
   {

   }

}
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Dimon456 писал(а):при чем тут аппаратный?
вопрос не ко мне - я отвечал на упоминание аппаратного :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Открыл глаза
Сообщения: 55
Зарегистрирован: Пн сен 11, 2017 10:49:54

Сообщение kot2004 »

Знаю, что наглею, но самим ни как не получается! Собрал такую схему (во вложении) и написал такую программу:

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

#define F_CPU 10000000
#include <avr/interrupt.h>
#include <util/delay.h>
volatile uint8_t i;

volatile uint8_t pwm1 = 0;
volatile uint8_t pwm2 = 0;
volatile uint8_t pwm3 = 0; 

volatile uint8_t chanel = 2; 


ISR(TIMER0_OVF_vect)
{
	static uint8_t counter;
	
	counter++;
	if (pwm1 != 0){
		if(counter < pwm1){

			PORTB &=~(1<<0);
		}
		else {

			PORTB |= (1<<0);
		}
	}
	else {
		PORTB &=~(1<<0);
	}
	
	
	
	if (pwm2 != 0){
		if(counter < pwm2){

			PORTB &=~(1<<1);
		}
		else {

			PORTB |= (1<<1);
		}
	}
	else {
		PORTB &=~(1<<1);
	}
	
	
	
	if (pwm3 != 0){
		if(counter < pwm3){

			PORTB &=~(1<<2);
		}
		else {

			PORTB |= (1<<2);
		}
	}
	else {
		PORTB &=~(1<<2);
	}
	
}


ISR(INT1_vect){
	i = PIND;
	if (!((1 << PD0) & i))
	{
		if (chanel == 1){
			if (pwm1 < 255){
				pwm1 = pwm1 + 2;
			}
		}
		
		if (chanel == 2){
			if (pwm2 < 255){
				pwm2 = pwm2 + 2;
			}
			
		}
		
		if (chanel == 3){
			if (pwm3 < 255){
				pwm3 = pwm3 + 2;
			}
			
		}
	}
	
	
	if (!((1 << PD1) & i))
	{
		if (chanel == 1){
			if (pwm1 > -1){
				pwm1 = pwm1 - 2;
			}
		}
		
		if (chanel == 2){
			if (pwm2 > -1){
				pwm2 = pwm2 - 2;
			}
			
		}
		
		if (chanel == 3){
			if (pwm3 > -1){
				pwm3 = pwm3 - 2;
			}
			
		}
	}
	
	
	if (!((1 << PD3) & i))
	{
		if (chanel < 3){
			chanel++;
		}
		else{
			chanel--;
		}
	}
}


int main(void)
{
	DDRB=0b00000111;
	DDRD = 0;
	TIMSK = 0b00000010;
	TCCR0B = 0b00000001; 
	GIMSK=0b10000000;
	MCUCR=0b00001100;
	PORTB = 0;
	sei();         

	while (1)
	{

	}

}
Основная проблема такая: я хочу, чтобы при нажимании кнопки на PD3 происходило изменение канала шим. Даже завел отдельную переменную chanel. Но на практике ничего не происходит. Работает только тот канал, что я задал в начале программы. Что не так? Другой вопрос: как правильно определить пол и потолок, чтобы это не конфликтовало с условием гашения светодиода? Я попытался это как-то реализовать, но думаю, что не правильно! :oops:
Вложения
dfsfsfsd.png
(98.32 КБ) 457 скачиваний
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Где то валялся пример программного ШИМ-а на 32 светодиода... Но, на ассемблере...
Контактная информация:
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

kot2004 писал(а):Я попытался это как-то реализовать, но думаю, что не правильно!
Вам же пример дали.
Вот другой пример, с картинками
Спойлер

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

#define F_CPU 10000000 //fuse LOW=0x7a
#include <avr/interrupt.h>
#include <util/delay.h>

volatile uint8_t pwm0=0; // первый канал
volatile uint8_t pwm1=0; // второй канал
volatile uint8_t pwm2=0; // третий канал

volatile uint8_t chanel = 0;

#define max_chim 25	// 0-255 диапазон значений, чем больше разрешение шим тем меньше частота шим

ISR(TIMER0_COMPA_vect)
{
   static uint8_t counter;
  
   if (++counter==max_chim) { counter=0; }
   if(counter < pwm0){
      // включаем канал 0
      PORTB |= (1<<PB0);
      } else {
      // выключаем канал 0
      PORTB &=~(1<<PB0); 
   }
   if(counter < pwm1){
      // включаем канал 1
      PORTB |= (1<<PB1);
      } else {
      // выключаем канал 1
      PORTB &=~(1<<PB1); 
   }  
   if(counter < pwm2){
      // включаем канал 2
      PORTB |= (1<<PB2);
      } else {
      // выключаем канал 2
      PORTB &=~(1<<PB2); 
   }  
   
}

ISR(INT1_vect){
   if (chanel == 0) if(--pwm0 > max_chim) pwm0=0;
   if (chanel == 1) if(--pwm1 > max_chim) pwm1=0;
   if (chanel == 2) if(--pwm2 > max_chim) pwm2=0;   
}

ISR(INT0_vect){
   if (chanel == 0) if(++pwm0 > max_chim) pwm0=max_chim;
   if (chanel == 1) if(++pwm1 > max_chim) pwm1=max_chim;
   if (chanel == 2) if(++pwm2 > max_chim) pwm2=max_chim;   
}


int main(void)
{
// Crystal Oscillator division factor: 1

CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);

// Input/Output Ports initialization
// Port A initialization
// Function: Bit2=In Bit1=In Bit0=In 
DDRA=(0<<DDRA2) | (0<<DDRA1) | (0<<DDRA0);
// State: Bit2=T Bit1=T Bit0=T 
PORTA=(0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);

// Port B initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=Out Bit1=Out Bit0=Out 
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (1<<DDB2) | (1<<DDB1) | (1<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=0 Bit1=0 Bit0=0 
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Port D initialization
// Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRD=(0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit6=T Bit5=T Bit4=T Bit3=P Bit2=P Bit1=T Bit0=T 
PORTD=(0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (1<<PORTD3) | (1<<PORTD2) | (0<<PORTD1) | (1<<PORTD0);

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 1000,000 kHz
// Mode: CTC top=OCR0A
// OC0A output: Disconnected
// OC0B output: Disconnected
// Timer Period: 0,1 ms
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0A=0x63;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (0<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<TOIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<ICIE1) | (0<<OCIE0B) | (0<<TOIE0) | (1<<OCIE0A);

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Low level
// INT1: On
// INT1 Mode: Low level
// Interrupt on any change on pins PCINT0-7: Off
GIMSK=(1<<INT1) | (1<<INT0) | (0<<PCIE);
MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
EIFR=(1<<INTF1) | (1<<INTF0) | (0<<PCIF);

// USI initialization
// Mode: Disabled
// Clock source: Register & Counter=no clk.
// USI Counter Overflow Interrupt: Off
USICR=(0<<USISIE) | (0<<USIOIE) | (0<<USIWM1) | (0<<USIWM0) | (0<<USICS1) | (0<<USICS0) | (0<<USICLK) | (0<<USITC);

// USART initialization
// USART disabled
UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (0<<RXEN) | (0<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);

// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);
// Digital input buffer on AIN0: On
// Digital input buffer on AIN1: On
DIDR=(0<<AIN0D) | (0<<AIN1D);
   sei();               // разрешить прерывания

   while (1)       //бесконечная шарманка
   {
    if ((PIND & (1<<PD1)) == 0) {
    _delay_ms (5);
     if ((PIND & (1<<PD1)) == 0) {
     _delay_ms (5); 
      
	if(++chanel > 2) chanel=0;
	do { } while ((PIND & (1<<PD1)) == 0);   
      }
    }
   }
   
}
Изображение
Ответить

Вернуться в «AVR»