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
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
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
@ 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!!
@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 L100L010:
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.
> 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:
1
lcd_print8: ;Wird vom Makro aufgerufen. Gibt Byte als 2
2
;oder 3 Ziffern an LCD aus.
3
push wl ;Reg sichern
4
ldi wl,-1+'0' ;Hunderter-Stelle als ASCII-Zeichen,
5
Zahl
6
;ist positiv
7
inc wl ;Hunderter hoch und
8
subi xl,100 ;100 subtrahieren bis negativ wird
9
brsh pc-2 ;negativ? nein, 2 Zeilen hoch
10
cpi wl,'0' ;ja, ist Ziffer = "0"?
11
breq pc+2 ;ja, nicht ausgeben...
12
rcall lcd_data ;Hunderter ausgeben...
13
ldi wl,10+'0' ;Zehner-Stelle als ASCII-Zeichen, Zahl
@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!
@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...
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);
@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
@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
@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...
@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.