Hallo Jens,
danke für deine Info. Hab die Bariable jetzt global deklariert.
Es kommen zwar keine Fehlermeldungen mehr, aber das Programm funktioniert trotzdem nicht
Gruß Anna
Hallo,
schau dir bitte einmal folgenden Link zur Gültigkeit von Variablen an Link
Sowohl 11.6, 11.7 und wenn du schon dabei bist passt 11.8 zum Thema.
Du hast Izeit_1 lokal definiert. Es muss aber global definiert sein, um in allen Funktionen gültig zu sein. Für die Mikrocontroller Welt ist dann noch in deinem Fall das Schlüsselwort volatile wichtig. Der Compiler kann aus dem Code nicht Feststellen, dass die ISR ja jederzeit aufgerufen werden kann. Daher kann es durch Optimierungen zu Fehlern kommen. Volatile sagt einfach aus, dass die Variable zur Verwendung immer aus dem Speicher geladen werden muss und nicht in einem Register bevorratet werden darf.
Wenn du es genauer wissen möchtest, im Wissenbereich gibt es einen Artikel zu Interrupts und deren Fallstricke.
Gruß
Jens
Hallo Jens,
danke für deine Info. Hab die Bariable jetzt global deklariert.
Es kommen zwar keine Fehlermeldungen mehr, aber das Programm funktioniert trotzdem nicht
Gruß Anna
Hallo Anna,
könntest Du mal bitte Deinen Code posten? Dazu natürlich Controllertyp, Quarzfrequenz, halt das ganze Drumrum. Wenns geht weniger als 100 Seiten (ich bin total lese+sonst-faul und verliere schnell die Übersicht) - aber vielleicht können wir zusammen was rausfinden.
Ciao sagt der JoeamBerg
Hallo,
setzt du Izeit_1 noch in der while auf 0? Das gehört wohl in die main aber nicht in die while. Sonst poste bitte noch einmal den aktuellen Code.
Gruß
Jens
Schlimm schlimm, ich hatte es ja gesagt. Und nun - hab Deinen Code nicht beachtet, entschuldige. Sind ja auch nicht mal 100 Seiten.Zitat von oberallgeier
Jens hat ja schon dieses "Iz... = 0" im main angemerkt. Warum machst Du das?
PS: Für so Chaotenleser wie mich sieht der code viel besser/lesbarer aus (wenn ich den mal lese), wenn Du ihn mit gestuften Einrückungen versiehst.
Ciao sagt der JoeamBerg
Hallo ihr beiden,
also ich hab noch ein bißchen was geändert... (wie Izeit_1 nicht in der while schleife auf 0 setzen![]()
) Ich habe auch noch ne else schleife dazugefügt.
Das komische ist er geht anscheinend nur in die Else-Schleife, da die LED3 (PC2) immer wieder toggelt. Also funktioniert es irgendwie schon aber nicht wirklich befriedigendDie Bedingung in der IF schleife führt er nicht aus....
Rahmenbedingungen: Atmega16 16 MHz
am PortC sind LEDs angeschlossen
Danke schon mal im vorraus für die Mühe........Code:#include <stdlib.h> #include <avr/pgmspace.h> #include <stdio.h> #include <util/delay.h> #include <avr/io.h> #include <avr/interrupt.h> uint16_t Izeit_1=0; void Timer0_init(void) // Init Tmr/Cntr 0, 8-Bit auf 20 kHz = 50 µs { TCCR0 |= (1<<WGM01) | (1<<CS01); // Timer im CTC-Mode, Top=OCR2A Prescaler 1/8 / Clock <- CPU OCR0 = 49; // Preset 48 für 50µs bei 16Mhz TIMSK |= (1<<OCIE0); // Tmr/Cntr CompareA interrupt enabled } /* Routine zählt hoch im Takt 20 kHz = 50 µs. */ ISR(TIMER0_COMP_vect) // Vektor 7 { if (Izeit_1 <= 60000) //Timer bis 60 000 - 3 sec Datenerfassung möglich Izeit_1 ++; // war: alle drei Sekunden wird 60000 erreicht // und Izeit_1 bleibt in der uint16-Grenze else { Izeit_1 = 0; // ansonsten: Rückstellen auf Null PORTC ^= (1<<PC5); // Zur Anzeige gLED am PC5/SCL toggeln } } int main(void) { Izeit_1=0; Timer0_init(); DDRC |= 0xff; PORTC=0x00; while(1) { cli(); sei(); if (Izeit_1>2) { PORTC ^= (1<<PC0); } else { PORTC ^= (1<<PC2); } cli(); } }
Gruß Anna[/code]
Hi, Anna,
möglicherweise geht es so, ich habe das aber (noch) nicht getestet - muss jetzt essen gehen.
Wenn Du das in der Zwischenzeit testen kannst wär schön, ansonsten hol ich nachher meine RNControl, dafür habe ich auch einen m16. Es sei denn, wir können uns vorerst mit Tests auf (m)einem m168/20MHz begnügen.Code:#include <stdlib.h> #include <avr/pgmspace.h> #include <stdio.h> #include <util/delay.h> #include <avr/io.h> #include <avr/interrupt.h> /* ============================================================================== */ void Timer0_init(void) { TCCR0 |= (1<<WGM01) | (1<<CS01); OCR0 = 124; TIMSK |= (1<<OCIE0); } /* ============================================================================== */ /* ============================================================================== */ /* === Nicht unterbrechbare ISR für timer2 ===================================== */ ISR(TIMER0_COMP_vect) // Vektor 7 { if (Izeit_1 <= 60000) //Timer bis 60 000 - 3 sec Datenerfassung möglich Izeit_1 ++; // war: alle drei Sekunden wird 60000 erreicht // und Izeit_1 bleibt in der uint16-Grenze else { Izeit_1 = 0; // ansonsten: Rückstellen auf Null // PORTC ^= (1<<PC5); // Zur Anzeige gLED am PC5/SCL toggeln // Hallo Anna: das Toggeln hier würde Deinen Schaltvorgang im main // stören - daher wurde es "auskommentiert". } } /* ============================================================================== */ int main(void) { uint16 Izeit_1=0; Timer0_init(); DDRC |= 0xff; PORTC=0x00; //####### Grundlegende Initialisierungen der Hardware, Portdefinition ------------- //Pins/Ports als Ein- (0) oder Ausgänge (1) konfigurieren, Pull Ups (1) aktivieren DDRC = 0b00000001; // PC0 .. 6, (kein PC7 bei m168), NUR Ausgang PC1 aktiv PORTC = 0b00000000; // Anmerkung: die binäre Codierung der Ports hat den // Vorteil, dass man/ich gleich sehe, "was los ist". // So kann ich es mir eben besser vorstellen als in hex. cli(); Izeit_1=0; sei(); while(1) { if (Izeit>5000) { PORTC ^= (1<<PC1); } } }
Viel Glück
Ciao sagt der JoeamBerg
Hallo Oberallgaier,
danke für den Code. Ich habe ihn getestet. Er funktioniert bei mir leider nicht.
Ich habe Izeit_1 ausserhalb der main routine deklariert und in der while-Schleife Izeit auf Izeit_1 geändert. Es compiliert zwar ohne Fehler, aber es ist nur dauerhaft LED1 an. Sonst passiert nichts.......
Ich muß jetzt leider auch essen gehen. Weiß deshalb nicht ob ich heute noch weiter probieren kann. Aber morgen bin ich wieder online......
Bis dann Gruß Anna
Hallo,
es fehlen bei euch beiden noch die geschweiften Klammern bei
und benutzt bitte als globale DefinitionCode:if (Izeit_1 <= 60000) {<- fehlt Izeit_1 ++; // war: alle drei Sekunden wird 60000 erreicht // und Izeit_1 bleibt in der uint16-Grenze fehlt -> } else
volatile uint16 Izeit_1;
@beginner1101 falls das noch nicht zum gewünschten Ergebnis führt, beschreibe vielleicht noch einmal kurz, was du erreichen möchtest. Sorry das steht bestimmt irgendwo, aber ich finde da jetzt nicht durch.
Gruß
Jens
Hi Anna,
tut mir leid - nun artet das bei mir in experimenteller Softwareentwicklung aus (kann meinen m16 nicht finden *grrrrrrrr* - und der m168 hat andere Registernamen, dann hätten wir hier noch mehr Konfusion). Daher - nochmal ungetestet, aber ohne Fehler compiliert. Ausserdem hat Jens recht - was wollen wir machen? Ich verstehe das so, es soll in einem bestimmbaren, zeitlichen Abstand einfach die LED auf PC1 getoggelt werden.
Hier der code:Code:#include <stdlib.h> #include <avr/interrupt.h> #define MCU = AVR_ATmega16 // #define F_CPU 20000000 // Quarz 20 Mhz-CPU #define F_CPU 16000000 // Quarz 16 Mhz-CPU volatile uint16_t Izeit_1; // Timervariable // ================================================================================ void Timer0_init(void) { TCCR0 |= (1<<WGM01) | (1<<CS01); OCR0 = 125; TIMSK |= (1<<OCIE0); } // ================================================================================ // ================================================================================ // ================================================================================ ISR(TIMER0_COMP_vect) // Vektor 7 { if (Izeit_1 <= 60000) //Timer bis 60 000 - 3 sec Datenerfassung möglich Izeit_1 ++; // war: alle drei Sekunden wird 60000 erreicht // und Izeit_1 bleibt in der uint16-Grenze else { Izeit_1 = 0; // ansonsten: Rückstellen auf Null PORTC &= ~(1<<PC1); // Port PC1 ausschalten // Hallo Anna: der Port wird hier bei Izeit_1 = 0 ausgeschaltet } } // ================================================================================ int main(void) { //uint16 Izeit_1 = 0; Timer0_init(); DDRC |= 0xff; PORTC=0x00; //####### Grundlegende Initialisierungen der Hardware, Portdefinition ------------- //Pins/Ports als Ein- (0) oder Ausgänge (1) konfigurieren, Pull Ups (1) aktivieren DDRC = 0b00000010; // PC0 .. 7, NUR Ausgang PC1 aktiv PORTC = 0b00000000; // Anmerkung: die binäre Codierung der Ports hat den // Vorteil, dass man/ich gleich sehe, "was los ist". // So kann ich es mir eben besser vorstellen als in hex. //####### So werden Ausgänge geschaltet ------------------------------------------- // PORTC |= (1<<PC1); // Port PC1 einschalten // PORTC &= ~(1<<PC1); // Port PC1 ausschalten // PORTC ^= (1<<PC1); // Port PC1 toggeln // ###>>> BEACHTE: die Pins zählen von 0 bis 7, PC1 ist also der ZWEITE PortPin cli(); Izeit_1 = 0; sei(); while(1) { if (Izeit_1 == 5000) { PORTC |= (1<<PC1); // Port PC1 einschalten // Hallo Anna: der Port wird hier bei Izeit_1 = 5000 eingeschaltet } } }Ohhh - das ist - bei einem einzigen Statement nach dem "if" soweit ich weiß ANSI-konform.Zitat von McJenso
Edit 23:20: Mein verlorener mega16 ließ mir keine Ruhe. Und als ich ihn gefunden hatte ist mir auch der Fehler aufgefallen. Nun ist der Code ok - und auf meinem fabrikfrischen mega16 läuft er mit 16MHz-Quark auf der RNControl: die LED auf PC1 blinkt.
###>>> Code korrigiert!
Sorry für die ungenaue Bearbeitung.
Ciao sagt der JoeamBerg
Lesezeichen