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

[Atmega128][ethernut] przerwania się 'kłócą'

herszt 29 Lis 2009 17:44 1583 2
  • #1 7324116
    herszt
    Poziom 18  
    Witam!

    Mam taki dość nietypowy problem. Kontroler ma reagować na jedno z trzech przerwań: TIMERa 0 i dwóch zewnętrznych (czujki ruchu). Te przerwania zewnętrzne zliczają liczbę reakcji czujek, natomiast TIMER 0 ma odmierzać czas i dzięki niemu co kilka sekund mają być wyświetlane statystyki. Bez TIMERa 0 wszystko działa ok, ale statystyki lecą cały czas, natomiast po dodaniu TIMERa 0 liczby zliczeń z czujek zaczynają szaleć i pojawiają się jakieś abstrakcyjne rzeczy (bez przerwania licznik się zwiększa o kilkadziesiąt, kilkaset itd.). Kod prezentuje się następująco (oczywiście tak wybiórczo):

    
    volatile int i;
    volatile int j;
    volatile int timer_overflow_counter, timer_counter ;
    volatile int wyswietl_statystyki ;
    
    static void IrqHandler0(void *arg)
    {
    	++i ;
    }
    
    static void IrqHandler1(void *arg)
    {
    	++j ;
    }
    
    void T0_init(void)						 // Inicjalizacja TIMERa
    {   
       timer_overflow_counter = 0 ;
       timer_counter = 0 ;
       TIMSK &=~((1<<TOIE0)|(1<<OCIE0));   // Disable TC0 interrupt
       ASSR |= (1<<AS0);                    // set Timer/Counter0 to be asynchronous from the CPU clock with a second
    										 // external clock(32,768kHz) driving it.
       TCNT0 = 0x00;
       TCCR0 = 0x05;                         // prescale the timer to be clock source 128 to make it exactly 1 second for every overflow to occur
       while(ASSR&0x07);                    // Wait until TC0 is updated
       TIMSK |= (1<<TOIE0);                 // set 8-bit Timer/Counter0 Overflow Interrupt Enable
    }
    
    static void IrqTimer0(void *arg)       // Przerwanie TIMERa
    {
    
    	++timer_overflow_counter ;
    											 // !!!!
    	if (timer_overflow_counter==5)			 // !!!! ILE SEKUND POMIEDZY WYSWIETLENIEM STATYSTYK
    		{									 // !!!!
    			timer_counter = 1 ;
    			wyswietl_statystyki = 1 ;
    		}
    }
    
    [...]
    
    int main()
    {
    	confcom.baud = 115200;  // UART speed
    	
    	DDRD =  0x00 ; // PORTD jako wejscie
    	PORTD = 0xFF ; // podciagniecie wejsc do 1
    	EICRA = 0xAA ; // wejscie reaguje na opadajace zbocze
    	EIMSK = 0x0F ; // odblokowuje przerwania na wejsciach INT0...INT3
    	
        NutRegisterIrqHandler(&sig_INTERRUPT0, IrqHandler0, NULL);    // obsluga przerwania czujki 1
    	NutRegisterIrqHandler(&sig_INTERRUPT1, IrqHandler1, NULL);    // obsluga przerwania czujki 2
    	NutRegisterIrqHandler(&sig_OVERFLOW0, IrqTimer0, NULL); 	   // obsluga przerwania TIMERa 0
    
    [...]
    
    T0_init() ; // Inicjalizacja TIMERa 0
    
    int wykonaj = 1;
    
    wyswietl_statystyki = 1 ;
    timer_counter = 0 ;
    
    	for(;;)
    	{
    		if(timer_counter && wyswietl_statystyki) // status licznikow co 5 sekund if(timer_counter && wyswietl_statystyki)
    		{
    			timer_counter = 0 ;
    			timer_overflow_counter = 0 ;
    			wyswietl_statystyki = 0 ;
    			//printf_P(PSTR("\r\nWatek glowny\r\n")) ;
    			printf_P(PSTR("\n\rCzas wyswietlenia danych:\t%s\n\r"), timeToAscii(getTime()));
    			printf_P(PSTR("Licznik 0: %i\n\r"), i) ;
    			printf_P(PSTR("Licznik 1: %i"), j) ;
    		}
    		//NutDelay(1000) ;
    		if (wykonaj)
    		{
    		wykonaj = 0;
    		read_f() ;
    		}
    	}
    


    Jeszcze dodam, że kod obsługi jest skopiowany z urządzenia gdzie chodził na kwarcu 37MHz, a tu mam 25MHz, ale wydaje mi się że jest ok. Choć mogę się mylić.
    Może ktoś ma jakiś pomysł jak temu zaradzić?

    z góry dzięki
    pozdrawiam
    herszt
  • #2 7328033
    herszt
    Poziom 18  
    Odkryłem, że nie wiedzieć czemu wraz z przerwaniami TIMERa 0 wywoływane są przerwania INT0 oraz INT1 pomimo, że nic się na nich fizycznie nie dzieje. Nie mam pojęcia czemu się tak dzieje... może jakieś pomysły?

    z góry dzięki
    pozdrawiam
    herszt
  • #3 7645888
    Przemek_100
    Poziom 11  
    Nie wolno ci w ethernucie uzywac Timera 0 jest on przeznaczony dla systemu operacyjnego :) - ponizej z helpa

    void NutRegisterTimer ( void(*)(void *) handler )

    Initialize system timer.

    Initialize system timer hardware.

    This function is automatically called by Nut/OS during system initialization.

    Nut/OS uses on-chip timer 0 for its timer services. Applications should not modify any registers of this timer, but make use of the Nut/OS timer API. Timer 1 and timer 2 are available to applications.

    Definition at line 174 of file ostimer_at91.c.

    Dodano po 34 [minuty]:

    Nie wolno ci w ethernucie uzywac Timera 0 jest on przeznaczony dla systemu operacyjnego :) - ponizej z helpa

    void NutRegisterTimer ( void(*)(void *) handler )

    Initialize system timer.

    Initialize system timer hardware.

    This function is automatically called by Nut/OS during system initialization.

    Nut/OS uses on-chip timer 0 for its timer services. Applications should not modify any registers of this timer, but make use of the Nut/OS timer API. Timer 1 and timer 2 are available to applications.

    Definition at line 174 of file ostimer_at91.c.

    Dodano po 49 [sekundy]:

    Nie wolno ci w ethernucie uzywac Timera 0 jest on przeznaczony dla systemu operacyjnego :) - ponizej z helpa

    void NutRegisterTimer ( void(*)(void *) handler )

    Initialize system timer.

    Initialize system timer hardware.

    This function is automatically called by Nut/OS during system initialization.

    Nut/OS uses on-chip timer 0 for its timer services. Applications should not modify any registers of this timer, but make use of the Nut/OS timer API. Timer 1 and timer 2 are available to applications.

    Definition at line 174 of file ostimer_at91.c.
REKLAMA