Hallöchen,
ich arbeite in der Schule an einem Mikrocontroller-Projekt mit
dem AVR 8515. Dazu sollen verschiedene Slave-Module mit einem
Master über einen Bus kommunizieren. Zu diesem Zweck soll über
8 DIP Schalter eine Adresse am Slave von 0-255 einstellbar sein.
Diese DIP Schalter benutze ich am PORTC des AVR.
Mein Problem ist das ich gerne die Adresse die ich als DIP Schalter
einstelle als Dezimalzahl auf einem LCD anzeigen möchte.
Leider kann ich ja nicht einfach das Byte vom PORTC auf das Display
senden da er ja 1 Zeichen interpretiert aber nicht die Dezimalzahl
die ja 3 Byte hätte. Kann mir jemand helfen wie ich dieses in
Assembler realisieren kann ?
Und das zweite ähnliche Problem ist das ich gerne meine Eingänge
auf PORTA als 0 und 1 auch auf dem Display darstellen möchte.
Also praktisch die Ausgabe "PORTA = 00011011" auf dem Display
haben möchte und die Bitfolge meine Eingänge repräsentieren soll.
Wäre wirklich super nett wenn mir jemand helfen könnte !
Liebe Grüße
Thomas
hi
schau dir mal die ACSII Tabelle an
in temp1, PORTC
rcall convert ;2 Stellige Zahl teilen -> temp2 (10), Temp3 (1)
ldi temp, 0b00110000
mov temp1, temp3
or temp1, temp
rcall lcd_data ;temp wird ausgegeben
mov temp1, temp2
or temp1, temp
rcall lcd_data
ach ja PUSHen und POPen nicht vergessen sonnst sind bei rcall die
Register von temp bis temp 3 futch bei der LCD Routine aus dem
Tutorial
_______________
convert:
ldi temp3, 0x00 ; 1te Stelle (1X)
convert_11:
cpi temp1, 0x0a
brsh convert_1
mov temp2, temp1 ; 2te Stelle (X)
ret
convert_1:
ldi temp, 0x0a
sub temp1, temp
inc temp3
jmp convert_11
Das ist so fuer 2 Stellen ausgelegt solltest aber Problemlos fuer 3
Stellen umschreiben koennen
Gruss Jens
PS
>Und das zweite ähnliche Problem ist das ich gerne meine Eingänge>auf PORTA als 0 und 1 auch auf dem Display darstellen möchte.>Also praktisch die Ausgabe "PORTA = 00011011" auf dem Display>haben möchte und die Bitfolge meine Eingänge repräsentieren soll.>Wäre wirklich super nett wenn mir jemand helfen könnte !
nicht dein ernst, dass du damit Probleme hast?????
Hallo Jens,
erstmal vielen Dank für Deine Hilfe.
Ich bin gerade erst dabei richtig Assembler zu lernen und da fehlt es
mir manchmal noch etwas an Vorstellungsvermögen.
In C oder Basic hätte ich für die Bitfolge an PortC einfach
eine IF Anweisung geschrieben und mir einen String gebastelt
den ich an das LCD geschickt hätte aber sowas gibt es ja in Assembler
glaube ich nicht. Deshalb wäre ich wirklich dankbar wenn Du einen
Denkanstoss für mich hättest wie ich die Bitfolge aufs LCD bringe.
Liebe Grüße
Thomas
schau dir mal die ascii tabelle an
da steht alles, was du brauchst
in dem fall kannst du die 0 und die 1 einfach mit oder verknuepfen und
somit bekommst du das ascii zeichen raus
Sinnvoller wäre wahrscheinlich eine Hex-Anzeige (00...FF)?
In dem Fall einfach high- und low-nibble trennen,
dann prüfen ob >9
nein: 0x30 addieren
ja: 0x37 addieren
Finde ich deshalb sinnvoller, weil die Adressen von Bausteinen auch in
Hex angegeben werden (EEPROM 0xA0 z.B.)
ANsonsten kannst du das Adress-Byte natürlich auch in 3 Dezimal-digits
aufsplitten (durch Division oder fortlaufende Subtraktion),
anschliessend zu jedem Digit 0x30 addieren, dann hast du die Zahl im
Ascii-Format, die du an das Display schicken kannst.
Genauso geht es auch mit der Dual-Anzeige für die Eingänge. Bit für Bit
testen und dann entweder 0x30 (->"0") oder 0x31 (->"1") ausgeben.
Eleganter in einer Schleife, das Register durch carry schieben, je nach
Zustand von c 0x30 oder 0x31 ausgeben, das ganze 8 Mal.
Warum nicht gleich so:
Main:
in r20,PORTC
rcall PrintDez
....
PrintDez:
ldi r16,'0'-1 ;Startziffer '0' als ASCCI laden
PDez100:
inc r16 ;Die auszugebene Ziffer solange um 1 erhöhen
subi r20,100 ;und die Zahl solange durch 100 teilen
brcc PDez100 ;bis Unterlauf.
rcall lcd_data ;Zeichen ausgeben.
ldi r16,'9'+1 ;Startziffer '9' als ASCCI laden
PDez10:
dec r16 ;Die auszugebende Ziffer solange um 1 verringern
subi r20,-10 ;und die Zahl solange durch 10 teilen
brcc PDez10 ;bis Überlauf.
rcall lcd_data ;Zeichen ausgeben.
mov r16,r20 ;Rest von der Ausgabezahl nach r16.
subi r20,-'0' ;Erste ASCII-Ziffer '0' dazu addieren.
rjmp lcd_data ;Zeichen ausgeben.
In r20 wird der auszugebende Wert übergeben.
Der Wert wird erst durch 100 geteilt und währenddessen die
100ter-Stelle ermittel und ausgegeben.
Das gleiche passiert dann für die 10er-Stelle.
Auf die übriggebliebene 1er-Stelle wird dann einfach nur der ASCII-Wert
aufaddiert z. B. bei 2 + ASCII '0' = ASCII '2'.
Für die binäre Anzeige hät ich auch was:
Main:
in r20,PORTA
rcall PrintBin
....
PrintBin:
ldi r19,8 ;Schleifenzähler für 8 Bit.
PBin1:
clr r16 ;r16 löschen.
lsl r20 ;Oberes Bit ins Carry-Bit schieben.
rol r16 ;Aus dem Carry-Bit nach r16 an die unterste Stelle
subi r16,-'0' ;ASCII-Zeichen aufaddieren.
;Ist je nach Carry dann '0' oder '1'.
rcall lcd_data ;Zeichen ausgeben.
dec r19 ;Schleifenzähler verringern.
brne PBin1 ;Solange wiederholen bis alle 8 Bit angezeigt sind
ret
Erklärt sich eigentlich von selber.
Oberstes Bit in das Carry-Bit schieben, an die unterste Stelle von r16
und den ASCII-Wert '0' aufaddieren und ausgeben.
Gruß
Andi
Ach ja, verd..... Tippfehler!
Der letzte Block in der Routine "PrintDez" sollte eigentlich so
sein:
mov r16,r20 ;Rest von der Ausgabezahl nach r16.
subi r16,-'0' ;Erste ASCII-Ziffer '0' dazu addieren.
rjmp lcd_data ;Zeichen ausgeben.
Gruß
Andi
Hallo Andi,
deine Binär-Bitanzeige klappt wirklich ausgezeichnet !
Ich habe allerdings Probleme mit der DEZ-Umrechnung.
Mein LCD zeigt nur Hyroglyphen an. Welches Register
enthält denn die einzelnen Ziffern ? Das ist doch r16 oder ?
Liebe Grüße
Thomas
Stimmt, in r16 (Temp1 aus dem Tut) ist das auszugebende Zeichen.
Allerdings steckt der Fehlerteufel mal wieder im Detail:
ldi r20,197
rcall PrintDez
HALT:
rjmp HALT
PrintDez:
ldi r16,'0'-1 ;Startziffer '0' als ASCCI laden
PDez100:
inc r16 ;Die auszugebene Ziffer solange um 1 erhöhen
subi r20,100 ;und die Zahl solange durch 100 teilen
brcc PDez100 ;bis Unterlauf.
rcall lcd_data ;Zeichen ausgeben.
ldi r16,'9'+1 ;Startziffer '9' als ASCCI laden
PDez10:
dec r16 ;Die auszugebende Ziffer solange um 1 verringern
subi r20,-10 ;und die Zahl solange durch 10 teilen
brcs PDez10 ;bis Überlauf.
rcall lcd_data ;Zeichen ausgeben.
mov r16,r20 ;Rest von der Ausgabezahl nach r16.
subi r16,-'0' ;Erste ASCII-Ziffer '0' dazu addieren.
rjmp lcd_data ;Zeichen ausgeben.
Da der Zeichencode bei der 10er-Teilung (PDez10) nicht wie bei der
100er-Teilung durch Aufwärtszählen sondern durch rückwärts zählen von
r16 ermittelt wird muß es dort brcs und nicht brcc heißen.
Oben die korrekte Version.
Hatte die beiden kleinen Progs auch hier nur mal schnell reingehackt
und nicht getestet.
Ein Wunder, dass das mit der Bit-Ausgabe PrintBin auf Anhieb geklappt
hat was ich selbst noch nicht getestet habe aber dafür Du.
Wenn Du noch andere (größere) Zahlen, 16, 24 und 32Bit, Dezimal
ausgeben möchtest gibs noch was in der Codesammlung:
http://www.mikrocontroller.net/forum/read-4-127504.html#new
Lies Dir bei Bedarf dazu alles durch und hole Dir dann erst unten die
neueste Version.
Gruß
Andi
Eine eigene Frage?
Dieser Thread ist über 21 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.