- 12V Akku mit 280 Ah bauen         
Ergebnis 1 bis 6 von 6

Thema: mega168 - INT0 - Timer2 - Programm Reset?!? :(

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    22.09.2005
    Beiträge
    30

    mega168 - INT0 - Timer2 - Programm Reset?!? :(

    Anzeige

    Praxistest und DIY Projekte
    Hi.

    - ATmega168
    - AVR-Studio 4.12 SP1
    - AVR-GCC 3.4.5
    - AVR-DUDE 1.72 mit GUI 0.2.0

    Mit folgendem Code wird Pin13 bei Programm-Start eingeschaltet und bei einem externen Interrupt - INT0 (mit steigender Flanke an Pin32) ausgeschaltet und bleibt dann auch da..
    Verhält sich also genau wie erwartet.

    Code:
    /*
     * Testprogramm um über Externen Interrupt ein Pin zu ändern...
     * - ATmega168
     * - AVR-Studio 4.12 SP1
     * - AVR-GCC 3.4.5
     * - AVR-DUDE 1.72 mit GUI 0.2.0
     */
    
    #include <inttypes.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    volatile char done = 0;
    
    ISR (INT0_vect) /* Externer Interrupt 0 löst aus.. */
    {
    	PORTB = (0<<PB1); /* Pin 13 ausschalten für Interrupt-Test*/
    }
    
    int main (void)
    {
    	if ( done == 0 ) /* "sicherstellen", dass Initialisierung nur 1 MAL stattfindet!!! */
    	{	
    		/* clk_IO auf 8MHz setzen.. */
    		CLKPR = (1<<CLKPCE)|(0<<CLKPS3)|(0<<CLKPS2)|(0<<CLKPS1)|(0<<CLKPS0);
    		CLKPR = (0<<CLKPCE)|(0<<CLKPS3)|(0<<CLKPS2)|(0<<CLKPS1)|(0<<CLKPS0);
    
    		DDRD = (1<<DDD3)|(0<<DDD2); /* PinD3 als Ausgang */
    		DDRC = (0<<DDC0);			/* PinC0 als Eingang */
    		DDRB = (1<<DDB3)|(1<<DDB1); /* PinB3 und B1 als Ausgang */
    
    		/* INT0 LevelChange, INT1 auf falling Edge scharf machen */	
    		EICRA = (1<<ISC00)|(0<<ISC01)|(0<<ISC10)|(1<<ISC11);
    		/* INT0 enablen, INT1 disablen - da nicht benötigt */
    		EIMSK = (0<<INT1)|(1<<INT0);
    
    //		PCICR = (1<<PCIE2); /* PinChangeInterrupt 16-23 enabled */
    //		PCMSK2 = (1<<PCINT18); 
    
    		PORTB = (1<<PB1); /* Pin 13 anschalten, für Interrupt-Test */
    		done = 1; /* Initialisierung abhaken */
    
    		sei(); /* Interrupts ON */
    	}
    
    	while (1 == 1)	{	} /* Loop forever */
    
    	return (0);
    }
    Wenn ich nun aber Timer2 (8Bit) in dem Initilisierungsteil auf Fast PWM setze mit einem Compare Wert von 0, dann wird der Pin13 spätestens nach 256 Taktzyklen wieder auf High gesetzt, nachdem INT0 funktioniert hat..
    Hat jemand ne Idee, wodurch das verursacht wird?

    Code:
    /*
     * Testprogramm um über Externen Interrupt ein Pin zu ändern...
     * - ATmega168
     * - AVR-Studio 4.12 SP1
     * - AVR-GCC 3.4.5
     * - AVR-DUDE 1.72 mit GUI 0.2.0
     */
    
    #include <inttypes.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    volatile char done = 0;
    
    ISR (INT0_vect) /* Externer Interrupt 0 löst aus.. */
    {
    	PORTB = (0<<PB1); /* Pin 13 ausschalten für Interrupt-Test*/
    }
    
    int main (void)
    {
    	if ( done == 0 ) /* "sicherstellen", dass Initialisierung nur 1 MAL stattfindet!!! */
    	{	
    		/* clk_IO auf 8MHz setzen.. */
    		CLKPR = (1<<CLKPCE)|(0<<CLKPS3)|(0<<CLKPS2)|(0<<CLKPS1)|(0<<CLKPS0);
    		CLKPR = (0<<CLKPCE)|(0<<CLKPS3)|(0<<CLKPS2)|(0<<CLKPS1)|(0<<CLKPS0);
    
    		/* Timer2: CompareMatch A/B, FastPWM, Prescaler = 1 */
    		TCCR2A = (1<<COM2A1)|(0<<COM2A0)|(1<<COM2B1)|(1<<COM2B0)|(1<<WGM21)|(1<<WGM20);	
    		TCCR2B = (0<<FOC2A)|(0<<FOC2B)|(0<<WGM22)|(0<<CS22)|(0<<CS21)|(1<<CS20);			
    		TIMSK2 = (1<<OCIE2A)|(1<<OCIE2B)|(0<<TOIE2); /* Capture Overflow A/B Enablbe */
    
    		OCR2A = 0; /* Compare Match Values = 0 */
    		OCR2B = 0;
    
    		DDRD = (1<<DDD3)|(0<<DDD2); /* PinD3 als Ausgang */
    		DDRC = (0<<DDC0);			/* PinC0 als Eingang */
    		DDRB = (1<<DDB3)|(1<<DDB1); /* PinB3 und B1 als Ausgang */
    
    		/* INT0 LevelChange, INT1 auf falling Edge scharf machen */	
    		EICRA = (1<<ISC00)|(0<<ISC01)|(0<<ISC10)|(1<<ISC11);
    		/* INT0 enablen, INT1 disablen - da nicht benötigt */
    		EIMSK = (0<<INT1)|(1<<INT0);
    
    //		PCICR = (1<<PCIE2); /* PinChangeInterrupt 16-23 enabled */
    //		PCMSK2 = (1<<PCINT18); 
    
    		PORTB = (1<<PB1); /* Pin 13 anschalten, für Interrupt-Test */
    		done = 1; /* Initialisierung abhaken */
    
    		sei(); /* Interrupts ON */
    	}
    
    	while (1 == 1)	{	} /* Loop forever */
    
    	return (0);
    }
    Für mich sieht das immer so aus, als ob der Chip einen Reset erfährt - besonders als ich in AVR-Studio den Code mal getestet hab.. da springt er nachdem der Timer (TCNT2) auf 256 gelaufen ist wieder an den Anfang von main {}.. genau deshalb hab ich ja die if-Abfrage fürs initialisieren eingfügt.. aber sie nutzt nichts.
    Hilfe..


    Und dann hab ich noch 2 Fragen

    - AVRDUDE-Gui betreffend..
    Wo muss ich rumstellen, damit der ATmega168 oben links in der Auswahl erscheint und ich ihn nicht immer selber unten in die Commandozeile eintragen muss?

    -Worin besteht der Unterschied, wenn ich ein Register mit:
    TIMSK2 |= (...
    oder mit
    TIMSK2 = (...
    beschreibe?!

    Vielen Dank
    0tes_Gesetz

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    22.09.2005
    Beiträge
    30
    Hab grad herausgefunden, dass wenn ich die Anweisung:

    "TIMSK2 = (1<<OCIE2A)|(1<<OCIE2B)|(0<<TOIE2); /* Capture Overflow A/B Enablbe */"

    ..weglasse, es dann so wie gedacht funktioniert.
    Nur versteh ich jetzt nicht, wie das sein kann?!
    TIMSK schaltet doch die Pins, welche ich für die Ausgabe des PWM-Signals brauche EIN, wenn ich dort OCIE auf 1 setze...
    Ich bin verwirrt..

    Die Pins die zur PWM Ausgabe gehören geben aber genau das PWM-Signal aus.. obwohl sie nach meiner Meinung nicht dafür freigeschaltet wurden, nachdem die Zeile da oben nun fehlt.

    Mit anderen Worten:
    Das Programm funktioniert jetzt wie gewollt, aber WARUM es das tut ist mir nicht klar...

    Die beiden anderen Fragen bestehen auf jeden Fall noch.. ich würde mich freuen, wenn ich wenigstens darauf ne Antwort bekäme, falls das andere keiner weiß

    Danke

  3. #3
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    22.05.2005
    Ort
    12°29´ O, 48°38´ N
    Beiträge
    2.731
    Hallo,

    wir haben da grad auch einen andren Thread in dem es M168 und AVRDude geht:
    https://www.roboternetz.de/phpBB2/ze...ag.php?t=18416

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    1) Wenn du OCIE2A und OCIE2B aktivierst, solltest du den IRQs auch ihre ISRs spendieren. Ansonsten landest du beim Auftreten der IRQ bei __bad_interrupt, und dann bei Adresse 0.
    2) das id (done==0) kannst du rauswerfen. Es schützt dich nicht vor mehrfachinitialisierungen durch einen Warmstart, denn im init-Code wird done auf 0 gesetzt. Willst du das verbeiden, musst du done dach .noinit lokatieren und MCUCSR auswerten, um es vernünftig zu initialisieren.
    Disclaimer: none. Sue me.

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    22.09.2005
    Beiträge
    30
    @SprinterSB..
    Danke, dein Punkt 1) erklärt das aufgetretene Verhalten vollständig.

    Fehler liegt mit 100% Wahrscheinlichkeit bei mir in einer Missinterpretation des Datenblattes (Interrupts wollte ich ja gar nicht, nur die Pins mit PWM versorgen)..

    Dein Punkt 2) ist mir klar, nachdem es sich um einen "Warmstart" handelt, kann das nichts nutzen... war ja auch nur drin, um ein Symptom zu bekämpfen..
    Aber mit deiner Ursachenklärung hat sich das erledigt.

    @Linux_80..
    Habs gelesen, aber beim EEPROM bin ich noch lange nicht und mit den oben angegebenen Tools funzt bei mir erstmal alles soweit.. man sollte ja schon mehr als dankbar sein, wenn es die Tools kostenlos gibt, da trage ich auch gerne mal "m168" per Hand in ne Kommandozeile ein, wenn's z.Zt. nicht besser geht

    --

    Wäre nur noch die Sache mit der Registersetzung einmal mit " | " und einmal ohne.. worin besteht da der Unterschied?!

    Danke
    0tes_Gesetz

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    a |= b;
    ist eine Abkürzung für

    a = a | b;

    Es werden also in a die Bits gesetzt, die in b 1 sind (zu denen, die in a schon 1 sind).

    a = b; ist eine Zuweisung, das ist was anderes.
    Disclaimer: none. Sue me.

Berechtigungen

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

12V Akku bauen