www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 8-Bit Zahl an LCD ausgeben


Autor: luxx (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo
ich will eine 8-Bit Zahl aus register xy an ein lcd ausgeben.
wie stell ich das an?
weil ich muss die zahl ja praktisch in 1er, 10er und 100er zerlegen und
die Ziffern dan einzeln an das LCD senden. Aber wie ist sowas zu
bewerkstelligen?

Ich verwende den ATMega16 unter Assembler.

luxx

Autor: Klaus2m5 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Luxx,

Du brauchst also eine binär nach ASCII Umwandlung und die findest Du
hier: http://www.avr-asm-tutorial.net/avr_de/rechnen/kon...

Gruß, Klaus

Autor: Mech-Michi (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich hab ein Programm in Verbindung mit dem aus dem Tutorial gegebenen
LCD-routines für eine 8 bit Zahl geschrieben.
War aber eines meiner ersten, daher vielleicht vom Code nicht so
einbahnfrei. Nach dem Programmtext befindet sich eine Erklärung,
 zudem habe ich den Programmcode auch dokumentiert.
Falls du noch fragen hast, noch mal schreiben.

Greetz

Mech-Michi

Autor: Conlost (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

das geht einfach, zuerst festellen ob Zahl größer als 100
wenn ja dann 100 abziehen
Zähler um eins erhöhen
Rest vergleichen ob größer als 100
wenn ja dann nochmal 100 abziehen
Zähler um 1 erhöhen

wenn nein dann das Selbe mit 10

Im Zähler steht dann immer deine 100er oder 10er Stelle.
Wenn 10er fertig ist der Rest die 1er Stelle.

es grüsst,
Arno

Autor: luxx (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ arno:
stimmt da hätte ich ja selber auch draufkommen können.

ich werde mal den quelltext von Mech_michi hernehmen , der is garnet
schlecht! Danke fürs posting!!

Autor: Jogibär (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi ich habe da jetzt mal selber was geschrieben nur Klappt das ganze
nicht so wie ich will, die Zahlen 0 - 227 werden korekt angezeigt von
228 an zeigt mein Display nur noch "000" an. Wäre nett wenn sich
jemand das mal kurz anschauen könnte wo mein Fehler ist?

Mfg Jogibär.


.include "m16def.inc"

;Port A = Taster
;Port B =
;Port C =
;Port D = LCD

;r20 = Dauer 0b00110000 (Auf LCD eine "0")
;r21 = Dauer 0x01
;r22 = SUB Wert
;r23 =
;r24 =
;r25 =
;r26 =
;r27 = Wert 100er
;r28 = Wert 10er
;r29 = Wert 1er
;r30 =
;r31 =

.def temp = r16
.def temp1 = r19
.def temp2 = r18
.def temp3 = r17

; STACKPOINTER INITIALISIEREN

  ldi temp, LOW(RAMEND)
        out SPL, temp
        ldi temp, HIGH(RAMEND)
        out SPH, temp

;PORTS DEFINIEREN

  ldi r16, 0b00000000
  out DDRA, r16    ;PORT A = EINGANG

        ldi r16, 0b11111111
  out DDRD, r16           ;PORT D = AUSGANG

;PROGRAMM

  rcall lcd_init
  rcall lcd_clear

loop:
  in r16, PINA
  ldi r27, 0b00110000
  ldi r28, 0b00110000
  ldi r29, 0b00110000
  ldi r21, 0x01

L100:
  cpi r16, 0b01100100    ;Vergleichen mit 100
  brmi L010      ;Kleiner 100 --> L010
  add r27, r21
  ldi r22, 0b01100100
  sub r16, r22
  rjmp L100

L010:
  cpi r16, 0b00001010    ;Vergleichen mit 10
  brmi L001      ;Kleiner 10 --> L001
  add r28, r21
  ldi r22, 0b00001010
  sub r16, r22
  rjmp L010

L001:
  cpi r16, 0b00000001    ;Vergleichen mit 1
  brmi Ausgabe      ;Kleiner 1 --> Fertig
  add r29, r21
  ldi r22, 0b00000001
  sub r16, r22
  rjmp L001

Ausgabe:
  rcall lcd_1zeile

  mov temp1, r27     ;1.Zeichen anzeigen
  rcall lcd_data

  mov temp1, r28     ;2.Zeichen anzeigen
  rcall lcd_data

  mov temp1, r29     ;3.Zeichen anzeigen
  rcall lcd_data

  rjmp loop

.include "lcd-routines.asm"   ;LCD-Routinen werden hier eingefügt

Autor: Conlost (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe dein Programm etwas verändert,
die Änderungen sind mit ***** gekennzeichnet.
So sollte es funktionieren.

Es grüsst,
Arno

.include "m16def.inc"

;Port A = Taster
;Port B =
;Port C =
;Port D = LCD

;r20 = Dauer 0b00110000 (Auf LCD eine "0")
;r21 = Dauer 0x01
;r22 = SUB Wert
;r23 =
;r24 =
;r25 =
;r26 =
;r27 = Wert 100er
;r28 = Wert 10er
;r29 = Wert 1er
;r30 =
;r31 =

.def temp = r16
.def temp1 = r19
.def temp2 = r18
.def temp3 = r17

; STACKPOINTER INITIALISIEREN

  ldi temp, LOW(RAMEND)
        out SPL, temp
        ldi temp, HIGH(RAMEND)
        out SPH, temp

;PORTS DEFINIEREN

  ldi r16, 0b00000000
  out DDRA, r16    ;PORT A = EINGANG

        ldi r16, 0b11111111
  out DDRD, r16           ;PORT D = AUSGANG

;PROGRAMM

  rcall lcd_init
  rcall lcd_clear

loop:
  in r16, PINA
  ldi r27, 0b00110000
  ldi r28, 0b00110000
  ldi r29, 0b00110000
  ldi r21, 0x01

L100:
  cpi r16, 0b01100100    ;Vergleichen mit 100
  brcs L010      ;Kleiner 100 --> L010  *****
  add r27, r21
  ldi r22, 0b01100100
  sub r16, r22
  rjmp L100

L010:
  cpi r16, 0b00001010    ;Vergleichen mit 10
  brcs L001      ;Kleiner 10 --> L001 *****
  add r28, r21
  ldi r22, 0b00001010
  sub r16, r22

L001:
  add r29, r16   ;***** in r16 sind nur noch Einer *****
    rjmp Ausgabe

Ausgabe:

  rcall lcd_1zeile

  mov temp1, r27     ;1.Zeichen anzeigen
  rcall lcd_data

  mov temp1, r28     ;2.Zeichen anzeigen
  rcall lcd_data

  mov temp1, r29     ;3.Zeichen anzeigen
  rcall lcd_data

  rjmp loop

.include "lcd-routines.asm"   ;LCD-Routinen werden hier eingefügt

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jogibär

L100:
  cpi r16, 0b01100100    ;Vergleichen mit 100
  brcs L010      ;Kleiner 100 --> L010  *****
  add r27, r21
  ldi r22, 0b01100100
  sub r16, r22
  rjmp L100


Warum um alles in der Welt schreibst Du 100 als 0b01100100.
Ich bein jetzt 25 Jahre im Geschäft, aber das 0b01100100
dezimal 100 ergibt sehe ich immer noch nicht auf einen Blick.
Schreib das doch als

  cpi r16, 100        ;Vergleichen mit 100

und gut is.
Allerdings steht jetzt im Code und im Kommentar exakt dasselbe.
D.h. der Kommentar erzaehlt mir nichts, was ich nicht auch
im Code sehen wuerde und ist damit überflüsig und kann weg.

L100:
  cpi r16, 100
  brcs L010      ;Kleiner 100 --> L010  *****
  add r27, r21
  ldi r22, 100
  sub r16, r22
  rjmp L100

Allerdings waere ein Kommentar interessant, was den in diesem
Code Abschnitt tatsaechlich passiert:

; Ziehe von r16 immer wieder 100 ab solange bis r16 kleiner
; als 100 geworden ist. In r27 wird mitgezaehlt, wie oft das
; moeglich war

L100:
  cpi r16, 100
  brcs L010      ;Kleiner 100 --> L010  *****
  add r27, r21
  ldi r22, 100
  sub r16, r22
  rjmp L100

L010:

So erzaehlt mir der Kommentar sehr viel mehr, als wenn ich
nur im Kommentar das dokumentiere, was ohnehin im Code
auch ersichtlich ist. Den Kommentar beim brcs wuerde ich
(fuer mich) lassen, da ich weiss, dass ich immer wieder
Minutenlang ueberlegen muss, wie das nun mit den Flags
nach einem Compare ist: Welches Flag bedeutet was?
Und somit ist das 'Kleiner' etwas, was zumindest ich nicht
sofort (ohne Nachdenken) aus dem brcs ersehen kann.

PS: Anders als beim add, gibt es beim sub eine Variante in
der man die zu subtrahierende Zahl direkt angeben kann.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Warum um alles in der Welt schreibst Du 100 als 0b01100100.

Ich vermute mal, weil es dem Unwissenden zeigt, dass man Ahnung hat...

;-)  <--- datt iss'n 'Lächeln'...

Aber um die Verwirrung mal perfekt zu machen:
lcd_print8:             ;Wird vom Makro aufgerufen. Gibt Byte als 2
                        ;oder 3 Ziffern an LCD aus.
 push wl                    ;Reg sichern
 ldi wl,-1+'0'              ;Hunderter-Stelle als ASCII-Zeichen,
Zahl
                            ;ist positiv
 inc wl                     ;Hunderter hoch und
 subi xl,100                ;100 subtrahieren bis negativ wird
 brsh pc-2                  ;negativ? nein, 2 Zeilen hoch
 cpi wl,'0'                 ;ja, ist Ziffer = "0"?
 breq pc+2                  ;ja, nicht ausgeben...
 rcall lcd_data             ;Hunderter ausgeben...
 ldi wl,10+'0'              ;Zehner-Stelle als ASCII-Zeichen, Zahl
                            ;ist negativ
 dec wl                     ;Zehner runter und
 subi xl,-10                ;10 addieren bis positiv wird
 brlo pc-2                  ;positiv? nein, 2 Zeilen hoch...
 rcall lcd_data             ;ja, Zehner Stelle ausgeben...
 ldi wl,'0'                 ;ASCII-0
 add wl,xl                  ;Einer addieren (Rest war ja positiv)
 rcall lcd_data             ;Einer ausgeben...
 pop wl                     ;Reg wiederherstellen
 ret                        ;zurück

Grins, duck & weg...

...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Hannes

Ich denke mal Du hast nichts dagegen, wenn ich diesen Code,
so wie vieles andere von Dir Geschriebene, einfach verwende.
Ich finde naemlich, dass Dein Assembler extrem gut zu lesen
und zu verstehen ist.

Das musste naemlich auch mal gesagt werden!

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Karl Heinz:

Erstmal danke für das Lob...

Was soll ich denn dagegen haben? Ist doch auch nur zusammengestoppelt,
aufbereitet und dabei auf das Niveau eines Hobbybastlers gebracht. Aber
er ist verstanden , besteht also nicht nur aus zusammengesuchten
unverstandenen Schnipseln.

Die 'gute Lesbarkeit' hat damit zu tun, dass ich den Code ja selbst
verstehen möchte, wenn ich ihn nach Wochen oder Jahren wieder lese.

Bit- & Bytebruch...
...HanneS...

Autor: Profi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schonmal über sowas nachgedacht:

#include<stdio.h>
unsigned char byt;
void main(void){
  for(byt=0;byt<255;byt++){
    printf("%d%d%d ",byt/100,byt%100/10,byt%10);
  }
}

Sollte in Asm auch nur ein paar Zeilen sein, denn div (/) und mod
(%)können die meisten µC in Asm.

Führende Nullen unterdrücken:
    printf("%c%c%d ",byt/100?'0'+byt/100:' ',
                     byt/10?'0'+byt%100/10:' ',
                     byt%10);

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Profi,

printf macht auf nem 8051 erstmal nen riesen Hopser um 2kB nach oben.
Anders gesagt, ein AT89C2051 macht sofort die Grätsche (hat nur 2kB).

Und der AVR hat keine Division.

Dein Rat war also richtig gut um zu zeigen, wie man es nicht machen
sollte !


Peter

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@HanneS

Ich mußte erstmal nachgucken, daß BRSH = BRCC ist.

Der Kommentar zu Zeile 9 ist nicht ganz korrekt, da das Carry nur für
positive Zahlen gilt. Man sollte wohl besser von Überlauf und Unterlauf
sprechen.

Und deshalb darf man auch nicht die Vergleiche für vorzeichenbehaftete
Zahlen (BRPL, BRMI) nehmen, sonst stimmen Werte über 227 nicht mehr.


Peter

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter:

Danke...

> Der Kommentar zu Zeile 9 ist nicht ganz korrekt, da das Carry nur
> für
> positive Zahlen gilt. Man sollte wohl besser von Überlauf und
> Unterlauf
> sprechen.

Dann werde ich aus:

brsh pc-2                  ;negativ? nein, 2 Zeilen hoch

wohl

brsh pc-2                  ;Unterlauf? nein, 2 Zeilen hoch

machen müssen...

Auf BRPL und BRMI bin ich anfangs auch gelegentlich reingefallen, ist
mir aber schon lange nicht mehr passiert. Inzwischen benutze ich BRSH
und BRLO nicht mehr, dafür BRCC und BRCS (ist ja das selbe), das
erscheint mir irgendwie logischer bzw. direkter. Aber da besteht bei
mir noch etwas Lernbedarf, so richtig sattelfest bin ich da noch
nicht...

Gruß...
...HanneS...

Autor: Jogibär (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja wunderbär, mit BRCS statt BRMI klappt das ganze.

Dankeschön Jogibär.

Autor: Conlost (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Freut mich wenn ich helfen konnte.

Es grüsst,
Arno

Autor: Profi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter:
tut mir leid, ich wußte nicht, dass der AVR keine Div kann. Habe damit
noch nichts gemacht.

Das mit dem C-Programm und dem printf sollte ja nicht heißen, dass man
es so programmieren soll, sondern rein als Denkanstoß, dass es außer
der Subtraktionsmethode auch noch andere Wege gibt.

>Dein Rat war also richtig gut um zu zeigen, wie man es nicht machen
sollte !

besser: ... wie man es nicht auf einem µC, der kein div und mod kann,
machen sollte.

z.B. auf einem 68hc908 läuft das nämlich wunderbar, ist halt ein CISC.

Deshalb hier noch der Code für 16-bit-Ausgabe:
#include<stdio.h>
unsigned int w;  //Word
void main(void){
  for(w=0;w<567;w++){
    printf("%d%d%d%d%d
",w/10000,w%10000/1000,w%1000/100,w%100/10,w%10);
  }
}

Führende Nullen unterdrücken:
    printf("%c%c%c%c%d   ",
       w/10000?'0'+w     /10000:' ',
       w/ 1000?'0'+w%10000/1000:' ',
       w/  100?'0'+w% 1000/ 100:' ',
       w/   10?'0'+w%  100/  10:' ',
       w%10);
Läuft natürlich auf einem 16-bitter optimal, auf einem 8-bitter gibt es
bestimmt elegantere Methoden.

Code aus dem Stegreif gedichtet, ohne ihn kontrolliert zu haben.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.