-         
Seite 2 von 2 ErsteErste 12
Ergebnis 11 bis 17 von 17

Thema: Kein Interrupt nach Reset/Neustart

  1. #11
    Erfahrener Benutzer Roboter Genie Avatar von HeXPloreR
    Registriert seit
    08.07.2008
    Ort
    24558
    Alter
    41
    Beiträge
    1.360
    Anzeige

    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.
    "Es ist schwierig, jemanden dazu zu bringen, etwas zu verstehen, wenn er sein Gehalt dafür bekommt, dass er es nicht versteht" [Upton Sinclair] gez-boykott

  2. #12
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Ort
    Berlin
    Beiträge
    1.034
    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 ?

  3. #13
    Neuer Benutzer Öfters hier
    Registriert seit
    29.07.2013
    Beiträge
    11
    Ich habe sowohl hardware-als auch software den taster versucht zuentprellen.daran liegt es nicht.

    Das muss einfach an dem Programm liegen.
    @Siro
    ich habe versuch die "sec" umzubenennen und auch die Interrups vorrübergehend zuverbieten,kein erfolg.
    Ich werde das Programm neu schreiben.Aber von hinten aufgerollt.Sprich:Erst "sec" setzen und dann immer weiteren Code zufügen.und diesmal will ich das hochzählen aus zwei variablen auslagern und diese auch im interrupt nullen.
    ca so:
    Code:
    Interruptfunktion{
     i_ohne++; (wenn >=255-> i_ohne =0;)
    i_mit++; (wenn i_mit >=255 -> i_mit =0;)
    wenn taster PD3 dann sec=1;
    }
    main()
    {
    if sec=1 dann
    switch(i_mit)
    
    case 12:
    case23:
    usw
    ...
    case 234: sec= 0;
    
    if sec=0 dann
    
    switch (i_ohne)
    case 12:
    case 23:
    usw
    der derzeitige Code sieht so aus:
    Code:
    /*
     * Ampel_mit_Timer.c
     *
     * Created: 10.08.2013 10:05:38
     *  Author: Gerrus
     */ 
    
    //#define F_CPU 16000000UL //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 igr;
    volatile unsigned m_sec;
    
    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)
    {
    	while(1)
    	{
    		
    	
    	if (igr==0)
    	{
    		rot_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);
    		rotf_schalten(aus);
    	}
    	
    	if (igr==213)
    	{
    		gelb_schalten(aus);
    		igr=0;
    	}
    	break;
    	
    	}
    }
    void schalten_mit (void)
    {
    	
    	while (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)
    	{
    		m_sec=0;
    		rotf_schalten(aus);
    		gelb_schalten(aus);
    		igr=0;
    		
    	}
    	break;
    	}
    	
    }
    
    
    
    
    ISR (TIMER0_OVF_vect) // Die Funktion die beim Overflow aufgerufen wird
    {
    	int temp;
    	temp=PIND;
    	if ((temp &(1<<PD3)))
    	{
    		
    		m_sec = 1; // setzen den Wert
    		
    
    		
    	}
    	 igr ++;
    	
    }
    
    
    
    
    
    
    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)
        {	
    		
    		
    		switch(m_sec)
    		{
    			
    			case 0:
    			schalten_ohne();
    			break;
    			
    			case 1:
    			schalten_mit();
    			break;
    			
    		}
    
    	}
    }
    und es funktioniert NUR wenn ich den Taster dauerhaft gedrückt halte.dann geht das.Los lasse,dann geht er wieder in Phase ohne Fussgänger-Ampel.wieder gedrückt halte,wieder mit Fussgänger.
    Ich weiss nicht warum das Programm die variable "sec" immer wieder auf null setzt ,bevor die Funktion schalten_mit eintritt...

    Ich melde mich,sobald ich das neue Programm fertig habe

  4. #14
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Ort
    Berlin
    Beiträge
    1.034
    Nabend,
    die while schleifen in den beiden schalten_mit schalten_ohne und den break am Ende benötigst Du nicht,
    da die Funktionen vom Hauptprogramm immer wieder aus der Schleife aufgerufen werden.

    Ich bin gespannt....

  5. #15
    Neuer Benutzer Öfters hier
    Registriert seit
    29.07.2013
    Beiträge
    11
    Zitat Zitat von Siro Beitrag anzeigen
    Nabend,
    die while schleifen in den beiden schalten_mit schalten_ohne und den break am Ende benötigst Du nicht,
    da die Funktionen vom Hauptprogramm immer wieder aus der Schleife aufgerufen werden.

    Ich bin gespannt....
    ich weiss, das ist alles schon wegen des verzweifelns entstanden
    wollte damit ganz sicher gehen ,dass if anweisungen ausgeführt werden bevor die variable zurückgesetzt wird

    SChönen Abend noch!

    P.S: Ich sehe grad i-in der Version habe ich gar keine Rücksetzung der variable..wie gesagt bin zur Zeit sehr viel am rum rumprobieren

  6. #16
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Ort
    Berlin
    Beiträge
    1.034
    die letzte Abfrage würde ich sicherheitshalber mit >= abfragen.
    if (igr>=213) denn wenn das Programm mal etwas länger braucht könnte der Zähler evtl. schon auf 214 stehen, was passiert dann eigentlich ?
    Ich vermute dann stehen deine Lampen eine ganze Weil lang still bis die Variable bis auf 65535 hochgezählt hat und dann auf 0 springt.
    Ich würde diese Abfrage sogar direkt in die Interrupt Routine packen.

    if (igr < 213) igr++; else igr = 0;

    dann kann das erst garnicht passieren und die Variable wird nur noch im Interrupt geändert.

    klärt aber immer noch nicht dein Problem
    Geändert von Siro (14.08.2013 um 20:37 Uhr)

  7. #17
    Neuer Benutzer Öfters hier
    Registriert seit
    29.07.2013
    Beiträge
    11
    Das habe ich zur Zeit.
    Funktioniert auch soweit ganz gut.

    [SPOILER]
    Code:
    /*
     * timer_von_null.c
     *
     * Created: 14.08.2013 17:14:16
     *  Author: Gerrus
     */ 
    
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    
    // eigene Bezeichnungen
    #define		rot		PC0
    #define		gelb	PC1
    #define		gruen	PC2
    #define		rotf	PC4
    #define		gruenf	PC5
    #define		ein		1
    #define		aus		0
    
    volatile unsigned char zaehler=0,timer_mit=0,timer_ohne=0,temp=0,temp2=0;
    
    
    ISR (TIMER0_OVF_vect)					// Die Funktion die beim Overflow aufgerufen wird
    {
    	
    	if ((~PIND &(1<<PD3)))				//Prüfen ob Taster gedrückt wurde.Taster ist gegen Ground gezogen
    	{
    		if ((~PINC&(1<<gruenf)))
    		{
    		
    		rotf_schalten(ein);				// Fussgänger Rot auf rot stellen.vorher war signal aus.
    		
    		}
    		
    		zaehler=1;						//Zähler für Tasterzustand auf eins -Taster wurde betätigt.
    	}
    	
    	if (timer_ohne < 214) timer_ohne++; else timer_ohne=0; //Variable um auf Sekunden zukommen.Eine Sekunde gleich 15,15 Ticks.beim erreichgen von 213,wieder auf null.
    	
    
    	
    }
    
    void rotf_schalten(unsigned int i)			//Fussgänger Rot
    {
    	if (i==ein){PORTC	 |= (1 << rotf);}   // Setzen
    	else {PORTC &= ~(1 << rotf);}  // Rьcksetzen
    	
    	
    	
    };	
    void gruenf_schalten(unsigned int i)		//FUssgänger Grün
    {
    	if (i==ein){PORTC	 |= (1 << gruenf);}   // Setzen
    	else {PORTC &= ~(1 << gruenf);}  // Rьcksetzen
    	
    	
    	
    };		
    void rot_schalten(unsigned int i)			//Auto Rot
    {
    	if (i==ein){PORTC	 |= (1 << rot);}   // Setzen
    	else {PORTC &= ~(1 << rot);}  // Rьcksetzen
    	
    	
    	
    };
    void gelb_schalten(unsigned int i)			//Auto Gelb
    {
    	if (i==ein){PORTC	 |= (1 << gelb);}   // Setzen
    	else {PORTC &= ~(1 << gelb);}  // Rьcksetzen
    	
    	
    	
    };
    void gruen_schalten(unsigned int i)			//Auto Grün
    {
    	if (i==ein){PORTC	 |= (1 << gruen);}   // Setzen
    	else {PORTC &= ~(1 << gruen);}  // Rьcksetzen
    	
    
    	}
    void schalten (void)						//Hauptfunktion um Ampel zuschalten
    {
    	
    	
    	
    	if (timer_ohne==0)						//Sekunde 0
    	{
    		rot_schalten(ein);
    		
    	}
    	if (timer_ohne==15&&zaehler==1)			//Sekunde 1 aber nur wenn Taster gedrückt wurde
    	{
    		rotf_schalten(aus);
    		gruenf_schalten(ein);
    	}
    	if (timer_ohne==61&&zaehler==1)			//Sekunde 4 aber nur wenn Taster gedrückt wurde
    	{
    		gruenf_schalten(aus);
    		rotf_schalten(ein);					//WICHTIG!!!
    		zaehler=2;							//Zähler wird auf Zwei gesetzt damit man nicht durcheinander kommt beim rücksetzen später
    	}
    	
    	if (timer_ohne==70&&zaehler==2)			//Sekunde 4,6 Schaltet Fussgängerrot aus ,ABER nur wenn schon eine Phase durchgelaufen
    	{
    		
    		rotf_schalten(aus);
    		
    	}
    	if (timer_ohne==76)						// Sekunde 5
    	{
    		gelb_schalten(ein);
    		
    	}
    
    	if (timer_ohne==107)					//Sekunde 7
    	{
    		rot_schalten(aus);
    		gelb_schalten(aus);
    		gruen_schalten(ein);
    		
    		
    	}
    	
    	if (timer_ohne==183)					//Sekunde 12,2
    	{
    		
    		gruen_schalten(aus);
    		gelb_schalten(ein);
    		//rotf_schalten(aus);
    	}
    	
    	if (timer_ohne==213)					//Letzter Schaltvorgang Sekunde 14
    	{
    		
    		gelb_schalten(aus);
    		if (zaehler==2)
    		{
    			zaehler=0;						//Wird nur resetet wenn Fussgängerphase schon durchgelaufen ist
    		}
    	}
    	
    	
    
    }
    /*void schalten_mit (void)
    {
    	
    	
    	
    		
    		if (timer_mit==0)
    		{
    			
    			rot_schalten(ein);
    			rotf_schalten(ein);
    		}
    		if (timer_mit==15)
    		{
    			rotf_schalten(aus);
    			gruenf_schalten(ein);
    		}
    		if (timer_mit==61)
    		{
    			gruenf_schalten(aus);
    			rotf_schalten(ein);
    		}
    		if (timer_mit==76)
    		{
    			gelb_schalten(ein);
    		}
    		if (timer_mit==107)
    		{
    			rot_schalten(aus);
    			gelb_schalten(aus);
    			gruen_schalten(ein);
    		}
    		if (timer_mit==183)
    		{
    			gruen_schalten(aus);
    			gelb_schalten(ein);
    		}
    		if (timer_mit==213)
    		{
    			
    			rotf_schalten(aus);
    			gelb_schalten(aus);
    			zaehler=0;
    			
    			
    		}
    	
    	
    	
    }
    */
    
    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();									//Interrups aktivieren
        
    	
    	while(1)
        {
        
    		schalten();							 //Hauptschleife
    	}
    
    
    }
    [/SPOILER]

    Als nächstes will ich das ganze auf eine Kreuzung portieren.Sprich das ganze noch einmal aber mit verknüpfung zu einander.

    Außerdem stelle ich grade fest,dass ich noch eine Sperre für Rot_fuss einbauen muss,sobald gruen_fuss leuchtet.Quasi ein BUG entdeckt.Mein erster!!!!*freu* :-D (siehe EDIT)

    In Planung ist auch das ganze in Hardware umzusetzen,mit Batterie Einspeisung.Bin schon am ausschau halten nach ampel gehäuse.vlt einen dicken Kugelschreiber oder ähnliches.
    Hier nochmal ein kleiner Plan,falls jemand auf die schnelle ausprobieren möchte.(Widerstände vor den LEDs ,in Höhe von 330 Ohm , fehlen auf der Zeichnung. Diese müssen unbedingt aber in die reele Schaltung rein)

    Klicke auf die Grafik für eine größere Ansicht

Name:	New-Project.jpg
Hits:	2
Größe:	24,9 KB
ID:	26236


    Nicht desto trotz,wenn jemand etwas zu verbessern oder zu optimieren weiss,immer her damit!

    Vielen Dank und viel Erfolg!

    EDIT: Einfache IF-Anweisung hat den "BUG" behoben.
    Code:
    if ((~PINC&(1<<gruenf)))
    		{
    		
    		rotf_schalten(ein);				// Fussgänger Rot auf rot stellen.vorher war signal aus.
    		
    		}
    P.S: Hat evtl. jemand weitere deutsche Foren für Programmieren in C für ATMEL? (ausser microkontroller.net,da sind ja nur "profis"... )
    Geändert von Cheffe Boss (16.08.2013 um 21:28 Uhr)

Seite 2 von 2 ErsteErste 12

Ä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, 13:22
  2. kein RXD Empfang nach "Reset"
    Von neo3000 im Forum Controller- und Roboterboards von Conrad.de
    Antworten: 0
    Letzter Beitrag: 10.10.2010, 13:39
  3. Motorport wird nach Neustart angesteuert am ATMEGA 32 ?
    Von M.Huhnke im Forum AVR Hardwarethemen
    Antworten: 2
    Letzter Beitrag: 20.01.2010, 15:00
  4. Problem nach RESET
    Von bombatz im Forum Assembler-Programmierung
    Antworten: 7
    Letzter Beitrag: 12.08.2006, 11:10
  5. Timer1 reset nach Compare1A
    Von Theo16505 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 11.02.2006, 22:33

Stichworte

Berechtigungen

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