mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Text in Variable??


Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich wollt ne variable deklarieren wie in c aber ich bekomm des einfach 
nicht hin. muss ich des mit nem Register machen??

folgend soll es aussehen:
ldi  temph, "Test Adresse"

Wie lad ich den text in die variable damit ich se dann an das lcd 
dispaly übergeben kann??
Der Befehl zum übertragen sieht so aus:
daten:
.db $temph,0

Ich bin mir nicht sicher ob das $-Zeichen vorne dran sein muss oder ob 
ein anderes zeichen hin muss???

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du c kannst, Assembler aber nicht, dann mach es doch in c.

Ansonsten

http://www.avr-asm-tutorial.net/avr_de/index.html

Oliver

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja c kann ich eigentlich schon aber eben in asm steh ich grad auf dem 
schlauch!!

Trotzdem danke für die antwort!

Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also versteh ich des richtig im asm kannst du so viele variablen 
definieren wie du register hast oder?? Das mit den Registern weis ich 
schon aber ich wollt nur wissen ob man auch ohne register variablen 
deklarieren kann aber ich glaub das geht nicht bzw. gibt keinen sinn!!

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
An das LCD Display kannst du nur zeichenweise Daten übergeben. D.h. 
deine Variable ist grundsätzlich ein Zeiger auf eine Zeichenkette. Nach 
und nach wird das Zeichen auf das dieser Zeiger zeigt an das LCD gegeben 
und der Zeiger wird auf die nächste Adresse gesetzt - eine Schleife bis 
zum Endezeichen (in C Nullbyte, in ASM im Prinzip egal, Nullbyte ist 
praktisch).

Die Ausgabe ist im AVR Tutorial beim LCD erklärt...
http://www.mikrocontroller.net/articles/AVR-Tutori...

[ASM]
text:
           .db "Test",0                ; Stringkonstante, durch eine 0
                                       ; abgeschlossen
[/ASM]

Legt den Text unter der (16 BiT) Adresse (Label) text ab. Die Null dient 
später als Endezeichen.

[ASM]
           ldi ZL, LOW(text*2)         ; Adresse des Strings in den
           ldi ZH, HIGH(text*2)        ; Z-Pointer laden
[/ASM]

Lädt das 16-Bit Z-Register mit obiger Anfangsadresse des Textes. Die 
beiden 8-Bit Hälften der 16-Bit Adresse werden auf die beiden 8 Bit 
Registerhälften verteilt.

[ASM]
lcd_flash_string_1:
           lpm   temp1, Z+             ; Zeichen von Anfangsadresse (Z)
                                       ; nach temp1 schauffeln, Z um
                                       ; eins erhöhen

           cpi   temp1, 0              ; Endezeichen (0) erreicht?
           breq  lcd_flash_string_2    ; JA, dann Sprung zu
                                       ; lcd_flash_string_2

           call  lcd_data              ; (NEIN), dann Zeichen ausgeben

           rjmp  lcd_flash_string_1    ; Sprung zum nächsten Zeichen 
holen
lcd_flash_string_2:
[/ASM]


Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> also versteh ich des richtig im asm kannst du so viele variablen
> definieren wie du register hast oder?? Das mit den Registern weis ich
> schon aber ich wollt nur wissen ob man auch ohne register variablen
> deklarieren kann aber ich glaub das geht nicht bzw. gibt keinen sinn!!

Du definierst dir mit z.B. .def temp1 = r16 nur einen neuen Namen temp1 
für das Register r16. Das kann die Lesbarkeit deines Quelltextes 
erhöhen.

Wenn dir die Register als Speicherplatz für Variablen ausgehen, kannst 
du die Variablen auch im Speicher (RAM) anlegen. Im obigen Fall kann man 
text als eine (konstante ;-) Variable ansehen.

Speicherzugriffe sind langsamer als Registerzugriffe, deshalb arbeitet 
man - vereinfacht - so lang es geht mit Registern.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Speicherzugriffe sind langsamer als Registerzugriffe, deshalb arbeitet
> man - vereinfacht - so lang es geht mit Registern.
...Und nur in Registern kann man Daten auch bearbeiten (berechnen). 
Deshalb müssen alle Daten, mit denen eine Operation durchgeführt werden 
soll, in Register geladen werden. Im SRAM kann man Daten "nur" 
speichern.

Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah ok ich versteh!

jetzt nur nochmal zu meinem Porblem wie kann ich dann folgendes 
realisieren:

  cpi  menu_cnt, 0x01
  ldi  temph, "Menuepkt 1"
  cpi  menu_cnt, 0x02
  ldi  temph, "Menuepkt 2"
  cpi  menu_cnt, 0x03
  ldi  temph, "Menuepkt 3"

also ich geb über taster ein signal rein das mit hochzählt und dann soll 
im lcd display der passende Text stehen. Mein gedanke war der dass ich 
dann hier die daten in die variable speicher und an das unterprog 
weitergeb. also wie oben schon geschrieben mit
 daten:
 .db $temph, 0

Also quasi wenn menu_cnt 0x01 ist dann soll im display menuepkt 1 stehn 
und so weiter.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ldi  temph, "Menuepkt 1"
Das hat so keinen Zweck. Dir fehlen die absoluten Assembler-Grundlagen. 
In ein 8-Bit-Register kannst Du keinen Textstring legen. Da passt nur 
ein einziges ASCII-Zeichen rein. Wenn Du mit .db eine Tabelle im 
Programmspeicher angelegt hast, dann kannst Du mit lpm auf die einzelnen 
Zeichen zugreifen. Schau Dir bitte erst gründlich das Tutorial an. Und 
wenn Du dazu Fragen hast, dann kannst Du die hier stellen. Assembler und 
C sind zwei völlig verschiedene Paar Schuhe!

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist ziemlich straightforward...

menuetext_1:
  .db "Menuepkt 1",0
menuetext_2:
  .db "Menuepkt 2",0
menuetext_3:
  .db "Menuepkt 3",0

; ... Rest vom Programm ...

  cpi  menu_cnt, 0x01
  breq ausgabe_menue_1       ; JA, dann Sprung zu

  cpi  menu_cnt, 0x02
  breq ausgabe_menue_2       ; JA, dann Sprung zu

  cpi  menu_cnt, 0x03
  breq ausgabe_menue_3       ; JA, dann Sprung zu

  ; Kein Menue 1-3 gefunden
  rjmp sonstwohinzumbeispielneuentastereinlesen

ausgabe_menue_1:
           ldi ZL, LOW(menuetext_1*2)         ; Adresse des Strings in 
den
           ldi ZH, HIGH(menuetext_1*2)        ; Z-Pointer laden
           rjmp ausgabe_menue

ausgabe_menue_2:
           ldi ZL, LOW(menuetext_2*2)         ; Adresse des Strings in 
den
           ldi ZH, HIGH(menuetext_2*2)        ; Z-Pointer laden
           rjmp ausgabe_menue

ausgabe_menue_3:
           ldi ZL, LOW(menuetext_3*2)         ; Adresse des Strings in 
den
           ldi ZH, HIGH(menuetext_3*2)        ; Z-Pointer laden
           rjmp ausgabe_menue

ausgabe_menue:
lcd_flash_string_1:
           ; temp1 muss definiert sein und ggf. push/pop zum Retten
           ; siehe Tutorial
           lpm   temp1, Z+             ; Zeichen von Anfangsadresse (Z)
                                       ; nach temp1 schauffeln, Z um
                                       ; eins erhöhen

           cpi   temp1, 0              ; Endezeichen (0) erreicht?
           breq  lcd_flash_string_2    ; JA, dann Sprung zu
                                       ; lcd_flash_string_2

           call  lcd_data              ; (NEIN), dann Zeichen ausgeben

           rjmp  lcd_flash_string_1    ; Sprung zum nächsten Zeichen
                                       ; holen
lcd_flash_string_2:
           ret

Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja ich weis dass ich in nem reg nur 8 bit speichern kann deshalb frag 
ich ja hier nach wie cih das lösen kann. ich weis auch dass nur asci 
zeichen gespeichert werden können und da geht ja immer nur ein 
buchstabe. soviel weis ich auch! Des programm oben soll nur den gedanken 
verdeutlichen. lies mal den betreff dann weist du um was es geht!

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ähm statt ret natürlich rjmp sonstwohinzumbeispielneuentastereinlesen, 
ist ja mit Sprüngen gemacht und nicht mit Unterprogrammaufrufen.

Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thx stefan! so hab ich mir das auch gedacht aber ich hab halt gemeint ob 
vielleicht das geht so wie in c dass ich in ner variablen einen ganzen 
text speichern kann! Sowas nenn ich mal ne vernünftige antwort!

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In C speichert es in diesem Fall eigentlich auch nur eine Adresse in der 
Variable. Es erscheint dir so, als ob der Text dann dort drin steht. Die 
Fummelei mit Platz im Speicher für die eigentlichen Zeichen anlegen und 
Laden der Speicheradresse ins Arbeitsregister bei Zugriff ist bei C 
"versteckt". Du könntest (und solltest ruhig mal zu Lernzwecken) dir aus 
dem C ein ASM machen lassen (ASM-Listing oder ASM-Ansicht im Debugger) 
und wenn du dort nachsiehst, wirst du obiges Verfahren erkennen.

Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
des uprog lcd_flash_string ist das das selbe wie in der datei 
lcd_routines.asm oder?? weil dann könnt ich ja das weglassen oder?

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wahrscheinlich und wegen der Registerretterei sogar besser. Ich habe das 
gestrippte aus der ersten Antwort nur eingefügt, um zu zeigen, was 
ausgabe_menue machen muss. Du kannst mit Unterfunktion so arbeiten:

ausgabe_menue:
   rcall lcd_flash_string                         ; ausgeben
   rjmp sonstwohinzumbeispielneuentastereinlesen  ; fertig, nächste 
Taste?

Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
funktioniert das ganze dann mit einer einzelnen zahl?
also ich mein ich hab in ner variable eine zahl z.b. 5. ist ja weniger 
als 8 bit! kann ich die so verarbeiten wie ich oben schon gedacht hab?

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meinst du, ob du eine Zahl direkt in ein Register laden kannst? Ja das 
geht.

           ldi  temp1, $21

Lädt die hexadezimale Zahl $21 (=0x21 in C Schreibweise) in das 
Register, für das du den Namen temp1 vergeben hast. Andere Schreibweise 
mit 5 als Beispiel:

           ldi  temp1, 5

Im Wiki steht das unter
http://www.mikrocontroller.net/articles/Adressieru...

Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja das weis ich aber ich meinte dann mit dem variablenaufruf.
also:
daten:
 .db $temp, 0

wenn ich jetzt davor eine Zahl in temp geladen hab macht der des dann???

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das hängt von dem dir nicht angegebenen Teil ab.

Wenn das "Laden" ein Laden als Register bedeutet, d.h. temp als Name für 
ein Register steht, kommt nichts sinnvolles raus

.def temp = r16
ldi  temp, 5
daten:
 .db $temp, 0  ; ???? wäre ja  .db $r16, 0 nach der .def Regel

Wenn das Laden ein C-ähnliches Define (Textersetzung) bedeutet, also 
temp ein symbolischer Name für die Zahl 5 bedeuten soll, könnte es 
klappen.

Ich weiss nur nicht, ob der Hex-Prefix $ zum Bezeichner gehört, also ob 
der Assembler "$temp" sieht oder $"temp", bzw. befürchte ich dass es 
einen Syntaxfehler gibt weil Hex-Prefix + kein Zeichen aus 0-9A-F 
vorkommt.

.equ temp = 5
daten:
 .db $temp, 0  ; wäre dann .db $5

Bestimmt geht

.equ temp = $5
daten:
 .db temp, 0  ; wäre dann .db $5

Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also ich mein so
.def temp = r16    als beispiel
ldi temp = 5
daten:
.db temp, 0

geht des, dass dann das das gleiche ist wie

daten:
.db "5" , 0

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein geht so nicht. Du könntest mit direkter Adressierung arbeiten wie 
es bei 
http://www.mikrocontroller.net/articles/Adressieru... 
beschrieben ist.

Wenn du den Wert 5 bereits im Register temp (bzw. r16) hast, schreibst 
du den mit sts in den Speicher.

.def temp = r16    ; als beispiel

daten:
   .db 23, 0

   ldi temp, 5       ; daten sieht noch so aus:   23,0
   sts daten, temp   ; daten sieht danach so aus: 5, 0

Mit "" musst du aufpassen. "5" ist das ASCII-Zeichen 5. Das ist was 
anderes als das Byte 5.

.def temp = r16    ; als beispiel

daten:
   .db "5", 0

   ldi temp, 5       ; daten sieht noch so aus:   53,0
   sts daten, temp   ; daten sieht danach so aus: 5, 0

Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ah ok des is schlecht dass des net geht!!!

ich hab folgendes problem ich lass einen zähler laufen und die gezählte 
zahl soll im display erscheinen deshalb fragte ich wie des geht!!

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

Bewertung
0 lesenswert
nicht lesenswert
Bittte, bitte, bitte:
Schau ins Tutorial.

> lass einen zähler laufen und die gezählte
> zahl soll im display erscheinen deshalb fragte ich wie des geht!!

Auch das findest du im Tutorial: Wie man eine Zahl
so aufbereitet, dass man die einzelnen Stellen als
ASCII Code vorliegen hat und diese dann an ein LCD bzw.
an eine UART übergeben kann.

Es hat wirklich keinen Sinn, hier alles nochmal durchzukauen.
Wenn zum Tutorial Fragen bleiben dann stell sie. Das ist ok,
denn es hilft mir(uns) das Tutorial in diesen Punkten klarer
zu machen.

Danke.

Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich hab das ganze doch nach dem tut gebaut aber etwas anders deshalb hab 
ich hier gefragt ob es so auch geht!

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

Bewertung
0 lesenswert
nicht lesenswert
Wichtig: Lies auch die Teile vom Tutorial, die dich momentan
nicht interessieren. Sehr oft sind Techniken und Verfahren
in Artikeln versteckt, in denen man sie nicht vermutet.
zb. Ist besagte Zahlenausgabe sowohl im LCD Artikel als auch
im Uhrenartikel drinnen (und wahrscheinlich auch noch an
anderen Stellen).

Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also hier jetzt mal mein code der vorläufig so ist! ich hab eine 10 bit 
breite zahl und dann funktioniert das so nicht wie in dem tut!

adr_lcd:
  push  temp1
  push  temp2
  push  temp3

  mov  temp2, dmx_adrl
  mov  temp3, dmx_adrh
  ldi  hun, '0'
  ldi  ein, '0'
  ldi  zen, '0'
  rjmp lcd_number1

lcd_number1:
  subi  temp2, 100
  brcs  lcd_number2
  inc    hun
  rjmp  lcd_number1

lcd_number2:
  ldi    temp1, 0x02
  subi  temp2, -100
  cpi    temp3, 0x01
  add    hun, temp1
  rjmp  lcd_number3

lcd_number3:
  subi  temp2, 10
  brcs  lcd_number4
  inc    zen
  rjmp  lcd_number3

lcd_number4:
  ldi   temp1, 0x05
  subi  temp2, -10
  cpi    temp3, 0x01
  cpi    zen, 0x09
  rjmp  overflow_zen
  add    zen, temp1
  rjmp  lcd_number5

overflow_zen:
  ldi    zen, 0x00
  ldi    temp1, 0x01
  add    hun, temp1
  rjmp  lcd_number5

lcd_number5:
  ldi    temp1, 0x06
  add    ein, temp2
  cpi    temp3, 0x01
  cpi    ein, 0x09
  rjmp  overflow_ein
  add    ein, temp1
  pop    temp1
  pop    temp2
  pop    temp3
  rjmp  adr

overflow_ein:
  ldi    ein, 0x00
  ldi    temp1, 0x01
  add    zen, temp1
  pop    temp1
  pop    temp2
  pop    temp3
  rjmp  adr

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

Bewertung
0 lesenswert
nicht lesenswert
Big_Daddi wrote:
> ich hab das ganze doch nach dem tut gebaut aber etwas anders deshalb hab
> ich hier gefragt ob es so auch geht!

Wo ist dann das Problem.

> lass einen zähler laufen und die gezählte
> zahl soll im display erscheinen deshalb fragte ich wie des geht!!

Der Zähler ist in einem Register und im Tut gibt es
eine Funktion die den Inhalt eines Registers als Zahl
auf das LCD ausgeben kann.



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

Bewertung
0 lesenswert
nicht lesenswert
> also hier jetzt mal mein code der vorläufig so ist! ich hab eine 10 bit
> breite zahl und dann funktioniert das so nicht wie in dem tut!

Doch, das tut es.
Nur nicht direkt.

Aber du kannst dir vom Tutorial das Prinzip abschauen wie
man das macht.

Dein Code schaut doch gar nicht so schlecht aus.
Nur musst du berücksichtigen, dass
* es auch Tausender gibt (10 Bit: größte Zahl == 1023)
* du anstelle von nur 8Bit Arithmetik eine 16Bit Arithmetik
  machen musst (weil die Zahl ja in 2 Registern verteilt ist)

  Das Registerpärchen temp2/temp3 beschreibt bei dir eine 16 Bit
  Zahl.
  Um da 100 abzuziehen, musst du die Operation natürlich in
  16 Bit machen:

  subi  temp2, 100     // low Byte
  sbci  temp3, 0       // High Byte

Der sbci temp3, 0 mag seltsam aussehen. Was soll es bringen
0 abzuziehen. Dazu muss man aber berücksichtigen, dass ja nicht
nur die 0 abgezogen wird, sondern auch das Carry Bit, welches
gesetzt wird wenn im unmittelbar vorhergehenden subi ein Unterlauf
entstanden ist.


-> Siehst du: Steht schon auf meiner TODO Liste:
   Tutorial - LCD Funktionen - 16 Bit Zahlen ausgeben

Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jetzt kommen wir der sache schon näher! ne die zahl geht max bis 511! 
also reichen mir 9 bit!

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

Bewertung
0 lesenswert
nicht lesenswert
Big_Daddi wrote:
> jetzt kommen wir der sache schon näher! ne die zahl geht max bis 511!
> also reichen mir 9 bit!

OK. Dann kannst du die Tausender weglassen.
Ändert aber nichts an der Tatsache, dass du zum abzählen
der Hunderter mit 16 Bit Arithmetik arbeiten musst.


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

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
> Big_Daddi wrote:
>> jetzt kommen wir der sache schon näher! ne die zahl geht max bis 511!
>> also reichen mir 9 bit!
>
> OK. Dann kannst du die Tausender weglassen.
> Ändert aber nichts an der Tatsache, dass du zum abzählen
> der Hunderter mit 16 Bit Arithmetik arbeiten musst.

Nachdem du die Hunderter bearbeitet hast, kannst du
wieder bei 8 Bit Arithemtik bleiben. Denn wenn die
Hunderter erledigt sind, dann ist das 9. Bit schon
mit Sicherheit eine 0 und die übrig gebliebene Zahl
ist nur noch im Register temp2.
Nach Bearbeiten der Hunderter bleibt ja nach den
ganzen Subtraktionen nur noch eine Zahl <100 übrig.

Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
warum ne null??? wenn das 9. bit 1 ist dh 256 dann muss ich doch noch 
bei den zehner 5 dazu zählen oder nicht??

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

Bewertung
0 lesenswert
nicht lesenswert
Big_Daddi wrote:
> warum ne null??? wenn das 9. bit 1 ist dh 256 dann muss ich doch noch
> bei den zehner 5 dazu zählen oder nicht??

Nein.

Wenn du wissen willst, weiviele Hunderter in 387 enthalten
sind, dann musst du schon von 387 jeweils 100 abziehen
und nicht nur von dem Teil der Zahl der kleiner als 256
ist.


Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja des is klar ich hab mir nur des so gedacht also wenn bit 9 gesetzt 
ist dann zähl 2 bei den hunderter 5 bei den zehner und 6 bei den einern 
dazu! Also des war halt mein grundgedanke.

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

Bewertung
0 lesenswert
nicht lesenswert
Big_Daddi wrote:
> ja des is klar ich hab mir nur des so gedacht also wenn bit 9 gesetzt
> ist dann zähl 2 bei den hunderter 5 bei den zehner und 6 bei den einern
> dazu! Also des war halt mein grundgedanke.

Machs nicht unnötig kompliziert durch die einführung
von Spezialfällen.

> 2 bei den hunderter 5 bei den zehner und 6 bei den einern
und dann musst du wieder berücksichtigen, dass die 6 bei den
Einern wieder einen Überlauf in die Zehner produzieren
können, die ihrerseits wieder einen Überlauf in die Hunderter
produzieren können.
Und dann gilt das Ganze nur bei 9 Bit Zahlen, wenn du aber mal
mehr hast (10 Bit), dann kannst du diese Spezialfunktion auf
den Müll werfen und dafür wieder eine Spezialfunktion schreiben.

Mit 16 Bit Arithmetik ist das doch viel einfacher. Es folgt
nach wie vor dem bewährten Muster:

    10000-er zählen, indem 10000 abgezogen wird bis etwas
                     kleiner als 0 erreicht wird.

    1000-er zählen, indem 1000 dazugezählt wird bis etwas
                    größer als 0 erreicht wird

    100-er zählen, indem 100 abgezogen wird bis etwas
                   kleiner als 0 erreicht wird

    10-er zählen, indem 10 dazugezählt wird bis etwas
                  größer als 0 erreicht wird

    1er zählen, ... die braucht man nicht zählen, die bleiben
                    übrig.

Alles was dazu nötig ist, ist das man die Arithmetik von 8
Bit auf 16 Bit bringt. Dafür ist der Prozessor in Form des
Carry Bits vorbereitet.

(Nicht vergessen: Auch die Vergleiche auf kleiner/größer 0
müssen in 16 Bit ausgeführt werden. Das ist aber einfach, denn
das Vorzeichen ist immer im Highbyte das höchstwertige Bit,
es reicht also eine Abfrage mit dem HighByte aus temp3)



Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Sourcecode kann ich so nicht zuordnen bzw. mit deiner Zählerei in 
Einklang bringen. Ist das vorhandener Code, den du für deine Zwecke 
anpassen willst?

Es könnte sich um einen Teil einer Unterroutine handeln, die anscheinend 
eine 16-Bit (10 Bit valid?) DMX Adresse (dmx_adrh, dmx_adrl) in eine 
dreistellige dezimale Zahl (hun, zen, ein) aufsplittet.

Die Ausgabe an sich müsste straightforward sein. Die in Registern 
gehalteten Ziffern hun, zen, ein sind bereits durch den Startwert '0' so 
angelegt, dass sie direkt und nacheinander als Ziffer aufs LCD 
ausgegeben werden können.

Wenn man hun, zen, ein unbedingt im RAM speichern möchte und eine 
Zeichenkette ausgeben will, könnte man so vorgehen (obiges Beispiel 
weiterverwendet):

daten:
daten_hun:
   .db "H"
daten_zen:
   .db "Z"
daten_ein:
   .db "E"
   .db 0

; neues adr
adr:
   sts daten_hun, hun ; speicher <= register
   sts daten_zen, zen
   sts daten_ein, ein

Und dann kann man die komplette Ziffernfolge an der Adresse daten 
ausgeben

   ldi ZL, LOW(daten*2)
   ldi ZH, HIGH(daten*2)
   rcall lcd_flash_string
   ; ... alter Code ab adr ...




Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@stefan:
ne der code ist der code den ich geschrieben hab. g sorry bin noch 
nicht so erfahren damit! Ich will mich dadurch eigentlich ein wenig in 
die mcte einarbeiten da ich des ganze nur theoretisch lern!

@Karl Heinz:
ja das mit dem überlauf hab ich zwar schon abgefangen aber nicht 
komplett. ich schau jetzt einfach mal dass ich des ganze nach deinen 
vorschlägen versuch.

Autor: Big_Daddi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist es dann so eher richtig?

adr_lcd:
  push  temp1
  push  temp2
  push  temp3

  mov  temp2, dmx_adrl
  mov  temp3, dmx_adrh
  ldi temp1, '0'

lcd_number1:
  subi  temp2, 100
  sbci  temp3, 0
  brcs  lcd_number2
  inc    temp1
  rjmp  lcd_number1

lcd_number2:
  rcall  lcd_data
  subi  temp2, -100


  ldi  temp1, '0'

lcd_number3:
  subi  temp2, 10
  brcs  lcd_number4
  inc    temp1
  rjmp  lcd_number3

lcd_number4:
  rcall  lcd_data
  subi  temp2, -10

  ldi  temp1, '0'
  ldi  temp1, temp2
  rcall  lcd_data

  pop  temp1
  pop  temp2
  pop  temp3

  ret

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

Bewertung
0 lesenswert
nicht lesenswert
Big_Daddi wrote:
> Ist es dann so eher richtig?
>
> adr_lcd:
>   push  temp1
>   push  temp2
>   push  temp3
>
>   mov  temp2, dmx_adrl
>   mov  temp3, dmx_adrh
>   ldi temp1, '0'
>
> lcd_number1:
>   subi  temp2, 100
>   sbci  temp3, 0
>   brcs  lcd_number2
>   inc    temp1
>   rjmp  lcd_number1
>
> lcd_number2:
>   rcall  lcd_data

Ich kanns hier nicht ausprobieren (mangels Hardware und
Emulator), aber das sieht schon mal nicht schlecht aus.

Was passiert wenn du das laufen lässt?

(muss jetzt leider weg. Ich schau spätestens morgen wieder rein).

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.