logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[ATmega32][c/AVR] Odbiór Protokołu RC5

mgiro 28 Lis 2009 17:52 2374 4
REKLAMA
  • #1 7319973
    mgiro
    Poziom 22  
    Witam,

    Wiem, że RC5 ten wątek był poruszany wiele razy na forum, ale chcę sie nauczyć programować w C, wiec chciałem wykorzystać odbiornik podczerwieni z mojego zestawu(ZL3AVR) i napisać protokół do RC5

    Pracuje na kwarcu 16MHz i ATmega32. Odbiornik podczerwieni podłaczylem do PD3

    
    
    #include <avr/io.h>                // dostęp do rejestrów
    #include <avr/interrupt.h>
    #define F_CPU 16000000
    
    
    volatile uint8_t RC5cmd;
    volatile uint8_t RC5addr;
    //volatile unsigned char T;
    volatile unsigned char ready;
    volatile unsigned long int tmp;
    
    SIGNAL(INT1_vect) 
    {
    	//unsigned int tmp = 0;
    	uint16_t ilosc_bitow = 0;
    	uint8_t liczba_zboczy = 0;
    	unsigned char mem_bit;
    	uint8_t i = 1; // Jezeli nie ma bledu i = 1, jezeli jest => i = 0;
    
    
    	GICR &= ~_BV(INT1); //zamaskowanie przerwania INT1
    	TCCR0 = (1<<WGM01); //tryb CTC
    	TCCR0 = (1<<CS02); //preskaler 256
    	TCNT0 = 0; OCR0 = 81;// T=1,296ms ==> f=771,605Hz
    
    	tmp = 0;
    
    	while(i)
    	{
    		mem_bit=(!(PIND & 0x08));
    		liczba_zboczy = 0;
    		
    		TIFR |= (1<<OCF0); //kasowanie flagi przerwania przez wpisanie jedynki		
    
    		while(!OCF0)
    		{
    			if(mem_bit != ((!(PIND & 0x08))))
    			{
    				liczba_zboczy++;
    				mem_bit=(!(PIND & 0x08));
    
    				if(liczba_zboczy>1) //wiecej niz jedno zbocze
    				{
    					//ERROR
    					i=0;
    					GICR |= (1<<INT1);  //odblokowanie przerwania INT1
    					return;
    				}
    			}
    		}
    		
    		tmp<<=1;// przesuniecie wszystkich bitow o jeden w lewo
    		tmp |= mem_bit; //tmp |=(!(PIND & 0x08));
    		TIFR |= (1<<OCF0); //kasowanie flagi przerwania przez wpisanie jedynki
    		
    		ilosc_bitow++;
    	
    		if(ilosc_bitow == 13)
    		{
    		
    			RC5cmd = tmp&0x3f;
    			RC5addr = (tmp>>6) & 0x1f;
    			ready = 1;
    			GICR |= (1<<INT1);  //odblokowanie przerwania INT1	
    			//T = ;
    			i=0;
    			return;	
    		} 
    		
    	/*	while(mem_bit == ((!(PIND & 0x08)))
    		{
    			//trzeba odczekac 1/4T
    			//na zbocze
    			GICR |= (1<<INT1);  //odblokowanie przerwania INT1
    			i=0;
    			return;
    		}
    	*/
    		TCNT0 = 0; OCR0 = 81;// T=1,296ms ==> f=771,605Hz
    
    	}
    }
    
    int main(void)
    {
    	DDRA = 0xff; //wyjscia dla diod
    	DDRD = 0x00; //wejscia
    	 GICR |= (1<<INT1);  //odblokowanie przerwania INT1	
    	 MCUCR |= (1<<ISC11); // Zbocze opadajace na INT1 wywola przerwanie
    	sei();
    
    
    	while(1)
    	{
    	
    		if(ready)
    		{
    			PORTA = RC5cmd;
    		
    			ready = 0;
    			
    
    		}
    	}
    }
    
    


    Proszę o sprawdzenie kodu, bo ciągle mam to samo (same jedynki) niezależnie od tego, który przycisk na pilocie wybiorę.

    Sądzę, że problem jest podczas odczytu z PORTD (PD3)

    Z góry dzięki za pomoc!!!

    Pozdrawiam osoby znające się na ortografii!!!
  • REKLAMA
  • #2 7327303
    ktrot
    Poziom 20  
    while(!OCF0) - OCF0 to stała (1) czyli while(!OCF0) znaczy tyle co while(0) - nie wykona się ani razu.
  • REKLAMA
  • #3 7328483
    mgiro
    Poziom 22  
    A OCF0 jest chyba tylko jedynka, jak liczniki się zrównają? W pozostałym czasie jest zerem.

    Ta pętla działa, mam na diodach(PORTA) same jedynki => RC5cmd =0b111111

    Przyczyna musi być w innym miejscu moim zdaniem!!!
  • REKLAMA
  • #4 7330098
    MODI
    Poziom 17  
    mgiro napisał:
    A OCF0 jest chyba tylko jedynka, jak liczniki się zrównają? W pozostałym czasie jest zerem.

    ktrot dobrze gada. Jak nie wierzysz to looknij do pliku io.h atmegi
    Spróbuj tak
    while(!(TIFR&(1<<OCF0)))
  • #5 7331358
    mgiro
    Poziom 22  
    MODI, zrobiłem tak jak mówiłeś, teraz mam na same zera. Żadna dioda na PORTA się nie zapala. (Wysoki poziom zapala diodę)

    Aktualny kod programu:
    
    
    #include <avr/io.h>                // dostęp do rejestrów
    #include <avr/interrupt.h>
    #define F_CPU 16000000
    
    
    volatile uint8_t RC5cmd;
    volatile uint8_t RC5addr;
    //volatile unsigned char T;
    volatile unsigned char ready;
    volatile unsigned long int tmp;
    
    SIGNAL(INT1_vect) 
    {
    	//unsigned int tmp = 0;
    	uint16_t ilosc_bitow = 0;
    	uint8_t liczba_zboczy = 0;
    	unsigned char mem_bit;
    	uint8_t i = 1; // Jezeli nie ma bledu i = 1, jezeli jest => i = 0;
    
    //	PORTA ^= 0x01;
    	GICR &= ~_BV(INT1); //zamaskowanie przerwania INT1
    	TCCR0 = (1<<WGM01); //tryb CTC
    	TCCR0 = (1<<CS02); //preskaler 256
    	TCNT0 = 0; OCR0 = 81;// T=1,296ms ==> f=771,605Hz
    
    	tmp = 0;
    
    	while(i)
    	{
    		mem_bit=(!(PIND & 0x08));
    		liczba_zboczy = 0;
    		
    		TIFR |= (1<<OCF0); //kasowanie flagi przerwania przez wpisanie jedynki		
    
    		while(!(TIFR&(1<<OCF0))) //while(!OCF0) 
    		{
    			if(mem_bit != ((!(PIND & 0x08))))
    			{
    				liczba_zboczy++;
    				mem_bit=(!(PIND & 0x08));
    
    				if(liczba_zboczy>1) //wiecej niz jedno zbocze
    				{
    					//ERROR
    					i=0;
    					GICR |= (1<<INT1);  //odblokowanie przerwania INT1
    					return;
    				}
    			}
    		}
    		
    		tmp<<=1;// przesuniecie wszystkich bitow o jeden w lewo
    		tmp |= (!(PIND & 0x08));
    		TIFR |= (1<<OCF0); //kasowanie flagi przerwania przez wpisanie jedynki
    		
    		ilosc_bitow++;
    	//	if (ilosc_bitow == 4)
    	//	{
    	//		PORTA = 0x80;
    	//	}
    		if(ilosc_bitow == 13)
    		{
    		//	PORTA = 0x80;
    			RC5cmd = tmp&0x3f;
    			RC5addr = (tmp>>6) & 0x1f;
    			ready = 1;
    			GICR |= (1<<INT1);  //odblokowanie przerwania INT1	
    			//T = ;
    			i=0;
    			return;	
    		} 
    		
    	/*	while(mem_bit == ((!(PIND & 0x08))>>3))
    		{
    			//trzeba odczekac 1/4T
    			//na bocze
    			GICR |= (1<<INT1);  //odblokowanie przerwania INT1
    			i=0;
    			return;
    		}
    	*/
    		TCNT0 = 0; OCR0 = 81;// T=1,296ms ==> f=771,605Hz
    
    	}
    }
    
    int main(void)
    {
    	DDRA = 0xff; //wyjscia dla diod
    	DDRD = 0x00; //wejscia
    	 GICR |= (1<<INT1);  //odblokowanie przerwania INT1	
    	 MCUCR |= (1<<ISC11); // Zbocze opadajace na INT1 wywola przerwanie
    	sei();
    
    
    	while(1)
    	{
    	//	PORTA ^= 0x04;
    		if(ready)
    		{
    			PORTA = RC5cmd;
    		
    			ready = 0;
    			
    
    		}
    	}
    }
    
    


    Proszę o pomoc i dalsze wskazówki!!!
REKLAMA