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

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

Добавлено: 18 май 2014, 14:26
winston1777
Привет всем ! Помогите новичку в написании программы на C в Codevisionavr. Чтобы когда на кнопку нажимая светодиод загорался, еще раз нажимая он погас ?

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

Добавлено: 19 май 2014, 15:44
AntonChip
Светодиод подключен к PB0, кнопка подключена к PD0

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

char temp = 0;

while(1)
{
if(PIND.0 == 0} // Проверяем нажатие кнопки
{
while(PIND.0 == 0){}// Ждем отпускания кнопки
temp++;
delay_ms(100);
}

if(temp)
{
PORTB.0 = 1; // зажигаем светодиод
}

if(temp == 0)
{
PORTB.0 = 0; // гасим светодиод
}

if(temp > 1)
{
temp = 0;
}

}

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

Добавлено: 01 июл 2014, 07:38
AntonChip
Специально для Рената пример кода синхронного мигания светодиодов, с использованием прерываний от двух таймеров. Кнопки подключены к PC3 - 0, светодиоды к PD3 - 0

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

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

char s_1 = 0, s_2 = 0, s_3 = 0, s_4 = 0;

volatile char pwm_counter_0, pwm_counter_2;

///////////////////////////////////////////////////////////////////////////
/////////////  Обработчик прерывания по переполнению Т0      //////////////
/////////////  Индикация включенного состоянии светодиодов, мигание  //////
/////////////////////////////////////////////////////////////////////////// 

ISR (TIMER0_OVF_vect)
{
pwm_counter_0++;

if(pwm_counter_0 > 40) 
{
  if(s_1)
  PORTD &= ~(1 << PD0);
  if(s_2)
  PORTD &= ~(1 << PD1);
  if(s_3)
  PORTD &= ~(1 << PD2);
  if(s_4)
  PORTD &= ~(1 << PD3);
  pwm_counter_0 = 0;
}

if(pwm_counter_0 > 20 && s_1)
PORTD |= (1 << PD0);
if(pwm_counter_0 > 20 && s_2)
PORTD |= (1 << PD1);
if(pwm_counter_0 > 20 && s_3)
PORTD |= (1 << PD2);
if(pwm_counter_0 > 20 && s_4)
PORTD |= (1 << PD3);
}

///////////////////////////////////////////////////////////////////////////
/////////////  Обработчик прерывания по переполнению Т2      //////////////
/////////////  Индикация выключенного состоянии светодиодов  //////////////
/////////////////////////////////////////////////////////////////////////// 

ISR (TIMER2_OVF_vect)
{
pwm_counter_2++;

if(pwm_counter_2 > 40) 
{
  if(s_1 == 0)
  PORTD &= ~(1 << PD0);
  if(s_2 == 0)
  PORTD &= ~(1 << PD1);
  if(s_3 == 0)
  PORTD &= ~(1 << PD2);
  if(s_4 == 0)
  PORTD &= ~(1 << PD3);
  pwm_counter_2 = 0;
}

}

///////////////////////////////////////////////////////////////////////////
//////                    Основная программа               ////////////////
///////////////////////////////////////////////////////////////////////////

int main (void)
{

DDRD = 0xFF; // Выход
PORTD = 0x00;

DDRC = 0x00; // Вход
PORTC = 0xFF;

TCCR0 = (1 << CS02); // clkI/O/256 (From prescaler)
TIMSK |= (1 << TOIE0); // разрешение прерывания от таймера

TCCR2 |= (1 << CS21); // clkI/O/8 (From prescaler)
TIMSK |= (1 << TOIE2); // разрешение прерывания от таймера

sei();

while(1)
{

///////////////////////////////////////////////////////////////////////////
/////////////             Управление кнопкой 1               //////////////
///////////////////////////////////////////////////////////////////////////      
  if((PINC & ( 1 << PC0)) == 0)
   {
    while((PINC & ( 1 << PC0)) == 0){} // Ждем отпускания кнопки
	_delay_ms(10);
    s_1++;
	if(s_1 > 1) s_1 = 0;
   }

///////////////////////////////////////////////////////////////////////////
/////////////             Управление кнопкой 2               //////////////
///////////////////////////////////////////////////////////////////////////      
  if((PINC & ( 1 << PC1)) == 0)
   {
    while((PINC & ( 1 << PC1)) == 0){}
	_delay_ms(10);
    s_2++;
	if(s_2 > 1) s_2 = 0;
   }

///////////////////////////////////////////////////////////////////////////
/////////////             Управление кнопкой 3               //////////////
///////////////////////////////////////////////////////////////////////////      
  if((PINC & ( 1 << PC2)) == 0)
   {
    while((PINC & ( 1 << PC2)) == 0){}
	_delay_ms(10);
    s_3++;
	if(s_3 > 1) s_3 = 0;
   }

///////////////////////////////////////////////////////////////////////////
/////////////             Управление кнопкой 4               //////////////
///////////////////////////////////////////////////////////////////////////      
  if((PINC & ( 1 << PC3)) == 0)
   {
    while((PINC & ( 1 << PC3)) == 0){}
	_delay_ms(10);
    s_4++;
	if(s_4 > 1) s_4 = 0;
   }
  
}
}


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

Добавлено: 02 июл 2014, 07:55
Renat
В общем хотел промоделировать твой код на протеусе, и хотел скомпилировать его. Ругается на <avr/io> на interrupt и на ISR (TIMER0_OVF_vect).
Даже не знаю с какой стороны подойти... SOS...SOS....SOS.. :roll:

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

Добавлено: 02 июл 2014, 09:02
Renat
#include <mega16.h>
#include <delay.h>
// Declare your global variables here

void main(void)
{
// Port A initialization
PORTA=0x00;
DDRA=0x00;


// Port B initialization
PORTB=0x00;
DDRB=0x00;

// Port C initialization

PORTC=0b11111111;
DDRC=0b11111111;

// Port D initialization
PORTD=0b11111111;
DDRD=0b11111111;

while (1)
{
if (PINA.0==0)
{
PORTC.0=1;
delay_ms(500);
PORTC.0=0;
delay_ms(810000);
PORTC.0=1;
delay_ms(500);
PORTC.0=0;
delay_ms(60000);
}
else if(PINA.1==0)
{
PORTC.1=1;
delay_ms(500);
PORTC.1=0;
delay_ms(810000);
PORTC.1=1;
delay_ms(500);
PORTC.1=0;
delay_ms(60000);
}
else if(PINA.2==0)
{
PORTC.2=1;
delay_ms(500);
PORTC.2=0;
delay_ms(810000);
PORTC.2=1;
delay_ms(500);
PORTC.2=0;
delay_ms(60000);
}
if (PINA.3==0)
{
PORTC.3=1;
delay_ms(500);
PORTC.3=0;
delay_ms(228000);
PORTC.3=1;
delay_ms(500);
PORTC.3=0;
delay_ms(60000);
}
if (PINA.4==0)
{
PORTC.4=1;
delay_ms(500);
PORTC.4=0;
delay_ms(111000);
PORTC.4=1;
delay_ms(500);
PORTC.4=0;
delay_ms(60000);
}
if (PINA.5==0)
{
PORTC.5=1;
delay_ms(500);
PORTC.5=0;
delay_ms(111000);
PORTC.5=1;
delay_ms(500);
PORTC.5=0;
delay_ms(60000);
}
if (PINA.6==0)
{
PORTC.6=1;
delay_ms(500);
PORTC.6=0;
delay_ms(111000);
PORTC.6=1;
delay_ms(500);
PORTC.6=0;
delay_ms(60000);
}
if (PINA.7==0)
{
PORTC.7=1;
delay_ms(500);
PORTC.7=0;
delay_ms(111000);
PORTC.7=1;
delay_ms(500);
PORTC.7=0;
delay_ms(60000);
}



}
}
Вот такой код был у меня, и именно такой нужен. Только чтоб все работало одновременно. А где и как настраивать время с таймером и прерываниями, я не понимаю((((

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

Добавлено: 02 июл 2014, 11:42
AntonChip
А задержки разные между переключениями светодиодов разные, это так и должно быть?

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

Добавлено: 03 июл 2014, 10:35
Renat
Да, на самом деле мне нужен сигнал 0.5 сек. для включения выпрямителей, после включения через определенное время их нужно снова выключить(снова сигнал 0.5 сек.). Для простоты, чтоб наглядно увидеть я поставил светодиоды.

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

Добавлено: 03 июл 2014, 17:20
AntonChip
При нажатии и удержании на кнопку должно быть постоянное переключение выхода или одноразовое? Просто не вникну в суть задачи

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

Добавлено: 04 июл 2014, 08:08
Renat
Вот смотри, пришел сигнал с датчика. Когда приходит сигнал с датчика, у меня порт, где стоят кнопки, заземляется через оптрон. То есть кнопка постоянно нажата. В это время начинается цикл. 0.5 секунд сигнал 5 вольт на порте где светодиоды, и снова ноль в течении некоторого времени. Потом снова 0.5 секунд сигнал и в течении минуты снова ноль. Время, как на выходе появилось 5 вольт, исчезло, снова появилось через некоторое время и исчезло примерно равно времени нажатого состояния кнопки. Постоянного переключения быть не должно. Если даже по каким то причинам сигнал исчез с датчика на секунду и снова появился цикл должен работать не обращая на это внимания пока не законцится

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

Добавлено: 08 июл 2014, 08:54
Renat
есть мысли?

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

Добавлено: 09 июл 2014, 07:35
Renat
Антооооон))) Такое возможно вообще? чтоб микроконтроллер выполнял несколько задач одновременно? Я читал про прерывания, и так и не понял, то ли процессор останавливается и выполняет команду, то ли в фоновом режиме выполняет разные команды. И если в моем случае применить прерывания на все 8 кнопок, и если придет сигнал со всех кнопок одновременно, микроконтроллер сможет обработать все команды?

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

Добавлено: 09 июл 2014, 07:37
Renat
http://www.ap-impulse.ru/podklyuchaem-k ... r-shag-12/ вот здесь есть что то подобное, но я не могу написать программу от и до чтоб она скомпилировалась без ошибок((

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

Добавлено: 09 июл 2014, 07:38
Renat
здесь есть кто?((

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

Добавлено: 11 июл 2014, 06:07
Renat
я забыт? или это с прерываниями нельзя сделать? Скажите что нибудь, или я реализую это на 8 МК((

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

Добавлено: 13 июл 2014, 12:09
AntonChip
Все 8 кнопок можно опрашивать по прерыванию таймера, например сделать чтобы прерывание было каждые 10мс, а в самом цикле прерывания смотреть какой сигнал будет с кнопок, лог. 0 или лог. 1. Останется свободных еще 2 таймера, а их использовать для синхронного включения выключения нагрузки.

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

Добавлено: 14 июл 2014, 10:34
Renat
Антон, посоветуй литературу, для дебилов)) и может это сделаем как занятие? я думаю что кому то в будущем пригодятся такие знания...

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

Добавлено: 18 июл 2014, 09:01
Renat
Я нашел код программы для 5 кнопок на атмега8
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

//////////////////////////////////////////////////////////////////
// Раздел функций
//////////////////////////////////////////////////////////////////

// Функция задержки. Минимальная задержка с кварцем 8MHz, равна около 1 ms

void delay_ms2(unsigned short ms)
{
unsigned short i, j, k;

for (i=0; i<ms; i++) /* цикл формирования временной задержки */
for(j=0; j<185;j++) /* вложенный цикл формирования временной задержки */
k++; /* произвольное действие */
}



// signal handler для внешнего прерывания int0

SIGNAL(SIG_INTERRUPT0)
{

PORTD &= ~_BV(PD1);// Сбросить бит PD1 в "0" = 0V, светодиод выключен , pin=0V
delay_ms2(1000); // Ждем 1 сек.
PORTD |= _BV(PD1); // Установить бит PD1 в "1" = 5V, светодиод включен, pin=1V


}

//////////////////////////////////////////////////////////////////



int main(void) // ОСНОВНАЯ ПРОГРАММА
{


DDRD |= 1<<1; // вывод 1 порта D работает на вывод
PORTD |= _BV(PD1); // инициализировать начальное состояние, установить бит PD1 в "1"

DDRD &= ~(0<<2); // вывод 2 порта D работает на ввод
PORTD |= _BV(PD2); // активизировать подтягивающий резистор

GIMSK = 1<<INT0; // разрешить внешнее прерывание Int0
MCUCR = 1<<ISC01; // сигнал низкого уровня на Int0 вызовет внешнее прерывание

sei(); // разрешить прерывания

for (;;) { } // бесконечный цикл

}
и нифига не понятно что и как делается((

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

Добавлено: 18 июл 2014, 09:05
Renat
Допустим как мне в этом примере сделать так чтоб при нажатии кнопки на выходе появился сигнал на 0.5 сек. и появился через 14 минут снова на 0.5 сек?

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

Добавлено: 18 июл 2014, 09:09
Renat
где обозначения пинов под кнопки? где обозначение пинов под светодиоды?

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

Добавлено: 18 июл 2014, 09:11
Renat
где настраивается прерывание от кнопки?