Problem mit Übertragung an LCD-Display

OP #2186051
Lesenswert?

Hallo Forum,

zurzeit arbeite ich an einem Schulprojekt, vorgenommen habe ich mir 
mithilfe eines uC einen digitalen Drehzahlmesser für einen Zweitaktmotor 
zu bauen.
(Hab hier im Forum schon viel darüber gelesen sowie auch auf anderen 
Seiten und fand es ein interessantes Projekt)
Das Programm MUSS leider in ASM geschrieben werden.

Hier der Stand:
Das Zündsignal kommt auf einen Interrupt, ein Timer zählt eine Sekunde 
lang die Impulse, die Anzahl wird mit 60 Multipliziert und (sollte) 
anschliessend aufs Display ausgegeben (werden).

Das Problem:
Nach dem Multiplizieren von A- und B-Register landet das Ergebnis 
aufgeteilt in Lower Byte (A) und Higher Byte (B) wieder in den 
Registern. Nun kann ich aber immer nur 8 Bit an das Display übertragen.
Bsp:
A = 5
B = 60
A*B = 300 => B=01h (256d), A=2Ch (44d)

Ich müsste also irgendwie das 16Bit ergebnis der Multiplikation in seine 
einzelnen Stellen aufteilen und nacheinander auf dem Display ausgeben, 
oder so irgendwie.
Hat da jemand einen Rat wie ich das am besten lösen könnte?

Mfg Tobias
#2186077
Lesenswert?

@  Tobias B. (betsch)

>Registern. Nun kann ich aber immer nur 8 Bit an das Display übertragen.

Reicht das nicht? Du kannst auch keinen Satz auf einmal übertragen, 
immer nur einzelene Buchstaben bzw. Zeichen.

>Ich müsste also irgendwie das 16Bit ergebnis der Multiplikation in seine
>einzelnen Stellen aufteilen

Ist es doch schon nach deiner Aussage.

> und nacheinander auf dem Display ausgeben,

Und wo ist das Problem?

>Hat da jemand einen Rat wie ich das am besten lösen könnte?

Du musst sogar noch mehr. Du must die Binärzahl in eine Zeichenkette 
umwandeln. Siehe Festkommaarithmetik.

MFG
Falk
Gast #2186304
Lesenswert?

Ich würde es mit einer "lookup table" lösen.
Also den über 1 sek. gezählten Wert gar nicht mit 60 multiplizieren, 
sondern als Index auf ein String array benutzen:

0 -> "0000"
1 -> "0060"
2 -> "0120"
3 -> "0180"
(...)
166 -> "9960"

mehr als 10000 U/min wird der Motor ja nicht machen...
Gast #2186320
Lesenswert?

Und noch ein Tip:
für Drehzahlmessungen ist es besser, einen Timer zu nehmen (z.B. mit 10 
kHz), und die Zeit, die zwischen 2 Umdrehungen vergeht in U/min 
umzurechnen.
Dann hast du ein feingradigeres Ergebnis, statt grober 60 U/min-Stufen.
OP #2187338
Lesenswert?

Vielen dank für die Vorschläge.
Ich glaube die Lösungen von Falk und Manfred sind leider nicht 
umsetzbar, da ich nur das A-Register durch das B-Register dividieren 
kann, und da maximal 255 reinpasst. Ich bräuchte also für diese Lösung 
einen Speicherplatz für 16Bit, mit dem ich auch rechnen kann.

Also wird eswohl die lösung von kolabier. So hatte ich es auch Anfangs 
geplant, falls die andere Methode nicht lösbar ist.
Aber mit nem kleinen Unterschied:

Ich bekomme ne Routine für Textausgabe am Display zur verfügung 
gestellt, diese funktioniert so:
1
mov dptr, #1_umdr_pro_sek
2
lcall LCDTextZeile1

Für die einzelnen Werte hätte ich dann geplant:
1
#1_umdr_pro_sek:
2
db '   60 rpm', 0
3
#2_umdr_pro_sek:
4
db '  120 rpm', 0
5
etc.

Ich denke die Lösung ist nicht so gut wie die mit dem String-Array, nur 
leider hab ich keine Ahnung wie man String-Arrays in Assembler 
deklariert/benutzt/etc.

Ich weiss, dass man irgend eine Anfangsadresse festlegt, bsp 0000h und 
dann in 16er Schritten die einzelnen Strings ablegt um danach mit nem 
Zeiger drauf zuzugreifen, aber kein Plan wie man das in ASM macht. :(

MFG
#2187377
Lesenswert?

Tobias B. schrieb:
> Ich glaube die Lösungen von Falk und Manfred sind leider nicht
> umsetzbar, da ich nur das A-Register durch das B-Register dividieren
> kann, und da maximal 255 reinpasst. Ich bräuchte also für diese Lösung
> einen Speicherplatz für 16Bit, mit dem ich auch rechnen kann.

Da musst Du halt mit 2 Registern für eine Variable arbeiten :)

mit
  Var_xy:2
reserviert Dir der Compiler zwei aufeinander folgende Register,
Var_xy = LoByte
Var_xy+1 = HiByte (die Var.Namen sind ja nur Platzhalter im 
Assemplercode
                   für die reellen Registeradressen)

Hier ein Beispiel für eine 16Bit Addition mit 8Bit breiten Registern
1
Add16                           ; 16-bit add: f := f + xw
2
        movf    Math_Temp2,W    ; Math_Temp2 nach W
3
        addwf   Math_Temp1,F    ; Math_Temp1 := Math_Temp1 + Math_Temp2
4

5
        movf    Math_Temp2+1,W  ; Math_Temp2+1 nach W
6
        btfsc   STATUS,C        ; fall ein Überlauf auftrat:
7
        incfsz  Math_Temp2+1,W  ; Math_Temp2+1+1 nach W
8
        addwf   Math_Temp1+1,F  ; Math_Temp1+1 := Math_Temp1+1 + Math_Temp2+1
9

10
        return                  ; fertig

mfg
Manfred
Gast #2191508
Lesenswert?

Hallo Manfred,

ich versteh zwar was du meinst, bin mir aber nicht sicher ob sich das so 
umsetzen lässt. Übrigens, der Controller ist ein AT89C5131, und die 
Befehle die du verwendest hab ich auch nicht, mir steht nur "mov", 
"movx" und "movc" zur Verfügung.

Was ich bisher auch noch nicht erwähnt habe: So wie ich es ursprünglich 
vor hatte war geplant die LCD Routine "LCDDezAus" zu benutzen, welche 
die 8Bit die im Akku stehen als Dezimalzahl auf dem Display ausgibt.

Bsp: Die Anzahl der in 1 sek gemessenen Impulse beträgt mit 60 
Multipliziert 400d (0190h), nach der Operation steht also 01h in B und 
90h in A.

Den Pseudocode stell ich mir in etwas so vor:
1
WENN ((0*16^3) + (1*16^2) + (9*16^1) + (0*16^0) / 1000) > 1
2
   AUSGABE AN POS1 (0*16^3) + (1*16^2) + (9*16^1) + (0*16^0) / 1000)
3
WENN (0*16^3) + (1*16^2) + (9*16^1) + (0*16^0) % 1000) / 100) > 1
4
   AUSGABE AN POS2 (0*16^3) + (1*16^2) + (9*16^1) + (0*16^0) / 100)
5
WENN (0*16^3) + (1*16^2) + (9*16^1) + (0*16^0) % 100) / 10 > 1
6
...
7
etc

Und genau diese Operation, "IST B-Register + A-Register > IRGENDWAS" 
bekomm ich glaub ich nicht gebacken :(

mfg
#2191631
Lesenswert?

Moin moin,

Tobias B. schrieb:
> ich versteh zwar was du meinst, bin mir aber nicht sicher ob sich das so
> umsetzen lässt. Übrigens, der Controller ist ein AT89C5131, und die
> Befehle die du verwendest hab ich auch nicht, mir steht nur "mov",
> "movx" und "movc" zur Verfügung.

das ist ein aus meinem momentanen Projekt kopierter, funktionierender 
Code für einen PIC16F.... der Dir nur mal den  grundsätzlichen Umgang 
mit Zahlen größer als die Bitbreite des verwendeten µC's zeigen soll.
Ok, Pseudocode hätte es anschaulicher gemacht, war aber zu faul, sorry 
:)


Tobias B. schrieb:
> Und genau diese Operation, "IST B-Register + A-Register > IRGENDWAS"
> bekomm ich glaub ich nicht gebacken :(

BReg + AReg = CReg
CReg - IRGENDWAS ; erzeugt einen Unterlauf bei CReg ist kleiner...
test des zuständigen Flgs (CarryFlag)
....


mfg
OP #2192114
Lesenswert?

Tach,

> BReg + AReg = CReg
> CReg - IRGENDWAS ; erzeugt einen Unterlauf bei CReg ist kleiner...
> test des zuständigen Flgs (CarryFlag)

genau hier ist mein Problem, quasi. Sowohl B und A haben jeweils 8 Bit, 
wenn die addiere brauch ich auf jeden Fall mehr als 8 Bit speicher um 
die Zahl irgendwo zu speichern. Das hab ich ja nicht.

Ich hab mal ne Testsimulation gemacht:
1
mov B, #60d
2
mov A, #05d
3
mul AB           ;danach steht in B 01h und in A 2Ch
4
add A,B          ;danach steht in B immernoch 01h in A aber 2Dh

Hierbei ignoriere ich ja, dass B das HiByte is und bei 16^2 anfängt.

mfg
#2192366
Lesenswert?

installiere Var C und C+1 ; C:=LoBit, C+1:=HiBit

a + b = c ; LoBit
Test CarryFlag
wenn ja dann increment c+1 ; HiBit

wie das mit Multiplikation bei Deinem Prozessor genau funst weiß ich 
nicht, sollte aber ein SpezialRegister geben der das HiByte aufnimmt o. 
Hi im ersten Argument, Lo im zweiten ö.ä.
Muss ja irgend wo hin der ÜBERSCHÜSSIGE Müll :)


Tobias B. schrieb:
> mov B, #60d
> mov A, #05d
> mul AB           ;danach steht in B 01h und in A 2Ch
> add A,B          ;danach steht in B immernoch 01h in A aber 2Dh

bitte bleib bei einer Zahlendarstellung (d o. h) bin'n Alter Man und hab 
nich mehr so viele Gehirnzellen übrig für's umrechnen :)


mfg

EDIT:
Gug mal den Thread "rechnen in Assembler mit AVR"
Beitrag "rechnen in Assembler mit AVR"
Die kennen dich sicher besser aus als ich!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren