Ich scheine ja nicht viel Erfolg mit meinen bisherigen Fragen gehabt zu
haben... gebe ich ZU viele Infos?
Egal, ich hab grade folgendes Problem, ich finde den Fehler einfach
nicht (seit ca. 1 Woche auf der Suche):
Ich schreibe einen Hamster-Tacho mit grafischer Ausgabe der
Laufgeschwindigkeit der letzten 24h (als Kurve), der Uhrzeit und der
gesamten Kilometer pro 24h. Dafür sollen alle 20min die gezählten
Tachokontakte am Laufrad ins EEPROM geschrieben werden (72 rotierend
verwendete Bytes), ausserdem soll die Uhrzeit dort abgelegt werden und
einige andere Variablen, unter anderem zwei WORDS mit der EEPROM-Adresse
der Umdrehungszähler. Da es dabei gelegentlich Fehler beim Programmieren
gibt, prüfe ich aktuell meine EEPROM-Routinen. Die sind auch fehlerhaft,
vermute ich.
Das Problem ist nun: Ich schreibe das EEPROM folgendermassen ganz ans
Ende meines Programms,
1
.ESEG ; EEPROM-Datensektion
2
Uhrzeit_Stunden:
3
.db 12
4
Uhrzeit_Minuten:
5
.db 34
6
NumIntervals:
7
.db 0
8
Umdrehungen_save: ; 72 Speicherplätze für die Kurve
Wenn ich das mit avrasm2 (von Atmel) mit -e-Parameter compiliere, ergibt
sich ein EEPROM-File, das die Daten in sinnvoller Weise enthält.
Wenn ich den µC damit beschicke (und mit dem Flashprogramm), sollen
davon Schritt für Schritt die Werte gelesen und aufm LCD ausgegeben
werden, klappt auch für den ersten Wert (12). Danach werden nur noch
0xFF ausgegeben.
Lese ich das EEPROM mittels avrdude ... -Ueeprom:r:eeprom.dat:i aus,
stehen die obigen Daten korrekt drin!
Hier der asm-Code:
1
main_loop_debug:
2
; lcd_number, lcd_x und lcd_y sind die Argumente für print_byte_LCD und
3
; print_byte_number_LCD: die Zahl wird an der Spalte lcd_x, page lcd_y
4
; beginnend als Byte oder Dezimalzahl ausgegeben
5
ldi lcd_number, 0
6
ldi lcd_x, 0
7
ldi counter,0
8
9
ldi ZH,0 ; dient zu EEPROM-Adressierung, wie hier im Tutorial beschrieben
10
mov ZL,counter ; geht auch mit adiw, gleicher Effekt fürs Debuggen
11
counter_loop:
12
rcall EEPROM_read ; siehe unten, beschreibt tmp2 mit dem Wert an ZL/ZH
13
mov lcd_number, tmp2
14
ldi lcd_y, 0
15
ldi lcd_x, 6
16
rcall print_byte_LCD ; Ausgabe des EEPROM-Wertes als Byte
17
ldi lcd_y, 1
18
rcall print_byte_number_LCD ; Ausgabe des EEPROM-Wertes als Zahl
19
20
inc counter ; Counter hochzählen
21
mov ZL, counter
22
ldi lcd_y, 2
23
mov lcd_number, ZL
24
rcall print_byte_number_LCD ; Ausgabe des Adress-Counters, zur Kontrolle
> Ich scheine ja nicht viel Erfolg mit meinen bisherigen Fragen gehabt zu> haben... gebe ich ZU viele Infos?
Zu viele, so dass keiner mosern will "mehr Infos!". Und zu wenige, um
sich in absehbarer Zeit der Sache annehmen zu können...
Einen kompletter Sourcecode, der das Problem zeigt, könnte man in den
Simulator werfen und sich ansehen, ob es dort richtig läuft bzw. was
schief läuft. Idealerweise käme der Code ohne externe Hardware (LCD)
aus. Benutzt dein Restcode Interrupts und wenn ja ist das push/pop von
Registern OK?
Wenn dein Code im Simulator den Fehler nicht zeigt, dann wären Angaben
zur Hardware (Schaltung und Fuses - Bronwout?) notwendig.
Angaben zu Unterschieden bei der Implementierung zwischen deinem Code
und dem Tutorialcode wären auch gut. Bei meinem Vergleich meine ich zu
sehen: Die eigentliche EEPROM_read ist 1:1 übernommen. Ich spekuliere
(da nicht simulierbar s.o.) auf den Verlust des Werts in ZL. Was macht
dein Code mit diesem Stück?
OK, danke, zuviele Infos, ich hatte sowas schon vermutet...
Also: Mein Code verwendet Interrupts, genauer gesagt, den Timer1 im
CTC-Modus mit Interrupt bei Erreichen des Maximalwerts (als
"Uhr"-Zeitgeber) und den INT0 für die Reedkontaktsignale. Ist etwas
schwierig zu simulieren, ABER momentan läuft nur ein Minimalbeispiel des
Codes, den ich mal anhänge. Alle push/pop-Paare sind überprüft (und es
treten nicht wirklich viele auf). Alle Label-Sprünge sind überprüft. Ich
meine, das Problem auf ein meinerseits irriges Verständnis des
EEPROM-Ansprechens reduziert zu haben.
Ich habe schon gelegentlich funktionierenden Code gesehen, bei dem ZH
einmal gesetzt und dann nicht mehr verändert wurde, das sollte
hoffentlich nicht das Problem sein, zumal das jetzt nur die Testversion
ist.
denk *denk* ins Handbuch schau *fett in den eigenen Hintern tret*
nochmal im Tutorial nachles
1
.include "m8def.inc"
2
3
ldi R16, 0xFF
4
out DDRB, R16 ; Port B: Ausgang
5
6
ldi ZL, LOW(daten*2) ; Low-Byte der Adresse in Z-Pointer
7
ldi ZH, HIGH(daten*2) ; High-Byte der Adresse in Z-Pointer
8
9
lpm ; durch Z-Pointer adressiertes Byte
10
; in R0 laden
11
out PORTB, R0 ; an PORTB ausgeben
12
13
ende:
14
rjmp ende ; Endlosschleife
15
16
daten:
17
.db 0b10101010
Mal ne saublöde Frage -- wieso wird hier ZL VOR ZH belegt? Im
Datenblatt steht, dass mit dem Setzen von ZL direkt auch ZH übernommen
wird, also kann dieses Beispiel von
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Speicher doch gar
nicht funktionieren... oder?
Tjaaaaa... selig sind, die nicht wissen und doch glauben? In dem Fall
wohl nicht, das war der eklatante Fehler -- ich hatte ÜBERALL im Code ZL
vor ZH beschrieben, getreu dem Beispiel im EEPROM-Tutorial... jetzt
klappts. VIELEN DANK!! Es war zwar kein klarer Hinweis dabei, aber durch
deine Antwort (Helfer) bin ich ins Nachdenken und auf die Lösung
gekommen.... oh mann. In Zukunft wird NUR noch das Datenblatt zu sowas
befragt :/
Äääähm... die Geschichte mit dem low/high(LABEL*2) scheint auch nicht zu
stimmen, es klappt bei mir nur OHNE das *2... was ist das eigentlich für
ein Tutorial?!?
> Mal ne saublöde Frage -- wieso wird hier ZL VOR ZH belegt? Im> Datenblatt steht, dass mit dem Setzen von ZL direkt auch ZH übernommen> wird,
Mal eine andere saublöde Frage: Wo genau im Datenblatt liest du das? Die
zusammengefassten Register X,Y,Z sind was anderes als die speziellen
16-Bit Hardwareadressen/-register wie z.B. EEAR. Bei letzteren ist die
Reihenfolge für Lesen/Schreiben wichtig.
Die anderen Fragen kann ich nicht beantworten, weil aus deinen Beiträgen
nicht klar hervor geht, was du machst. Deshalb nur ein allgemeiner Rat:
In den x2 Beispielen musst du beachten, wo die Daten abgelegt sind: Im
Flash-ROM (Beitrag "Re: [AVR] m8535-EEPROM wird falsch gelesen"), im
EEPROM (Beitrag "[AVR] m8535-EEPROM wird falsch gelesen") oder im
SRAM. Alle drei Arten verlangen ihre eigene Adressierung!
Den versprochenen Anhang finde ich nicht.
> Äääähm... die Geschichte mit dem low/high(LABEL*2) scheint auch nicht zu> stimmen, es klappt bei mir nur OHNE das *2... was ist das eigentlich für> ein Tutorial?!?
Wenn du ein bestimmtes Beispiel mit seinen Problemen benennen kannst,
schaue ich mir das an. Die Zeit und Muse alle Beispiele auf potentielle
Probleme durchzunudeln habe ich nicht.
Hast recht, sorry, hab den Anhang einfach vergessen... ok. Blöd. Der
liegt daheim aufm Rechner...
Im Datenblatt steht nicht direkt drin, daß man ZH vor ZL besetzen muß
(es wird nur als Word-Register eingeführt und ich hab dieses Prinzip von
den anderen 16-Bit-Sachen übernommen), aber nach dieser Änderung tat
mein Code auf einmal. Ehrlich gesagt verstehe ich aber nach nochmaliger
Lektüre aller dazugehörigen Texte hier im Tutorial immer weniger, warum
eigentlich... kann das Behandeln des X-, Y- Z-Pointers ggf.
compilerabhängig sein?
Das *2 hatte sich offenbar bei MIR reingemogelt, obwohl ich gar kein lpm
verwende. Problem geklärt.
OK. Damit, trotz immer noch andauerndem Unverständnis: Probleme gelöst.
Es tut alles. Vielen Dank!
P.S.: Wenn der Hamstertacho mal fertig ist, stell ich Schaltplan und
Code ins Archiv, das ist vermutlich sinnvoller, als die xhundert Zeilen
Code hier ins Forum zu packen...