Sie sind nicht angemeldet.

1

Mittwoch, 4. März 2020, 18:36

ATtiny13A : Sleep-Mode -> Power Down mittels externen level Interrupt INT0 beenden

Hallo zusammen,
wundere mich, dass bereits nach einer Low-Zeit von 10µs der ATtiny13A aus seinem Power-Down-Sleep-Mode, per Low-Level-Interrupt INT0 geweckt wird. Als Systemtakt wird der Interne RC-Oszillator mit 4,8Mhz per FUSE BYTES ( $FF39 ) eingestellt und dieser durch 256 geteilt, was einem SYS-Takt von nominal 18,750kHz bzw. eine Zeit von 53,333µs pro Takt ergibt.

Da der µC mit 5V betrieben wird,ist natürlich der von der Fabrik kalibrierte Takt ( für 3V bei 25°C ) dermaßen daneben, dass bei mir ein SYS-Takt von 12,776kHz ( 78,272µs ) entsteht.


9.2.1 Low Level Interrupt
A low level interrupt on INT0 is detected asynchronously. This implies that this interrupt can be used for waking the part also from sleep modes other than Idle mode. The I/O clock is halted in all sleep modes except Idle mode.Note that if a level triggered interrupt is used for wake-up from Power-down, the required level must be held long enough for the MCU to complete the wake-up to trigger the level interrupt. If the level disappears before the end of the Start-up Time, the MCU will still wake up, but no inter-rupt will be generated. The start-up time is defined by the SUT and CKSEL fuses as described in“System Clock and Clock Options” on page 23.If the low level on the interrupt pin is removed before the device has woken up then programexecution will not be diverted to the interrupt service routine but continue from the instruction following the SLEEP command.

Die Wake-Up Time ist ja 4 Takte und die Start-Up Time 6T. 4T => 4x78,272µs = 313,088µs.

Warum wird der µC dann schon nach 10µs aus dem Power-Down-Modus geweckt?

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
;
.include "Header.inc"   	;Label und Werte Zuweisungen
.include "Hardware.inc" 	;Hardware Label  Zuweisungen
;
;Programmstart nach RESET  ( Interrupt Vektoren Tabelle )
;
.CSEG                   	;Was ab hier folgt kommt in den FLASH-Speicher
.ORG $0000              	;Programm beginnt an der FLASH-Adresse 0x0000..

 rjmp  _reset           	;..mit der RESET-Vectortabelle

.include "IRQt13.inc"   	;Restliche Interrupt Vektortabelle

.ORG INT_VECTORS_SIZE   	;Programmadresse nach den ganzen IRQ-Vektoren
;
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
;I Erstinitialisierungen
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
;
;Stapelzeiger initialisieren (fuer Unterprogramme und / oder Interrupts)
;
_reset:
 ;ldi  a,High(RAMEND)    	;RAMEND, also das Ende vom SRAM, ist in der.. 
 ;out  SPH,a             	;..Definitions-datei festgelegt  
 ldi  a,Low (RAMEND)    	;Hier reicht ein Byte, weil das...
 out  SPL,a             	;...SRAM nur 64Byte gross ist
;
;Ports Erstkonfiguration
; 
 sbi   DDRB,pin.pla			;PORT-Bit als Ausgang f. PLA-LED
 sbi   DDRB,led.ora			;PORT-Bit als Ausgang f. SLEEP-LED
 sbi   DDRB,led.ge			;PORT-Bit als Ausgang f. Wake-Up
 
 sbi   PORTB,led.ge			;LED Gelb ausschalten

 sbi   PORTB,pin.int0		;Pull-up f. INT0 Low Level Interrupt
;
;Variablen initialisieren ( r0-r31 haben unbestimmten Inhalt )
;
 clr  flag_reg          	;Allgemeines Flaggenregister;
 clr  ovf0_zlr          	;Timer0 Overflow-Zaehler initialisieren

 sbr  flag_reg,1<<slp		;Sleep ist gewuenscht
;
;Systemtakt ( 4,8MHz ) durch 256 teilen ( 18,750kHz = 53,333µs )
;
 in   a,CLKPR				;Clock Prescaler Register laden..
 sbr  a,1<<CLKPCE			;..Sicherheitsprozedur..
 cbr  a,1<CLKPS3|1<<CLKPS2|1<<CLKPS1|1<<CLKPS0;.. 
 out  CLKPR,a           	;..durchfuehren..
 cbr  a,1<<CLKPCE			;..jetzt den Teiler..
 sbr  a,1<<CLKPS3			;..neu einstellen..
 out  CLKPR,a				;..und ueberschreiben
;
;EXTERNAL INTERRUPT -> INT0 Low Level ist default
;
 in   a,GIMSK				;General Interrupt Masken Register laden..
 sbr  a,1<<INT0				;..INT0 Interruput Freigabebit setzen..
 out  GIMSK,a				;..INT0 Interrupt freigeben

 sei                    	;Alle programmierbaren Interrupts freigeben
;
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;H Hauptprogrammschleife
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;
_main:

 ;sbi  PINB,pin.pla			;++++++++LED-PLA toggeln f. die Systemtaktbestimmung
 ;rjmp PC-1					;+++++++++++++++++++++++++++++++++++++++++++++++++++

 sbr  flag_reg,1<<pla.flg   ;Programmlaufanzeige-Flag quitieren
 sbrs flag_reg,slp			;SLEEP erwuenscht?
 rjmp _nsleep				;Nein -> No Sleep
;
;SLEEP-MODE -> Power Down
;
 in   a,MCUCR				;MCU Control Register laden..
 sbr  a,1<<SM1|1<<SE		;..Power-Down-Mode und Sleep Enable vorbereiten..
 out  MCUCR,a				;..und freigeben
 sleep						;µC in den Schlaf-Modus versetzen
 in   a,MCUCR				;MCU Control Register laden..
 cbr  a,1<<SM1|1<<SE		;..PD-Mode & SE rueckgaengig..
 out  MCUCR,a				;..machen
 
 cbi  PORTB,led.ge			;LED Gelb einschalten
 
_nsleep: 
 rjmp _main             	;Ja -> Jetzt mit rising INT0
 
 ;rjmp PC					;Endlosschleife
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;Q Beginn der verwendeten Interrupt Service Routinen ( ISR )
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
.include "ISR.inc"      	;Interrupt Service Routinen

.EXIT                   	;Ende des Quelltextes



_Machtwas_
CRS Robotics A255, TRONXY X3A, TinkerCAD, c´t-Lab, ProfiLab Expert, AVR8 Assembler

EDV-Dompteur

Administrator

Beiträge: 2 004

Wohnort: Hamburg

Beruf: Techniker

  • Nachricht senden

2

Mittwoch, 4. März 2020, 22:46

Als Systemtakt wird der Interne RC-Oszillator mit 4,8Mhz per FUSE BYTES ( $FF39 ) eingestellt und dieser durch 256 geteilt, was einem SYS-Takt von nominal 18,750kHz bzw. eine Zeit von 53,333µs pro Takt ergibt.

Da der µC mit 5V betrieben wird,ist natürlich der von der Fabrik kalibrierte Takt ( für 3V bei 25°C ) dermaßen daneben, dass bei mir ein SYS-Takt von 12,776kHz ( 78,272µs ) entsteht.
Bin skeptisch, ob das sein kann.
Bezüglich Temperatur kann ich aus eigener Erfahrung sagen, dass diese keinen nennenswerten Einfluss hat. Getestet mit Kältespray vs. Heißluftgebläse.
Es ist zwar Jahre her, aber ich meine mich zu erinnern, dass die Frequenzdrift zwischen beiden Extremen kaum 1% erreichte.
Die Frequenzstabilität war jedenfalls über den vollen Temperaturbereich genau genug, um eine Infrarot-Fernbedienung zu decodieren, ohne einen Quarz verbauen zu müssen.

Was die spannungsabhängige Frequenzdrift betrifft, wage ich mich nicht festzulegen, aber 18,75kHz vs. 12,776kHz kommt mir gefühlsmäßig unrealistisch hoch vor.
Wobei ich zugeben muss, dass der Faktor von knapp 1,5 tatsächlich auffällig gut zum Verhältnis der beiden Spannungen passt.
Ich war bisher der Meinung, dass der RC-Oszillator an der internen Referenzspnnungsquelle hängt (könnte mich aber irren).
Hänge den AVR doch mal an ein Labornetzteil und regele die Spannung hoch/runter, während Du die Frequenz misst.


Warum wird der µC dann schon nach 10µs aus dem Power-Down-Modus geweckt?
Tja, vermutlich wegen dem, was Du selbst zitierst:
9.2.1 Low Level Interrupt
A low level interrupt on INT0 is detected asynchronously.
"asynchronously" ...
Also wenn Du einen asynchronen Interrupt verwendest, dann würde ich tatsächlich genau das erwarten, was bei Dir ja auch passiert. Nämlich dass es mit dem Takt nüschts zu tun hat.

Mit den Interrupts hatte ich bei AVR-Controllern aber selbst immer wieder meinen Kummer und musste da ewig dran herum stellen, damit wirklich das passierte, was ich wollte. Intuitiv ist es jedenfalls nicht.
Es ist jedenfalls zu unterscheiden, ob eine positive Flanke, oder eine negative Flanke, oder ein quasi statischer Zustand den Interrupt auslösen soll. Und ob das irgendwie mit dem Takt synchron passieren soll, oder eben asynchron.

Ich habe nun schon ein paar Jahre nichts mehr gemacht, mit AVR, aber ich erinnere mich noch düster, dass ich einmal am INT0-Pin das gewünschte Verhalten partout nicht hin bekam. Verblüffenderweise war das Problem aber sofort aus der Welt, als ich einen völlig anderen Pin verwendete. Da ging es jedoch nicht um das Aufwecken aus einem Sleep- oder Idle-Modus, sondern halt um einen Interrupt bei laufendem Betrieb.
Will sagen: Das mit den Interrupts ist so eine Sache ... da muss man schon allerhand Versuche machen, denn rein aus dem Datenblatt wird man da nicht schlau (ich jedenfalls nicht). Bzw. das was passiert ist nicht unbedingt immer das, was man nach Studium des Datenblatts erwarten würde.
Macht Technik dir das Leben schwör, ruf' schnell den EDV-Dompteur! ;-)

- Technische Fragen zu Eigenreparaturen bitte öffentlich im Forum stellen, nicht telefonisch! -

3

Donnerstag, 5. März 2020, 14:39

Will sagen: Das mit den Interrupts ist so eine Sache ... da muss man schon allerhand Versuche machen, denn rein aus dem Datenblatt wird man da nicht schlau (ich jedenfalls nicht). Bzw. das was passiert ist nicht unbedingt immer das, was man nach Studium des Datenblatts erwarten würde.

Schon allein für diese Aussage lohnt es sich für mich, sich weiter mit der Forensoftware herumzuschlagen. In dem anderen Forum, wo ich sehr aktiv bin / war, kamen meistens Antworten in dieser Art: " RTFM ". Und natürlich weitere, in dieser Art, nützliche ;-). Es gibt dort natürlich auch vernünftige Leute, nur gerade bei Assembler scheint man sich doch schwer zu tun, die Programme von Anderen zu verstehen. Die aller, aller meisten tun dies nicht. Wenn es also ins Eingemachte ging, war ich auf mich selbst gestellt. Werde jetzt mal diesen Thread parallel laufen lassen um festzustellen, wo ich mit meinen AVR8ASM-Problemen und überhaupt mit dem Verständnis der AVR-Mikrocontroller, besser unterstützt werde.

Hänge den AVR doch mal an ein Labornetzteil und regele die Spannung hoch/runter, während Du die Frequenz misst.

Halte ich erstmal für unnötig, aber lass mich da mal evtl. überraschen. Kann ja eine gute Idee sein, weil ich mich evtl. verrannt habe und dies hierdurch bemerke.

Die Frequenzstabilität war jedenfalls über den vollen Temperaturbereich genau genug, um eine Infrarot-Fernbedienung zu decodieren, ohne einen Quarz verbauen zu müssen.

Was ein Zufall. Etwas ähnliches habe ich auch vor - jedoch mit Funksteckdosen :

https://www.mikrocontroller.net/topic/487338#6099487

Ich war bisher der Meinung, dass der RC-Oszillator an der internen Referenzspnnungsquelle hängt (könnte mich aber irren).

Würde gerne hierzu die Spannungsabhängigkeit als selbstgemachten Screenshot aus dem Datenbuch ( DB ) hier einfügen, bin aber leider nicht in der Lage dazu, weil mir das Wissen fehlt, wie dies geht.

"asynchronously" ...
Also wenn Du einen asynchronen Interrupt verwendest, dann würde ich tatsächlich genau das erwarten, was bei Dir ja auch passiert. Nämlich dass es mit dem Takt nüschts zu tun hat.

Hierzu möchte ich den von mir vielleicht missverstandenen englischen Textausschnitt verwenden, der für mich aussagt, dass mindestens 4 Takte lang der Low-Pegel am INT0-Pin anliegen muss ( Wake-Up Time ) bis der µC aus dem Sleep-Mode -> PowerDown ( PDM ) geweckt wird. Weitere 6T ( Start-Up Time ) sind nötig damit die INT0-ISR angesprungen wird, sonst geht es halt mit dem Befehl nach SLEEP einfach weiter ohne das die INT0-ISR angesprungen wird.
Aber unterhalb von 4T sollte der µC weiter im PDM verweilen. Und 4T sind für mich 4x der Systemtakt von 78,272µs die ich ermittelt habe.

Note that if a level triggered interrupt is used for wake-up from Power-down, the required level must be held long enough for the MCU to complete the wake-up to trigger the level interrupt. If the level disappears before the end of the Start-up Time, the MCU will still wake up, but no interrupt will be generated.


Ah, hab mir das jetzt selbst noch mal durchgelesen. Die meinen vielleicht, dass der µC geweckt wird, aber die INT0-ISR nicht angesprungen wird. Aber warum gibt es dann diese quasi "Wake-Up Zeitangabe" im DB?

7.1 Sleep Modes
If an enabled interrupt occurs while the MCU is in a sleep mode, the MCU wakes up. The MCU is then halted for four cycles in addition to the start-up time, executes the interrupt routine, and resumes execution from the instruction following SLEEP.


Ahh.., ich begreife immer besser was ich da poste. " If an enabled interrupt occurs while the MCU is in a sleep mode, the MCU wakes up ". Da steht doch ganz deutlich, dass der µC geweckt wird und erstmal 4Takte lang nichts macht und sich daran die Start-Up Zeit von 6T anschließt. Und das meinen die mit " ..., the required level must be held long enough for the MCU to complete the wake-up to trigger the level interrupt.". Der µC wird also auf alle Fälle geweckt, dazu muss natürlich der Low-Pegel eine gewisse Zeit anliegen, aber nicht was ich dachte ( mindestens 4T ). Danke Desi, du hast mir die Augen geöffnet.
Oh, scheiße ich muss doch weg, hoffe das wars oder ich komm rechtzeitig zurück um dies noch zu bearbeiten.


So, bin wieder da und habe mir alles noch mal durchgelesen und empfinde deine Analogie ( im Posting direkt hiernach ) als gute Gedächnisstütze. Bearbeiten funktioniert also noch. Sollte ja bei meinem " Status " 3h funktionieren, wenn ich mich recht erinnere.
_Machtwas_
CRS Robotics A255, TRONXY X3A, TinkerCAD, c´t-Lab, ProfiLab Expert, AVR8 Assembler

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Machtwas« (5. März 2020, 16:47)


EDV-Dompteur

Administrator

Beiträge: 2 004

Wohnort: Hamburg

Beruf: Techniker

  • Nachricht senden

4

Donnerstag, 5. März 2020, 15:06

Ah, hab mir das jetzt selbst noch mal durchgelesen. Die meinen vielleicht, dass der µC geweckt wird, aber die INT0-ISR nicht angesprungen wird. Aber warum gibt es dann diese quasi "Wake-Up Zeitangabe" im DB?
Ja, es geht ratzfatz, den Controiller aus dem Schlaf aufzuwecken ... aber er braucht seine Zeit, bis er sich aus dem Bett erhoben hat und "ganz da" ist.
Und wenn der Wecker bereits wieder ruhig ist, noch bevor der Controller überhaupt aus dem Bett aufgestanden ist, dann kümmert der Controller sich anschließend nicht mehr um den Wecker.
Wach ist er nun aber trotzdem! Nur sieht er keinen Handlungsbedarf mehr, sich mit dem inzwischen bereits schweigsamen Wecker noch beschäftigen zu müssen.

Also:
Aufwecken geht schnell.
Aufstehen und handlungsbereit werden, dauert ein paar Takte.
Macht Technik dir das Leben schwör, ruf' schnell den EDV-Dompteur! ;-)

- Technische Fragen zu Eigenreparaturen bitte öffentlich im Forum stellen, nicht telefonisch! -