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

[C] Atmega16a dekodowanie RC5

politech 02 Sty 2011 15:43 902 0
REKLAMA
  • #1 8947359
    politech
    Poziom 2  
    Witam,
    znalazłem na tym forum kod dekodujący sygnał rc5, ale nie do końca go rozumiem i chciałbym prosić o pomoc.
    Kod:
    
    #include <avr/io.h> 
    #include <avr/interrupt.h> 
    #include <avr/signal.h> 
    
    
    #define RC5BitHigh()    (bit_is_set(PIND,PD3)) 
    #define RC5BitLow()     (bit_is_clear(PIND,PD3)) 
    #define WAITFORTIMER()  { while ( timerflag == 0); timerflag = 0; } 
    
    // CLK = 4MHz 
    #define TIMER_0_CNT 0xC9     //  111us = 1/( (CLK/8)/(0xFF-0xC9) ) 
    #define RC5BITREF1  6 
    #define RC5BITREF2  11 
    #define RC5BITREF3  14 
    #define IR_int_enable GIFR|=(1<<INT1);GICR|=(1<<INT1) 
    #define IR_int_disable GICR&=~(1<<INT1) 
    
    
    volatile uint8_t timerflag;  
    volatile unsigned int    rc5data; 
    
    
    void rc5_init() 
    { 
       DDRD  &= ~(1<<PD3);           // konfiguracja PD3 jako wejście 
        PORTD |= (1<<PD3);           // enable internal pull-up resistors 
      
          MCUCR|=_BV(ISC11); // ext. int. activated by falling edge 
          MCUCR&=~_BV(ISC10); 
          GIFR = (1<<INTF1); // clear ext. int. flag 
          GICR|=_BV(INT1); // enable ext. int. 
    } 
    
    
    SIGNAL(SIG_OVERFLOW0)  
    { 
        timerflag = 1;               // set global variable 
        TCNT0 = TIMER_0_CNT;         // reset counter to get this interrupt again 
    } 
    
    SIGNAL(SIG_INTERRUPT1) 
    { 
       IR_int_disable;      //wylaczenie przerwan zewnetrznych 
       sei(); 
        unsigned char   timer, i; 
        // init timer/Counter2    
        TCCR0 = 0x02;                    // use CLK/8 prescale 
        TCNT0 = TIMER_0_CNT;             // set timer T/16 = 111us 
        TIMSK |= (1<<TOIE0);             // enable TCNT0 overflow interrupt 
        TIMSK &=~(1<<TOIE2);             // disable TCNT2 overflow interrupt 
        
        // measure startbit 
        timerflag = 0; timer = 0; 
        while ( RC5BitLow() && (timer < RC5BITREF2) ) { 
            WAITFORTIMER(); 
            timer++; 
        } 
        if ( (timer > RC5BITREF1) && (timer < RC5BITREF2) ) { 
            // startbit ok, decode 
    
            // wait T/4: synchronize in the middle of first half of second bit 
            while ( timer < RC5BITREF3 ) { 
                WAITFORTIMER(); 
                timer++; 
            } 
            
            // read the remaining bits 
            rc5data = 1; 
            for (i=0; i<13; i++) { 
                rc5data <<= 1; 
                if ( RC5BitHigh() ) { 
                    rc5data |= 0x0001; 
                    // wait max T/2 for H->L transition (middle of next bit) 
                    timer = 0; 
                    while ( RC5BitHigh() && (timer < 16) ) { 
                        WAITFORTIMER(); 
                        timer++; 
                    } 
                }else{ 
                    rc5data &= ~0x00001; 
                    // wait max T/2 for L->H transition (middle of next bit) 
                    timer = 0; 
                    while ( RC5BitLow() && (timer < 16) ) { 
                        WAITFORTIMER(); 
                        timer++; 
                    } 
                }                    
                if ( timer == 16 ) { 
                    rc5data = 0x0000;   // error, next bit not found 
                    return; 
                } 
                
                // wait 3/4 T: await next bit 
                for ( timer=0; timer < 12 ; timer++) WAITFORTIMER(); 
            } 
    
        }else { 
            rc5data = 0x0000;  // error, invalid RC-5 code 
        } 
    
        TCCR0=0; 
        TIMSK &=~(1<<TOIE0);              // disable TCNT0 overflow interrupt 
        TIMSK |= (1<<TOIE2);              // enable TCNT2 overflow interrupt 
       IR_int_enable; 
    } 
    
    int main() 
    { 
       DDRD=0;;//Porty D jako wejścia 
       rc5_init(); 
       sei(); 
       while(1) 
       { 
             if(rc5data) 
             { 
                PORTB=0x00; 
             } 
       } 
    } 


    W projekcie korzystam z 4Mhz, w kodzie determinuje to wartość makra TIMER_0_CNT, dzięki któremu wypracowany będzie czas 111us, co który przepełniać się będzie 8-bitowy licznik.
    I rozumiem to tak: przychodzi przerwanie z dekodera IR(tsop1736), wywoływana jest procedura obsł. przerwania w której na początku wyłączane są przerwania zewnętrzne, żeby móc dalej zdekodować sygnał. (to jeszcze, jeszcze rozumiem).
    Pierwszy bit jest startowy, ma zawsze wartość "1"(czyli w połowie bitu zmiana 0->1) więc w pętli:
    while ( RC5BitLow() && (timer < RC5BITREF2) ) { 
            WAITFORTIMER(); 
            timer++; 
        } 

    czekamy dopóki wartość na PD3 to "0" lub do 1221us(czyli mniej niż 0.75 bitu) i za pętlą mamy niby zdekodowany ten pierwszy bit startu.
       // wait T/4: synchronize in the middle of first half of second bit 
            while ( timer < RC5BITREF3 ) { 
                WAITFORTIMER(); 
                timer++; 
            } 


    a pętla, wdł. mnie czeka do 1554us, co nawet nie jest drugim bitem, natomiast z komentarza wynika, że ma to być środek połowy drugiego bitu:(
    Dalej jest niby odczytywanych 13 bitów(2gi bit startu, toggle bit, adres, komenda), tak że:
    rc5data = 1 jest przesuwane z każdym przebiegiem pętli (1 bo ten drugi bit startu chyba?) w którym sprawdzany jest stan PD3, niby w chwili T/4. Jeśli "1" to jest ustawiana jedynka w rc5data jeśli "0" to 0.
    I nawet tutaj mam wątpliwość, bo jeśli w pierwszej połowie bitu jest "1" to będzie zmiana z 1->0, czyli "0".
    Nie jestem w stanie tego zrozumiec, dlatego zwracam się o pomoc.
  • REKLAMA
REKLAMA