Hallo liebes Forum! Ich bin ein wenig am verzweifeln, hab schon den halben Tag gesucht und nix gefunden: An meinem Attiny13 hängt ein Schieberegister. Mein Programm funktioniert wie es soll. Nun habe ich das Problem, dass nach (zufälliger?) Zeit die Pins beim SIPO kurz anschalten. Was ich schon versucht habe: -im Programm nur Sipo angesteuert: funktioniert, deswegen muss auch SIPO funktionieren -Widerstand an Strobe von SIPO gehalten: funktioniert nicht, AVR-Pins gehen also nicht in tristate. -Bei rcall AUSGABE die Ausgabe ans SIPO auf einen bestimmten Wert gezwungen: funktioniert nicht: der Fehler kann nicht bei meinem Unterprogramm rcall AUSGABE liegen. -Es werden aber sonst keine Portpins geschalten!?!? -Es tritt auch kein Reset auf. Ich würde mich freuen wenn noch jemand eine Idee hat!!!
oh, und der code natürlich:
1 | /*
|
2 | * Garagentoranzeige.asm
|
3 | *
|
4 | * Created: 28.04.2013 09:48:12
|
5 | * Author: Meister x.
|
6 | * 128kHz, Div: 0
|
7 | *
|
8 | *
|
9 | */
|
10 | |
11 | |
12 | ;Konstanten |
13 | .equ kErinnerung = 10 ;2ms |
14 | .equ kAnzeigemodus = 100 ;1s |
15 | |
16 | |
17 | ;Definitionsdatei für Attiny13 Einbinden |
18 | .include "tn13def.inc" |
19 | |
20 | |
21 | .CSEG ;ab hier beginnt Programm => Flash |
22 | |
23 | |
24 | ;Interruptvektoren setzen |
25 | .org 0x0000 ;Reset Handler |
26 | rjmp RESET |
27 | .org 0x0002 ;PCINT (Taster) |
28 | rjmp TESTMODUS |
29 | .org 0x0003 ;Timer0 overflow für Clock |
30 | rjmp CLOCK |
31 | .org 0x0008 ;WD interrupt |
32 | rjmp MESSUNG |
33 | .org 0x0009 ;ADC Conversion Complete |
34 | //rjmp ADC_READY
|
35 | |
36 | |
37 | ;Variablen deklarieren |
38 | .def rClock2ms = r1 |
39 | .def rClock100ms = r2 |
40 | .def rClock1s = r3 |
41 | |
42 | .def rTemp1 = r16 |
43 | .def rTemp2 = r17 |
44 | .def rTemp3 = r18 |
45 | .def rTemp4 = r19 |
46 | .def rTemp5 = r20 |
47 | .def rTemp6 = r21 |
48 | .def rSIPO = r22 |
49 | .def rZustand = r23 |
50 | |
51 | RESET: |
52 | |
53 | cli ;Global Interrupt disable |
54 | |
55 | |
56 | ;Ein- und Ausgänge festlegen (0=EIN, 1=AUS) |
57 | ldi rTemp1, 0b00000111 |
58 | out DDRB, rTemp1 |
59 | ;Ausgänge aus- und Pullups einschalten |
60 | ldi rTemp1, 0b00001000 |
61 | out PORTB, rTemp1 |
62 | |
63 | |
64 | ;Stackpointer ans Ende von SRAM setzen |
65 | ldi rTemp1, LOW(RAMEND) |
66 | out SPL, rTemp1 |
67 | |
68 | |
69 | ;Variablen rücksetzen |
70 | clr rClock2ms |
71 | clr rClock100ms |
72 | clr rClock1s |
73 | ldi rZustand, 0b10001111 |
74 | wdr
|
75 | |
76 | |
77 | ;Sleepmode einstellen (Power Down) |
78 | ldi rTemp1, (1<<SE)|(1<<SM1) |
79 | out MCUCR, rTemp1 |
80 | |
81 | ;Timer0 (für Clock 8bit) konfigurieren |
82 | ldi rTemp1, (1<<CS00) ;Vorteiler /1 |
83 | out TCCR0B, rTemp1 |
84 | ldi rTemp1, (1<<TOIE0) ;Interupt bei overflow erlauben |
85 | out TIMSK0, rTemp1 |
86 | |
87 | ; ADC konfigurieren: Vcc als Referenz, Single Conversion |
88 | ldi rTemp1, (1<<MUX1) ; Kanal PB3, Referenzspannung Vcc |
89 | out ADMUX, rTemp1 |
90 | ldi rTemp1, (1<<ADPS2) ; VT /16 |
91 | out ADCSRA, rTemp1 |
92 | ldi rTemp1, (1<<ADC2D)|(1<<ADC1D) ;Disable DigPIN bei adc01 |
93 | out DIDR0, rTemp1 |
94 | |
95 | ;Watchdog konfigurieren |
96 | ldi rTemp1, (1<<WDTIE)|(1<<WDP2)|(1<<WDP0) ;Interrupt mode, WD bei 0,5s |
97 | out WDTCR, rTemp1 |
98 | |
99 | ;PCINT konfigurieren |
100 | ldi rTemp1, (1<<PCIE) ;PC Interrupt enable |
101 | out GIMSK, rTemp1 |
102 | ldi rTemp1, (1<<PCINT3) ;PCINT3: PB3 |
103 | out PCMSK, rTemp1 |
104 | |
105 | |
106 | sei ;Global interupt enable |
107 | wdr
|
108 | ldi rSIPO, 0b00100000 ;SV erstmal an |
109 | rcall AUSGABE |
110 | |
111 | ;------------------------------------------------------------------------------------------------------------------------------------------------------ |
112 | |
113 | |
114 | MAIN: |
115 | |
116 | |
117 | ;Modus-Flags abfragen |
118 | sbrc rZustand, 6 ;Sleep? |
119 | rjmp SLEEPP |
120 | sbrs rZustand, 7 ;Anzeige/Erinnerung? |
121 | rjmp ERINNERUNG |
122 | |
123 | ANZEIGE: |
124 | ;Timer rücksetzen |
125 | clr rClock100ms |
126 | clr rClock1s |
127 | ANZ_LOOP: |
128 | ;Zustand ausgeben |
129 | mov rSIPO, rZustand |
130 | cbr rSIPO, 0b11000000 ;flags aus SIPO entfernen |
131 | sbr rSIPO, 0b00100000 ;SV an lassen |
132 | rcall AUSGABE |
133 | ;prüfe ob Anzeigemodus zuende |
134 | mov rTemp1, rClock1s |
135 | cpi rTemp1, kAnzeigemodus |
136 | brlo ANZ_LOOP |
137 | rjmp SLEEPP |
138 | |
139 | ERINNERUNG: |
140 | ;Zustand ausgeben |
141 | mov rSIPO, rZustand |
142 | cbr rSIPO, 0b11000000 ;flags aus SIPO entfernen |
143 | sbr rSIPO, 0b00100000 ;SV an lassen |
144 | rcall AUSGABE |
145 | ;Timer rücksetzen |
146 | clr rClock2ms |
147 | ERI_LOOP: |
148 | ;prüfe ob Erinnerung zuende |
149 | mov rTemp1, rClock2ms |
150 | cpi rTemp1, kErinnerung |
151 | brlo ERI_LOOP |
152 | ;LEDs erst aus |
153 | ldi rSIPO, 0b00100000 |
154 | rcall AUSGABE |
155 | |
156 | SLEEPP: |
157 | ;Sleepflag |
158 | sbr rZustand, 0b01000000 |
159 | cbr rZustand, 0b10000000 |
160 | ;SV und LEDs Aus |
161 | ldi rSIPO, 0b00000000 |
162 | rcall AUSGABE |
163 | sleep
|
164 | rjmp MAIN |
165 | |
166 | ;------------------------------------------------------------------------------------------------------------------------------------------------------ |
167 | |
168 | |
169 | CLOCK: |
170 | push rTemp1 ;SREG und rTemp1 sichern |
171 | in rTemp1, SREG |
172 | push rTemp1 |
173 | |
174 | inc rClock2ms |
175 | ldi rTemp1, 50 |
176 | cp rClock2ms, rTemp1 |
177 | brsh INCR100ms |
178 | rjmp CLOCKENDE |
179 | INCR100ms: |
180 | clr rClock2ms |
181 | inc rClock100ms |
182 | ldi rTemp1, 10 |
183 | cp rClock100ms, rTemp1 |
184 | brsh INCR1s |
185 | rjmp CLOCKENDE |
186 | INCR1s: |
187 | clr rClock100ms |
188 | inc rClock1s |
189 | ldi rTemp1, 60 |
190 | cp rClock1s, rTemp1 ;max Anzahl s erreicht? |
191 | brlo CLOCKENDE |
192 | clr rClock1s |
193 | CLOCKENDE: |
194 | |
195 | pop rTemp1 ;SREG und rTemp1 widerherstellen |
196 | out SREG, rTemp1 |
197 | pop rTemp1 |
198 | reti
|
199 | |
200 | |
201 | AUSGABE: ;(rSIPO=Data) |
202 | push rTemp1 ;SREG und rTemp sichern |
203 | in rTemp1, SREG |
204 | push rTemp1 |
205 | push rTemp2 |
206 | |
207 | mov rTemp2, rSIPO |
208 | ldi rTemp2, 0b00100000 |
209 | ldi rTemp1, 8 |
210 | AUSGABE_NEXT: |
211 | cbi PORTB, 0 |
212 | cbi PORTB, 1 |
213 | rol rTemp2 |
214 | brcc AUSGABE_0 |
215 | sbi PORTB, 1 |
216 | AUSGABE_0: |
217 | sbi PORTB, 0 |
218 | dec rTemp1 |
219 | brne AUSGABE_NEXT |
220 | sbi PORTB, 2 |
221 | cbi PORTB, 2 |
222 | |
223 | pop rTemp2 |
224 | pop rTemp1 ;SREG und rTemp wiederherstellen |
225 | out SREG, rTemp1 |
226 | pop rTemp1 |
227 | ret
|
228 | |
229 | |
230 | TESTMODUS: |
231 | push rTemp1 ;SREG und rTemp sichern |
232 | in rTemp1, SREG |
233 | push rTemp1 |
234 | |
235 | ldi rSIPO, 0b00101111 ;SV und LEDs ein |
236 | rcall AUSGABE |
237 | TES_LOOP: |
238 | wdr
|
239 | sbis PINB, 3 ;Taster noch gedrückt? |
240 | rjmp TES_LOOP |
241 | |
242 | pop rTemp1 ;SREG und rTemp wiederherstellen |
243 | out SREG, rTemp1 |
244 | pop rTemp1 |
245 | reti
|
246 | |
247 | |
248 | MESSUNG: |
249 | sbr rSIPO, 0b00110000 ;SV und Messstrom ein |
250 | rcall AUSGABE |
251 | push rTemp1 ;SREG und rTemp sichern |
252 | in rTemp1, SREG |
253 | push rTemp1 |
254 | push rTemp2 |
255 | push rTemp3 |
256 | push rTemp4 |
257 | push rTemp5 |
258 | push rTemp6 |
259 | |
260 | wdr
|
261 | //evtl. warten
|
262 | ldi rTemp1, (1<<ADEN)|(1<<ADSC) ;ADC aktivieren und starten |
263 | out ADCSRA, rTemp1 |
264 | MES_NFERTIG: |
265 | in rTemp1, ADCSRA |
266 | sbrc rTemp1, ADSC ;fertig? |
267 | rjmp MES_NFERTIG |
268 | cbr rSIPO, 0b00010000 ;Messtrom aus |
269 | rcall AUSGABE |
270 | in rTemp2, ADCL |
271 | in rTemp3, ADCH |
272 | ldi rTemp1, (0<<ADEN) ;ADC deaktivieren |
273 | out ADCSRA, rTemp1 |
274 | |
275 | ;LOOKUP ergebnis in rTemp6 |
276 | clr rTemp6 ;erster Torwert |
277 | ldi ZL, low(LOOKUP*2) ;laden des ersten Vergleichwertes |
278 | ldi ZH, high(LOOKUP*2) |
279 | MES_NEXTVAL: |
280 | inc rTemp6 ;nächster Torwert |
281 | lpm rTemp4, Z+ ;Vergleichwert Low |
282 | lpm rTemp5, Z+ ;Vergleichwert High |
283 | cp rTemp2, rTemp4 ;prüfe ob drunter |
284 | cpc rTemp3, rTemp5 |
285 | brlo MES_NEXTVAL |
286 | dec rTemp6 ;wieder eins zurück |
287 | cbr rTemp6, 0b11110000 |
288 | |
289 | ldi rTemp6, 0b00001001 |
290 | |
291 | ;Alle Tore aus? |
292 | cpi rTemp6, 0b00000000 |
293 | breq MES_SLEEPMODUS ;Ja |
294 | ;Nein: |
295 | |
296 | ;Anderungen? |
297 | mov rTemp2, rZustand |
298 | cbr rTemp2, 0b11000000 ;evtl Flags entfernen |
299 | cp rTemp6, rTemp2 |
300 | brne MES_ANZEIGEMODUS ;Ja |
301 | ;Nein: |
302 | |
303 | ;war Anzeigemodus aktiv? |
304 | sbrs rZustand, 7 |
305 | rjmp MES_ERINNERMODUS ;Nein |
306 | ;Ja |
307 | |
308 | rjmp MES_ENDE |
309 | |
310 | MES_SLEEPMODUS: |
311 | ;Sleepflag, Zustand 0000 |
312 | ldi rZustand, 0b01000000 |
313 | rjmp MES_ENDE |
314 | |
315 | MES_ANZEIGEMODUS: |
316 | ;Zustand übernehmen |
317 | mov rZustand, rTemp6 |
318 | ;Anzeigeflag |
319 | sbr rZustand, 0b10000000 ;Anzeigemodusflag setzen |
320 | cbr rZustand, 0b01000000 ;Sleepflag aus |
321 | rjmp MES_ENDE |
322 | |
323 | MES_ERINNERMODUS: |
324 | ;Erinnerungsflag |
325 | cbr rZustand, 0b11000000 |
326 | |
327 | MES_ENDE: |
328 | pop rTemp6 |
329 | pop rTemp5 |
330 | pop rTemp4 |
331 | pop rTemp3 |
332 | pop rTemp2 |
333 | pop rTemp1 ;SREG und rTemp wiederherstellen |
334 | out SREG, rTemp1 |
335 | pop rTemp1 |
336 | reti
|
337 | |
338 | |
339 | |
340 | ;------------------------------------------------------------------------------------------------------------------------------------------------------ |
341 | |
342 | |
343 | LOOKUP: |
344 | .dw 978 |
345 | .dw 891 |
346 | .dw 818 |
347 | .dw 751 |
348 | .dw 694 |
349 | .dw 652 |
350 | .dw 616 |
351 | .dw 568 |
352 | .dw 526 |
353 | .dw 504 |
354 | .dw 484 |
355 | .dw 464 |
356 | .dw 445 |
357 | .dw 430 |
358 | .dw 417 |
359 | .dw 0 |
Was ich noch weiß: Attiny ist im sleep. Er wird durch WD-Timer geweckt (ca. 0,5s). Bei wecken (WD-interrupt) wird was mit adc gemessen... Danach wird Flag für Anzeigemodus gesetzt. Danach reti. Jetzt springt er ins Hauptprogramm Main. Dort wird Flag ausgewertet und er springt wieder zum Anzeigemodus. Diese falsche SIPO-Ausgabe muss zwischen dem Flag setzen und dem Anzeigemodus passieren.
Ich hab noch was rausgefunden: Es muss mit den Interrupts zusammenhängen: wenn ich in meinem Unterprogramm Interrupts verbiete (cli und zum schluss sei), so hab ich diese Probleme nicht. Wo liegt die Ursache? ich hab doch alle register schön gesichert?!?!
na denn simuliere es doch mal richtig wenn du es schon auf die INTroutine eingrenzen konntest
Hi
1 | .org 0x0008 ;WD interrupt |
2 | rjmp MESSUNG |
3 | .org 0x0009 ;ADC Conversion Complete |
4 | //rjmp ADC_READY |
Was passiert wenn der ADC Conversion Complete Interrupt auftritt? würde das auskommentierte mal durch ein RETI ersetzen.
Helmut H. schrieb: > Was passiert wenn der ADC Conversion Complete Interrupt auftritt? > würde das auskommentierte mal durch ein RETI ersetzen. dieser Interrupt ist disabled. Und ich hab auch schon mal das ganze adc-Zeugs auskommentiert: hilft leider nichts.
GLeich vorweg. Dein Code ist zu umfangreich, als das ich ihn hier im Kopf auf alle Eventualitäten abklopfen könnte. Aber hier ist mir, im Zusammenhang mit deinem letzten Posting, etwas aufgefallen Du rufst
1 | TESTMODUS: |
2 | push rTemp1 ;SREG und rTemp sichern |
3 | in rTemp1, SREG |
4 | push rTemp1 |
5 | |
6 | ldi rSIPO, 0b00101111 ;SV und LEDs ein |
7 | rcall AUSGABE |
8 | TES_LOOP: |
9 | wdr |
10 | sbis PINB, 3 ;Taster noch gedrückt? |
11 | rjmp TES_LOOP |
12 | |
13 | pop rTemp1 ;SREG und rTemp wiederherstellen |
14 | out SREG, rTemp1 |
15 | pop rTemp1 |
16 | reti |
die Funktion AUSGABE aus dem Interrupt heraus auf. Was, wenn die Funktion Ausgabe gerade läuft, die ersten Bits rausgetaktet hat, dann kommt der Interrupt und leiert seinerseits wieder die Ausgabe an. Dann kommt alles durcheinander. Stell sicher, dass du für Shared Resources (also alles was es nur ein einziges mal gibt, so wie das Schieberegister) immer einen einzigen gesicherten Pfad hast, der einzig und ausschliesslich benutzt wird. Nicht so wie hier, dass eine Ausgabe durch einen Interrupt unterbrochen werden kann, der dann selbst wieder eine Ausgabe macht. Das ist ein Garant für Ärger.
Selbiges hier
1 | MESSUNG: |
2 | sbr rSIPO, 0b00110000 ;SV und Messstrom ein |
3 | rcall AUSGABE |
4 | ... |
Tus nicht. Du öffnest die Büchse der Pandora. Es gibt nur eine Stelle, an der Aufrufe an AUSGABE gemacht werden dürfen. Und das ist die Hauptschleife. Oder alternativ: es gibt nur und ausschliesslich Aufrufe dieser Funktion in ISR-Routinen. Aber auf keinen Fall in beidem: Hauptschleife und ISR.
Karl Heinz schrieb: > die Funktion AUSGABE aus dem Interrupt heraus auf. > Was, wenn die Funktion Ausgabe gerade läuft, die ersten Bits > rausgetaktet hat, dann kommt der Interrupt und leiert seinerseits wieder > die Ausgabe an. Ja klaaar! Ich bin ja ein Depp! Der halbe Tag fürn A... :-D Das passiert mir mit sicherheit nicht nochmal! Karl Heinz schrieb: > Tus nicht. Du öffnest die Büchse der Pandora. > Es gibt nur eine Stelle, an der Aufrufe an AUSGABE gemacht werden > dürfen. Und das ist die Hauptschleife. Oder alternativ: es gibt nur und > ausschliesslich Aufrufe dieser Funktion in ISR-Routinen. > Aber auf keinen Fall in beidem: Hauptschleife und ISR. Ok, du hast absolut recht. Ich denke ich machs hier mal quick and dirty und disable die Interrupts am Anfang der Ausgabe und enable sie am ende wieder. Ein herzliches Dankeschön!
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.