Forum: Projekte & Code Taschenrechner


von Markus (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche mit dem ATMega16 ein LCD-Display zur aktuellen Ausgabe des 
Zahlenwertes sowie die Ausgabe des ergebnisses zu nutzen.
Das Addieren usw. funktioniert. Nur leider bei der AUsgabe zum DIsplay 
kommt bei Zahlen über 9 nur murx raus. Unten steht meien Variante noch 
als umwandlung, als Anhang mein Hauptprogramm.

VIelleicht kann mir jemand helfen wie man vernünftig dies umwandeln 
kann, dass dort z.B. 10+1=11 steht.

-----Funktionsprogramm
;dual2bcd Umwandlung r16 dual nach dezimal in r17 und r16
dual2bcd: push     r15     ;Hilfsregister retten
      clr     r17       ;Hunderte löschen

dual2bcd1: cpi     r16,100   ;Hunderteprobe
       brlo   dual2bcd2    ;dual<100 fertig
       subi   r16,100    ;dual>=100 abziehen
       inc     r17      ;Hunderte zählen
       rjmp   dual2bcd1  ;bis dual<100

dual2bcd2: clr     r15      ;zehner löschen

dual2bcd3: cpi    r16,10    ;zehner probe
       brlo    dual2bcd4  ;dual<10 fertig
       subi    r16,10    ;dual>=10 abziehen
       inc    r15      ;zehner zählen
       rjmp    dual2bcd3  ;bis dual<10

dual2bcd4: swap    r15      ;r15=zehner 0000
       or    r16,r15    ;r16<-Zehner Einer
       pop    r15      ;Hilfsregister zurück


      subi   r16,-$30    ;in ASCII umwandeln



       ret

von Besserwisser (Gast)


Lesenswert?

dual2bcd4: swap    r15      ;r15=zehner 0000
       or    r16,r15    ;r16<-Zehner Einer
       [snip]
       subi   r16,-$30    ;in ASCII umwandeln

Na, schau mal im Simulator. Nach dem or hast Du in R16 eine zweistellige 
BCD Zahl. Nehmen wir mal an es sei 11 (also 0x011 oder $11)
Um daraus ein ASCII-Zeichen zu machen müsstest Du die beiden Nibbles 
wieder trennen.

Es wäre also besser die beiden garnicht erst in ein Register zu 
vereinigen.
Ich nehme auch an, das Du die ASCII-Zeichen für die Zahl in der 
Reihenfolge 100er, 10er und 1er ausgeben musst.

        [snip]
        ADIW R17, 0x30
        call lcd_output   ; vorher R17 entsprechend umladen
dual2bcd2:
        [snip]
        ADIW R15, 0x30
        call lcd_output   ; vorher R15 entsprechend umladen
dual2bcd4:
        [snip]           ; swap und or fallen weg
        ADIW R16, 0x30
        call lcd_output  ; vorher R16 entsprechend umladen

von Markus Engelmann (Gast)


Lesenswert?

Hey,

danke für die schnelle Antwort. Da kommt aber invalid Register. Muss man 
bei ADIW nicht irgendwie mit ZH und ZL arbeiten?

von Joerg W. (joergwolfram)


Lesenswert?

Nimm anstelle des ADIW ein

subi     reg,0xd0

dann sollte es passen.

Gruß Jörg

von Besserwisser (Gast)


Lesenswert?

@ Markus

>Da kommt aber invalid Register. Muss man
>bei ADIW nicht irgendwie mit ZH und ZL arbeiten?

Ja. Tschuldigung bitte.

von Markus Engelmann (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

also gerechnet wird richtig. Wenn man z.B. A=1 und B=10 wird auf dem 
LCD-Display in Oshonsoft folgendes Ausgegeben:
1+0=1

Ebenfalls bei der Eingabe erscheint:
1 (für A)
0 (für B)

In der Registeranzeige kann man sehen, dass dort zum jeweiligen 
Zeitpunkt das richtig drin ist. Denn am Ende steht in r19: die 10 für B 
und in r18: steht die 11 für das Ergebnis den der Wert A wird 
überschrieben.

Somit ist leider immer noch das Problem, dass nicht die Gesamtezahl 
sondern nur die letzte Stelle ausgegeben wird.

Ich habe im Anhang die geänderte Funktionsdatei da der Hauptteil ja 
nicht verändert wurde von mir.

Ich danke euch schon mal für eure Hilfe!

von Markus Engelmann (Gast)


Lesenswert?

@Besserwisser: Kein Problem. War ja nett das du so schnell helfen 
wolltest! Danke dir!

von Besserwisser (Gast)


Lesenswert?

@ Markus:

>in r18: steht die 11 für das Ergebnis
Mag sein, aber die Umwandlung arbeitet ja auf R16 und nicht R18

>Somit ist leider immer noch das Problem, dass nicht die Gesamtezahl
>sondern nur die letzte Stelle ausgegeben wird.

Irgendwie hast Du auch was komisches aus meinen Änderungen gemacht:

;dual2bcd Umwandlung r16 dual nach dezimal in r17 und r16
dual2bcd: push     r15     ;Hilfsregister retten
      clr     r17       ;Hunderte löschen

dual2bcd1: cpi     r16,100   ;Hunderteprobe
       brlo   dual2bcd2    ;dual<100 fertig
       subi   r16,100    ;dual>=100 abziehen
       inc     r17      ;Hunderte zählen
       rjmp   dual2bcd1  ;bis dual<100
        subi  R17, 0xd0
        call lcd_output   ; vorher R17 entsprechend umladen
dual2bcd2: clr     r15      ;zehner löschen

dual2bcd3: cpi    r16,10    ;zehner probe
       brlo    dual2bcd4  ;dual<10 fertig
       subi    r16,10    ;dual>=10 abziehen
       inc    r15      ;zehner zählen
       rjmp    dual2bcd3  ;bis dual<10
        subi R15, 0xd0
        call lcd_output   ; vorher R15 entsprechend umladen
dual2bcd4:
      subi   r16,0xd0    ;in ASCII umwandeln
        call lcd_output  ; vorher R16 entsprechend umladen
          pop    r15      ;Hilfsregister zurück

       ret

Wenn Du den output nicht in der subroutine machen willst,
dann musst Du R15 vor dem Aufruf der Umwandlung sichern und nach der 
Umwandlung R17 = Hunderter, R15 = Zehner und R16 = Einer ausgeben.
Nach der Ausgabe kannst Du R15 dann wieder vom Stack holen.

Klar?

von Besserwisser (Gast)


Lesenswert?

Oh, habe selbst noch einen Fehler gemacht:

;dual2bcd Umwandlung r16 dual nach dezimal in r17 und r16
dual2bcd: push     r15     ;Hilfsregister retten
      clr     r17       ;Hunderte löschen

dual2bcd1: cpi     r16,100   ;Hunderteprobe
       brlo   dual2bcd2    ;dual<100 fertig
       subi   r16,100    ;dual>=100 abziehen
       inc     r17      ;Hunderte zählen
       rjmp   dual2bcd1  ;bis dual<100
dual2bcd2:
        subi  R17, 0xd0
        call lcd_output   ; vorher R17 entsprechend umladen
        clr     r15      ;zehner löschen

dual2bcd3: cpi    r16,10    ;zehner probe
       brlo    dual2bcd4  ;dual<10 fertig
       subi    r16,10    ;dual>=10 abziehen
       inc    r15      ;zehner zählen
       rjmp    dual2bcd3  ;bis dual<10
dual2bcd4:
        subi R15, 0xd0
        call lcd_output   ; vorher R15 entsprechend umladen

      subi   r16,0xd0    ;in ASCII umwandeln
        call lcd_output  ; vorher R16 entsprechend umladen
          pop    r15      ;Hilfsregister zurück

       ret

von Besserwisser (Gast)


Lesenswert?

Vielleicht sollte man den Thread mal umhängen.
Kommt mir nicht so vor als hätte er in der Codesammlung was zu suchen.

von Markus Engelmann (Gast)


Lesenswert?

Hallo,

bei dual2bcd4:
        subi R15, 0xd0   sagt er an dieser Stelle invalides Register. 
Wenn man dies ausklammert um zu prüfen, ob noch ein Fehler ist, ist die 
Ausgabe

2xLeerfeld 00+2xLeerfeld11=2xLeerfeld111
Wenn A=10 und B=1

von Besserwisser (Gast)


Lesenswert?

@ Markus
>subi R15, 0xd0   sagt er an dieser Stelle invalides Register.

subi geht nicht mit allen Registern. Das hatte ich in dem Augenblick 
nicht im Kopf aber guck einfach mal in der Befehlsbeschreibung und nimm 
ein anderes Register.

2xLeerfeld 00+2xLeerfeld11=2xLeerfeld111 entspricht "  00  11  111" 
Richtig?

Das lässt sich so aus dem Code nicht ableiten. Das musst Du selber 
wissen, wie das zustandekommt.

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.