- Akku Tests und Balkonkraftwerk Speicher         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 11

Thema: Code: Globale Boolvariable mit INT0 Interrupt auf Tiny13 set

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    12.01.2010
    Beiträge
    64

    Code: Globale Boolvariable mit INT0 Interrupt auf Tiny13 set

    Anzeige

    Praxistest und DIY Projekte
    Hallo Community,

    ich brauche hilfe für ein projekt, für das ich nur noch eine Funktion implementieren muss und es dann echt geschafft habe- aber die bereitet mir momentan probleme:

    Ich möchte über einen hardwareentprellten taster und dem INT0 Interrupt
    bestimmen, ob der µC die Funtion "signal_event" in der mainschleife
    ausführt oder nicht. Zum wechseln ob ja oder nein, dachte ich an die
    if-bedingungen im ISR und eine globale boolvariable.
    Bei meinem Code wird über den INT0 immer nur der zweite teil der
    ifbedingung ausgeführt, das heißt die bool ändert sich nicht.

    Könnt ihr mir sagen, was ich falsch mache? Sehr viel mehr code passt
    nicht rein, bin momentan bei ca 88%.


    Code:
    #include <stdbool.h>
    #include <stdlib.h>
    #include <stdint.h>
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/power.h>
    #include <avr/sleep.h>
    
    #define F_CPU 9.6E6
    #include <util/delay.h>
    
    #define CLOCK_PRESCALER 256
    #define TIMER_PRESCALER 1024
    
    #define TIMER_PERIOD (256 / (F_CPU / CLOCK_PRESCALER / TIMER_PRESCALER))
    
    #define MEDIAN ( 1 * 60)  /* 10 minutes */
    
    static uint16_t countdown;
    static volatile bool timer_expired;
    volatile bool on;
    
    
    ISR(TIM0_OVF_vect)
    {
      if (--countdown == 0) {
        TCCR0B = 0;  /* turn off timer */
        timer_expired = true;
        clock_prescale_set(clock_div_1);
      }
    }
    
    ISR(INT0_vect)
    {  
      if (on)
      {
        on = false;
        
        PORTB |= (1<<PB4); // LED 2*flashing: Off
        _delay_ms(20);
        PORTB &= ~(1<<PB4);
        _delay_ms(20);
        PORTB |= (1<<PB4); 
        _delay_ms(20);
        PORTB &= ~(1<<PB4);
        _delay_ms(20);
      }
      else if (!on)
      {
        on = true;
        
        PORTB |= (1<<PB4); // LED 1*flashing: On
        _delay_ms(20);
        PORTB &= ~(1<<PB4);
        _delay_ms(20);
      }
    }
    
    static void starttimer(uint16_t timeout)
    {
      countdown = timeout;
      TCNT0 = 0;
      timer_expired = false;
      clock_prescale_set(clock_div_256);
      TCCR0B = _BV(CS02) | _BV(CS00);  /* start timer with prescaler 1024 */
    }
    
    static void ioinit(void)
    {
      TIMSK0  = _BV(TOIE0);
      GIMSK  |= (1<<INT0); 
      MCUCR  |= (1<<ISC01);    // Falling edge
      MCUCR  &= ~(1<<ISC00);    // INT0 detection   
          
      sei();
      DDRB = _BV(4);  /* connection for LED or something else */
    }
    
    static void signal_event(void)
    {
      PORTB |= _BV(4);
      _delay_ms(1000);
      PORTB &= ~_BV(4);
    }
    
    int
    main(void)
    {
      ioinit();
    
      for (;;) {
        int r = rand();
        uint16_t timeout = (unsigned)r % (unsigned)(2 * MEDIAN / TIMER_PERIOD) + 1;
    
        starttimer(timeout);
        do
        {
          sleep_mode();
        }
        while (!timer_expired);
        
      if (on)
      signal_event();
      }
    }


    Beste Grüße[/code]

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    26.08.2006
    Beiträge
    84
    Nur ein Schuss ins Blaue, aber probiers mal so:
    Code:
    ISR(INT0_vect)
    { 
      if (on) {
        on = false;
        ...   
      } else {
        on = true;
        ...
      }
    }
    Wer weiß, wie der Compiler das else if wirklich evaluiert und was dann passiert wenn du die Bedingung im ersten Teil veränderst...

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    12.01.2010
    Beiträge
    64
    danke, ändert aber leider nichts. :/

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    36
    Beiträge
    5.070
    Ich habe es im AVR Studio getestet (mit und ohne Änderung). Ohne Änderung hat es nicht funktioniert (hat "on" und "!on" ausgeführt).
    Mit der Änderung hat es aber funktioniert.

    Da ich keinen Tiny13 habe kann ich es nur im Simulator testen.

    Hast du es im Simulator getestet oder auf dem µC?

    MfG Hannes

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    12.01.2010
    Beiträge
    64
    auf dem µC, mit dem simulator habe ich keine erfahrung...
    was meinst du mit änderung? die änderung der booleschen in der if/else schleife?

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    26.08.2006
    Beiträge
    84
    Die ISR macht komische Dinge im Simulator...

    Hab die bools mal durch uint8 ersetzt und den Wechsel mit nem xor realisiert.
    Zumindest im Simulator tuts jetzt in der ISR.

    Code:
    #include <stdlib.h> 
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/power.h>
    #include <avr/sleep.h>
    
    #define F_CPU 9.6E6
    #include <util/delay.h>
    
    #define CLOCK_PRESCALER 256
    #define TIMER_PRESCALER 1024
    
    #define TIMER_PERIOD (256 / (F_CPU / CLOCK_PRESCALER / TIMER_PRESCALER))
    
    #define MEDIAN ( 1 * 60)  /* 10 minutes */
    
    volatile uint16_t countdown;
    volatile uint8_t timer_expired;
    volatile uint8_t on;
    
    
    ISR(TIM0_OVF_vect)
    {
      if (--countdown == 0) {
        TCCR0B = 0;  /* turn off timer */
        timer_expired = 0x01;
        clock_prescale_set(clock_div_1);
      }
    }
    
    ISR(INT0_vect)
    { 
      on ^= 0x01;
      if (on) {
    	   	PORTB |= (1<<PB4); // LED 2*flashing: Off
        	_delay_ms(20);
        	PORTB &= ~(1<<PB4);
        	_delay_ms(20);
        	PORTB |= (1<<PB4);
        	_delay_ms(20);
        	PORTB &= ~(1<<PB4);
        	_delay_ms(20);
      	} else {
        	PORTB |= (1<<PB4); // LED 1*flashing: On
        	_delay_ms(20);
        	PORTB &= ~(1<<PB4);
        	_delay_ms(20);
      	}
    }
    
    static void starttimer(uint16_t timeout)
    {
      countdown = timeout;
      TCNT0 = 0;
      timer_expired = 0x00;
      clock_prescale_set(clock_div_256);
      TCCR0B = _BV(CS02) | _BV(CS00);  /* start timer with prescaler 1024 */
    }
    
    static void ioinit(void)
    {
      TIMSK0  = _BV(TOIE0);
      GIMSK  |= (1<<INT0);
      //MCUCR  |= (1<<ISC01);    // Falling edge
      //MCUCR  &= ~(1<<ISC00);    // INT0 detection   
      MCUCR = 0x02;
    
      on = 0x00;
         
      sei();
      DDRB = _BV(4);  /* connection for LED or something else */
    }
    
    static void signal_event(void)
    {
      PORTB |= _BV(4);
      _delay_ms(1000);
      PORTB &= ~_BV(4);
    }
    
    int
    main(void)
    {
      ioinit();
    
      while(1) {
        int r = rand();
        uint16_t timeout = (unsigned)r % (unsigned)(2 * MEDIAN / TIMER_PERIOD) + 1;
    
        starttimer(timeout);
        do
        {
          sleep_mode();
        }
        while (!timer_expired);
       
      	if (on) {
    		signal_event();
      	}
      }
    }

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    12.01.2010
    Beiträge
    64
    ich muss zugeben, ich verstehe nicht so ganz, was da im code jetzt passiert.. ^^
    ich will ja einen wechsel innerhalb der if/else bedingungen. also wenn on an war, dann soll es danach aus sein und andersrum.
    dein wechsel kommt ja vor der schleife!
    Ich habe die wechsel wie bei meinem boolbeispiel dann wieder hineingetan - und es funktioniert auch nicht

    ist doch verhext...

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    12.01.2010
    Beiträge
    64
    Ist doch merkwürdig.. wenn ich die funktion so verändere:

    Code:
    ISR(INT0_vect)
    {
    	if (on)
    	{
    		PORTB |= (1<<PB4); // LED 1*flashing: Off
    		_delay_ms(2);
    		PORTB &= ~(1<<PB4);
    		_delay_ms(10);
    
    		on = 0;
    		if (!on)
    		{
    			PORTB |= (1<<PB4);
    			_delay_ms(2);
    			PORTB &= ~(1<<PB4);
    			_delay_ms(2);
    		}
    	}
    	else 
    	{
    		PORTB |= (1<<PB4); // LED 2*flashing: On
    		_delay_ms(2);
    		PORTB &= ~(1<<PB4);
    		_delay_ms(2);
    		PORTB |= (1<<PB4); 
    		_delay_ms(2);
    		PORTB &= ~(1<<PB4);
    		_delay_ms(10);
    
    		on = 1;
    		if (on)
    		{
    			PORTB |= (1<<PB4);
    			_delay_ms(2);
    			PORTB &= ~(1<<PB4);
    			_delay_ms(2);
    		}
    	}
    }
    zeigt sich, dass die variable in der schleife definitiv geändert wird (wenn ich mit on=0 initialisiere, wird die else schleife aufgerufen und es blinkt dreimal). Danach wird sie anscheinend wieder zurückgesetzt!
    Woran liegt das? Was habe ich da nicht begriffen?

  9. #9
    Benutzer Stammmitglied
    Registriert seit
    26.08.2006
    Beiträge
    84
    Zu deinem code:
    ...
    on = 0;
    if (!on)
    ...
    und
    ...
    on = 1;
    if (on)
    ...
    Beide if werden auf diese Weise immer zutreffen

    Zu meinem code:
    Ein uint8_t ist ein byte und das kann man fast genauso testen wie ein bool.
    Wenn es null ist treffen Vergleiche nicht zu (false), wenn es größer ist treffen Vergleiche zu (true). Man kann also wie bei bool 'if (on)' verwenden, muß nur auf 0 oder 1 setzen statt false und true.

    In der ISR mach das 'on ^= 0x01;' den Wechsel genauso wie du es im if else beabsichtigst, nur kann der compiler im Vergleich dahinter keinen Blödsinn mehr veranstalten wie wenn du on zwischendurch setzt.
    XOR:
    0^0 ist 0
    1^0 ist 1
    0^1 ist 1
    1^1 ist 0
    Wenn on 1 ist und mit ner 1 xored, wird es 0, aus true wird false.
    Wenn on 0 ist und mit ner 1 xored, wird es 1, aus false wird true.

    Ausgeschrieben wirds evtl. deutlicher:
    on = on ^ 0x01;

  10. #10
    Benutzer Stammmitglied
    Registriert seit
    26.08.2006
    Beiträge
    84
    Scheißding...

    Probier mal den Code aus deinem ersten Post, aber stell im Projekt mal die Optimierung von -Os auf -O3.
    Sonst passieren in der ISR nur komische Sachen.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress