Skocz do zawartości

[C] timer - zapalanie diody na 10s po przyciśnięciu przycisku.


morthell

Pomocna odpowiedź

Witam.

Niedawno zaopatrzyłem się w mikrokontroler atmega8, postanowiłem więc trochę się pobawić w rożne projekty.

Próbuje zbudować program który jest podobny do systemu automatycznego oświetlenia w domu na czujkach PIR.

Otóż, chcę aby przyciski wirtualizowały czujkę w taki sposób że naciśnięcie przyciska jest równo znaczne z wykryciem ruchu przez czujkę. Chcę aby program zapalał diodę led po przyciśnięciu przycisku na 10s. Jeśli jeszcze raz nacisnę przycisk odliczanie 10s powinno się resetować a dioda wciąż palić. Jednak jeśli jednak 10s minie to dioda ma zgasnąć. Zbudowałem program na timerze, jednak nie działa on tak jak powinien:

1. Dioda gaśnie po określonym czasie, lecz po kolejnym takim samym czasie znów się zapala;

2. Puszczenie przycisku powoduje że dioda pozostaje na stanie w jakim była przez wyłączeniem jej tj. jeśli się paliła to dalej się pali, jeśli zgasła to jest zgaszona.

I tu jest moje pytanie, gdzie jest błąd w moim myśleniu i co powinienem zmienić by program zaczął działać zgodnie z założeniami?

 
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 12000000UL

#define LED1 PB2
#define LED2 PB3
#define LED3 PB4

//definicja początkowej wartości timera
#define timer_start 0

//zmienna pomocnicza-licznik używana w przerwaniu
volatile uint8_t cnt=0;

int main(void)
{
int licznik;
//########### I/O ###########
//port D jako wejscie
DDRD &= ~(1<<PD2);
DDRD &= ~(1<<PD3);
DDRD &= ~(1<<PD4);

DDRB  |= (1<<LED1) | (1<<LED2) | (1<<LED3); //Ustawienie pinów sterujących diodami
PORTD = 0xFF;
//##########################

//######## konfiguracja timera ##############
TIMSK |= (1<<TOIE0);           //Przerwanie overflow (przepełnienie timera)
TCCR0 |= (1<<CS02) | (1<<CS00); // źródłem CLK, preskaler 1024
TCNT0 = timer_start;//          //Początkowa wartość licznika
//###########################################

sei();//Globalne uruchomienie przerwań

while(1);//główna pętla programu

}


//############ Procedura obsługi przerwania od przepełnienia timera ############
ISR(TIMER0_OVF_vect)
{
TCNT0 = timer_start;          //Początkowa wartość licznika

cnt++;     //zwiększa zmienną licznik
if(cnt >=100)  
{
	if (!(PIND & (1<<PIND3)))
	{
	PORTB ^=(1<<LED1); 
	}		
	else
	{		
	PORTB &=~ (1<<PB2);
	cnt=0;
	}		




	//PORTB ^=(1<<LED3);

	//PORTB ^=(1<<LED2); 
	}	
}

Docelowo w programie chcę aby działały 3 diody stąd też tyle wejść i wyjść zdefiniowanych.

Pozdrawiam.

Link do komentarza
Share on other sites

Masz źle skonstruowany warunek - najpierw sprawdzasz, czy cnt>=100 - więc automatycznie przyciśnięcie klawisza gdy cnt<100 nic nie daje.

Co więcej cnt po dojściu do 100 rośnie dalej do 255, a następnie przepełnia się zmienna i liczysz od 0.

Przerwanie powinno wyglądać tak (nie wiem tylko kiedy klawisz masz wciśnięty i kiedy led się pali, bo nie ma schematu, ale opis jest w programie)

TCNT0 = timer_start;          //Początkowa wartość licznika

if ((PIND & (1<<PIND3)))
{//klawisz naciśnięty
  cnt=0;
  PORTB ^=(1<<LED1); //wlaczyliśmy LED1
}
else
{//klawisz nie jest naciśnięty
 if (cnt<100) cnt++;
 else PORTB &=~ (1<<LED1); //wyłącz LED1
}

Jak widać zmienną cnt kasujemy tylko gdy jest wciśnięty przycisk, natomiast dodajemy do niej coś tylko jak przycisk nie jest wciśnięty - wtedy następuje faktyczne naliczanie czasu.

Rozwinąć to na wiele ledów możesz najłatwiej poprzez zrobienie tablicy zmiennej cnt i LED (o ile są na tym samym porcie) i zrobić pętle for wywołującą w przerwaniu ten kod if/else dla każdej komórki w tablicy - nie będziesz musiał kopiować całego kodu.

Link do komentarza
Share on other sites

Anonim
Ten temat został zamknięty.
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.