- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 10 von 17

Thema: Kein Interrupt nach Reset/Neustart

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Roboter-Spezialist Avatar von robo_tom_24
    Registriert seit
    04.02.2012
    Ort
    Burgenland, Österreich
    Beiträge
    485
    Wieso machst du ds eigentlich mit einer Interrupt routine?

    Klar, Timer sind besser, bei delays rechnet die CPU andauernd, bei Timern nicht da dies ein externes Modul am die ist und unabhängig von der cpu läuft. Am besten eine Timer machen, der alle 100ms einen Interrupt auslöst, diese Interrupts mit einer static variable mitzählen und je nach Zählerstand handeln (nach 10x100ms => 1s Rot aus, Gelb ein; nach 16x100ms => 1.6s Gelb aus, usw), wenn man dann einmal durch ist mit dem Ampelprogramm Variable zurücksetzten und das Spiel beginnt von neuem

  2. #2
    Neuer Benutzer Öfters hier
    Registriert seit
    29.07.2013
    Beiträge
    11
    Hallo geehrte Freunde der "C"-Sprache!

    Nun habe ich etwas weiter gemacht.Ich bin auf Timer umgestiegen!
    Soweit funktioniert es auch grundsätzlich!Ein Problem habe ich aber...
    Ich schaffe es nicht zuverlässig den Taster abzufragen..
    Nun habe ich schon in fast jede zweite Code-Zeile die Abfrage reingepackt...kein erfolg..Es funktioniert einfach unzuverlässig.
    Prinzip ist schnell erklärt:Es wird immer die Funktion schalten_ohne(); ausgeführt.bis der Taster PB3 gedrückt wird!dann soll in der nächsten Rot-Phase für Autos, grün für Fußgänger angehen.

    Was mache ich falsch?muss ich tatsächlich auf interrupt für Taster ausweichen(wie in der ersten Version vom Code)?Gibt es vlt doch eine andere Lösung?

    Code:
    /*
     * Ampel_mit_Timer.c
     *
     * Created: 10.08.2013 10:05:38
     *  Author: Gerrus
     */ 
    
    #define F_CPU 4000000UL //Takt auf 4Mhz festlegen
    
    
    
    
    
    #include <avr/io.h>
    #include <avr/interrupt.h> //Include fürs INterrupt
    
    // eigene Bezeichnungen
    #define		rot		PC0
    #define		gelb	PC1
    #define		gruen	PC2
    #define		rotf	PC4
    #define		gruenf	PC5
    #define		ein		1
    #define		aus		0
    
    volatile  int sec,igr;
    void rotf_schalten(unsigned int i)
    {
    	if (i==ein){PORTC	 |= (1 << rotf);}   // Setzen
    	else {PORTC &= ~(1 << rotf);}  // Rücksetzen
    	
    	
    	
    };
    void gruenf_schalten(unsigned int i)
    {
    	if (i==ein){PORTC	 |= (1 << gruenf);}   // Setzen
    	else {PORTC &= ~(1 << gruenf);}  // Rücksetzen
    	
    	
    	
    };
    void rot_schalten(unsigned int i)
    {
    	if (i==ein){PORTC	 |= (1 << rot);}   // Setzen
    	else {PORTC &= ~(1 << rot);}  // Rücksetzen
    	
    	
    	
    };
    void gelb_schalten(unsigned int i)
    {
    	if (i==ein){PORTC	 |= (1 << gelb);}   // Setzen
    	else {PORTC &= ~(1 << gelb);}  // Rücksetzen
    	
    	
    	
    };
    void gruen_schalten(unsigned int i)
    {
    	if (i==ein){PORTC	 |= (1 << gruen);}   // Setzen
    	else {PORTC &= ~(1 << gruen);}  // Rücksetzen
    	//_delay_ms(1000);
    	
    	
    };
    void schalten_ohne (void)
    {
    	if (!(PIND &(1<<PD3)))
    	{
    		sec=1;
    	}
    	if (igr==0)
    	{
    		rot_schalten(ein);
    		
    	}
    	if (!(PIND &(1<<PD3)))
    	{
    		sec=1;
    	}
    	if (igr==76)
    	{
    		gelb_schalten(ein);
    	}
    	if (!(PIND &(1<<PD3)))
    	{
    		sec=1;
    	}
    	if (igr==107)
    	{
    		rot_schalten(aus);
    		gelb_schalten(aus);
    		gruen_schalten(ein);
    	}
    	if (!(PIND &(1<<PD3)))
    	{
    		sec=1;
    	}
    	if (igr==183)
    	{
    		gruen_schalten(aus);
    		gelb_schalten(ein);
    	}
    	if (!(PIND &(1<<PD3)))
    	{
    		sec=1;
    	}
    	if (igr==213)
    	{
    		gelb_schalten(aus);
    		igr=0;
    	}
    	
    }
    void schalten_mit (void)
    {
    	if (!(PIND &(1<<PD3)))
    	{
    		sec=1;
    		
    	}
    	
    	if (igr==0)
    	{
    		rot_schalten(ein);
    		rotf_schalten(ein);
    	}
    	if (igr==15)
    	{
    		rotf_schalten(aus);
    		gruenf_schalten(ein);
    	}
    	if (igr==61)
    	{
    		gruenf_schalten(aus);
    		rotf_schalten(ein);
    	}
    	if (igr==76)
    	{
    		gelb_schalten(ein);
    	}
    	if (igr==107)
    	{
    		rot_schalten(aus);
    		gelb_schalten(aus);
    		gruen_schalten(ein);
    	}
    	if (igr==183)
    	{
    		gruen_schalten(aus);
    		gelb_schalten(ein);
    	}
    	if (igr==213)
    	{
    		rotf_schalten(aus);
    		gelb_schalten(aus);
    		igr=0;
    		sec=0;
    	}
    
    	
    }
    
    
    
    
    ISR (TIMER0_OVF_vect)					// Die Funktion die beim Overflow aufgerufen wird
    {
    	
    	 igr ++;
    	if (!(PIND &(1<<PD3)))
    	{
    		sec=1;
    	}
    }
    
    
    
    
    
    
    int main(void)
    {
    	//PORT C als Ausgang
    	PORTC	=	0x00;
    	DDRC	=	0xFF;
    	
    	//PORT D als Eingang
    	
    	DDRD	=	0<<PD3;
    	PORTD	=	1<<PD3;
    	
    	
    	
    	TCCR0 |= (1<<CS02)|(1<<CS00);	//Einstellen Von Preteiler 1/1024. Datasheet Seite 85
    	TIMSK |= (1<<TOIE0);			//Interrupt auslösen beim Overflow Datasheet Seite 85
    	TCNT0 = 0;						//den timer selber reseten.Eine Null reinschreiben
    	sei();							//Interruos aktivieren
    	
    	
    	while(1)
        {	
    		if (!(PIND &(1<<PD3)))
    	    {
    		    sec=1;
    	    }
    		if (sec==0)
    		{
    			schalten_ohne();		//Ampelschaltung ohne fussgaenger
    			
    		}
    		if (!(PIND &(1<<PD3)))
    		{
    			sec=1;
    		}
    		if (sec==1)
    		{
    			schalten_mit();			//Ampelschaltung mit fussgaenger
    		}
    		
    		
    
    	}
    }
    P.S: Bin über jede Art von Tips dankbar!!Vlt verfolge ich komplett verkehrten weg?vlt geht es einfacher,stabiler,besser?

    Vielen Dank!

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Hallo,
    ich lange über deinen Code gesessen und möchte dazu folgendes beitragen
    Viel Text mit hoffentlikch einer Lösung ganz am Ende.

    Deine Tastenabfrage kannst Du so schreiben, da brauchst Du keine Klammern, weil nur eine Anweisung folgt

    if (!(PIND &(1<<PD3))) sec=1;

    Diese Abfrage kommt eigentlich nur einmal in deine Interrupt Funktion, alle abderen identischen Abfragen kannst Du rausnehmen, die geben dann keinen Sinn.
    Wenn die Taste betätigt wird, setzt Du ja im Interrupt dann die Variable "sec" auf 1. Diese bleibt nun solange auf 1 bis sie vom Hauptprogramm wieder auf 0 gesetzt wird.
    Dies passiert bei Dir NUR in der Funktion schalten_mit bei dem Zählerstand 213 also nach einem kompletten Durchlauf mit Fussgänger. Das sieht soweit okay aus.

    Ich weis jetzt nicht wie oft dein Interrupt ausgelöst wird, anhand deiner Zahlenwerte anscheinend nicht sonderlich häufig. Da könnte es mit der eben genannten Methode "nur im Interrupt" problematisch werden, also lass das vorerst mal so, das tut keinem ja weh, obwohl nicht schön.
    Du könntest noch den Int Aufruf schneller machen, z.B. 10 mal schneller und deine Zeitwertabfragen auch entsprechend mit 10 multiplizieren.
    Dann reicht die Tastenabfrage nur im Interrupt sicherlich aus.

    Idee, aber wieder verworfen....
    Könnte es sein, das an deinem Pin wo die Taste dran ist kein Widerstand nach Plus dran ist, dann bekommt er zwar eine schöne Null wenn Du die Taste drückst, aber wenn Du sie losläst hängt der Pin irgendwie inder Luft.
    Gibt aber auch keinen Sinn, da der High Pegel bei Dir nie ausgewertet wird.


    etwas übersichtliche ist folgende Vorgehensweise:
    Code:
      while(1)
      {
    
        if (sec==0) schalten_ohne();  //Ampelschaltung ohne fussgaenger
               else schalten_mit();   //Ampelschaltung mit  fussgaenger
    
        switch(igr)   /* den Zeitwert auswerten */
        {
    
          case   0 : rot_schalten(ein);
                     break;                /* fertig, sprige hinter die switsch Anweisung */
    
          case  76 : gelb_schalten(ein);
                     break;
    
          case 107 : rot_schalten(aus);
                     gelb_schalten(aus);
                     gruen_schalten(ein);
                     break;  
    
          case 183 : gruen_schalten(aus);
                     gelb_schalten(ein);
                     break;
    
          case 213 : gelb_schalten(aus);
                     igr=0;
                     break;
    
        } /* ende switch */
      } /* ende while */
    Was fällt mir noch ein:
    Ist dein Taster defekt und gibt schlechten Kontakt ?
    ich davon tonnenweise rumliegen.....


    dann hab ich ein ein Read Modify Write Problem gedacht, kenne ich von den PICs von Microchip her.
    Port lesen Bit ändern und zurück schreiben. Dein Taster ist aber auf einem anderen Port als deine LEDs, also eher unwahrscheinlich.


    Letzte Idee:
    Die Variable sec wird im Interrupt gesetzt,
    du hast sie als int definiert, könnte also sein, dass sie 2 Bytes belegt
    Wenn nun im Hauptprogramm der Wert gesetzt wird und ein Interrupt während der Verarbeitung
    der beiden Bytes auftritt, könnte das schief gehen.
    Um das zu verhindern versuche mal folgendes:
    Sperre die Interrupts während Du den Wert sec auf Null setzt.

    Atomaren Code erzeugen nennt man das wohl, also so:

    cli(); // sperre alle Interrupts
    sec = 0; // setzen den Wert
    sei(); //Interrupts aktivieren


    vielleicht konnte ich Dir irgendwie weiterhelfen
    viel Spass noch wünscht Dir
    Siro
    Geändert von Siro (14.08.2013 um 01:06 Uhr)

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    29.07.2013
    Beiträge
    11
    Hallo Siro!
    Vielen Dank für deine Tips!
    Ich bin mi meinem Programm immer noch nicht erfolgreich.
    Wie ich inzwischen raus gefunden habe,reicht die Abfrage in dem Timer-Interupt komplett aus.Denn,ich lasse jetzt ein Port setzen und damit eine extra LED (zur Kontrolle) aufleuchten.Das blöde ist,schein bar wird die Variable "sec" entwider nicht gesetzt (obwohl im gleich "IF"-Strang) oder wird wieder zurückgesetzt ,wie auch immer...
    Leider kriege ich das auch nicht mit dem Debuggen in Atmel Studio raus..
    bin so bischen schon am lust zuverlieren weiter zumachen...

    zB : wenn ich Rücksetzten von "sec" rausnehme aus dem Code ,dann wird "sec" richtig gesetzt(also wenn ich den Taster drücke) und danach läuft wirklich immer die Funktion "schalten_mit"..aber wenn ich die "sec" am ende der Funktion "schalten_mit" wieder auf null setze ,dann funktioniert nichts mehr..
    ich will jetzt nochmals die "IF"`s auf switch umschreiben,aber viel hoffnung, dass es was bringt,ausser übersicht, habe ich nicht.
    es müssen doch zu hauf programme sein ,die ständig auf tasteneingabe warten und trotzdem etwas machen?!Sind die alle über INT0 (1) gemacht?Kann doch nicht sein.

    Ich habe wirklich das Gefühl ,dass die "sec" aus versehen immer überschrieben wird.

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Das ist wirklich merkwürdig was da anscheined passiert.
    Kann es eine Überlappung von Stack und Variablen geben ?
    Ich habe mit den AVR's noch nicht gearbeitet aber man kann sicher so einiges in der Entwicklungsumgebeung umstellen, oder es gibt einen Linker FIle....
    Wenn Du der Meinung bist, dass sich ein Speicher überschreibt:
    Mach doch mal ein paar unnütze Variablen vor den momentanen, um Speicher zu verschwenden....
    Das Problem ist, dass die Compiler unbenutzen meist wegoptimieren, meist reicht das volatile davor.

    volatile char dummy[20]; /* reserviere 20 Bytes für Muell */

    dann deine wirklicehn Variablen

    volatile int sec,igr;

    dadurch verschieben sich die Speicherstellen deiner Variablen
    Dann schaust Du wie sich das Programm dadurch verhält.

    und ganz wichtig: NIE aufgeben jeder Fehler ist zu finden

  6. #6
    Erfahrener Benutzer Roboter Genie Avatar von HeXPloreR
    Registriert seit
    08.07.2008
    Ort
    Bad Bramstedt
    Alter
    45
    Beiträge
    1.369
    Hallo,

    hast Du Software- oder Hardware-Entprellung am Taster? Für die Hardware Entprellung einen Keramikkondensator (etwa 20p - 100p ) parallel zum Taster schalten.
    Das entprellt den Taster damit der Interrupt nicht mehrfach undefiniert ausgelöst wird.
    Das schont die eigenen Nerven und erspart merkwürdige Effekte die man oft nicht so einfach aufspürt.

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Hallo HeXPloreR,
    er wertet in der Software nur das Low Signal aus.
    Erst wenn sein gesamter Ampelablauf durch ist, wird die Variable err wieder auf 0 gesetzt. Prellen sollte da eigentlich keine Rolle spielen.
    Aber Kondi kann nie schaden, 100nF geht auch.

    Falls Speicherproblem: Tipps:
    Ich weis nicht wie der Compiler seine Variablen ablegt, manche machen es sortiert nach Namen, oder man kann das sogar einstellen.
    Vertausche mal die Variablen indem Du ihn andere Namen gibst oder die Reihenfolge veränderst wie sie definiert sind.
    Nenn die einfach mal a_sec und probiere oder das nächste mal z_sec. Wenn der Compiler die dann Namentlich im Speicher sortiert landen sie
    in andere Reihenfolge im Speicher und wenn es ein Speicherüberlappungsproblem ist wird sich das Programm dann auch anders verhalten.

    Im .MAP File, falls dieser erzeugt wird, kann man nachschauen wo der Compiler die Variablen abgelegt hat.

    Der Stack muss eingestellt sein, aber bei deinem Miniprogramm sollte das vermutlich voreingestellt sein.
    Der Heap (Halde) wird nicht benötigt solange Du keine dynamische Speicherverwaltung benutzt. Hast Du ja nicht.

    Ändere mal dein err zu einem char, nicht int, somit belegt die Variable nur noch 1 Byte.

    Hast Du das mit dem sti() cli() ausprobiert ?

Ähnliche Themen

  1. Kein Reset mit angeschlossenem ISP Programmer
    Von Markus87 im Forum Schaltungen und Boards der Projektseite Mikrocontroller-Elektronik.de
    Antworten: 5
    Letzter Beitrag: 23.08.2011, 14:22
  2. kein RXD Empfang nach "Reset"
    Von neo3000 im Forum Controller- und Roboterboards von Conrad.de
    Antworten: 0
    Letzter Beitrag: 10.10.2010, 14:39
  3. Motorport wird nach Neustart angesteuert am ATMEGA 32 ?
    Von M.Huhnke im Forum AVR Hardwarethemen
    Antworten: 2
    Letzter Beitrag: 20.01.2010, 16:00
  4. Problem nach RESET
    Von bombatz im Forum Assembler-Programmierung
    Antworten: 7
    Letzter Beitrag: 12.08.2006, 12:10
  5. Timer1 reset nach Compare1A
    Von Theo16505 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 11.02.2006, 23:33

Stichworte

Berechtigungen

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

Solar Speicher und Akkus Tests