Forum: Mikrocontroller und Digitale Elektronik Anfängerproblem mit AVR-Tutorial: Uhr


von Leon (Gast)


Angehängte Dateien:

Lesenswert?

Hallo liebe Forengemeinde,

ich bin Anfänger im Mikrocontroller Bereich und arbeite grade das 
Tutorial zu diesem Forum durch.
Momentan bin ich bei dem Kapitel: "Die Timer: Uhr und CTC Modus." 
angelangt
und komme beim Versuch das Beispielprogramm in das AVR-Studio zu 
übernehmen nicht weiter.
Sobald ich das Beispielprogramm (im Anhang "uhrtest.asm") assemblieren 
möchte erhalte ich die folgenden beiden Errors:

C:\(Dateipfad)\uhrtest.asm(108): error: Duplicate label: 'lcd_number'
C:\Programme\Atmel\AVR 
Tools\AvrAssembler2\Appnotes\lcd-routines.asm(170): info: previous 
definition of 'lcd_number'
C:\(Dateipfad)\uhrtest.asm(117): error: Duplicate label: 'lcd_number_1'
C:\Programme\Atmel\AVR 
Tools\AvrAssembler2\Appnotes\lcd-routines.asm(179): info: previous 
definition of 'lcd_number_1'
Assembly failed, 2 errors, 4 warnings

Wenn ich das richtig verstehe sind die Labels "lcd_number" und 
"lcd_number_1" zwei mal vorhanden. Wenn ich mir die lcd_routines.asm 
(befinden sich auch im Anhang) anschau stimmt das auch.

Das Programm "uhrtest.asm" habe ich aus dem Tutorial herauskopiert und 
die LCD-Funktionen ("lcd_routines.asm")stammen ebenfalls
aus dem Tutorial (Kapitel LCD)
Im Uhr-Tutorial wird erwähnt, dass die aus dem Kapitel "LCD" stammenden 
lcd-Funktionen verwendet werden sollen.
Nach meinen verständnis sollten diese also kompatibel sein (?).

Jetzt meine Frage: Wo liegt mein Fehler?

Falls mir jemand einen Tipp geben kann wäre ich sehr Dankbar!

Viele grüße, Leon

von MWS (Gast)


Lesenswert?

Leon schrieb:
> Jetzt meine Frage: Wo liegt mein Fehler?

Das sind zwei Ausgaberoutinen mit gleichem Namen, ob kompatibel, hab' 
ich mir nicht angesehen. Die Sublabels _1, _2 usw. gehören jeweils zum 
Hauptlabel lcd_number. Nur eine der Routinen kann mit gleichem 
Labelnamen eingebunden werden, also muss die andere inklusive Sublabels 
raus.

von jjflash (Gast)


Lesenswert?

... ich hab es mir angesehen !

Ab dem Label "lcd_number" ist ein Unterprogramm enthalten, dessen Zweck 
es ist, eine Zahl dezimal auszugeben !

Dem Autor des Uhrenprogramms "uhrtest.asm" ist es entgangen, dass die 
Subroutinen in "lcd-routines.asm" ein gleichlautendes Unterprogramm 
besitzt.

Leider sind die beiden Unterprogramme in uhrtest.asm und 
lcd-routines.asm NICHT kompatibel zueinander:

Das Unterprogramm in lcd-routines.asm gibt den Zahlenwert in Register 
"temp1" dezimal 3-stellig mit einer führenden 0 aus (was für eine Uhr 
unbrauchbar ist), auf dem Display würde bspw. "023" erscheinen.

Das Unterprogramm in uhrtest.asm gibt auch den Zahlenwert dezimal auf 
dem Display aus, diesen jedoch nur 2-stellig. Ein Wert von 48 in temp1 
würde auf dem Display tatsächlich "48" escheinen lassen (Werte größer 
als 99 in temp1 machen "Murks").

Lösung des Problems (beispielhaft fuer den Anfänger):

Im Programm "uhrtest.asm" alles (inklusive des Labels) lcd_number 
löschen und durch folgendes ersetzen:

------------------------------------------------------------------------ 
----

; Eine Zahl aus dem Register temp1 2 stellig ausgeben

2st_lcd_number:
        push    temp2               ; register sichern,
                                    ; wird für Zwsichenergebnisse 
gebraucht
        ldi     temp2, '0'
2st_lcd_number_10:
        subi    temp1, 10           ; abzählen wieviele Zehner in
        brcs    2st_lcd_number_1    ; der Zahl enthalten sind
        inc     temp2
        rjmp    2st_lcd_number_10
2st_lcd_number_1:
        push    temp1               ; den Rest sichern
        mov     temp1,temp2         ;
        rcall   lcd_data            ; die Zehnerstelle ausgeben
        pop     temp1               ; den Rest wiederherstellen
        subi    temp1, -10          ; 10 wieder dazuzählen, da die
                                    ; vorhergehende Schleife 10 zuviel
                                    ; abgezogen hat
                                    ; das Subtrahieren von -10
                                    ; = Addition von +10 ist ein Trick
                                    ; da kein addi Befehl existiert
        ldi     temp2, '0'          ; die übrig gebliebenen Einer
        add     temp1, temp2        ; noch ausgeben
        rcall   lcd_data

        pop     temp2               ; Register wieder herstellen
        ret

------------------------------------------------------------------------ 
--


Alle Aufrufe von "rcall lcd_number" zwischen

loop:

und

rjmp loop

durch

"rcall 2st_lcd_number" ersetzen !

Die Anführungszeichen natürlich weglassen !

von Leon (Gast)


Angehängte Dateien:

Lesenswert?

Riesen Dank schonmal!
Also lag es wohl doch nicht direkt an mir.

Nachdem ich alle Labels im Programm "uhrtest.asm" geändert habe kam bei 
der neuen Benennung "2st_lcd_number" usw. eine neue Fehlermeldung, also 
änderte ich sie auf "st_lcd_number" usw. (also ohne die 2 davor)
Jetzt sind die Fehlermeldungen schonmal verschwunden.

Es blieben noch 4 Warnungen über, die verschwanden als ich in den 
LCD-Routinen die Umbenennungen der Register einfach gelöscht hab.
.def temp2 = r22
.def temp3 = r23
War ja schließlich doppelt gemoppelt.

Jetzt läuft die Uhr sogar, leider braucht sie für 10 Sekunden ca. 39 
Sekunden.
Fehler in meinem Testaufbau sind natürlich möglich, vermutlich ist mein 
Oscillator falsch eingestellt (?).

Die fast funktionierenden Codes hab ich Angehängt.


Als Blutiger Anfänger werde ich wohl nicht an dem Tutorial rumtüfteln um 
nicht an 2 fronten gleichzeitig kämpfen zu müssen.


Vielen Dank nochmal!

von Karl H. (kbuchegg)


Lesenswert?

Leon schrieb:

> Jetzt läuft die Uhr sogar, leider braucht sie für 10 Sekunden ca. 39
> Sekunden.

Also ein Faktor von ca 1:4

Das Tutorial ist ausgelegt für einen ATMega8, der auf 4Mhz getaktet ist. 
Dein µC ist wahrscheinlich noch im 'Takt'-Original Zustand und läuft 
wahrscheinlich noch mit 1Mhz. Und schon erklärt sich der Faktor von 1:4 
ganz zwanglos.

Da du aber Lernender bist und auch verstanden hast, was du da 
programmierst und nicht einfach nur vorhandene Programme in deinen µC 
lädst und dich am Eregbnis erfreust, sollte es für dich kein Problem 
sein, diese unterschiedliche Taktfrequenz durch Anpassung der Timerwerte 
auf 1Mhz auszugleichen.
Ist ein schöner Test, ob du auch tatsächlich verstanden hast, was da im 
Programm warum passiert.

> Als Blutiger Anfänger
... solltest du im Tutorial vorne anfangen und lernen! Lernen bedeutet 
nicht, dass man sich von einer Web-Seite ein paar Files runterlädt, die 
in den µC lädt und sich zurücklehnt und 'so so' sagt.

: Bearbeitet durch User
von Martin V. (oldmax)


Lesenswert?

Hi
Karl Heinz hat recht. Es mag interessant sein, gleich mit einer (wow) 
Uhr anzufangen. Aber um das zu verstehen, was da abgeht, ist die 
Thematik schon einen Schritt zu weit. Beginn doch erst einmal wie alle 
anderen auch mit einer blinkenden LED. Einer LED, die du mit einem 
Taster ein- und aussschaltest. Ein Relais, angesteuert wie eine LED, 
aber eben mit Treibertransistor und einer Freilaufdiode. Lern zu 
verstehen, was Register sind und wie sie genutzt werden. Schau dir die 
Befehle an, entweder im Datenblatt oder im AVR Studio unter Hilfe. 
Verstehe, was ein Exclusiv-Oder, ein Und-, ein Oder-Befehl bewirkt und 
bau nicht gleich als erstes eine Uhr. Wie willst du eine Fehlersuche 
machen, wenn dein Programm nicht läuft. Gut, eine Compilermeldung zu 
erklären kriegen wir noch hin, aber wenn zur Laufzeit Fehler auftreten, 
was dann? Wir werden uns nicht hinsetzen und seitenweise Assemblercode 
prüfen, um dann zu sagen, das Problem liegt in Zeile 349.. Wenn ein 
Zeittakt nicht passt, ok, das solltest du selbst finden, ist aber für 
uns leicht nachvollziehbar. Doch wenn eine LED 3 mal blinkt und dann für 
immer aus bleibt, wird es dann schon schwieriger. Und hier auf der 
anderen Seite deines Monitors ungleich mehr. Aber vielleicht hast du ja 
auch die ersten Schritte abgearbeitet.
Gruß oldmax

von Woher (Gast)


Lesenswert?

Martin Vogel schrieb:
> Es mag interessant sein, gleich mit einer (wow)
> Uhr anzufangen. Aber um das zu verstehen, was da abgeht, ist die
> Thematik schon einen Schritt zu weit. Beginn doch erst einmal wie alle
> anderen auch mit einer blinkenden LED.

Leon schrieb:
> arbeite grade das
> Tutorial zu diesem Forum durch.
> Momentan bin ich bei dem Kapitel: "Die Timer: Uhr und CTC Modus."
> angelangt

Woher wisst Ihr, dass Leon alles im Tutorial vorher übersprungen hat?

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.