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][atmega8]wywołanie funkcji w przerwaniu,aby while(1)pusty

esnow 26 Lis 2009 12:58 3355 12
REKLAMA
  • #1 7310771
    esnow
    Poziom 14  
    w mainie w funkcji while(1), sprawdzam tylko warunek if(bit_is_clear(PIND,PD2)) rc5decode(); <-- TAK DZIAŁA !
    jak wywołać tą funkcję w przerwaniu SIGNAL(SIG_INTERRUPT0) {}, ?
    probowałem tak:
    w mainie:
    GICR |=1<<INT0;

    w przerwaniu od INTO:
    
    SIGNAL(SIG_INTERRUPT0)  {
    GICR &= ~BV(INT0);
    rc5decode();  //wywołanie porządanej funkcji
    GICR |= _BV(INT0);
    }
    ale nie działa.

    kod programu:
    
    SIGNAL(SIG_OVERFLOW0)  //  przerwanie od przepelnienia timer0
    {
        timer_flag = 1;               // ustawienie 1 jako flagi globalnej
        TCNT0 = TIMER_0_CNT;         // resetowanie timera, aby przerwanie wywolalo sie znowu
    }
    

    
    void rc5decode( void )  //  decoded RC5 data is returned, or 0x0000 if RC5 data not recognized
    {
        rc5data=0;
        unsigned char   timer, i;
        
        // init timer/Counter0    
        TCCR0 = _BV(CS01);                // use CLK/8 prescale
        TCNT0 = TIMER_0_CNT;              // set timer T/16 = 111us 
        TIMSK = _BV(TOIE0);              // enable TCNT0 overflow interrupt
        
        // measure startbit
        timer_flag = 0; timer = 0; 
        while ( RC5BitLow() && (timer < RC5BITREF2) ) 
    	{
            { while ( timer_flag == 0); timer_flag = 0; }
            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 ) {
                { while ( timer_flag == 0); timer_flag = 0; }
                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) ) {
                        { while ( timer_flag == 0); timer_flag = 0; }
                        timer++;
                    }
                }else{ 
                    rc5data &= ~0x00001;
                    // wait max T/2 for L->H transition (middle of next bit)
                    timer = 0;
                    while ( RC5BitLow() && (timer < 16) ) {
                        { while ( timer_flag == 0); timer_flag = 0; }
                        timer++;
                    }
                } 
                if ( timer == 16 ) {
                    rc5data = 0x0000;   // error, next bit not found
                    break;
                }
                
                // wait 3/4 T: await next bit
                for ( timer=0; timer < 12 ; timer++) { while ( timer_flag == 0); timer_flag = 0; }
            }
    
        }else {
            rc5data = 0x0000;  // error, invalid RC-5 code
        }
        TCCR0 = 0;            // stop timer0    
        
            if ( rc5data & 0x3000 ) 
    		{		   
    		   komenda = rc5data & 0x3F;
    		   
    		   adres = rc5data & 0x7C0;
    		   adres >>= 6;
    		   
    		   toggle = (rc5data & 0x800);
    		   toggle >>= 11;
    		
    		   sprintf(bufor,"adres:%u komenda:%u toggle:%u \n\r",adres,komenda,toggle);
    		   send_string(bufor);  
            }
    }
    

    
    int main(void)
    {
        DDRB  = 0xff;               // use all pins on port B for output 
        PORTB = 0xff;
    	
    	DDRC = 0xff;
    	PORTC = 0x00;
    	
    	USART_Init(UART_CONST); 			// inicjalizacja rs'a
        
        sei();                      //globalne zezwolenie na przerwania
        
        while(1)  
        {
            //while ( RC5BitHigh() );           // wait until RC5 code received
    		if(RC5BitLow())
            rc5decode();
        }
    }
    
  • REKLAMA
  • #2 7314016
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #3 7318217
    esnow
    Poziom 14  
    czemu głupią rzecz?
    chce poprostu aby przerwanie od INT0 albo INT1 dekodowało sygnał RC5, czy naprawdę to jest takie głupie?

    wcześniej tak próbowałem z rc5 jak nie miałem pojęcia o synchronizacji:
    
    SIGNAL(SIG_INTERRUPT0)
    {
    	TCCR1B |= ((1<<WGM12) | (1<<CS12)); //tryb CTC und preskaler 256
    	GICR = 0x00;//GICR &= ~(1<<INT0); 	 // wylaczenie przerwania od INT0
    	//GIFR |= _BV(INTF0);                //kasowanie flagi INTF0 , 	
    }
    
    
    SIGNAL(TIMER1_COMPA_vect)
    {
    	OCR1A = 0xDE;    					//nastepna pętla po 1,778ms
    	PORTC ^= _BV(5);
    	
    	if(bit_is_clear(PIND,2))
    	data++;
    	data<<=1;
    	
    	if((data & 0xC000)==0xC000)
    	{
    		adres = data & 0x3F;
    		komenda = data & 0x7C0;
    		komenda >>= 6;
    		
    		sprintf(bufor,"adres:%u komenda:%u \r\n",adres,komenda);
    		send_string(bufor);
    
    		TCCR1B = 0x00;  //wylaczenie timera
    		OCR1A = 0x37;  //znowu pętelka po 0,4445ms   na początek
    		GICR = 0x40;    // wlaczenie przerwania od INT0
    	}
    
    }
    
  • REKLAMA
  • Pomocny post
    #4 7318865
    BoskiDialer
    Poziom 34  
    Zasada jest taka, że podczas wykonywania przerwania, wszystkie inne przerwania są zablokowane (chyba, że się jawnie ponownie załączy przerwania, ale to wymaga kilku drobnych operacji aby nie przeładować stosu). Jeśli w pętli głównej jest wywoływane "rc5decode", to przerwanie ustawiające "timer_flag" będzie się wykonywać. Natomiast załączenie rc5decode w przerwaniu nie daje możliwości ustawienia "timer_flag", przez co kod nie działa. Kod można by przeprojektować aby w całości działał tylko na przerwaniu od timera i nie blokował wykonywania reszty (automat skończony). Prostszym rozwiązaniem natomiast było by pominąć przerwanie od timera ustawiające "timer_flag": zamiast tego testować bezpośrednio flagę TOV0 w rejestrze TIFR (która to jest ustawiana w następstwie przepełnienia timera i która powoduje wystąpienie przerwania), po wykryciu, że jest ustawiona skasować ją i wpisać nową wartość do timera.
  • #5 7319114
    esnow
    Poziom 14  
    BoskiDialer, mądrze prawisz!
    wieczorem spróbuje przerobić kod w ten sposób!
  • #6 7319429
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Za 2 tygodnie napiszesz temat, że giną Ci inne przerwania.

    Nie dziwne, skoro wewnątrz przerwania będziesz spędzał połowę czasu... Pusty while(1) {} w main() jest jakiś super czy coś?

    4\/3!!
  • #7 7334807
    esnow
    Poziom 14  
    BoskiDialer,

    zastąpiłem oczekiwanie na flagę od timera 0
    
    { while ( timer_flag == 0); timer_flag = 0; } 
    

    na:
    
    { while (TOV0==1); TIFR |= 1<<TOV0; TCNT0 = TIMER_0_RECEIVE; }
    


    w mainie włączenie przerwania od INT0:
    
    	GICR |= 1<<INT0;
    	MCUCR |= 1<<ISC01;
        
        sei(); 
    


    TIMSK |= _BV(TOIE0); oraz przerwania od przepełnienia timera wyrzuciłem z kodu.

    i na koniec przerwanie od INT0:
    
    SIGNAL(SIG_INTERRUPT0) 
    {
    PORTC ^= _BV(5); //zmiania stanu na LED
    	GICR &= ~_BV(INT0);
    	rc5decode();  //wywołanie porządanej funkcji
    	GICR |= _BV(INT0); 
    }
    


    dioda jest po to, żeby było widać czy przerwanie się wywołuje i owszem - dioda mruga jak się przytrzyma klawisz na pilocie, NATOMIAST TERMINAL NIC NIE ODBIERA...
  • #8 7334892
    Freddie Chopin
    Specjalista - Mikrokontrolery
    To co napisałeś w ogóle nie ma prawa działać... Zastanów się np nad tym co to jest TOV0, bo ja jestem na 100% pewien, że nie jest tym co Ci się wydaje, ale na Twoje szczęście akurat jest takim czymś, że program nie wiesza się w tej "pętli oczekiwania na flagę".

    4\/3!!
  • #9 7339753
    esnow
    Poziom 14  
    Cytat:
    • Bit 0 – TOV0: Timer/Counter0 Overflow Flag
    The bit TOV0 is set (one) when an overflow occurs in Timer/Counter0. TOV0 is cleared by hardware
    when executing the corresponding interrupt Handling Vector. Alternatively, TOV0 is
    cleared by writing a logic one to the flag. When the SREG I-bit, TOIE0 (Timer/Counter0 Overflow
    Interrupt Enable), and TOV0 are set (one), the Timer/Counter0 Overflow interrupt is executed.


    to w takim razie jak mam to sprawdzać ?
  • #10 7341391
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Chyba masz zerowe pojęcie o programowaniu w C...

    Jeszcze raz więc zastanów się, co oznacza napis "TOV0" w Twoim programie. Popatrz sobie np na ten zapis:
    while (TOV0==1); TIFR |= 1<<TOV0;
    i sam domyśl się, które z tych dwóch sprzecznych użyć TOV0 jest poprawne.

    4\/3!!
  • REKLAMA
  • #12 7342846
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Właśnie o to chodziło! (nie mówię jednak, że nie ma już żadnego błędu, ale na pewno nie ma w tym już błędnego użycia makr)

    Tylko jeszcze zdecyduj się, czy używasz _BV(x) czy (1<<x) (polecam zawsze pisać nawiasy!). Ja polecam to drugie, bo kto wie co to jest to pierwsze? Chyba tylko tacy, którzy używają jedynie AVR, a na nich świat się nie kończy.

    4\/3!!
  • #13 7344698
    esnow
    Poziom 14  
    mam taki i nadal nie działa, a dioda mruga w przerwaniu....
    
    #define TIMER_0_RECEIVE 0x32   // dla 8MHz i preskalera 64
    
    #define RC5BITREF1  6  
    #define RC5BITREF2  11
    #define RC5BITREF3  14
    
    // makra i stale
    #define RC5BitHigh()    (bit_is_set(PIND,PD2))
    #define RC5BitLow()     (bit_is_clear(PIND,PD2))
    #define CZEKAJ_NA_TIMER() { while(TIFR & (1<<TOV0)); TIFR |= (1<<TOV0);  TCNT0 = TIMER_0_RECEIVE; } 
    

    
    SIGNAL(SIG_INTERRUPT0) 
    {
    PORTC ^= (1<<5); //zmiania stanu na LED
    	GICR &= ~(1<<INT0);
    	rc5decode();  //wywołanie porządanej funkcji
    	GICR |= (1<<INT0); 
    }
    

    
    void rc5decode( void )  //  decoded RC5 data is returned, or 0x0000 if RC5 data not recognized
    {
        rc5data=0;
        unsigned char   timer, i;
        
        // init timer/Counter0    
        TCCR0 |= (1<<CS00) | (1<<CS01);                // use CLK/64 prescale
        TCNT0 = TIMER_0_RECEIVE;              // set timer T/16 = 111us 
    	TIMSK |= (1<<TOIE0); 
        
        // measure startbit
        TIFR |= (1<<TOV0);
    	timer = 0; 
        while ( RC5BitLow() && (timer < RC5BITREF2) ) 
    	{
            CZEKAJ_NA_TIMER();
            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 ) {
                CZEKAJ_NA_TIMER();
                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) ) {
                        CZEKAJ_NA_TIMER();
                        timer++;
                    }
                }else{ 
                    rc5data &= ~0x00001;
                    // wait max T/2 for L->H transition (middle of next bit)
                    timer = 0;
                    while ( RC5BitLow() && (timer < 16) ) {
                        CZEKAJ_NA_TIMER();
                        timer++;
                    }
                } 
                if ( timer == 16 ) {
                    rc5data = 0x0000;   // error, next bit not found
                    break;
                }
                
                // wait 3/4 T: await next bit
                for ( timer=0; timer < 12 ; timer++) CZEKAJ_NA_TIMER();
            }
    
        }else {
            rc5data = 0x0000;  // error, invalid RC-5 code
        }
        TCCR0 = 0;            // stop timer0    
        
            if ( rc5data & 0x3000 ) 
    		{		   
    		   komenda = rc5data & 0x3F;
    		   
    		   adres = rc5data & 0x7C0;
    		   adres >>= 6;
    		   
    		   toggle = (rc5data & 0x800);
    		   toggle >>= 11;
    		
    		   sprintf(bufor,"adres:%u komenda:%u toggle:%u \n\r",adres,komenda,toggle);
    		   send_string(bufor);  
            }
    }
    
    
REKLAMA