wollte mal kurz fragen wie ich den µC in den Sleepmodus bekomme, habe schon alles eingestellt. Wei0 aber nicht ob der letzte Befehl das ausführt oder ob man dann noch sleep schreiben muss. Die AD-Wandlung sollte ja laut Datenblatt automatisch starten und der "Fertig"-Interrupt sollte mir den µC wieder wecken, aber wo landet er dann muss da eine Interrupt-Routine hin oder ist es irgendwie möglich das Programm dort weiterlaufen zu lassen wo es zuletzt stand? sbi ADCSR, ADIE ;AD interrupt enable sbi ADCSR, ADEN ;AD enable cbi MCUSR, SM1 ;Noise reduction mode sbi MCUSR, SM0 ;Noise reduction mode sbi MCUSR, SE ;Sleep enable
MCUSR??? War das nicht MCUCR? Trotzdem ist bitweiser Zugriff nicht möglich, musst schon byteweise darauf zugreifen. Um Sleep nutzen zu können musst du bei Init SE in MCUCR setzen. Und dann im Programm SLEEP aufrufen, damit er bis zum nächsten Int pennt. Ich mach das üblicherweise in der Hauptschleife, nachdem geprüft wurde, dass alle anstehenden Jobs erledigt wurden. Für ADC-Betrieb (Noise-reduction) sollte SLEEP direkt auf das Setzen von ADEN in ADCSR folgen. ...
klar soll natürlich MCUCR sein. ich setzte jedes Bit einzeln damit ich nichts durcheinander würfle, wenns z.b. mit ADCSR, ADEN geht sollte es mit SM1 und SM0 doch auch gehen oder meinst du das ich es so machen sollte ldi temp,0b00000100 ;Vorteiler auf 16 out ADCSR,temp ;8Mhz / 16 = 125kHz statt so sbi ADCSR, ADPS2
> Wei0 aber nicht ob der letzte Befehl das ausführt oder ob man dann > noch sleep schreiben muss. Letzteres. Aus der Beschreibung des SE-Bit: "The SE bit must be written to logic one to make the MCU enter the sleep mode when the SLEEP instruction is executed. To avoid the MCU entering the sleep mode unless it is the programmer’s purpose, it is recommended to set the Sleep Enable (SE) bit just before the execution of the SLEEP instruction." Ncoh klarer geht's doch nicht. > Die AD-Wandlung sollte ja laut Datenblatt automatisch starten und > der "Fertig"-Interrupt sollte mir den µC wieder wecken, Genau. > aber wo landet er dann muss da eine Interrupt-Routine hin oder ist > es irgendwie möglich das Programm dort weiterlaufen zu lassen wo > es zuletzt stand? Einfach im Interrupt-Vektor ein reti eintragen. Wenn der Interrupt ausgelöst wird, wird auf jeden Fall dorthin gesprungen. Aber wer sagt, daß du dort was tun mußt? Und nach einem reti aus der Interrupt-Routine wird sowieso hinter dem sleep weitergemacht.
Beispiel für SLEEP (ohne ADC): Irgendwo in der Initialisierung des ABRs: ldi wl,1<<se ;Schlafmode out mcucr,wl ;aktivieren ;Einzelbit-Zugriff per SBI ist nicht möglich, da MCUCR oberhalb ;I/O-Adresse $1F liegt. SBI/CBI geht nur von $00 bis $1F... Dann in der Mainloop: mainloop: ;Hauptschleife sbrc key_reg,key_press ;Taster erneut gedrückt? nein... rjmp neuimp ;ja, abarbeiten... sleep ;schlafen gehen rjmp mainloop ;nochmal... Der AVR geht pennen, der Interrupt (hier Timer0 des AT90S1200) weckt ihn auf, es wird die ISR abgearbeitet und nach RETI der Befehl hinter SLEEP. Also zurück zu Mainloop, auf unerledigte Jobs testen (oft sind da mehrere Flags zu prüfen) und danach pennen gehen. Die Jobs (hier "neuimp") enden mit "rjmp mainloop", damit vor dem Schlafen erst alle Jobs abgearbeitet werden. Die Jobflags werden natürlich von der Jobroutine gelöscht. ...
so danke nochmals an alle. Denke jetzt bekomme ich es hin.
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.