Forum: Mikrocontroller und Digitale Elektronik Bascom ATmega8a - Problem aus Powerdown aufwecken


von Maschde (Gast)


Lesenswert?

Hallo zusammen!

Ich bin gerade dabei einen neuen Geocache zu entwickeln. Wer nicht weiß 
was das ist, auch egal...

Ich erzeuge mit dem Timer1 einen String in binärer Form, der dann auf 
dem Display ausgegeben wird. Dieser wird für 3 Sekunden angezeigt, dann 
soll der Bediener mit zwei Tasten diesen wieder eingeben.
Dann wird nur noch abgefragt, ob die beiden Strings übereinstimmen, wenn 
nicht beginnt das Ganze von vorne.
Dieses Programm funktioniert schon so wie ich das haben wollte.

Nun geht es darum, dass der Atmega8 in Powerdown Modus gehen soll wenn 
ca. 5 Min. keine Taste gedrückt wird. Das funktioniert auch (durch 
Strommessung bestätigt) nach diesen ca. 5 Sekunden. Ich kann ihn nur 
nicht mit einem Interrupt an Int0 aufwecken, wieso auch immer!

Ich habe das mit dem Powerdown und aufwecken mit einem simplen Programm 
getestet, eine Taste zum Powerdown und eine zum aufwecken an Int0, hier 
hat das einwandfrei funktioniert. Im unten stehenden Code bekomme ich 
ihn nicht mehr zum "leben".

Ich hoffe ihr könnt mir hierbei helfen!

Das Programm ist mein erstes wirkliches Projekt nach etlichen 
"Lern"-Projekten. Man kann in dem Code sicherlich einiges noch 
verbessern oder vereinfachen...

Vielen Dank!
1
$regfile = "m8adef.dat"
2
$crystal = 1000000
3
$hwstack = 40
4
$swstack = 16
5
$framesize = 32
6
7
8
Config Pinb.0 = Input
9
Portb.0 = 1
10
Config Pinb.1 = Input
11
Portb.1 = 1
12
Config Pinb.2 = Output
13
Config Pind.7 = Output
14
Config Pind.2 = Input
15
Portd.2 = 1
16
17
Config Lcd = 16 * 2
18
Config Lcdpin = Pin , Db7 = Portc.5 , Db6 = Portc.4 , Db5 = Portc.3 , Db4 = Portc.2 , E = Portc.1 , Rs = Portc.0
19
20
Config Int0 = Low Level
21
On Int0 Isr
22
Config Timer1 = Timer , Prescale = 8
23
Enable Timer1
24
On Timer1 Isr_timer
25
26
Enable Interrupts
27
28
29
30
Taster1 Alias Pinb.1
31
Taster2 Alias Pind.2
32
Beleuchtung Alias Portd.7
33
Cursor Off Noblink
34
35
Beleuchtung = 1
36
37
38
39
'---------------------------------------------
40
'Deklarationen
41
42
Dim Frage As String * 16
43
Frage = ""
44
45
Dim Antwort As String * 16
46
Antwort = ""
47
48
Dim X As Byte
49
X = 0
50
51
Dim Frageout As String * 16
52
Frageout = ""
53
54
Dim Wert_timer As Integer
55
Wert_timer = 0
56
57
Dim Abschaltzeit As Integer
58
Abschaltzeit = 0
59
60
61
Cls
62
63
'---------------------------------------------
64
'Begr¸flung
65
66
Lcd "Hallo!"
67
Wait 3
68
Locate 1 , 1
69
Lcd Space(16)
70
Locate 1 , 1
71
72
'---------------------------------------------
73
'Anweisung
74
75
Do
76
77
   Lcd "Druecke 1 um zu"
78
   Locate 2 , 1
79
   Lcd "beginnen!"
80
81
   Do
82
   Loop Until Taster2 = 0
83
   Abschaltzeit = 0
84
   Wert_timer = Timer1
85
   Frage = Bin(wert_timer)
86
   Cls
87
88
   Lcd "Merke dir diese"
89
   Locate 2 , 1
90
   Lcd "Zahlenfolge:"
91
   Wait 3
92
   Cls
93
94
   Lcd "Die Zahlenfolge:"
95
   Wait 2
96
97
   For X = 1 To 16
98
      Locate 2 , 1
99
      Lcd Space(16)
100
      Frageout = Frageout + Mid(frage , X , 1)
101
      Locate 2 , 1
102
      Lcd Frageout
103
      Waitms 500
104
   Next
105
106
   Wait 3
107
108
   Cls
109
110
111
'-------------------------------------------------
112
'Aufforderung zur Eingabe
113
114
   Locate 1 , 1
115
   Lcd "Nun bist du an"
116
   Locate 2 , 1
117
   Lcd "an der Reihe!"
118
   Wait 3
119
   Cls
120
121
'-----------------------------------------------
122
'Eingabe der Antwort
123
124
   Do
125
      Locate 1 , 1
126
      Lcd "Deine Eingabe:"
127
      Debounce Taster1 , 0 , Schreibe_0 , Sub
128
      Debounce Taster2 , 0 , Schreibe_1 , Sub
129
      If Len(antwort) = 16 Then
130
         If Frage = Antwort Then
131
            Gosub Antwort_richtig
132
         Else
133
            Cls
134
            Lcd "Leider falsch..."
135
            Locate 2 , 1
136
            Lcd "2 min. warten ;)"
137
            Wait 30
138
            Cls
139
            Antwort = ""
140
            Frage = ""
141
            Frageout = ""
142
            Exit Do
143
         End If
144
      End If
145
146
   Loop
147
148
Loop
149
150
151
Schreibe_0:
152
Locate 2 , 1
153
Antwort = Antwort + "0"
154
Lcd Antwort
155
Abschaltzeit = 0
156
Return
157
158
159
Schreibe_1:
160
Locate 2 , 1
161
Antwort = Antwort + "1"
162
Lcd Antwort
163
Abschaltzeit = 0
164
Return
165
166
167
Isr_timer:
168
Abschaltzeit = Abschaltzeit + 1
169
If Abschaltzeit = 100 Then
170
   Cls
171
   Beleuchtung = 0
172
   Gosub Power_down
173
End If
174
Return
175
176
177
Antwort_richtig:
178
Cls
179
Lcd "Herzlichen"
180
Locate 2 , 1
181
Lcd "Glueckwunsch!"
182
Wait 2
183
Portb.2 = 1
184
Wait 3
185
Portb.2 = 0
186
Wait 10
187
Cls
188
Beleuchtung = 0
189
Gosub Power_down
190
End
191
192
193
Power_down:
194
Enable Int0
195
Config Powermode = Powerdown
196
Return
197
198
199
Isr:
200
Disable Int0
201
Goto 1
202
Return

von So ne Idee (Gast)


Lesenswert?

Lass mal in der ISR: eine LED blinken.
Vielleicht Loops er nur am Anfang des Programms, weil der Int0 dort 
wieder enablen wird, dann wieder in die ISR gesprungen wird usw.

von Maschde (Gast)


Lesenswert?

Der Int0 wird ja im Code erst im Label Power_down: enabled und nicht 
oben bei den Configs oder sehe ich das falsch?
Ich werds auf jeden Fall morgen mal probieren wenn ich aus der Arbeit 
zurück bin.

von mue_c (Gast)


Lesenswert?

Hallo Maschke,
du legst den Controller im Interrupt schlafen. Da dort die Ints global 
abgeschaltet sind, bekommst du ihn über einen Int nicht wieder 
aufgeweckt.

von Karl H. (kbuchegg)


Lesenswert?

Und wenn die Sache mit dem Powermode in der ISR  dann erledigt ist
1
Isr:
2
Disable Int0
3
Goto 1
4
Return

goto 1?

wo soll das sein? Abgesehen davon. Du willst nicht aus einer Interrupt 
Service Routine rausspringen. Der einzige erlaubte 'Ausgang' ist der 
Return. Alles andere ist ein 'Ask for trouble'

von Martin R. (maschde)


Lesenswert?

> Lass mal in der ISR: eine LED blinken.
Habe ich mal gemacht (vor dem Disable Int0).
Die LED macht gar nichts. Somit gehe ich davon aus, dass Isr: gar nicht 
angesprungen wird?

> goto 1?
Ich habe mal in einem Forum (weiß nicht mehr welches) gelesen, dass es 
mit diesem Befehl möglich sei, an den Anfang (Zeile 1) des Codes zu 
springen.
Gibt es hierfür eine andere Möglichkeit? In meinem Fall soll ja das 
Programm nach dem Aufwecken immer von vorne beginnen.

mue_c schrieb:
> du legst den Controller im Interrupt schlafen. Da dort die Ints global
> abgeschaltet sind, bekommst du ihn über einen Int nicht wieder
> aufgeweckt.
Tut mir leid, da komme ich gerade nicht mit. Stehe ich auf dem Schlauch?

Mit dem Disable Int0 wollte ich diesen bis zum nächsten Power_down: 
deaktivieren, da die Taste 2 sonst keine 1 schreiben würde sondern immer 
in  Isr: springt.

Ich habe nun auch noch einen Versuch gestartet in dem ich die Isr: leer 
gelassen habe.
1
Isr:
2
3
Return

Leider tut sich hier auch nicht mehr.
Der Controller bleibt im Tiefschlaf und auch die Stromaufnahme ändert 
sich nicht.

Ist es möglich dass hier auch der Int1 noch eine Rolle spielt? Dieser 
ist ja in meinem Code nirgendwo behandelt.
Ist es allgemein ratsam alle Eingänge mit Ddrx = &bxxxxxxxx festzulegen?

von Bastler (Gast)


Lesenswert?

> ich hab mal gelesen
Da klingt nach "Programming by Gerücht". Da finde ich die 
Fehlermeldungen eines kostenlosen Compilers, den nicht namentlich 
genannt werden soll, besser. Der würde sowas nie zulassen. Und ich wüßte 
auch warum.

von mue_c (Gast)


Lesenswert?

Martin R. schrieb:
> mue_c schrieb:
>> du legst den Controller im Interrupt schlafen. Da dort die Ints global
>> abgeschaltet sind, bekommst du ihn über einen Int nicht wieder
>> aufgeweckt.
> Tut mir leid, da komme ich gerade nicht mit. Stehe ich auf dem Schlauch?

Maschde schrieb:
> Isr_timer:
> Abschaltzeit = Abschaltzeit + 1
> If Abschaltzeit = 100 Then
>    Cls
>    Beleuchtung = 0
>    Gosub Power_down
> End If
> Return
> ...
> Power_down:
> Enable Int0
> Config Powermode = Powerdown
> Return

Innerhalb der Timer_ISR legst du den Controller schlafen. Dabei gilt das 
oben Gesagte. Also muss das Powerdown da raus. Powerdown kannst du nur 
innerhalb einer ISR machen, wenn du die Ints wieder global eingeschaltet 
hast, da muss man aber wissen, was man tut.

> Mit dem Disable Int0 wollte ich diesen bis zum nächsten Power_down:
> deaktivieren, da die Taste 2 sonst keine 1 schreiben würde sondern immer
> in  Isr: springt.

Kannst du auch so machen, allerdings den Kommentar von Karl-Heinz 
beachten.

von Karl H. (kbuchegg)


Lesenswert?

Martin R. schrieb:

>> goto 1?
> Ich habe mal in einem Forum (weiß nicht mehr welches) gelesen, dass es
> mit diesem Befehl möglich sei, an den Anfang (Zeile 1) des Codes zu
> springen.

Zumindest die BASCOM Hilfe weiss von dieser Möglichkeit nichts.
Zumal es in BASCOM ja eigentlich auch gar keine Zeilennummern gibt, die 
man anspringen könnte.

> Gibt es hierfür eine andere Möglichkeit? In meinem Fall soll ja das
> Programm nach dem Aufwecken immer von vorne beginnen.

Der Normalfall ist:
Ein Programm macht nach dem Aufwachen genau an der Stelle weiter, an der 
es eingeschlafen ist.
Damit ein Programm aber durch einen Interrupt wieder aufgeweckt werden 
kann, müssen Interrupts auch erlaubt sein. Innerhalb einer ISR (wenn 
also ein anderer Interrupt gerade abgearbeitet wird), sind die 
Interrupts aber gesperrt. Und das ändert sich auch nicht, wenn du den 
Prozessor schlafen legst. Gesperrte Interrupts führen aber im Gegenzug 
wieder dazu, dass der Prozessor damit nicht mit einem Interrupt geweckt 
werden kann.

(Ist dasselbe was auch mue_c schon geschrieben hat. Nur mit anderen 
Worten)

: Bearbeitet durch User
von Uwe_gast (Gast)


Lesenswert?

Die Interrupt isr ist überflüssig wenn es ums wecken geht. Es reicht den 
INT0 mit enable zu aktivieren und natürlich global. Statt config 
powermode versuch mal nur:

Power Powerdown

Grüße, Uwe

von Martin R. (maschde)


Lesenswert?

Erst mal vielen Dank für die vielen schnellen Antworten!
Ich glaub jetzt hab ichs verstanden.
Ich miss also zusehen, dass ich den Powerdown Befehl aus der Timer-ISR 
raus bekomme.
Wieder etwas dazugelernt ;-)

Ich werde das Ganze morgen austesten und mich dann nochmal melden.

von Martin R. (maschde)


Lesenswert?

Vielen Dank!
Ich habe zwar das Programm etwas umstricken müssen, aber das Powerdown 
und Aufwecken funktioniert jetzt!
Es hat daran gelegen, dass der Powerdown Befehl in der isr des Timers 
war.


Nun habe ich jedoch ein anderes Problem...
Dazu werde ich aber einen neuen Thread aufmachen, geht um was anderes.

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
Noch kein Account? Hier anmelden.