Hallo zusammen, Ich möchte den Inhalt eines Registers (Binär) als ASCII-Code auf ein LC-Display ausgeben. Allerdings hab' ich da ein Problem mit dem Konvertieren des Binärtwerts nach ASCII. Im INET hab' ich dazu folgendes gefunden: http://www.avr-asm-tutorial.net/avr_de/quellen/konvert.asm Das ist alles schön und gut, aber irgendwie funktioniert das bei mir nicht so richtig... Mein Aufruf: 1. Zahl in rBin1H:rBin1L laden 2. Z-Pointer auf die Adresse eines Labels am Ende des Codes setzen 3. Routine 'Bin2ToAsc5' aufrufen Soweit so gut, nur: Auf meinem Display werden damit einfach vier Zeichen angezeigt, die aber sicher keine Zahlen sind. Und es sind immer die gleichen. Was ich an dem Code eben vor allem nicht verstehe, ist, wie hier Daten gespeichert werden sollen. Vom laufenden Programm aus kann man doch nicht ins Flash-ROM schreiben, oder? Gibt's den Z-Pointer denn noch für's RAM oder EEPROM? Ich hoffe, mir kann jemand den richtigen Aufruf zeigen/erklären. Vielen Dank schonmal! mfG Philipp Burch PS: Im Anhang befindet sich mein Code. Wundert euch nicht über das Durcheinander dort, ich hab' heute den ganzen Tag versucht, was gescheites auszugeben, da ist der halt so geworden... Das Label, wo die Zahl hingeschrieben werden soll(te) befindet sich ganz unten.
Hab' gerade gesehen, dass da steht "Der Z-Pointer zeigt entweder ins SRAM [...]". Wie krieg' ich das hin? Im Tutorial hier wird die Arbeit mit dem RAM ja leider nicht beschrieben :(
Danke vielmals für den Code. Leider schiesst der bei mir etwas über's Ziel hinaus. Mir wär's lieber, ich könnte den Code den ich jetzt habe ein bisschen ändern. Eigentlich scheitert es momentan einfach am SRAM. Da weiss ich eben nicht, wie man das verwendet... Kann mir da vielleicht mal schnell jemand erklären, wie das geht? Denn irgendwie muss man dem doch beibringen, dass der Z-Pointer nun auf eine Adresse im SRAM statt im Flash zeigt. Vielen Dank schonmal!
Dann schau dir doch mal die LD... und ST... -Befehle in der Hilfe zum AVR-Studio an. Als Referenz (welche Befehle es gibt) hilft vielleicht die Befehlsliste des Datenblatts. Übrigens war der Hinweis auf den Code nicht als Angebot zur unbesehenen Benutzung gedacht, sondern als Möglichkeit, durch Code-Analyse zu verstehen, wie es gemacht werden kann. Da der Code recht üppig kommentiert ist, gibt es eine Chance, ihn zu verstehen. ...
Also, ich hab' jetzt mal versucht, das Zeug ordnungsgemäss über's RAM laufen zu lassen. Leider kommt auf meinem LCD immernoch nur Mist... Hier mal der Code: --- Meine Hauptschleife (Ausschnitt) --- ;Zeit in rBin1H:rBin1L speichern mov rBin1H, TimeH mov rBin1L, TimeL ;Z-Pointer initialisieren ldi ZL, LOW(adrNumbers) ldi ZH, HIGH(adrNumbers) ;Konvertieren rcall Bin2ToAsc5 ;LCD leeren ldi Temp, 0b00000001 ldi Temp2, 0b000 rcall LCDSend ldi Temp3, 5 ;5 Zeichen rcall LCDPrint --- --- adrNumbers hat den Wert 0x0061. Der sollte also auf einem Bereich nach den Registern zeigen, oder? Dann kommt hier die Routine zum Schreiben: --- Schreibroutine --- ;Einen String auf's LCD ausgeben ('Temp3' Zeichen) von der Adresse ;im Z-Pointer aus LCDPrint: ld Temp, Z+ ;Byte lesen und Z inkrementieren ldi Temp2, 0b100 rcall LCDSend dec Temp3 brne LCDPrint ;Warten bis alles ausgegeben ist _LCDPrint_End: ret --- --- Und zum Schluss noch die Routine zum Senden eines Bytes an's LCD: --- LCDSend --- ;Dem LCD ein Byte senden ;Das Byte muss sich in Temp befinden, der Wert für die Status- ;leitungen (R/W b1, RS b2) in Temp2 LCDSend: rcall Delay ;Byte in PC schreiben out PORTC, Temp rcall Delay ;Enable High und die anderen Statusleitungen ausgeben andi Temp2, 0b110 out PORTE, Temp2 sbi PORTE, E rcall Delay ;Enable wieder Low cbi PORTE, E ret --- --- An dieser Routine wird's aber eher nicht liegen, da es funktioniert hatte, als ich einfach einen statischen String verwendet hatte. Der ganze Code von hier http://www.avr-asm-tutorial.net/avr_de/quellen/konvert.asm hab' ich einfach unten angehängt. Die verwendeten Funktionen sind wohl diese: ; Paket II: Von Binär nach ASCII bzw. BCD ; ; Bin2ToAsc5 ; ========== ; wandelt eine 16-Bit-Binärzahl in eine fünfstellige ASCII- ; kodierte Dezimalzahl um ; Aufruf: 16-Bit-Binärzahl in rBin1H:L, Z zeigt auf Anfang ; der Zahl ; Rückkehr: Z zeigt auf Anfang der Zahl, führende Nullen sind ; mit Leerzeichen überschrieben ; Benutzte Register: rBin1H:L (bleibt erhalten), rBin2H:L ; (wird überschrieben), rmp ; Aufgerufene Unterroutinen: Bin2ToBcd5 ; Bin2ToAsc5: rcall Bin2ToBcd5 ; wandle Binärzahl in BCD um ldi rmp,4 ; Zähler auf 4 mov rBin2L,rmp Bin2ToAsc5a: ld rmp,z ; Lese eine BCD-Ziffer tst rmp ; prüfe ob Null brne Bin2ToAsc5b ; Nein, erste Ziffer <> 0 gefunden ldi rmp,' ' ; mit Leerzeichen überschreiben st z+,rmp ; und ablegen dec rBin2L ; Zähler um eins senken brne Bin2ToAsc5a ; weitere führende Leerzeichen ld rmp,z ; Lese das letzte Zeichen Bin2ToAsc5b: inc rBin2L ; Ein Zeichen mehr Bin2ToAsc5c: subi rmp,-'0' ; Addiere ASCII-0 st z+,rmp ; und speichere ab, erhöhe Zeiger ld rmp,z ; nächstes Zeichen lesen dec rBin2L ; noch Zeichen behandeln? brne Bin2ToAsc5c ; ja, weitermachen sbiw ZL,6 ; Zeiger an Anfang ret ; fertig ; Bin2ToBcd5 ; ========== ; wandelt 16-Bit-Binärzahl in 5-stellige BCD-Zahl um ; Aufruf: 16-Bit-Binärzahl in rBin1H:L, Z zeigt auf die ; erste Stelle der BCD-kodierten Resultats ; Stellen: Die BCD-Zahl hat exakt 5 gültige Stellen. ; Rückkehr: Z zeigt auf die höchste BCD-Stelle ; Benötigte Register: rBin1H:L (wird erhalten), rBin2H:L ; (wird nicht wieder hergestellt), rmp ; Aufgerufene Unterroutinen: Bin2ToDigit ; Bin2ToBcd5: push rBin1H ; Rette Inhalt der Register rBin1H:L push rBin1L ldi rmp,HIGH(10000) ; Lade 10.000 in rBin2H:L mov rBin2H,rmp ldi rmp,LOW(10000) mov rBin2L,rmp rcall Bin2ToDigit ; Ermittle 5.Stelle durch Abziehen ldi rmp,HIGH(1000) ; Lade 1.000 in rBin2H:L mov rBin2H,rmp ldi rmp,LOW(1000) mov rBin2L,rmp rcall Bin2ToDigit ; Ermittle 4.Stelle durch Abziehen ldi rmp,HIGH(100) ; Lade 100 in rBin2H:L mov rBin2H,rmp ldi rmp,LOW(100) mov rBin2L,rmp rcall Bin2ToDigit ; Ermittle 3.Stelle durch Abziehen ldi rmp,HIGH(10) ; Lade 10 in rBin2H:L mov rBin2H,rmp ldi rmp,LOW(10) mov rBin2L,rmp rcall Bin2ToDigit ; Ermittle 2.Stelle durch Abziehen st z,rBin1L ; Rest sind Einer sbiw ZL,4 ; Setze Zeiger Z auf 5.Stelle (erste Ziffer) pop rBin1L ; Stelle den Originalwert wieder her pop rBin1H ret ; und kehre zurück Bin leider noch ein ASM-N00b, daher bitte nicht über meine Postings wundern.
Och Menno! War ich 'n Idiot! Im Tut steht ja, dass der Z-Pointer die Register 25 und 26 belegt. Gut, die hab' ich nicht verwendet. Dummerweise hab' ich aber keine ATmega8, sondern einen ATmega8515. Und da liegen die doch bei 30 und 31. Trotzdem Danke für die Hilfe!
Na toll! Zitat aus dem hiesigen Tut: Um die Daten wieder auszulesen, muss man die Adresse auf die zugegriffen werden soll in den Z-Pointer laden. Der Z-Pointer besteht aus den Registern R25 (Low-Byte) und R26 (High-Byte), daher kann man das Laden einer Konstante wie gewohnt mit dem Befehl "ldi" durchführen. Statt R25 und R26 kann man übrigens einfach "ZL" und "ZH" schreiben, da diese Synonyme bereits in der include-Datei 4433def.inc definiert sind.
Dann schau mal ins Datenblatt deines AVRs. Oder ins Instruction-Set, oder in die Hilfe zum AVR.Studio, oder in die Include-Datei deines AVR. ...
Ich weiss ja jetzt, dass er bei r31:r30 ist. Aber im Tut steht trotzdem r26:r25. Das sollte vielleicht mal jemand korrigieren...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.