[AVR-GCC][Attiny2313] Problem z wysyłaniem rc5

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
ODPOWIEDZ
_Brutus
-
Posty: 26
Rejestracja: 01 gru 2006, 16:08
Lokalizacja: Złotopole / Łódź
Kontakt:

[AVR-GCC][Attiny2313] Problem z wysyłaniem rc5

Post autor: _Brutus » 06 cze 2009, 13:05

Witam mam następujący problem. Chciałem zrobić pilot rc5. Sam napisałem wszystko praktycznie od początku i funkcja wysyłająca kod rc5 działa wyśmienicie.

Problem pojawia się przy obsłudze przycisków w przerwaniu int0. Dwa microswitch'e podłączone mam tak: Jedna strona razem do PD2, czyli wejścia INT0 i z drugiej strony do PB1 i PB0 (każdego oddzielnie).

Robię tak, gdyż chcę usypiać procesor w docelowym układzie i ma on być budzony właśnie przerwaniem INT0 tylko na czas wysłania kodu rc5.

Chcę wykorzystać sztuczkę, której użył mirekk36 w swoim uniwersalnym pilocie. Mianowicie w obsłudze przerwania zmieniam PD2 na wyjście i ustawiam stan wysoki, następnie microswitch'e jako wejścia ze stanem niskim i sprawdzam na którym występuje stan wysoki (podciągnięty z PD2). Robię to, aby rozpoznać który przycisk został wciśnięty.

Tak wygląda kod, który działa w miarę dobrze (bez sprawdzania przycisków).

Kod: Zaznacz cały

int main (void)
{	
	toggle=0;
	
	DDRD &= ~(1<<SW_INT0);		// PD2 wejscie button do INT0
	PORTD |= (1<<SW_INT0);		// podciagniecie buttona do 1
	
	DDRB |= ( (1<<SW1) | (1<<SW2) | (1<<IR_LED) ); // guziki i dioda jako wyjscie	
	PORTB &= ~( (1<<SW1) | (1<<SW2) ); // stan niski na guzikach
	PORTB |= 1<<IR_LED; // dioda nie swieci
	
	MCUCR |= (1<<ISC01); 	// INT0 falling
	GIMSK |= 1<<INT0;		// INT0
	
	sei();	 // wlaczenie przerwan
	
	while(1);

	return 0;
}

SIGNAL(SIG_INTERRUPT0)
{	

	cli();
	
	_delay_ms(50);
		
	rc5_send(toggle,0,13);
	
	_delay_ms(200);
	
	sei();
}
Natomiast już tutaj układ czasami wysyła śmieci. Nie mogę dojść dlaczego...

Kod: Zaznacz cały

int main (void)
{	
	toggle=0;
	
	DDRD &= ~(1<<SW_INT0);		// PD2 wejscie button do INT0
	PORTD |= (1<<SW_INT0);		// podciagniecie buttona do 1
	
	DDRB |= ( (1<<SW1) | (1<<SW2) | (1<<IR_LED) ); // guziki i dioda jako wyjscie	
	PORTB &= ~( (1<<SW1) | (1<<SW2) ); // stan niski na guzikach
	PORTB |= 1<<IR_LED; // dioda nie swieci
	
	//MCUCR &= ~(1<<ISC01 | 1<<ISC00); 	// INT0 low level
	MCUCR |= (1<<ISC01); 	// INT0 falling
	GIMSK |= 1<<INT0;					// INT0
	
	sei();	// wlaczenie przerwan

	while(1);

	return 0;
}

SIGNAL(SIG_INTERRUPT0)
{	
	cli();
	
	_delay_ms(100);
	DDRB &= ~( (1<<SW1) | (1<<SW2) );	// guziki jako wejscie
	PORTB &= ~( (1<<SW1) | (1<<SW2) ); // stan niski na guziki
	
	DDRD |= 1<<SW_INT0; // pd2 jako wyjscie
	PORTD |= 1<<SW_INT0; // stan wysoki
	
	PORTB |= 1<<IR_LED; // dioda nie swieci
	
	
	if( PINB & (1<<SW1) )
	{
		_delay_ms(5);		
		if( PINB & (1<<SW1) )
			rc5_send(toggle,0,13);
	}
	
	if( PINB & (1<<SW2) )
	{
		_delay_ms(5);
		if( PINB & (1<<SW2) )
			rc5_send(toggle,0,12);
	}
	
	_delay_ms(200);
	
	DDRD &= ~(1<<SW_INT0);		// PD2 wejscie button do INT0
	PORTD |= (1<<SW_INT0);		// podciagniecie buttona do 1
	
	DDRB |= ( (1<<SW1) | (1<<SW2) | (1<<IR_LED) ); // guziki i dioda jako wyjscie	
	PORTB &= ~( (1<<SW1) | (1<<SW2) ); // stan niski na guzikach
	PORTB |= 1<<IR_LED; // dioda nie swieci
	
	sei();
}
Może mi ktoś pomóc? W przerwaniu używam cli(); i sei(); aby podczas wysyłania rc5 nie wyskoczyło mi następne przerwanie. Kody sprawdzam w programie Girder z IgorPlug'iem na USB. Powinienem otrzymywać 300D i 300C a czasami dostaję jakieś śmieci typu 5804 albo 4FF2 :/

Attiny2313 działa na wewnętrznym rezonatorze 8MHz. Generowanie nośnej 36kHz na timer0, odliczanie czasu potrzebnego do kodu rc5 na timer1.

[ Dodano: 2009-06-07, 12:40 ]
Już sobie poradziłem ;) Po prostu lekko zmieniłem koncepcję programu i już wszystko działa tak jak powinno.

Dodałem obsługę bitu toggle, która również działa wyświenicie ;P :D oraz usypianie procesora, aby mógł pracować pod baterią bez obawy o jej zbyt szybkie rozładowanie :)

Procesor w trakcie snu pobiera mniej niż 1uA, więc prąd jest praktycznie pomijalny.

Awatar użytkownika
kayron
Użytkownik
Posty: 2088
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 05 lip 2009, 19:05

Ja robiłem pilota RC5 na ATTiny 25, ale w BASCOM. Natomiast wszystko zrzuciłem na sprzętowe timery jak ty. Co do usypiania proca, lepszym (i prostszym) wyjściem jest użycie Watchdoga do tego, niż przerwań z portu. Głownie dla tego że zakłócenia na porcie mogą ci budzić procesor i wysyłać przypadkowe kody. A tak watchdog budzi ci proca co jakiś czas np. 64ms, proc sprawdza sobie klawiaturę czy jakiegoś klawisza nie wciśnięto, jak tak to wysyła kod i idzie sobie spać dalej. Przynajmniej ja tak zrobiłem.

_Brutus
-
Posty: 26
Rejestracja: 01 gru 2006, 16:08
Lokalizacja: Złotopole / Łódź
Kontakt:

Post autor: _Brutus » 05 lip 2009, 20:14

Ale jak watchdog budzi procka co 65ms, to pobiera on znacznie więcej prądu, niż gdy jest cały czas w trybie PowerDown.

Zresztą wszystko już dawno rozwiazane i działa jak natura chciała ;)

ODPOWIEDZ