Archiv verlassen und diese Seite im Standarddesign anzeigen : Zahl in Ziffern zerlegen
Hallo
Wie heisst der Befehl, der eine Zahl in einzelne Ziffern zerlegt? Und wie wird dieser angewendet? Die Zahl ist max. 4 Ziffern lang, sie kann aber auch kleiner sein.
mfg Luca
Edit: Dass man nicht den ganzen Thread durchwüllen muss, poste ich hier mal den Code, er ist in Bascom, und man kann damit eine Zahl mit 4 Ziffern in Ziffern zerlegen.
Dim Einer As Word
Dim Zehner As Word
Dim Hunderter As Word
Dim Tausender As Word
Dim A As Word
A = 8956
Einer = A Mod 10
A = A - Einer
A = A / 10
Zehner = A Mod 10
A = A - Zehner
A = A / 10
Hunderter = A Mod 10
A = A - Hunderter
A = A / 10
Tausender = A Mod 10
Print tausender '8
Print hunderter '9
Print zehner '5
Print einer '6
linux_80
01.08.2006, 18:34
Hallo,
was willst Du nachher damit machen, wenn Du sie über die UART senden willst, einfach die Variable mit Print ausgeben, da wird sie automatisch gewandelt.
Ansonsten schaust Dir mal str() an.
Hallo
Ich muss die Zahl zerlegen, damit ich sie nachher auf 4 Siebensegment (Rndigi)anzeigen, anzeigen lassen kann. Die Zahlen werden per I2C gesendet.
Wie wird str() angewendet?(Beispiel?)
Ich hätte die Ziffern dann gerne in variabeln.
mdg Luca
In der Bascom Hilfe steht der Befehl eigentlich gut beschrieben. Schau da mal nach. Das Forum liefert dir den Tip und dann muss Eigeninitiative gezeigt werden.
molleonair
01.08.2006, 20:29
ich hab das auch mal mit ner 7 segment gemacht
einfach die zahl (zb 8763) durch 1000 dann haste die 1.ziffer (8)
dann 1.ziffer mal 1000 (=8000) und von deiner zahl abziehen (8763-8000=763)
nun diese zahl durch 100 (=7) wieder mal 100 (=700) und die von der vorihgen abzihen (763-700=63) nun diese durch 10 und so weiter ...
ich hab das auch mal mit ner 7 segment gemacht
einfach die zahl (zb 8763) durch 1000 dann haste die 1.ziffer (8)
dann 1.ziffer mal 1000 (=8000) und von deiner zahl abziehen (8763-8000=763)
nun diese zahl durch 100 (=7) wieder mal 100 (=700) und die von der vorihgen abzihen (763-700=63) nun diese durch 10 und so weiter ...
Wobei zu beachten ist, das Divisionen und vor allem Kommaberechnungen bei AVR Mikrocontrollern recht lange dauern.
Einfacher und schneller ist die sogenannte Subtraktionsmethode um aus dieser Zahl die einzelnen Ziffern zu bekommen (Binär -> BCD Wandlung).
Grüße,
da Hanni.
Hallo
An die Hilfe hatte ich nicht gedacht. Diese Funktion wandelt aber einfach z.B. ein Byte zu einem String um oder? Wie aber kann ich den String nun zerlegen?
Hier ein Beispiel, wie ich die Zahl nachher gerne hätte:
A = 1354 'grundwert
...... 'Befehl
B = 4 'Zahl 1
C = 5 'Zahl2
D = 3 'Zahl3
E = 1 'Zahl4
@molleonair
Als Notlösung währe das möglich, aber dass geht sicher einfacher.
@Hanni
Leider verstehe ich bei der Hilfe für BCD nur Banhof.
mfg Luca
digitali
01.08.2006, 21:31
Also ich haette es so spontan gemacht:
Zunächst die ganze Zahl als String umwandeln:
Zahl_String= Str(Zahl)
Laenge des Strings ermitteln:
LZ = Len(Zahl_String)
Einzelne Zeichen aus Gesamtstring ermitteln:
For A = 1 To LZ
EZ(a) = Mid( Zahl_String, A , 1)
Next A
Einzelne Zeichen in numerische Werte umwandeln:
For A = 1 To LZ
Ew(a) = val(EZ(a))
Next A
Und somit haste die einzelnen Ziffern zur weiteren Verwendung.
Oder gab's einen direkten Befehl? Keine Ahnung, einfach die Bascom-Hilfe studieren. Da steht alles.
linux_80
01.08.2006, 21:39
hui,
besser gehts in etwa so:
DIM MyString AS STRING * 20
DIM MyArray(21) AS BYTE AT MyString OVERLAY
macht nicht soviel arbeit.
Man muss nur noch schauen wie lange der String wirklich geworden ist, damit man keinen Müll weiterverarbeitet.
Und daran denken, das die Zahlen als ASCII-Werte dastehen, d.H. 48 abziehen damit die 0 auch 'ne 0 ist !
Moin,
A = 1354
tausender = A / 1000
tausender = tausender mod 10
hunderter = A / 100
hunderter = hunderter mod 10
zehner = A / 10
zehner = zehner mod 10
einer = A mod 10
In den Variablen tausender, hunderter, zehner und einer stehen dann Deine einzelnen Ziffern.
Viele Grüße,
Bruno
Hallo
Danke Digitali für das Beispiel.
Auch wenn dass für euch ein bisschen nervig ist, leider habe ich nicht sehr viel Ahnung von Basic, darum frage ich so viel.
Nur zur Kontrolle ob ich denn Code von Digitali richtig verstanden habe:
Zahl_String = Anfangs Zahl, nachher String Zahl
LZ = Länge der Zahl
EZ(A) = Einzelne Zeichen
Ew(a) = Endgültige Ziffer
Zahl ist meine ZAhl
Zahl_String muss ich als String definieren?
Lz muss ich als Integer definieren?
Ez ebenso?
Ew auch als Integer?
Stimmt das?
Wenn ich jetzt Zahl_String als String definiere, dann muss man da noch “* (eine Zahl)“ eingeben, für was ist dass? Was muss ich beim obigem Beispiel einstellen?
Wenn ich nun alles so wie oben eingestellt habe, dann meldet Bascom 3 Fehler:
EZ(a) = Mid( Zahl_String, A , 1) Fehler: String expected for assignment [EZ(A)]
Ew(a) = val(EZ(a)) Fehler: Variable is not dimensioned as an array [EZ(A)]/[EW(A)]
Was muss ich ändern, dass diese Fehler verschwinden
mfg Luca
Ps: Sorry für die endlose Fragerei.
@ Lynux 80
Wie kann ich dann die länge bestimmen? In welcher variabel sind dann meine Zahlen?
@Bruno Pisarek
Kann ich dass so einfach ins Bascom übernehmen? Als was muss ich "A" definieren?
Also das Beispiel von Bruno Pisarek gefällt mir am besten, da es einfach ist.
mfg Luca
digitali
01.08.2006, 22:10
Nimm das Beispiel von Bruno. Er hat's wesentlich eleganter geloest. :)
Kann ich dass so einfach ins Bascom übernehmen? Als was muss ich "A" definieren?
Hi Luca,
ja - ist alles 100% Bascom, ich benutze diese Variante in sehr vielen Projekten. Wenn Du bei 4 Stellen bleibst, dann deklariere alle Variablen als Typ "Word".
Viele Grüße,
Bruno
Nimm das Beispiel von Bruno. Er hat's wesentlich eleganter geloest. :)
Wenn Du das so machst, wie der Hanni es beschrieben hat, ist es nicht nur elegant, sondern noch effektiv.
Gruß Sebastian
Moin,
A = 1354
tausender = A / 1000
tausender = tausender mod 10
hunderter = A / 100
hunderter = hunderter mod 10
zehner = A / 10
zehner = zehner mod 10
einer = A mod 10
Meiner Meinung nach effizienter müsste folgender Code sein:
A = 1354
einer = A mod 1
zehner = A mod 10
zehner = zehner - einer
hunderter = A mod 100
hunderter = hunderter - zehner
tausender = A mod 1000
tausender = tausender - hunderter
Eine Division wird im Controller ja nur als mehrfache Subtraktion durchgeführt (behauptet zumindest unser Lehrer), deshalb sollten hier weniger Schritte benötigt werden.
Hallo
Dann werde ich wohl die variante von Bruno gebrauchen, da sie wie schon erwähnt einfach, elegant und effektiv ist.
Ich danke hier aber auch allen anderen, die mir helfen wollten =D>
Eine Frage noch an Bruno, was ist wenn ich es erweiter will auf z.B. 6 Ziffern? Wass muss ich alles abändern?
mfg Luca
bei Brunos Lösung wüsste ich es nicht, allerdings bei meiner kann man leicht erweitern, einfach unten
zehntausender = A mod 10000
zehntausender = zehntausender - tausender
usw. anfügen =)
Eine Frage noch an Bruno, was ist wenn ich es erweiter will auf z.B. 6 Ziffern? Wass muss ich alles abändern?
Hi Luca,
die Prozedur ist so einfach, dass sich eigentlich mehr als 4 Stellen daraus ableiten lassen sollten - oder 8-[ ?
Ich bin der Meinung, dass Du auch selbst ein bisschen denken solltest und natürlich probieren!
Z.B. hat mich das Posting von Sebastian dazu veranlasst, Morgen auch mal die Hanni/Sebastian Version zu probieren. Wenn es ein paar Byte spart - prima! Ist mir nie in den Sinn gekommen..
Aber in Deinem Fall kommst Du mit meinem leicht zu erweiternden Beispiel auch ressourcenschonend und schnell ans Ziel.
Viele Grüße,
Bruno
Moin,
A = 1354
tausender = A / 1000
tausender = tausender mod 10
hunderter = A / 100
hunderter = hunderter mod 10
zehner = A / 10
zehner = zehner mod 10
einer = A mod 10
In den Variablen tausender, hunderter, zehner und einer stehen dann Deine einzelnen Ziffern.
Viele Grüße,
Bruno
Nunja. die Modulo Operatoren wären insofern sehr effektiv, wenn man sie direkt isn duale Zahlensystem übernehem könnte. Kann man aber leider nicht ... daher ist der Code eher sehr ineffizent und langsam.
Effektiv und Elegant ist es nicht deswegen, weil der Code schön aussieht. Effektiv wird es erst dann, wenn eine Aufgabe mit minimalem Aufwand an Ressourcen erledigt wird. Die Eleganz kommt meiner Meinung nach daher, dieses ganze Gebilde in eine kleinen Subroutine zu verbannen, damit ich sie immer, wann ich sie brauche nutzen kann.
Sicherlich kann man auf einem PC mit endlos krassen Resourcen derartige Codemonster realisieren (mach ich selbst gerne aber halt in ner Skriptsprache) aber auf einem Microcontroller ist dieses eher fehl am Platz.
Mir scheint es daher, das das Programmieren in einer Hochsprache zuweilen vergessen lässt, das man nur sehr geringe Ressourcen im µC zur Verfügung hat.
Wenn Du das so machst, wie der Hanni es beschrieben hat, ist es nicht nur elegant, sondern noch effektiv.
Danke für die zustimmenden Worte.
Grüße,
da Hanni.
Hallo
Leider funktioniern bei mir beide varianten nicht. Ich habe die erhaltene Zahl als Byte gespeichert, könnte es an dem liegen? Ich bin mir nicht ganz sicher, aber ich glaube die Zahl kann nur in einem Byte gespeichert werden, dass das Programm für die Anzeigen funktioniert. Hier mal den ganzen code, vileicht habe ich ja sonst wo einen Fehler.
Declare Sub Led_display_init()
Declare Sub Led_display(byval Ziffer As Byte , Byval Zahl As Byte)
$regfile = "m32def.dat"
Const Rn_digi_slave_write = &H70
Const Rn_digi_slave_read = &H71
Const Dezimalpunktziffer = 0 'Segment wo Dezimalpunkt leuchten soll (0=keinen)
Dim Segmente As Byte
Dim Z As Byte
Dim I As Byte
Dim Einer As Byte
Dim Zehner As Byte
Dim Hunderter As Byte
Dim Tausender As Byte
Dim A As Word
$crystal = 16000000 'Quarzfrequenz
$baud = 9600
Config Scl = Portc.0 'Ports fuer IIC-Bus
Config Sda = Portc.1
I2cinit
Led_display_init
I = 0
Sound Portd.7 , 400 , 450 'BEEP
Sound Portd.7 , 400 , 250 'BEEP
Sound Portd.7 , 400 , 450 'BEEP
Print
Print "**** RN-CONTROL V1.4 *****"
Print "Das neue Experimentier- und Roboterboard"
Print
Do
A = 1245
einer = A mod 1
zehner = A mod 10
zehner = zehner - einer
hunderter = A mod 100
hunderter = hunderter - zehner
tausender = A mod 1000
Tausender = Tausender - Hunderter
Print ; Tausender ; Hunderter ; Zehner ; Einer;
Print
Waitms 500
Led_display 1 , Tausender 'Anzeigen der Zahlen
Led_display 2 , Hunderter
Led_display 3 , Zehner
Led_display 4 , Einer
Loop
End
Sub Led_display_init()
I2cstart
I2cwbyte Rn_digi_slave_write
I2cwbyte 0 'Control Byte
'Dynamic Alternative Mode und Helligkeit
'Die oberen 3 Bits bestimmen die Helligkeit
'Wenn es dunkler sein soll dann z.b. &B0110111
I2cwbyte &B0110111
I2cstop
'Alle Ziffern auf 0
For Z = 1 To 4
Led_display Z , 0
Next Z
End Sub
Sub Led_display(ziffer An Byte , Zahl As Byte)
I2cstart
I2cwbyte Rn_digi_slave_write
I2cwbyte Ziffer
Select Case Zahl
Case 0:
Segmente = &H3F
Case 1:
Segmente = &H06
Case 2:
Segmente = &H5B
Case 3:
Segmente = &H4F
Case 4:
Segmente = &H66
Case 5:
Segmente = &H6D
Case 6:
Segmente = &H7D
Case 7:
Segmente = &H07
Case 8:
Segmente = &H7F
Case 9:
Segmente = &H67
Case Else :
Segmente = &H80 'Ansonsten Dezimalpunkt
End Select
If Dezimalpunktziffer = Ziffer Then Segmente = Segmente Or &H80
I2cwbyte Segmente
I2cstop
End Sub
anstatt der 1245 werden über Print 2012010 ausgegeben.
Das Display zeigt auf den ersten 2 Segmenten einen Dezimal Punkt an, dass heisst dass er keine Zahl bekommt. Auf dem 3ten Segment wird eine 1 angezeigt, auf dem ganz rechts eine 0.
Was mache ich falsch?
mfg Luca
Z.B. hat mich das Posting von Sebastian dazu veranlasst, Morgen auch mal die Hanni/Sebastian Version zu probieren. Wenn es ein paar Byte spart - prima! Ist mir nie in den Sinn gekommen
Schön, daß Du es ausprobieren willst :-)
Ich wollte Deinen Lösungsvorschlag auch nicht abwerten (sollte jemand es gedacht haben) Es ist sicher schnell geschrieben und für Anfänger verständlich.
Der Hanni hat ja schon die Gründe genannt, warum es mit subtrahieren schneller geht.
Gruß Sebastian
Meiner Meinung nach liegt der Fehler in der deklaration von A im typ Word. Soweit ich das jetzt gefunden habe kann man diesen Datentyp nur mit 1 und 0 belegen, was für diesen Fall zuwenig wäre. Bin allerdings auch nicht wirklich fit in Basecom, kenn mir nur mitm Algorithmus aus ;)
A = 1245
einer = A mod 1
zehner = A mod 10
zehner = zehner - einer
hunderter = A mod 100
hunderter = hunderter - zehner
tausender = A mod 1000
Tausender = Tausender - Hunderter
Dort liegt übrigens der Hund begraben ...
Vielleicht einige Worte zur Erklärung:
Der Modulo Operator besorgt mir den Rest einer Division durch x.
Damit ergibt sich nach deiner Rechnung:
einer = 0
zehner = 5
hunderter = 40
tausender = 205
Damit hast du defakto einen Denkfehler drinne.
Grüße,
da Hanni.
Hallo
Sorry, stimt natürlich, hab den Algorithmus nur im Kopf zusammengestellt, ihn dabei allerdings nicht wirklich nachgerechnet. Nach einigen Modifikationen sieht er ähnlich aus wie Brunos, funktionieren müsste er auch.
einer = A mod 10
A = A - einer
A = A / 10
zehner = A mod 10
A = A - zehner
A = A / 10
hunderter = A mod 10
A = A - hunderter
A = A / 10
tausender = A mod 10
Hallo
Also die 2t variante von simonit funktioniert, wenn ich die Ziffern dann in Integer speichere. Aber ich muss leider die Zahl in ein Byte speichern, da es dem Prog. sonst nicht passt. Wenn ich sie in ein Byte speichere, dann bekomme ich z.B. anstatt 8569, 8481. Auch wenn ich andere Zahlen verwende, dann stimmt der Tausender immer. Ich habe mal nur eine 3stellige Zahl eingegeben und er hatt immer die erste Zahl richtig gemacht, die 2te manchmal richtig und die erste immer falsch. Wie kann ich dass beheben?
Hier noch der neue code:
Declare Sub Led_display_init()
Declare Sub Led_display(byval Ziffer As Byte , Byval Zahl As Byte)
$regfile = "m32def.dat"
Const Rn_digi_slave_write = &H70
Const Rn_digi_slave_read = &H71
Const Dezimalpunktziffer = 0 'Segment wo Dezimalpunkt leuchten soll (0=keinen)
Dim Segmente As Byte
Dim Z As Byte
Dim I As Byte
Dim Einer As Byte
Dim Zehner As Byte
Dim Hunderter As Byte
Dim Tausender As Byte
Dim A As Word
$crystal = 16000000 'Quarzfrequenz
$baud = 9600
Config Scl = Portc.0 'Ports fuer IIC-Bus
Config Sda = Portc.1
I2cinit
Led_display_init
I = 0
Sound Portd.7 , 400 , 450 'BEEP
Sound Portd.7 , 400 , 250 'BEEP
Sound Portd.7 , 400 , 450 'BEEP
Print
Print "**** RN-CONTROL V1.4 *****"
Print "Das neue Experimentier- und Roboterboard"
Print
'-------------------------------------------------------------------------------
Do
A = 923
einer = A mod 10
A = A - einer
A = A / 10
zehner = A mod 10
A = A - zehner
A = A / 10
hunderter = A mod 10
A = A - hunderter
A = A / 10
Tausender = A Mod 10
Print ; Tausender ; Hunderter ; Zehner ; Einer;
Print
Waitms 500
Led_display 1 , Tausender 'Anzeigen der Zahlen
Led_display 2 , Hunderter
Led_display 3 , Zehner
Led_display 4 , Einer
Loop
End
'-------------------------------------------------------------------------------
Sub Led_display_init()
I2cstart
I2cwbyte Rn_digi_slave_write
I2cwbyte 0 'Control Byte
'Dynamic Alternative Mode und Helligkeit
'Die oberen 3 Bits bestimmen die Helligkeit
'Wenn es dunkler sein soll dann z.b. &B0110111
I2cwbyte &B0110111
I2cstop
'Alle Ziffern auf 0
For Z = 1 To 4
Led_display Z , 0
Next Z
End Sub
'-------------------------------------------------------------------------------
Sub Led_display(ziffer An Byte , Zahl As Byte)
I2cstart
I2cwbyte Rn_digi_slave_write
I2cwbyte Ziffer
Select Case Zahl
Case 0:
Segmente = &H3F
Case 1:
Segmente = &H06
Case 2:
Segmente = &H5B
Case 3:
Segmente = &H4F
Case 4:
Segmente = &H66
Case 5:
Segmente = &H6D
Case 6:
Segmente = &H7D
Case 7:
Segmente = &H07
Case 8:
Segmente = &H7F
Case 9:
Segmente = &H67
Case Else :
Segmente = &H80 'Ansonsten Dezimalpunkt
End Select
If Dezimalpunktziffer = Ziffer Then Segmente = Segmente Or &H80
I2cwbyte Segmente
I2cstop
End Sub
mfg Luca
Trotz langem Probieren, habe ich es nicht geschafft, dass er vernünftige werte ausgiebt.
Wenn ich die Zahl in ein Integer speichere, dann ist es kein Problem, jedoch muss ich es in ein Byte speicheren und dann funktioniert es nicht richtig.
Gibt es einen Befehl um einen Integer in einen Byte zu verwandeln?
mfg Luca
Hallo Luca,
lass das doch mal mit Integer - negative Werte erwartest Du doch nicht.
Nimm - wie schon beschrieben - für alle Variablen Typ "Word".
Also Dein A und auch die Variablen für die Ziffern.
Jetzt stehen also in den Word-Variablen hunderter, zehner, einer jeweils die einzelnen Ziffern, die ja vom Wert her auch in eine Variable "Byte" passen.
Was hindert Dich also daran, einfach für jede Stellen noch jeweils eine Byte-Variable zu deklarieren und den Wert zu übergeben?
Also angenommen, Deine Byte-Variablen heissen bhunderter, bzehner und beiner.
Dann einfach zuweisen:
bhunderter = hunderter
bzehner = zehner
beiner = einer
Fertig.
Gruß,
Bruno
Hallo Hanni & Sebastian,
ich finde die Subtraktionsmethode wunderbar!
Im mikrocontroller.net hat ja z.B. der Peter Dannegger in diesem Thread LINK (http://www.mikrocontroller.net/forum/read-1-154196.html) zwei schöne Beispiele in Assembler gegeben.
Einmal für 32Bit und einmal für 16Bit - prima.
Ich habe versucht, diese Beispiele in Bascom mit dem Inline-Assembler in bestehende Programme einzufügen. Leider meckert der Compiler an mehreren Stellen.
Weil es in Bascom keine BIN2BCD Wandlung gibt, hab ich dann ein wenig mit Schleifen-Konstrukten gearbeitet. Geht auch wunderbar, aber bläht leider den Code im Endeffekt noch mehr auf, also die Modulo-Lösung.
Ich hatte es ungefähr so versucht:
'============================================
' Stellen separieren
'============================================
Sub separieren()
hunderter = 0
zehner = 0
einer = 0
While result > 100
result = result - 100
Incr hunderter
Wend
While result > 10
result = result - 10
Incr zehner
Wend
einer = result
End Sub
'--------------------------------------------
In "result" stand die zu zerlegende Zahl. Geht wiegesagt, ist aber alles andere als effizient - liegt aber an mir O:)
Ich wäre dankbar für ein paar Denkanstöße, wie diese Methode auch in Bascom gut umzusetzen wäre..
Viele Grüße,
Bruno
Danke
Die Idee hatte ich auch schon, nur haber ich leider etwas vertauscht, ich habe anstatt bhunderter = hunderter, hunderter = bhunderter gemacht und mich dann gewundert warum er 0 ausgiebt. ](*,) ](*,) ](*,)
Also jetzt funktionierts. Hier noch einmal denn Code der Funktioniert:
Dim Einer As Word
Dim Zehner As Word
Dim Hunderter As Word
Dim Tausender As Word
Dim A As Word
A = 8956
Einer = A Mod 10
A = A - Einer
A = A / 10
Zehner = A Mod 10
A = A - Zehner
A = A / 10
Hunderter = A Mod 10
A = A - Hunderter
A = A / 10
Tausender = A Mod 10
Print tausender '8
Print hunderter '9
Print zehner '5
Print einer '6
In Tausender, Huderter,zehner,einer stehen dann die einzelnen Zahlen.
Nochmals Danke an alle die geholfen haben. Schönen Tag noch (ist ja nicht mehr lang)
mfg Luca
mfg Luca
Hallo Hanni & Sebastian,
ich finde die Subtraktionsmethode wunderbar!
Im mikrocontroller.net hat ja z.B. der Peter Dannegger in diesem Thread LINK (http://www.mikrocontroller.net/forum/read-1-154196.html) zwei schöne Beispiele in Assembler gegeben.
Einmal für 32Bit und einmal für 16Bit - prima.
Ich habe versucht, diese Beispiele in Bascom mit dem Inline-Assembler in bestehende Programme einzufügen. Leider meckert der Compiler an mehreren Stellen.
Weil es in Bascom keine BIN2BCD Wandlung gibt, hab ich dann ein wenig mit Schleifen-Konstrukten gearbeitet. Geht auch wunderbar, aber bläht leider den Code im Endeffekt noch mehr auf, also die Modulo-Lösung.
Hehe, Peter Dannegger steht nunmal für sehr effizienten Code. Such in der Codesammlung von mikrocontroller.net mal nach "Tasten entprellen - bullet proof" (3. oder 4. Seite) dann weisst du was ich meine.
Um den größeren Code zu erklären müsste man das sehen, was Bascom aus deinen Zeilen macht (also den Assembler Output). Ich tippe aber jetzt schon mal drauf, das a) so einige überflüssiger Vergleiche und b) so einige überflüssige Speicheroperationen darin versteckt sein werden.
Ansonsten könnte es meiner Meinung nach übrigens eine gute Idee sein, derartige Funktionen via Libs selbst zu erstellen und ggf hier zu veröffentlichen.
Wie man allerdings Libs in Bascom erstellt, kann ich dir nicht verraten (ich progge nunmal lieber etwas Hardwarenäher).
PS: Respekt, das du dir die Arbeit gemacht hast diesen Gedankenanstoß nachzuvollziehen.
Nachtrag:
vom Prinzip her sollte es aber mit inlineassembler recht einfach zu realisieren sein.
1. die Register die du verwenden willst auf den Stack sichern.
2. Die Ausgangswerte in diese laden
3. Peter Dannegger Methode anwenden (muss nur etwas angepasst werden)
4. die Ergebnisse ins RAM schreiben
5. die Register wiederherstellen
6. fertig.
Vielleicht hilft dir ja das etwas weiter.
Grüße,
da Hanni.
vom Prinzip her sollte es aber mit inlineassembler recht einfach zu realisieren sein.
Moin Hanni,
ja - dachte ich auch.
Die Hürden beginnen allerdings schon bei reservierten Worten des Compilers. Und High/low bei den Subtraktionsbefehlen gehören auch dazu. Tolle Sache das 8-[
subi a0, low(10000)
sbci a1, high(10000)
Viele Grüße,
Bruno
Moin Hanni,
peinlich peinlich!
Wollte mich gerade auf die Libs stürzen und selber Hand anlegen..
Da guck ich doch ins Lib-Verzeichnis und was sehen meine verquollenen Augen da? Eine BIN2BCD16 Lib O:)
Daaa muss ich doch glatt mal gucken..
Viele Grüße,
Bruno
Tja Dinge gibts :D
Grüße,
Hanni.
Hallo,
Ja Peter Danneggers Programme zu verstehen ist wirklich ein Ding, ich bin jedenfalls zu doof dafür :-$
Aber so in etwa wie Dein Code Bruno hab ich mir das schon vorgestellt, warum das dann so groß wird weiß ich auch nicht.
Wenn Du möchtest kann ich in meiner Codesammlung was passendes rauskopieren (das wäre dann zwar Assembler, aber vielleicht hilfreich)
viel Erfolg noch Sebastian
Wenn Du möchtest kann ich in meiner Codesammlung was passendes rauskopieren (das wäre dann zwar Assembler, aber vielleicht hilfreich)
Moin Sebastian,
das wäre prima!! Bitte mach mal.
Ich habe die Bascom Lib wieder verworfen, die ist nicht wirklich gut.
Dann habe ich Peters Routine benutzt, die Übergabe von Bascom und wieder zurück eingepflegt, aber der Compiler kann mit den High und Low´s nichts anfangen - unglaublich. FastAVR compiliert das Assemblerstück anstandslos - Bascom nicht.
Dann habe ich eine andere Routine ausprobiert - ging.
Aber... dort liegt nur das "einer"-Segment einzeln in einem Register. Die restlichen Segmente als gepacktes BCD in den Registern. Also 2x4 Bit pro Register. Konnte ich dann auch nicht weiterverarbeiten mit meinen Kenntnissen <Haare rauf>.
Viele Grüße,
Bruno
Ok, es ist zum Teil von Gerd Schmidt http://www.avr-asm-tutorial.net/index.html abgekupfert, habe nur etwas für mich angepasst, aber egal.
Alles dreht sich um Folgende Funktion:
Bin2ToDigit:
clr rmp ; Zähler auf Null
Bin2ToDigita:
cp rBin1H,rBin2H ; Vergleiche MSBs miteinander
brcs Bin2ToDigitc ; MSB Binärzahl kleiner, fertig
brne Bin2ToDigitb ; MSB Binärzahl größer, subtrahiere
cp rBin1L,rBin2L ; MSB gleich, vergleiche LSBs
brcs Bin2ToDigitc ; LSB Binärzahl kleiner, fertig
Bin2ToDigitb:
sub rBin1L,rBin2L ; Subtrahiere LSB Dezimalzahl
sbc rBin1H,rBin2H ; Subtrahiere Carry und MSB
inc rmp ; Erhöhe den Zähler
rjmp Bin2ToDigita ; Weiter vergleichen/subtrahieren
Bin2ToDigitc:
st z+,rmp ; Speichere das Ergebnis und erhöhe Zeiger
ret ; zurück
Kurz erklärt:
Ich speichere das Ergebnis in SRAM, der Z Zeiger muß auf die erste Speicherzelle eingestellt werden.
In rBin1H und rBin1L liegt meine Zahl die Umgewandelt werden soll.
Jetzt ruft man die Funktion 3 Mal auf, aber bevor man sie aufruft muß man in die Register rBin2H und rBin2L die Zahl laden, die substrahiert werden soll, etwa so:
ldi rBin2H,HIGH(1000)
ldi rBin2L,LOW(1000)
rcall Bin2ToDigit
ldi rBin2H,HIGH(100)
ldi rBin2L,LOW(100)
rcall Bin2ToDigit
ldi rBin2H,HIGH(10)
ldi rBin2L,LOW(10)
rcall Bin2ToDigit
Da die einer nicht mehr abgezogen werden müßen reicht ein
st z,rBin1L aus um die in Sram zu kriegen.
Ich hoffe, es ist verständlich und irgendwie nützlich :-k .
Bin mal gespannt was Ihr dazu sagt .
Gruß Sebastian
Hi Sebastian,
kenn ich doch irgendwo her? -> LINK (http://www.avr-asm-tutorial.net/avr_de/rechnen/konvert.html)
Sehr nützlich das ASM-Tut. Aber mir raucht Heute der Kopf 8-[
Ich seh mir das Morgen mal genauer an.
Vielen Dank Sebastian!
Gut´s Nächtle,
Bruno
kenn ich doch irgendwo her?
Ja ganau, die Quelle hab ich oben schon genannt, Gerds Beispiele sind sehr einfach und verständlich geschrieben :-)
Gruß Sebastian
Danke für diesen Tip.
Heute stand ich vor dem selben Problem.
Ich habe die sehr elegante Lösung von Linux_80 verwendet.
Funktioniert wunderbar.
Noch ein Mal: Vielen herzlichen Dank!
Gruss
Ali
a=1354
s=0
t=0
u=0
r=0
goto s_step
s_step:
if a<1000 then goto t_step else a=a-1000 and s=s+1 and goto s_step
t_step:
if a<100 then goto t_step else a=a-100 and t=t+1 and goto t_step
u_step:
if a<10 then goto u_step else a=a-10 and u=u+1 and goto u_step
r_step:
if a<1 then goto stepXXX else a=a-1 and r=r+1 and goto stepxxx
Hallo,
mal abgesehen davon, dass du dich vertippt hast und den µC in eine Endlosschleife geschickt hast, aber den Code meinst du doch wohl nicht ernst, oder?
erstmal habe ich meinen ganzen controller in einer schleife laufen ;o)
und ja ich meine es ernst mit dem Code - ist mal etwas anderes
Hallo,
hier ist meine Art eine 5 Stellige Zahl zu zerlegen. Dieser Code ist recht schnell.
Dim Az As Word
Dim Ah As Word
Dim Ata As Word
Dim Azt As Word
Dim Einer As Byte
Dim Zehner As Byte
Dim Hunderter As Byte
Dim Tausender As Byte
Dim Zehntausender As Byte At Azt Overlay
Dim Temp As Word
Dim A As Word
A = 54321
Az = A / 10
Ah = A / 100
Ata = A / 1000
Azt = A / 10000
Temp = Azt * 10
Tausender = Ata - Temp
Temp = Ata * 10
Hunderter = Ah - Temp
Temp = Ah * 10
Zehner = Az - Temp
Temp = Az * 10
Einer = A - Temp
End
lg
Günter
Variante, nur so, als Alternative : ( beispiel für maximal 6 Stellen )
Dim Zahl As Long
Dim Postext As String * 3
Dim Strg As String * 20
Dim Arr(21) As Byte At Strg Overlay
Dim Ix As Integer
Dim Iy As Byte
Dim Ln As Byte
Zahl = 348365 ' das ist die Zahle
Strg = Str(zahl)
Ln = Len(strg)
Iy = 6 - Ln
For Ix = 1 To Ln
Postext = Lookupstr(iy , Posit)
Print Postext ; Chr(arr(ix))
Incr Iy
Next
End
Posit:
Data "hT:" , "zT:" , "T:" , "H:" , "Z:" , "E:"
Hallo
Der code denn ich schlussund endlich verwendet habe, funktioniert sehr gut. danke einenweg.
mfg Luca
Ps: Habe denn Code im ersten Post hinzugefügt.
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.