Hat keiner eine Idee woran das liegen könnte? Probiere jetzt schon seit 3 Tagen das hinzubekommen. Leider ohne Erfolg. Prozessor wacht nicht mehr auf.
Wie der Titel schon sagt, im Simulator funktioniert das mit dem Sleep (PowerDown-Modus). Der Prozessor hält an. Und bei einer Änderung am INT0-Eingang (Taster gegen 0 mit internen PullUp-Widerstand) Pinchange-Interrupt wacht der Prozessor auf und arbeitet weiter.
Aber in der realen Schaltung tut sich nichts. Kein Aufwecken.
Im Programm habe ich zum Testen des Restes mal die Sleeps auskommentiert.
Hier mal der bisherige Quellcode:
Code:.include "TN15def.inc" ; Prozessor ATtiny15 .cseg ; Kennung für Programmcode .def TMP = R0 ; Allgemeine Variable für Rückgabewerte .def TMP1 = R16 ; Allgemeine Variable .def Status = R20 ; Statusregister für Betriebszustände .def Helligkeit = R21 ; Wert für PWM Regelung .def KeyOld = R26 ; Taster die gedrückt waren .def KeyNew = R27 ; Taster die gedrückt sind .def KeyEnter = R28 ; Taster die neu gedrückt wurden .def KeyExit = R29 ; Taster die neu losgelassen wurden .def ZL = R30 ; 16-Bit Variable L-Byte .def ZH = R31 ; 16-Bit Variable H-Byte ; Status 7 6 5 4 3 2 1 0 ; ^- 0=Lampe aus, 1=Lampe an .org 0x0000 ; Programm Startadresse $0000 rjmp Init ; Einsprung ins Hauptprogramm .org 0x0001 ; Interrupt Pin 7 (INT0) rjmp Test ; Sprung zur Testroutine Init: ; ******************************************************* ; * Internen Oszillator kalibrieren * ; ******************************************************* ldi ZL, low (2*Kalibrierung) ; Low-Byte Endadresse Flashspeicher lesen ldi ZH, high(2*Kalibrierung) ; High-Byte Endadresse Flashspeicher lesen lpm ; Kalibrierungsbyte auslesen ser ZL ; $FF in ZL setzen für Vergleich cpse TMP, ZL ; Kalibrierungsbyte gültig? (Nein, wenn $FF) out OSCCAL, TMP ; Ja, dann Chip kalibrieren und danach clr ZL ; den Vergleich löschen. mov Status, ZL ; Statusregister löschen. in TMP1, MCUCR ; Controllregister des Prozessors einlesen sbr TMP1, 1<<ISC00 ; PowerDown-Modus freischalten out MCUCR, TMP1 ; und speicehrn. ; ******************************************************* ; * Ports des ATtiny15 einstellen * ; ******************************************************* ldi TMP1, 1<<DDB4 | 1<<DDB3 | 1<<DDB1 ; Pin 2, 3, 6 auf Ausgabe schalten. out DDRB, TMP1 ; schalten und entsprechende com TMP1 out PORTB, TMP1 ; PullUp-Widerstände einschalten. in TMP1, PORTB ; Aktuellen Portinhalt einlesen und ori TMP1, 0b011000 ; grüne + rote LED ausschalten out PORTB, TMP1 ; neuen Zustand ausgeben. ; ******************************************************* ; * Interrupts freigeben * ; ******************************************************* in TMP1, GIMSK ; Interrupt an INT0 (Taster Aus/Ein) freigeben sbr TMP1, 1<<INT0 out GIMSK, TMP1 ; und speichern. sei ; Interrupts freigeben. in TMP1, MCUCR sbr TMP1, 1<<SE | 1<<SM1 out MCUCR, TMP1 ; sleep ; >>>>>>> Hauptprogramm Anfang <<<<<<< Start: rcall KeyCheck ; Tasten abfragen cpi KeyExit, 0x04 ; Taste "Ein/Aus" gedrückt $04 brne Weiter1 ; Nein, dann weiter, sonst rcall PinInt0 ; Sprung nach Ein- Ausschaltroutine Weiter1: rjmp Start ; >>>>>>>> Hauptprogramm Ende <<<<<<<< ; >>>>>>>> INTERRUPTPROGRAMME <<<<<<<< ; ******************************************************* ; * Testinterrupt um PowerDown-Mode zu beenden * ; ******************************************************* Test: nop reti PinInt0: ; ******************************************************* ; * Ein- / Ausschalter $04 an INT0 * ; ******************************************************* cpi Status, 0x00 ; Lampe ausgeschaltet? breq LampeEin ; Dann Lampe einschalten cbr Status, 1 ; Ist die Lampe an? Dann Lampe aus und in TMP1, PORTB sbr TMP1, 0b001000 out PORTB, TMP1 ; in TMP1, MCUCR ; Prozessorcontrollregister auslesen um ; sbr TMP1, 1<<SE | 1<<SM1 ; PowerDown-Mode zu aktivieren ; out MCUCR, TMP1 ; Speichern. ; sleep ; Prozessor in PowerDown-Mode versetzen. reti ; Rücksprung. LampeEin: sbr Status, 1 ; Kennung für Lampe an setzen ; --------- TEST ----------- in TMP1, PORTB cbr TMP1, 0b001000 out PORTB, TMP1 reti ; >>>>>>>>>> UNTERPROGRAMME <<<<<<<<<< ; ******************************************************* ; * Tasterabfrage mit Entprellung * ; ******************************************************* ; * Keyenter (R28) = Rückgabe neu gedrückte Taste * ; * Keyexit (R29) = Rückgabe der losgelassenen Taste * ; * Taste an PB0 (Hell/Dunkel) = 01 * ; * Taste an PB2 (Ein/Aus) = 04 * ; ******************************************************* KeyCheck: ; Unterprogramm zur Tastaturabfrage ldi KeyEnter, 0 ldi KeyExit, 0 in KeyNew, PINB ; Lade PB com KeyNew ; invertieren andi KeyNew, 0b000101 ; Maskieren der nicht verwendeten Pins cpse KeyOld, KeyNew ; Test ob Veränderung rjmp KeyAction ; Veränderung ret ; alles gleich KeyAction: rcall Wait12ms ; etwas warten in ZL, PINB ; nochmal einlesen com ZL ; invertieren bei neg. Logik andi ZL, 0b000101 ; maskieren der nicht verwendeten Pins cpse KeyNew, ZL ; ist es stabil ret ; war nix, da nicht stabil mov KeyEnter, KeyOld com KeyEnter ; invertieren and KeyEnter, KeyNew ; steigende Flanken, !alt & neu mov KeyExit, KeyNew com KeyExit ; invertieren and KeyExit, KeyOld ; fallende Flanken, alt & !neu mov KeyOld, KeyNew ; alt := neu ret ; Interrupt verlassen ; ******************************************************* ; * Warteschleife mit ca. 12ms * ; ******************************************************* Wait12ms: ldi ZL, low (2500) ; 16-Bit Zähler mit Startwert laden ldi ZH, high(2500) ; für Taktfrequenz 1.6MHz WaitMs1: dec ZL ; Low-Byte des Zählers erniedrigen brne WaitMs1 ; wenn 0, dann dec ZH ; High-Byte des Zählers erniedrigen brne WaitMs1 ; wenn auch0, dann Warteschleife ret ; verlassen. Kalibrierung: .db 0x79 ; Kalibrierungswert für int. Oszillator .exit
Hat keiner eine Idee woran das liegen könnte? Probiere jetzt schon seit 3 Tagen das hinzubekommen. Leider ohne Erfolg. Prozessor wacht nicht mehr auf.
Mein Bascom ist quasi non-existent, also kann ich nciht erkennen wie dein INT0 konfiguriert ist, aber aus dem Sleep bekommst du ihn nur mit dem LOW LEVEL Interrupt (und das low muss auch etwas länger sein als es gewöhnlich für den Interrupt braucht) um die CPU vollständig zu wecken.
Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
nicht.
Danke für den Hinweis mit dem Low-Level. habe ich jetzt so umgesetzt und es funktioniert. Laut dem Datenblatt steht bei PowerDown-Modus, dass sich dieser wohl auch mit PinChange aufwecken liese, aber das hat nicht funktioniert.
Hier der Quellcode, so wie ich es jetzt umgesetzt habe:
Code:.include "TN15def.inc" ; Prozessor ATtiny15 .cseg ; Kennung für Programmcode .def TMP = R0 ; Allgemeine Variable für Rückgabewerte .def TMP1 = R16 ; Allgemeine Variable .def Status = R20 ; Statusregister für Betriebszustände .def Helligkeit = R21 ; Wert für PWM Regelung .def KeyOld = R26 ; Taster die gedrückt waren .def KeyNew = R27 ; Taster die gedrückt sind .def KeyEnter = R28 ; Taster die neu gedrückt wurden .def KeyExit = R29 ; Taster die neu losgelassen wurden .def ZL = R30 ; 16-Bit Variable L-Byte .def ZH = R31 ; 16-Bit Variable H-Byte ; Status 7 6 5 4 3 2 1 0 ; |_ 0=Lampe aus, 1=Lampe an .org 0x0000 ; Programm Startadresse $0000 rjmp Init ; Einsprung ins Hauptprogramm .org 0x0001 ; Interrupt Pin 7 (INT0) rjmp Int0i ; Sprung zu INT0-Interrupt Init: ; ******************************************************* ; * Internen Oszillator kalibrieren * ; ******************************************************* ldi ZL, low (2*Kalibrierung) ; Low-Byte Endadresse Flashspeicher lesen ldi ZH, high(2*Kalibrierung) ; High-Byte Endadresse Flashspeicher lesen lpm ; Kalibrierungsbyte auslesen ser ZL ; $FF in ZL setzen für Vergleich cpse TMP, ZL ; Kalibrierungsbyte gültig? (Nein, wenn $FF) out OSCCAL, TMP ; Ja, dann Chip kalibrieren und danach clr ZL ; den Vergleich löschen. ; ******************************************************* ; * Statusregister löschen und PowerDown vorbereiten * ; ******************************************************* mov Status, ZL ; Statusregister löschen. in TMP1, MCUCR ; Controllregister des Prozessors einlesen cbr TMP1, 1<<ISC01 | 1<<ISC00 ; Interrupt an INT0 auf Low-Level stellen out MCUCR, TMP1 ; und speichern. in TMP1, TCCR1 ; Timer1 Kontrollregister für PWM sbr TMP1, 1<<PWM1 | 1<<CS12 | 1<<CS11 | 1<<CS10 ; vorbereiten und out TCCR1, TMP1 ; speichern.. ; ******************************************************* ; * Ports des ATtiny15 einstellen * ; ******************************************************* ldi TMP1, 1<<DDB4 | 1<<DDB3 | 1<<DDB1 ; Pin 2, 3, 6 auf Ausgabe schalten. out DDRB, TMP1 ; schalten und entsprechende com TMP1 out PORTB, TMP1 ; PullUp-Widerstände einschalten. in TMP1, PORTB ; Aktuellen Portinhalt einlesen und ori TMP1, 0b011000 ; grüne + rote LED ausschalten out PORTB, TMP1 ; neuen Zustand ausgeben. ldi Helligkeit, 0xC0 ; Startwert 40% Helligkeit ; ******************************************************* ; * Interrupts freigeben * ; ******************************************************* in TMP1, GIMSK ; Interrupt an INT0 (Taster Aus/Ein) freigeben sbr TMP1, 1<<INT0 out GIMSK, TMP1 ; und speichern. sei ; Interrupts freigeben. rcall PowerDown ; Prozessor in PowerDown-Modus versetzen. ; >>>>>>> Hauptprogramm Anfang <<<<<<< Start: rcall KeyCheck ; Tasten abfragen cpi KeyExit, 0x01 ; Taste Helligkeit gedrückt $01 brne Taste1 ; Nein, dann nächste Taste. tst Status ; Ist die Lampe ausgeschaltet? Ja, dann breq TastEnde ; nicht Taste heller/dunkler auswerten. rcall Dimmer ; Sprung nach Dimmroutine rjmp TastEnde ; Spung an Auswerteende. Taste1: cpi KeyExit, 0x04 ; Taste "Ein/Aus" gedrückt $04 brne TastEnde ; Nein, dann weiter, sonst rcall EinAus ; Sprung nach Ein- Ausschaltroutine TastEnde: rjmp Start ; >>>>>>>> Hauptprogramm Ende <<<<<<<< ; >>>>>>>> INTERRUPTPROGRAMME <<<<<<<< ; ******************************************************* ; * INT0-Interrupt * ; ******************************************************* Int0i: in TMP1, GIMSK ; Interrupt-Freigaberegister einlesen und cbr TMP1, 1<<INT0 ; INT0-Interrupt sperren um Prozessor out GIMSK, TMP1 ; beim Aufwachen nicht zu stören. reti ; Rücksprung. ; >>>>>>>>>> UNTERPROGRAMME <<<<<<<<<< ; ******************************************************* ; * Tasterabfrage mit Entprellung * ; ******************************************************* ; * Keyenter (R28) = Rückgabe neu gedrückte Taste * ; * Keyexit (R29) = Rückgabe der losgelassenen Taste * ; * Taste an PB0 (Hell/Dunkel) = 01 * ; * Taste an PB2 (Ein/Aus) = 04 * ; ******************************************************* KeyCheck: ; Unterprogramm zur Tastaturabfrage ldi KeyEnter, 0 ldi KeyExit, 0 in KeyNew, PINB ; Lade PB com KeyNew ; invertieren andi KeyNew, 0b000101 ; Maskieren der nicht verwendeten Pins cpse KeyOld, KeyNew ; Test ob Veränderung rjmp KeyAction ; Veränderung ret ; alles gleich KeyAction: rcall Wait12ms ; etwas warten in ZL, PINB ; nochmal einlesen com ZL ; invertieren bei neg. Logik andi ZL, 0b000101 ; maskieren der nicht verwendeten Pins cpse KeyNew, ZL ; ist es stabil ret ; war nix, da nicht stabil mov KeyEnter, KeyOld com KeyEnter ; invertieren and KeyEnter, KeyNew ; steigende Flanken, !alt & neu mov KeyExit, KeyNew com KeyExit ; invertieren and KeyExit, KeyOld ; fallende Flanken, alt & !neu mov KeyOld, KeyNew ; alt := neu ret ; Interrupt verlassen Dimmer: ; ******************************************************* ; * Taster für Dimmstufen $01 * ; ******************************************************* subi Helligkeit, 0x40 ; Bei jedem Aufruf Helligkeitswert -40 out OCR1A, Helligkeit ; Neuen wert ins PWM-Vergleichsregister ret ; Lampe wird heller. Rücksprung EinAus: ; ******************************************************* ; * Ein- / Ausschalter $04 an INT0 * ; ******************************************************* cpi Status, 0x00 ; Lampe ausgeschaltet? breq LampeEin ; Dann Lampe einschalten, sonst im cbr Status, 1 ; Statusregister Lampe ein löschen.. in TMP1, PORTB ; PortB einlesen und. sbr TMP1, 0b001000 ; LED grün durch H-Pegel ausschalten. out PORTB, TMP1 ; PortB ausgeben. in TMP1, TCCR1 ; PWM-Timer Steuerregister laden und cbr TMP1, 1<<COM1A1 | 1<<COM1A0 | 1<<CS12 | 1<<CS11 | 1<<CS10 ; diesen ausschalten. out TCCR1, TMP1 ; Alles Speichern. in TMP1, PORTB ; Falls Scheinwerfer-LED Ausgang geschaltet cbr TMP1, 1<<PORTB1 ; ist, diesen auf jeden Fall ausschalten. out PORTB, TMP1 ; LED wird sonst zerstört! in TMP1, GIMSK ; Vor PowerDown-Modus Interrupt sbr TMP1, 1<<INT0 ; INT0 wieder freigeben. Über diesen wird out GIMSK, TMP1 ; der Prozessor aufgeweckt. rcall PowerDown ; PowerDown-Modus aktivieren. ret ; Rücksprung. LampeEin: sbr Status, 1 ; Kennung für Lampe an setzen ldi TMP1, 0xA0 ; LED-Scheinwerfer ein mit ca. 60% Helligkeit out OCR1A, Helligkeit ; Wert in Timer-Vergleichsregister laden. out TCNT1, TMP1 ; Timercounter ebenfalls laden. in TMP1, TCCR1 ; Und Timer im PWM-Modus sbr TMP1, 1<<COM1A1 | 1<<COM1A0 | 1<<CS12 | 1<<CS11 | 1<<CS10 ; starten. out TCCR1, TMP1 ; Alles im Timer-Steuerregister speichern. ; --------- TEST ----------- in TMP1, PORTB ; PortB einlesen und LED grün durch Ausgabe cbr TMP1, 0b001000 ; von L-Pegel einschalten. out PORTB, TMP1 ; PortB ausgeben. ret ; Rücksprung. ; ******************************************************* ; * Warteschleife mit ca. 12ms * ; ******************************************************* Wait12ms: ldi ZL, low (2500) ; 16-Bit Zähler mit Startwert laden ldi ZH, high(2500) ; für Taktfrequenz 1.6MHz WaitMs1: dec ZL ; Low-Byte des Zählers erniedrigen brne WaitMs1 ; wenn 0, dann dec ZH ; High-Byte des Zählers erniedrigen brne WaitMs1 ; wenn auch0, dann Warteschleife ret ; verlassen. ; ******************************************************* ; * Prozessor in PowerDown-Modus versetzen * ; ******************************************************* PowerDown: in TMP1, MCUCR ; Prozessorcontrollregister auslesen um sbr TMP1, 1<<SE | 1<<SM1 ; PowerDown-Mode zu aktivieren out MCUCR, TMP1 ; Speichern. sleep ; Prozessor in PowerDown-Mode versetzen ret ; Nach Aufwecken Rücksprung Kalibrierung: .db 0x79 ; Kalibrierungswert für int. Oszillator .exit
Wenn PinChange den AVR aus den SLEEPmode holen soll, muss auch PINCHANGE aktiviert sein
GIMSK -> PCINT aktivieren seite 19/20
POWER-DOWN lesen Seite 24
http://ww1.microchip.com/downloads/e...oc/doc1187.pdf
@avr_racer sofern ich das Bascom richtig deute, hat er exakt das gemacht
Das Problem ist ein technisches, irgendwas in dem Wakeup dauert bei einem Pin Change Interrupt zu kurz und löst deswegen nicht erfolgreich den WakeUp aus (ich kann nur das Errata dazu nicht mehr finden)
Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
nicht.
@coes Bascom ?? Er schreibt es doch in ASM und nur darauf bin ich eingegangen. Deine Aussage findest sich in meinen ersten POST im LINK Power Down Seite 24
Bascom und ASM sehen für mich gleichartig aus, sorry für das Missverständnis
Mir war klar dass du darauf eingegangen bist, aber ich meinte mit meiner Aussage ja, dass er genau das Flag auch gesetzt hat oder nicht?!
in TMP1, GIMSK ; Interrupt an INT0 (Taster Aus/Ein) freigeben
sbr TMP1, 1<<INT0
out GIMSK, TMP1 ; und speichern.
Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
nicht.
WAHTT?? Gleichartig ?? Niemals Do/IF ELSE ist deutlich anders als genau zu wissen was welcher Befehl tut und NUR dann macht!
Es wird nur der INT0 als Interrupt freigegeben aber nicht PCIE
siehe Code
Code:.include "tn15def.inc" ;--------------------- ; Interrupt Vektoren ;--------------------- .cseg .org $0000 ; Interrupt Vektoren rjmp Init_int0 ;oder _PCIE .org $0001 rjmp INT0_addr .org $0002 rjmp PCI0_addr ;--------------------- init_INT0: ;PINB 2 im Simulator setzen in r16,GIMSK ori r16,(1<<INT0) out GIMSK,r16 in r16,MCUCR ori r16,( 1<<ISC01 | 1<<ISC00 ) ;Hier Flanken/levelaktivität aktivieren NUR FÜR INT0 out MCUCR,r16 sei rjmp start init_PCIE: ;PINB 0-5 kann gesetzt werden wird immer die gleiche Routine angesprungen in r16,GIMSK ori r16,(1<<PCIE) out GIMSK,r16 sei rjmp start start: rjmp start INT0_addr: nop nop nop nop reti PCI0_addr: nop nop nop nop nop reti
Geändert von avr_racer (01.10.2019 um 19:21 Uhr) Grund: Rechtschreibung
Lesezeichen