Страница 2 из 3

Re: Светодиод и кнопка

Добавлено: 18 июл 2014, 22:04
AntonChip
Вот пример опроса кнопок по таймеру

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

volatile unsigned char kod_key;

ISR (TIMER2_OVF_vect)
{
     if (bit_is_clear(PIND, PD0))  kod_key = 1;
else if (bit_is_clear(PIND, PD1))     kod_key = 2;
else if (bit_is_clear(PIND, PD2))   kod_key = 3;
else if (bit_is_clear(PIND, PD3)) kod_key = 4;
else kod_key = 0;
}
настройка таймера

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

TCCR2 |= (1 << CS22)|(1 << CS21)|(1 << CS20); // Таймер 2 для опроса клавиатуры раз в 32 мс
TIMSK |= (1 << TOIE2); // разрешение прерывания по переполнению таймера 2

Re: Светодиод и кнопка

Добавлено: 07 авг 2014, 06:22
Scroodge
Всем привет! Подскажите знающие, как решить задачу: при первом нажатии светодиод моргает с одной частотой, при следующем нажатии - частота меняется, при последнем нажатии - выключается? Интересует на си в avr студии. Спасибо!

Re: Светодиод и кнопка

Добавлено: 07 авг 2014, 10:42
AntonChip
Для формирования разных частот можно использовать 16-ти битный таймер, который работает в режиме СТС , где для управления частотой сигнала в регистр ICR1 заносятся предварительно расчитанные значения, сигнал снимается с выхода OC1A.

Re: Светодиод и кнопка

Добавлено: 07 авг 2014, 16:40
Scroodge
А получится без применения таймера? С помощью util_delay? Если можно, пример для светодиода и одной кнопки.

Re: Светодиод и кнопка

Добавлено: 07 авг 2014, 21:09
AntonChip
Самый простой пример

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

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

int main(void)
{
DDRB = 0x00; // Кнопка к PB0
PORTB = 0xFF;
DDRD = 0xFF; // Светодиод к PD0
PORTD = 0x00;	

char s_1 = 0;

while(1)
{
  if((PINB & ( 1 << PB0)) == 0)
   {
    while((PINB & ( 1 << PB0)) == 0){} // Ждем отпускания кнопки
    _delay_ms(10);
    s_1++;
    if(s_1 > 2) s_1 = 0;
   }

if(s_1 == 0)
{
PORTD &= ~(1 << PD0); // Выключаем светодиод
}

if(s_1 == 1)
{
PORTD |= (1 << PD0); // Включаем светодиод
_delay_ms(250); 
PORTD &= ~(1 << PD0); // Выключаем светодиод
_delay_ms(250);
}

if(s_1 == 2)
{
PORTD |= (1 << PD0); // Включаем светодиод
_delay_ms(25); 
PORTD &= ~(1 << PD0); // Выключаем светодиод
_delay_ms(25);
}

}
}

Re: Светодиод и кнопка

Добавлено: 08 авг 2014, 18:36
Scroodge
Спасибо! В протеусе все работает прекрасно. Поясни, пожалуйста: char s_1 = 0 -объявили число s_1 и присвоили ему число 0, правильно? Что потом с ним происходит: s_1++; и почему мы сравниваем s_1 с 0, 1 и 2?

Re: Светодиод и кнопка

Добавлено: 08 авг 2014, 18:46
AntonChip
При инициализации контроллера, т.е. после включения питания переменной s_1 присвоено значение 0, значит светодиод не горит при включении питания.
Этой командой s_1++ к нашей переменной добавляем единицу при каждом отпускании кнопки.
В бесконечном цикле переменную проверяем на значение 0, 1, 2, где уже запускается уже определенный цикл.

Re: Светодиод и кнопка

Добавлено: 08 авг 2014, 19:17
Scroodge
Не могу вкурить, мы ведь в установке на порт D уже подали все 0, потушили светодиод PortD=0x00?

Re: Светодиод и кнопка

Добавлено: 08 авг 2014, 19:38
AntonChip
Scroodge писал(а):Не могу вкурить, мы ведь в установке на порт D уже подали все 0, потушили светодиод PortD=0x00?
Это инициализация, а дальше идет основной цикл

Re: Светодиод и кнопка

Добавлено: 08 авг 2014, 20:56
Scroodge
Спасибо, Антон. Почитаю еще Белова

Re: Светодиод и кнопка

Добавлено: 09 авг 2014, 05:13
Scroodge
Слушай, Антон, а можно в этой же программе добавить:если нажать и удерживать кнопку в любом месте светодиод выключится? Или тут уже без прерываний не обойтись?

Re: Светодиод и кнопка

Добавлено: 13 авг 2014, 19:00
AntonChip
Можно без прерываний сделать

Re: Светодиод и кнопка

Добавлено: 13 авг 2014, 19:07
Scroodge
Подскажи, если не трудно. Хочу в машине регулировать обороты мотора отопителя с помощью программного ШИМа, но знаний пока не хватает, именно по программированию. Спасибо!

Re: Светодиод и кнопка

Добавлено: 13 авг 2014, 22:58
AntonChip
ШИМ это значит все равно использование прерывания по таймеру, если хочешь чтоб все нормально работало. На сайте есть статья "Использование ШИМ", для примера пойдет. А для контроллера мотора я бы посоветовал использовать аппаратный ШИМ. Кстати контроллер печки я делал на attiny13, с переменным резистором, выкладываю код

Re: Светодиод и кнопка

Добавлено: 15 авг 2014, 11:26
Scroodge
Спасибо, Антон! Такой вопрос относительно твоего кода для мотора отопителя: Каким образом вход РВ2 реагирует на изменение сопротивления?

Re: Светодиод и кнопка

Добавлено: 15 авг 2014, 15:04
AntonChip
Вход PB2 это вход АЦП, в зависимости от того какое напряжение на этом входе меняется скважность ШИМ

Re: Светодиод и кнопка

Добавлено: 07 окт 2014, 07:34
Scroodge
Антон, извини за назойливость, но повторю вопрос: как на 8 меге собрать контроллер отопителя с индикацией из 8 светодиодов. Интересует код в avr studio 6. Спасибо!

Re: Светодиод и кнопка

Добавлено: 22 окт 2014, 21:16
AntonChip
Scroodge писал(а):Антон, извини за назойливость, но повторю вопрос: как на 8 меге собрать контроллер отопителя с индикацией из 8 светодиодов. Интересует код в avr studio 6. Спасибо!
Вот пример кода только в AVRStudio4, в шестую переделать не составит особого труда. Код для Atmega8. Все задержки поменять на указанные в скобках или по своему усмотрению, мин. задержки сделал для симуляции в протеусе

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

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

unsigned int adc_bufer = 0;

void start_pwm(void)
{
TCCR2 |= (1 << COM21)|(1 << WGM21)|(1 << WGM20)|(1 << CS20); // режим FAST PWM, сброс OC2 при сравнении
PORTB |= (1 << PB1); // включаем светодиод
}

void stop_pwm(void)
{
TCCR2 = 0x00; // выключаем таймер
OCR2 = 0x00;
TCNT2 = 0x00;
PORTB &= ~(1 << PB1); // Выключаем светодиод
}

int main (void) 
{
PORTB = 0x00;
DDRB = 0b00000011; // PB0, PB1 - выход
DDRD = 0xFF;
PORTD = 0x00;
	
ADCSRA |= (1 << ADEN)|(1 << ADPS2)|(1 << ADPS1); // Включаем ADC, предделитель на 64
ADMUX |= (1 << ADLAR)|(1 << MUX0); // Помещаем результат в ADCH, Вход ADC1

ACSR |= (1 << ACD); // Отключаем аналаговый компаратор

stop_pwm(); // Выключаем ШИМ

ADCSRA |= (1 << ADSC); // начало преобразования
while((ADCSRA&(1 << ADIF)) == 0);
{
adc_bufer = ADCH;  // Считываем  ADC в буфер
}

if(adc_bufer > 50)
{
start_pwm();
for(char a=0; a < 32; a++)
{
_delay_ms(2); // 250ms
}
}
else
{
stop_pwm();
}

while(OCR2 < adc_bufer)
{
ADCSRA |= (1 << ADSC); // начало преобразования
while((ADCSRA&(1 << ADIF))== 0); // Ждем флага окончания преобразования
{
adc_bufer = ADCH;  // Считываем  ADC
}
OCR2++; // Плавный запуск мотора
_delay_ms(1); // 100ms
}	

while(1)
{
ADCSRA |= (1 << ADSC);	//Начинаем преобразование
_delay_ms(1);
while((ADCSRA&(1 << ADIF))== 0); // Ждем флага окончания преобразования    
{
//adc_bufer = ADCH;  // Считываем  ADC 
OCR2 = ADCH;

if (ADCH > 50)
     PORTD = 0b00000001;          
else
     PORTD = 0b00000000;         
if (ADCH > 75)
	 PORTD = 0b00000011;     
if (ADCH > 100)
	 PORTD = 0b00000111;
if (ADCH > 125)
	 PORTD = 0b00001111;
if (ADCH > 150)
	 PORTD = 0b00011111;
if (ADCH > 175)
	 PORTD = 0b00111111;
if (ADCH > 200)
	 PORTD = 0b01111111;
if (ADCH > 225)
	 PORTD = 0b11111111;
}

if(ADCH > 50)
{
start_pwm();
}
else
{
stop_pwm();
}

if(ADCH > 51)
{
  if(OCR2 < 50)
  OCR2++;
 _delay_ms(100); // 100ms
}
}
}


Re: Светодиод и кнопка

Добавлено: 29 окт 2014, 13:19
Scroodge
Почему-то в протеусе сразу подает 1 на весь порт D, а на изменение реостата не реагирует никак. Наверное где-то напортачил. Вход АЦП берем ножку PC1, верно?

Re: Светодиод и кнопка

Добавлено: 29 окт 2014, 13:35
Scroodge
И почему ты вот эту строчку закомментировал? //adc_bufer = ADCH; // Считываем ADC