Hier wurde mir schon sehr gut geholfen und ich hoffe auch hierfür eine Antwort zu bekommen! Ich habe ein minimales Programm geschrieben um zu gucken ob der ATmega 644P wirklich schlafen geht! Leider tut er es nicht! Kann mir jemand den Grund nennen? #include<avr/io.h> #include<avr/sleep.h> int main() { set_sleep_mode(SLEEP_MODE_PWR_SAVE); while(1) { sleep_cpu(); } return(0); } Warum schläft er nicht?
Tommy wrote: > Warum schläft er nicht? Er schläft schon, bloß Du hast keinen Code drin, mit dem man es feststellen kann. Setze z.B. ne PWM auf, die ne LED blinkt, dann merkst Du, ob die CPU den Takt anhält. An der Stromaufnahme kannst Du es nicht feststellen, da in Deinen Code alle IO-Pins lustig vor sich hin floaten und so ordentlich Strom verbrauchen. Peter
Bedeutet das, wenn ich ein besonders Stromsparendes Produkt bauen will, sollte ich alle nichtverwendeten PINS (PORTS) einen definierten Zustand geben? Ich dachte bei nicht aufgeführten Ports macht das der MC automatisch
Habe alle DDR Register auf Ausgang gestellt und alle PORTS auf 0x00. Trotzdem bleibt die Stromaufnahme die selbe. Müsste sich nicht nach deiner Theorie der Stromfluß jetzt ändern?
Hallo, ich vermisse sleep_enable(); Sonst schläft da nichts. Gruß aus Berlin Michael
Fangen wir mal vorne an: Wie misst du ob der mega schläft oder nicht? Strommessung mit irgendeiner Gurke? Strommessung in der komplett bestückten Schaltung?
Auch mit sleep_enable() tut sich nichts! Ich verwende ein STK600 mit dem TQFP44 Adater. Vielleicht spielt das ja eine Rolle
>Ich verwende ein STK600 mit dem TQFP44 Adater. Vielleicht spielt das ja >eine Rolle Nimm den ATMega mal raus aus dem Board und miss dann nochmal Strom ;)
Hab ich gemacht! Ich glaub ich verstehe! Die Einteilung meines Netzteils ist nicht gerade fein, sie schwankte zwischen 0.12 und 0.11 mA im Normabetrieb und wenn man genau im richtigen Moment hinguckt dann sieht man nur 0.11mA Stellt man jetzt auf powersave dann verbleibt der Strom auf 0.11mA und schwankt nicht mehr. Darus lässt sich schließen dass er in den Powersave Zustand geht, ich habs nur nicht richtig gesehen! Mache es jetzt zusätzlich mit einer Uart und Leds, hab allerdings feststellen müssen, dass der Timer2 stehengeblieben ist, wenn ich sleep_cpu() eingebe!
So hab jetzt folgendes Programm geschrieben: #include<avr/io.h> #include<avr/interrupt.h> #include<avr/sleep.h> #include<util/delay.h> #include"timer.h" #include"uart.h" #define F_CPU 4000000UL // 9600 baud #define UART_BAUD_RATE 9600 volatile uint8_t time=0; ISR(TIMER2_OVF_vect) { time++; } int main() { DDRA=0xff; PORTA=0xff; set_sleep_mode(SLEEP_MODE_PWR_SAVE); sleep_enable(); uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); // uart1_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); timer2_init(); sei(); while(1) { if(time==5) { uart_puts("Hello world"); time=0; } else { PORTA=time; // sleep_cpu(); } } return(0); } So funktioniert das Programm einwandfrei, aber wenn ich sleep_cpu(); aktiviere bleibt der timer2() stehen! Hat jemand eine Idee?
>So funktioniert das Programm einwandfrei, aber wenn ich sleep_cpu(); >aktiviere bleibt der timer2() stehen! Hat jemand eine Idee? Ist doch prima. Oder entspricht das nicht dem, was du erwartet hast? Oliver
Ne! Timer2 müsste auch im Power Save Zustand weiterlaufen! Das zeichnet den timer2() bzw. den Power Save Modus aus.
Hab jetzt mal auf Reset gedrückt und siehe da, er lief los. Aber es kommt kein Hello World über die Uart! Kann das Problem an falsch gesetzt Fuse Bits liegen? bzw. an diesem Fuse Bit: Ext. Crystal Osc. 3.0-8Mhz Start-up time: 16KCK+65ms
Ja. Es gibt da noch ein paar Bits, mit denen man den Powersave konfigurieren kann. Steht aber alles im Datenblatt.
>Ne! Timer2 müsste auch im Power Save Zustand weiterlaufen! Das zeichnet >den timer2() bzw. den Power Save Modus aus. Hast Recht. Da gabs bei den "alten" noch nicht. >Hab jetzt mal auf Reset gedrückt und siehe da, er lief los. Aber es >kommt kein Hello World über die Uart! Mit welchem Takt läuft Timer 2, wenn er läuft? Oliver
Die Artikel waren zwar sehr interessant aber wirklich weitegeholfen haben sie mir bei meinem Problem nicht! Die Artikel dienen eher zur Stromoptimierung, was später auf jeden Fall eine Rolle spielen wird aber Momentan muss der MC erstmal überhaupt laufen.
>Siehe Sleep Mode hab ich jetzt mal entsprechend erweitert. >aber Momentan muss der MC erstmal überhaupt >laufen. Zeig mal den ganzen Code. Oliver
#include<avr/io.h> #include<avr/interrupt.h> #include<avr/sleep.h> #include"timer.h" #include"uart.h" #define F_CPU 4000000UL // 9600 baud #define UART_BAUD_RATE 9600 volatile uint8_t time=0; #include<avr/io.h> void timer2_init() { ASSR|=(1<<EXCLK)|(1<<AS2);//externer Clock, asynchron Modus // ASSR|=(1<<AS2);//externer Clock, asynchron Modus TCCR2B|=(1<<CS22)|(1<<CS20);//takt durch 128 teilen TIMSK2|=(1<<TOIE2); //timer overflow einschalten } ISR(TIMER2_OVF_vect) { time++; } int main() { DDRA=0xff; PORTA=0xff; set_sleep_mode(SLEEP_MODE_PWR_SAVE); sleep_enable(); uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); // uart1_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); timer2_init(); sei(); while(1) { if(time==5) { uart_puts("Hello world"); time=0; } else { PORTA=time; sleep_cpu(); } } return(0); } Die Uart Routine hab ich jetzt mal weggelassen sonst wäre das Programm ein wenig zu groß für hier!
Habe jetzt mal von der JTAG Programmierung in die ISP Programmierung gewechselt, ändert sich aber auch nichts!
Dass der Timer im asynchronen Modus besonderen Regeln unterliegt, Interrupt inklusive, das hast du im Manual bestimmt genau durchgelesen?
Kapitel 14.9. Sind 1,5 Seiten darüber, was dabei anders funktioniert als gewohnt. Auch was den Power-Save Modus angeht.
So, hab jetzt gelesen, wenn ich es richtig verstanden habe, dass man warten soll bis das TCN2UB Bit wieder 0 ist, hab es so realisiert! #include<avr/interrupt.h> #include<avr/sleep.h> #include<util/delay.h> #include"timer.h" #include"uart.h" #define F_CPU 4000000UL // 9600 baud #define UART_BAUD_RATE 9600 volatile uint8_t time=0; ISR(TIMER2_OVF_vect) { while(ASSR|=(!(1<<TCN2UB))); time++; } int main() { DDRA=0xff; PORTA=0xff; set_sleep_mode(SLEEP_MODE_PWR_SAVE); sleep_enable(); uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); // uart1_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); timer2_init(); sei(); while(1) { if(time==5) {// while(ASSR|=(!(1<<TCN2UB))); uart_puts("Hello world"); time=0; } else { PORTA=time; sleep_cpu(); } } return(0); } Aber er kommt aus diesem while gar nicht mehr raus!
Welches while? Da sind zwei. Ich nehme an, es ist das while im Interrupt gemeint. Aber das betreffende Bit ist nur lesbar und das Assignment im while ohnehin einfach nur Mist. Lies dir 14.9 nochmal genau durch. Notfalls mehrfach. Und in jedem Absatz nachdenken, ob dich das betrifft. Gibt da noch mindestens eine weitere Stelle.
Ich habe folgendes gefunden: a. Write any value to either of the registers OCR2x or TCCR2x. b. Wait for the corresponding Update Busy Flag to be cleared. c. Read TCNT2. Also ich verstehe das so z.B. uint8_t test=0; TCCR2B|=(1<<CS22)|(1<<CS20); while(ASSR|=(1<<TCN2UB)); test=TCNT2; Warum klappt das denn nicht? Was verstehe ich denn falsch?
Realisieren wollte ich es so: include<avr/io.h> #include<avr/interrupt.h> #include<avr/sleep.h> #include<util/delay.h> #include"timer.h" #include"uart.h" #define F_CPU 4000000UL // 9600 baud #define UART_BAUD_RATE 9600 volatile uint8_t time=0; ISR(TIMER2_OVF_vect) { uint8_t test=0; TCCR2B|=(1<<CS22)|(1<<CS20);//takt durch 128 teilen while(ASSR|=(1<<TCN2UB)); test=TCNT2; time++; } int main() { uint8_t test=0; DDRA=0xff; PORTA=0xff; set_sleep_mode(SLEEP_MODE_PWR_SAVE); sleep_enable(); uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); timer2_init(); sei(); while(1) { if(time==5) { uart_puts("Hello world"); time=0; } else { PORTA=time; TCCR2B|=(1<<CS22)|(1<<CS20); while(ASSR|=(1<<TCN2UB)); test=TCNT2; sleep_cpu(); } } return(0); } Ich muss irgendetwas nicht verstanden haben! A. K. kannst du mir sagen was ich falsch mache?
Hab jetzt das while durch folgende Zeile ersetzt: while (ASSR & (1 << TCN2UB) ) ; Jetzt läuft der Quarz! Aber die Uart klappt noch nicht! Jedoch näher ich mich dem Ziel:)
14.9 dritter Absatz: "When entering Power-save or ADC Noise Reduction mode after having written to TCNT2, OCR2x, or TCCR2x, the user must wait until the written register has been updated...". Also auch in timer2_init() warten.
A. K. vielen Dank! Werde es gleich morgen ausprobieren muss jetzt leider aufhören! Aber Danke noch mal
A. K. vielen Dank hab es ausprobiert und scheint zu klappen! Jedoch habe ich auch noch ein anderes Problem festgestellt. Das habe ich aber erst gesehen, als ich das JTAGICE mk2 angeschlossen habe. Wenn er in die Timer2 Interrrupt Routine reinspringt, führt er diese Routine mehrmals hintereinander druch. Kann es sein, das man in dieser Routine auch warten muss, bis irgendein Interrupt Flag wieder Null geworden ist?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.