Hallo Leute, ich hab vollgendes Problem Ich muss für meine schule ein Strommessgerät entwickeln. Jetzt muss ich den Betrag vom Ad-wandler was an Ain 0 anliegt auf die Lcd bringen aber in einer Kommazahl. Bedeutet ja der Betrag in Ain0 wir durch 256 geteilt und der wert in den Akku gespeichert. Dieses muss ich dann nehmen ihn für eine Look uptable nehmen und den vorkommaWert suchen, diesen danna uf die lcd bringen. Dachach den Wert in eine andere Tabelle nehmen und den Nachkommastellen Wert suchen und auf die lcd beringen. Vorgabe ist ein Messbereich von 0-5V also hab die looUp schon 5:256 und dann die werte in die lookups geschrieben. Nund hab und keien idee wie ich den rest umsetzten soll
Teile uns doch mal mit, auf was für einem Mikrocontroller du arbeitest. Dann könnten wir dir vielleicht helfen. Bei einigen µCs gibt es bereits Funktionen, die die Funktionalität bereitstellen.
> Bedeutet ja der Betrag in Ain0 wir durch 256 geteilt und der > wert in den Akku gespeichert. Dieses muss ich dann nehmen > ihn für eine Look uptable nehmen und den vorkommaWert suchen, > diesen danna uf die lcd bringen. > Dachach den Wert in eine andere Tabelle nehmen und den > Nachkommastellen Wert suchen und auf die lcd beringen. Machs nicht so komplizert. Mach dir EINE Lookup Tabelle in der du zb das 100-fache des Wertes speicherst (als Vorkomma + 2 Nachkommastellen) und während der Ausgabe schummelst du vor die letzten beiden auszugebenden Stellen einen Dezimalpunkt ein. Und so wird dann aus 439, die du aus der Tabelle bekommst, auf der Anzeige ein "4.39" (aber aufpassen mit führenden 0-en. Aus 29 muss an der Ausgabe 0.29 werden, wenn deine Ausgaberoutinen führende 0-en unterdrückt)
Wenn in deiner Schule Deutschkurse angeboten werden, solltest du einmal einen besuchen.
Karl Heinz Buchegger schrieb: > 439 Wie soll ich denn diesen Pinkt dazwischen bekommen? Haben ein ATMEL 895131A
Manuel schrieb: > Haben ein ATMEL 895131A Das ist schön - schade nur, das der gar keinen AD Wandler hat. Und hilft auch nicht weiter, wenn du Pinkte einbauen willst. Und ausserdem wissen wir ja nicht einmal, in welcher Programmiersprache ihr da rumwurschtelt. Beitrag "Einheitlicher Umgang mit faulen Schülern etc.?"
Wie der hat kein Ad-Wandler hab auch den falschen gepostet. Hier nochmal der neue: Atmel 89C5131A-UM Hier mal wie wiet ich bisher bin: Teste noch herum ;----------------------------------------------------------------------- ;Auswahl zwischen Spannungsbereich 0-10V, 0-5V mov a,90h ;Wert von P1.0(90h) in akku mov r1,a ;Akku in r1 mov a,91h ;Wert von P1.1(91h) in akku mov r2,a ;Akku in r2 cjne r1,#1,Auswahl ;Vergleiche r1 mit Konstanten 1 lcall Ain0 ;Abfrage Wert an Ain0 mov DPTR,#tabelle10V1 ;Lookup Tablle einfügen movc a,@a+DPTR ;Wert aus Tabelle 10V1 holen mov r4,a lcall r4 lcall Ain0 mov DPTR,#tabelle10V2 movc a,@a+DPTR lcall dezaus ;Ausgabe Wert ind Dezimal von Ain0 (Ad-Wandler) Auswahl: cjne r2,#1,Auswahl lcall Ain0 ;Abfrage Wert an Ain0 mov DPTR,#tabelle5V1 ;Lookup Tablle einfügen movc a,@a+DPTR ;Wert aus Tabelle 5V1 holen mov r4,a mov DPTR,#tabelle5V2 movc a,@a+DPTR lcall dezaus ;Ausgabe Wert ind Dezimal von Ain0 (Ad-Wandler)
Na gut, zumindest scheint es so als ob du dich bemühst. Dann legen wir mal los ein bisschen zu helfen. Allerdings möchtest du doch wissen, wie du die Ausgabe des '.' oder ',' realisierst. Gerade die Funktion "dezaus" die das machen soll fehlt in deinem Beitrag. Bitte nachliefern. Am besten den kompletten Code posten. Gruß lowlevel
Hier bitte:D EXTRN Code (initLCD,loeschzeile1,loeschzeile2,textzeile1,textzeile2,cursorpos,texta us,zifferaus,hexaus,dezaus,Ain0,Aout) ;******************** Programm ************************************************ cseg at 0 mov sp,#2fh ;Stackpointer oberhalb Bitadressierbarer Bereich lcall initlcd ;Display initialisieren mov dptr,#Text3 lcall textzeile1 mov dptr,#Text1 lcall textzeile2 start: ;lcall loeschzeile1 ;lcall loeschzeile2 mov a,#0 mov a,#45h ;Textzeile zwei, Abstand zu 'U' lcall cursorpos ;----------------------------------------------------------------------- mov a,90h ;Wert von P1.0(90h) in akku mov r1,a ;Akku in r1 mov a,91h ;Wert von P1.1(91h) in akku mov r2,a ;Akku in r2 cjne r1,#1,Auswahl ;Vergleiche r1 mit Konstanten 1 lcall Ain0 ;Abfrage Wert an Ain0 mov DPTR,#tabelle10V1 ;Lookup Tablle einfügen movc a,@a+DPTR ;Wert aus Tabelle 10V1 holen mov p1,a lcall dezaus mov a,#49h lcall cursorpos lcall Ain0 mov DPTR,#tabelle10V2 movc a,@a+DPTR lcall dezaus ;Ausgabe Wert ind Dezimal von Ain0 (Ad-Wandler) Auswahl: cjne r2,#1,Auswahl lcall Ain0 ;Abfrage Wert an Ain0 mov DPTR,#tabelle5V1 ;Lookup Tablle einfügen movc a,@a+DPTR ;Wert aus Tabelle 5V1 holen mov r4,a mov DPTR,#tabelle5V2 movc a,@a+DPTR lcall dezaus ;Ausgabe Wert ind Dezimal von Ain0 (Ad-Wandler) ;----------------------------------------------------------------------- ----- lcall Zeit sjmp start ; mov dptr,#Text1 ; lcall textzeile1 ; lcall Zeit ; ; mov dptr,#Text2 ; lcall textzeile2 ; lcall Zeit ; ; lcall loeschzeile1 ; lcall loeschzeile2 ; ; mov dptr,#Text3 ; lcall textzeile1 ; lcall Zeit ; ; mov dptr,#Text4 ; lcall textzeile2 ; lcall Zeit ; ; lcall loeschzeile2 ; mov a,#12 ; lcall dezaus ; lcall Zeit ; ; jmp start ; ; ;********** Zeitverzögerung ************************************************************************ ** Zeit: mov R7, #3 Zeit2: mov R6, #255 Zeit1: mov R5, #255 Zeit0: djnz R5, Zeit0 djnz R6, Zeit1 djnz R7, Zeit2 ret ;************************ Texte ******************************************************* Text1: db 'U = . V',0 ;Text2: db ' V',0 Text3: db 'Spannungsmessge.',0 ;Text4: db ' Gymnasium',0 ; ; ;**********Lockup Table****** tabelle5V1: db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 db 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 db 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 db 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 db 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 db 5 tabelle5V2: db 00, 02, 04, 06, 08, 10, 12, 14, 16, 18, 20, 22, 24, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98 db 00, 02, 04, 06, 08, 10, 12, 14, 16, 18, 20, 22, 24, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98 db 00, 02, 04, 06, 08, 10, 12, 14, 16, 18, 20, 22, 24, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98 db 00, 02, 04, 06, 08, 10, 12, 14, 16, 18, 20, 22, 24, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98 db 00, 02, 04, 06, 08, 10, 12, 14, 16, 18, 20, 22, 24, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98 db 00 tabelle10V1: db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 db 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 db 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 db 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 db 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 db 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 db 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 db 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 db 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 db 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 db 10 tabelle10V2: db 00, 04, 08, 12, 16, 20, 24, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 67, 71, 75, 78, 82, 86, 90, 94, 98 db 02, 06, 10, 14, 18, 22, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96 db 00, 04, 08, 12, 16, 20, 24, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 67, 71, 75, 78, 82, 86, 90, 94, 98 db 02, 06, 10, 14, 18, 22, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96 db 00, 04, 08, 12, 16, 20, 24, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 67, 71, 75, 78, 82, 86, 90, 94, 98 db 02, 06, 10, 14, 18, 22, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96 db 00, 04, 08, 12, 16, 20, 24, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 67, 71, 75, 78, 82, 86, 90, 94, 98 db 02, 06, 10, 14, 18, 22, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96 db 00, 04, 08, 12, 16, 20, 24, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 67, 71, 75, 78, 82, 86, 90, 94, 98 db 02, 06, 10, 14, 18, 22, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96 db 00
dezaus fehlt immer noch Aber ich fürchte, selbst mit der Kentnis dieser Funktion wird das nichts. Solange du nicht mit 16 Bit Werten hantieren kannst, ist das vergebliche Liebesmühe. Zu deinen Tabellen. Ich weiß nicht, ob du das schon mal gehört hast. Aber dein µC ist ein kleiner Computer! Der kann rechnen! Du kannst natürlich eine Division durch eine Tabelle ersetzen. Sinnvoll ist das aber nicht. Sinnvoll wäre es, zu lernen, wie man in Assembler eine 16 Bit Division durchführt.
Manuel schrieb: > wo fehlt denn dieser befehl nicht 'er fehlt'. Sondern hier
1 | lcall dezaus ;Ausgabe Wert ind Dezimal von Ain0 (Ad-Wandler) |
wird ein Unterprogramm aufgerufen, welches offenbar die Ausgabe macht. Da es aber zu prüfen gilt, ob und wie man da während der Ausgabe einen '.' in die Ausgabe an der entsprechenden Stelle einschmuggeln kann, wird man sich wohl ansehen müssen, wie denn diese Ausgabefunktion eigentlich arbeitet. Nun versteh ich von deinem µC nicht viel. Was ich aber verstehe ist, dass du dich bei deinem ganzen Programm mehr oder weniger auf 8 Bit Arithmetik eingeschworen hast. Und solange das so ist, wird das auch nichts werden mit dieser vorgschlagenen Strategie. Du musst zumindest soweit in deinen Fähigkeiten sein, dass dich 16 Bit Arithmetik (Addieren, Subtrahieren, Multiplizieren, Dividieren) nicht vor unlösbare Probleme stellt. Wie willst du denn je vernünftig deinen µC zu Rechenaufgaben heranziehen, wenn du nicht wenigstens im Zahlenraum 0 bis 65-tausend problemlos einfache Berechnungen machen kannst? Du kannst dich nicht ewig mit 8-Bit Tabellen aus der Affäre ziehen, zumal das dann wieder andere Probleme (eben durch den beschränkten Zahlenraum) nach sich zieht.
Karl Heinz Buchegger schrieb: > Mach dir EINE Lookup Tabelle Nein!! Mach dir bitte KEINE Lookup-Tabelle. O Herr, lass Hirn regnen. das elendige Thema, daß die Leute in ihrer Beschränktheit immerzu glauben, daß ein Ergebnis eines ADC's eine Integerzahl darstellen würde, hatten wir doch schon so unsäglich oft. Anschließend kommt immer die Frage "Wie kann ich aus den Integerzahlen 0..255 ein Ergebnis 0.0 Volt bis 4.999 Volt machen?" Ich versuch's mal in diskreten Erkenntnis-Stufen: 1. Erkenntnis: Das, was ein ADC ausspuckt, sind Bits - und keine Spannungswerte. 2. Erkenntnis: Diese Bits haben üblicherweise (aber nicht immer) eine Wertigkeits-Reihenfolge untereinander, also es gibt ein "dickstes" sprich höchstwertigstes Bit (das MSB) und die anderen Bits haben einen kleineren Wert. Daß das immer ne Zweierpotenz sein muß, ist falsch. Es gibt auch BCD-ADC's (die in den Taschen-Multimetern) und es gibt welche, die Gray-Code ausspucken. 3. Erkenntnis: Niemand hat gesagt, daß ein bestimmtes Bit einen bestimmten Wert (z.B. 1 Volt) hat. Wer es nicht glauben will, der hängt vor den ADC einen Spannungsteiler oder ändert die Referenzspannung und schon bedeutet das Bit ne andere Eingangsspannung. Wir sehen also, daß die Wertigkeiten aller Bits von der Eingangsbeschaltung und der Referenz abhängt. 4. Wenn wir aus den Bits, die aus dem ADC kommen, eine ZAHL bilden wollen, dann müssen wir den Bits jeweils eine Wertigkeit zuweisen. Wir könnten (für das Beispiel aus dem Threadbeginn) z.B. dem MSB den Wert 0.5 zuweisen, dem nächsten den Wert 0.25, den dritten 0,125 usw. Alle so zugeordneten Bits bilden dann eine echt gebrochene Zahl von 0 bis 0.99606299212, die wir großzügig zu 0.996 runden. Was haben wir nun davon? Nun, wir multiplizieren später einen Faktor, der unsere Referenz und einen Spannungsteiler usw. enthält und schon haben wir unser Ergebnis in Volt. 5. Erkenntnis: Wenn ich eine echt gebrochene Zahl mit 10 multipliziere, bekomme ich vor dem Dezimalpunkt die erste Stelle und danach den Rest. Also ich hab 0.3745 und multipliziere: 0.345 * 10 --> 3.745 Nun kann ich den ganzen Teil abtrennen und ausgeben und rechne mit dem Rest weiter: 0.745 * 10 --> 7.45 Wieder ganzen Teil abtrennen und mit dem Rest weitermachen: 0.45 * 10 --> 4.5 usw. bis ich genug Stellen habe. 6. ne Nachüberlegung: Mein o.g. Faktor sei hier 5, weil ich einen ADC hab, der von 0 bis knapp 5 Volt "geht". (genauer: 5 * 0.99606299212 --> ca. 4.98 Volt) Ich müßte also 5 * ADCwert rechnen und dann hätte ich schon als erstes Ergebnis meinen ganzen Teil, den ich abtrennen kann. Der Rest ist ja wieder kleiner als 1 und damit geht die Rechnung so: 1. Schritt: ADC*5, ganzen Teil abtrennen 2. Schritt: Rest*10, ganzen Teil abtrennen 3. Schritt: Rest*10, ganzen Teil abtrennen das reicht, zu mehr taugen 8 Bit nicht. 7. Was braucht man zum Rechnen? Nun man kann das Ganze mit nem Integer, also einer 16 Bit Zahl rechnen. Die niederwertigen Bits 0..7 stellen unseren gebrochenen Teil dar und die höherwertigen Bits den ganzen Teil. Geht auch bequem mit 2 Bytes und Beachten des Carry zu rechnen. 8. Wie multipliziert man mit 10, wenn man keinen Befehl dazu hat? Zahl* 10 geht auch als ((Zahl << 2) + Zahl) << 1), also 2 Shifts und eine Addition. So. Den konkreten Quellcode schreibt sich unser Manuel nun selbst, nachdem er das hier verstanden hat. W.S.
W.S. schrieb: > Karl Heinz Buchegger schrieb: >> Mach dir EINE Lookup Tabelle > > Nein!! Mach dir bitte KEINE Lookup-Tabelle. Zu diesem Zeitpunkt wusste ich noch nicht, dass seine Umrechnungsfunktion eine simple lineare Gleichung ist. Hätte ja auch etwas Komplexeres sein können. Damit, dass er eine Multiplikation/Division in Form einer Tabelle abbildet, damit hatte ich nun wirklich nicht gerechnet.
Wird wohl eh etwas knapp mit dem Speicher. Was ich bisher von den Funktionen gesehen habe würde ich auf ein ganz spezielles Board tippen (wird in BaWü an vielen Schulen eingesetzt). Da wird in der Schule dann RIDE genutzt das in der kostenlosen Version nur 4k Code erzeugt. adda.a51 und lcdhilf.a51 brauchen so 600Bytes, die Tabelle knallt mit 2k rein... Wie wäre es denn, vom Digitalwert (Akku) so oft 51 (1V) abzuziehen, bis das Ergebnis negativ wird. Damit ist die Vorkommastelle bekannt. Der verbleibende Rest ist eine Zahl zwischen 0 und 50. dafür könnte man dann zur Not eine Tabelle anlegen. Wenn man etwas krumm mit Ulsb = 5V /255 rechnet kommt man auch auf genau 51Bit pro Volt. Die Ausgabe des Dezimalpunktes erledigt ein mov a, #'.' call charaus In C könnte man das als Zweizeiler schreiben (der dann aber auch die 4k vollmüllt) tschuessle Bernhard
> > 5. Erkenntnis: Wenn ich eine echt gebrochene Zahl mit 10 multipliziere, > bekomme ich vor dem Dezimalpunkt die erste Stelle und danach den Rest. > Also ich hab 0.3745 und multipliziere: > 0.345 * 10 --> 3.745 > Nun kann ich den ganzen Teil abtrennen und ausgeben und rechne mit dem > Rest weiter: > 0.745 * 10 --> 7.45 > Wieder ganzen Teil abtrennen und mit dem Rest weitermachen: > 0.45 * 10 --> 4.5 > usw. bis ich genug Stellen habe. > > 6. ne Nachüberlegung: > Mein o.g. Faktor sei hier 5, weil ich einen ADC hab, der von 0 bis knapp > 5 Volt "geht". (genauer: 5 * 0.99606299212 --> ca. 4.98 Volt) > Ich müßte also 5 * ADCwert rechnen und dann hätte ich schon als erstes > Ergebnis meinen ganzen Teil, den ich abtrennen kann. Der Rest ist ja > wieder kleiner als 1 und damit geht die Rechnung so: > 1. Schritt: ADC*5, ganzen Teil abtrennen > 2. Schritt: Rest*10, ganzen Teil abtrennen > 3. Schritt: Rest*10, ganzen Teil abtrennen > das reicht, zu mehr taugen 8 Bit nicht. ich habe es in gro´Zügen verstanden aber leider keine idee wie ich dies in asabler umsetzten soll wie ichd as trennne hinbekommen soll und alles Tut mir leid fange gerade an mit dieser sprache und alles umzugehen
Machen wir's in Assembler: Also, du hast beispielsweise eine Zahl wie 3.1415 und selbige so in ein 16 Bit Register (das du z.B. KarlHeinz nennst) gepackt, daß der (dazu gedachte) Dezimalpunkt genau zwischen Bit 7 und Bit 8 steht. Dann belegt der ganze Teil die Bits 8..15 und der gebrochene Teil die Bits 7..0. Wenn dein uC keine 16 Bit Register hat, dann nimmst du eben 2 Achtbit-Register und benenne sie z.B. KarlHi und KarlLo. Klaro? Wie kriegst du nun den ganzen Teil zur Ausgabe? Bei 16 Bit: - Lade KarlHeinz in ein anderes Register (Otto), also Otto = KarlHeinz; - dann Otto rechtsverschieben Otto = Otto shiftrechts 8 Bit. Damit fliegt der gebrochene teil aus Otto heraus und der Rest ist deine Stelle 0..9, aus der du nur noch ein Char machen mußt durch Addieren von 48 (= 30h = '0'), also GibAus(Otto+'0'); - dann schmeiß den ganzen Teil aus Karlheinz heraus: KarlHeinz = KarlHeinz AND 255; (255 = FFh = 0000000011111111 binär) Bei 2x 8 Bit ist es einfacher: KarlHi ist bereits der ganze Teil, den du mit GibAus(KarlHi+'0') direkt ausgeben kannst. Anschließend schmeißt du den ganzen Teil heraus, indem du KarlHi = 0; schreibst, also dieses Register mit 0 lädtst. Ist doch extrem easy, oder? W.S.
W.S. schrieb: > Machen wir's in Assembler: Ich denke sein Hauptproblem wird sein, dass er noch keine 16 Bit Arithmetikroutinen hat, mit denen er den ADC Wert entsprechend einer Formel in den Anzeigewert umrechnen kann. Leider versteh ich von diesem Assembler nichts, daher kann ich ihm da auch nicht weiterhelfen, wie man diese Dinge da am vernünftigsten aufbaut. PS: Nettes Namenswahl
Karl Heinz Buchegger schrieb: > keine 16 Bit Arithmetikroutinen hat Das dürfte die meisten (Berufs-)Schüler aber auch deren Lehrer überfordern. Daher ist die naheliegende Lösung so wie oben von mir beschrieben. Alternativ könnte man nach der mehrfachen Subtraktion noch versuchen die 1/10V-Schritte durch Subtraktion zu erledigen, aber das geht im 8-Bit-Zahlenraum auch nur ungenau, wenn die Ulsb 19,53mV/Bit entspricht. @Manuel: arbeitest du mit dem Board hier? http://www.ces.karlsruhe.de/bubbers/index.php/controller Da gibt es einen Trimmer für Uref. Wenn man jetzt 4,1V (genauer 4,096V) einstellt, dann entspricht Ulsb = 16mV/Bit. Damit lässt ich wesentlich einfacher rechnen. Noch einfacher ist es bei 2,56V, dann ist Ulsb = 10mV/Bit und eine Spannung (bis 2,55V) entspricht genau dem Digitalwert in 10mV-Schritten. Nachteil ist der reduzierte Eingangsspannungsbereich. tschuessle Bernhard
Bernhard Spitzer schrieb: > Karl Heinz Buchegger schrieb: >> keine 16 Bit Arithmetikroutinen hat > Das dürfte die meisten (Berufs-)Schüler aber auch deren Lehrer > überfordern. Daher ist die naheliegende Lösung so wie oben von mir > beschrieben. Du verstehst mich nicht, worauf ich hinaus will. Deine Ausgaberoutine ist ja super. Gut erklärt und auch für ihn umsetzbar. Das Problem ist: wo kommt der Wert her, den er ausgeben will. Zwischen dem, was er vom ADC bekommt und dem was er auf die Anzeige zaubern will, liegt ein Zwischenschritt. Wie berechnet er sich die (zb.) 8.8 Fixpunktzahl, die er dann schön ausgeben kann?
Bernhard Spitzer schrieb: > @Manuel: arbeitest du mit dem Board hier? > http://www.ces.karlsruhe.de/bubbers/index.php/controller > Da gibt es einen Trimmer für Uref. Wenn man jetzt 4,1V (genauer 4,096V) > einstellt, dann entspricht Ulsb = 16mV/Bit. Damit lässt ich wesentlich > einfacher rechnen. Noch einfacher ist es bei 2,56V, dann ist Ulsb = > 10mV/Bit und eine Spannung (bis 2,55V) entspricht genau dem Digitalwert > in 10mV-Schritten. Nachteil ist der reduzierte Eingangsspannungsbereich. > > tschuessle > Bernhard Ja, genau mit diesem arbeiten wir. Welcher Trimmer? Ich muss an das board noch ein spannungsteiler dran hängen wiel ich die eingäne bei Ani0 nehme mit 5v und Masse
Bernhard Spitzer schrieb: > Wie wäre es denn, vom Digitalwert (Akku) so oft 51 (1V) abzuziehen, bis > das Ergebnis negativ wird. Damit ist die Vorkommastelle bekannt. Der > verbleibende Rest ist eine Zahl zwischen 0 und 50. dafür könnte man dann > zur Not eine Tabelle anlegen. Wenn man etwas krumm mit Ulsb = 5V /255 > rechnet kommt man auch auf genau 51Bit pro Volt. > Die Ausgabe des Dezimalpunktes erledigt ein > mov a, #'.' > call charaus oki aber wie gebe ich das alles aus. ich habe ja dann die Kommastelle 0-50Bit entpricht evtl 0.2V wie bekomm ich nun die vorkommastelle? Wenn ich ein Signal habe mit 168 Würde es ja 3,.. geben Muss ich dann ne verzeigung machen, die Abfraget ob der wert größer 51 ist und dann wieder abzieht und dann ein register z.b hochzählt? Würde bedeuten, ich habe r=3 Tablle:25Bit=0,5V Wie füge ich dies zusammen mit einem Punkt.
Manuel schrieb: >> Die Ausgabe des Dezimalpunktes erledigt ein >> mov a, #'.' >> call charaus > > Würde bedeuten, ich habe r=3 Tablle:25Bit=0,5V > > Wie füge ich dies zusammen mit einem Punkt. Die letzte Frage wurde bereits beantwortet, bevor Du sie gestellt hast. Ansonsten stellst Du aus mehreren Variabeln (Speicherstellen von 7Fh abwärts eigenen sich da gut) deinen Zahlenwert zusammen. z.B. Vorkomma EQU 07Fh Nachkomma_Zehntel EQU 07Eh Nachkomma_Hundertstel EQU 07Dh Ausgabe erfoglt dann Ziffernweise mit mov a, Vorkomma call charaus mov a, #'.' call charaus mov a, Nachkomma_Zehntel undsoweiterundsofort... Nachdem Du Dir Gedanken gemacht hast, wie deine gewünschte physikalische Größe (Du willst doch Strom messen - redest aber nur von Spannungen. Also wie groß ist der Messwiderstand?) vom Digitalwert abhängt, kannst Du (zuerst mal auf Papier) die Formel Phy_Größe = m * Digitalwert + b aufstellen. Überprüfung mit 2 konkreten Digitalwerten sollte erfolgen. Da krumme Faktoren und Überläufe in Assembler nicht gut umsetzbar sind, rechnest Du Dir die Digitalwerte z.B. für 1A, 2A, 3A usw. aus. Dann misst Du den Analogkanal und vergleichst auf die Schwellen. Damit ist die Vorkommastelle klar. Wenn also 1A z.B. 51 entspricht, dann so:
1 | call ain0 ; im Akku steht jetzt der Digitalwert |
2 | cjne a,#51,Vergleich2 ; Wenn Akku gleich 51, dann 1.00A |
3 | mov Vorkomma, #1 |
4 | mov Nachkomma_Zehner, #0 ; und so weiter |
5 | jmp Anzeigen |
6 | |
7 | Vergleich2: ; jetzt das Carry prüfen. Wenn gesetzt ist der Akku unter 51, sonst drüber |
8 | jc Unter51 |
9 | Ueber51: ; 51 abziehen, dann weitere Vergleiche mit den übrigen Werten |
10 | |
11 | Unter51: |
12 | mov Vorkomma, #0 |
13 | ;Nachkommastellen aus Wertetabellen mit indir. Adressierung auslesen |
und das ganze für alle weiteren berechneten Digitalwerte. Ist zwar nervig, aber immer das gleiche Schema. @Karl Heinz: Eigentlich sollte der Lehrer sowas vorher mal im Unterricht vorgestellt haben. Für ASM-Anfänger ist sowas eine recht harte Nuss. Mehr als das obige will ich aber nicht mehr vorgeben. Erst soll er mal eigenen Code posten. (die nächste Frage zum Thema hat er als MA ja schon gestellt). tschuessle Bernhard
Karl Heinz Buchegger schrieb: > Zwischen dem, was er vom ADC bekommt und dem was er auf die Anzeige > zaubern will, liegt ein Zwischenschritt. Wie berechnet er sich die (zb.) > 8.8 Fixpunktzahl, die er dann schön ausgeben kann? Er berechnet sie überhaupt nicht, sondern setzt den ganzen Teil auf Null und lädt den gebrochenen Teil mit dem Ergebnis aus dem ADC. Das ist alles. Irgendwann verzweifle ich an euch allen!! Also nochmal vom nochmal: 1. Wir lesen den 8 Bit großen (also 1 Byte umfassenden) ADC-Wert aus dem ADC aus und laden ihn in ein Register oder eine Speichezelle, die ich hier mit KarlLo bezeichne. 2. Wir nehmen irgendwoher ein zweites Register oder eine zweite Speicherzelle, die ich hier KarlHi bezeichne. Dort schreiben wir ene NULL hinein oder führen einen Löschbefehl aus (je nach verwendetem uC) Also haben wir jetzt (mal pascalartig ausgedrückt): var KarlLo: byte; KarlHi: byte; Hilf : byte; begin KarlLo:= ADC_Resultat; KarlHi:= 0; Das ist der Anfang des Ganzen und der Ausgangspunkt für alles Weitere. War das SOOO schwer? jetzt mal ne Stegreif-Version für PIC: MOVF KarlLo,W MOVWF Hilf ; Hilf:= KarlLo; BCF Carry ; Carry löschen, damit ne 0 reingeschoben wird RLF Hilf,F ; 1x links verschieben über Carry RLF KarlHi,F ; KarlHi:= KarlHi shl 1 und Carry ins LSB RLF Hilf,F ; Carry sollte 0 sein, da KarlHi=0 war RLF KarlHi,F ; dito, also alles bisher mal 4 MOVF Hilf,W ADDWF KarlLo,F ; KarlLo:= KarlLo + Hilf; BTFSC Carry INCF KarlHi,F ; KarlHi:= KarlHi + Carry aud der Addition Jetzt haben wir KarlHi.KarlLo mit 5 multipliziert. MOVF KarlHi,W ; ganzen Teil abtrennen und ausgeben ADDLW '0' CALL GibZeichenAus CLRF KarlHi Für die nachfolgenden Schritte müssen wir mit 10 multiplizieren, also kommt noch dazu BCF Carry RLF KarlLo,F RLF KarlHi,F und der Rest ist wie bei obigem Multiplizieren mit 5. SO. Nochmal pascalartig das Ganze: var KarlHeinz: word; begin Karlheinz:= ADC_Resultat; { 1. Ziffer } KarlHeinz:= Karlheinz * 5; GibZeichenAus(chr(((Karlheinz shr 8) and 15) or '0')); KarlHeinz:= KarlHeinz and 255; GibZeichenAus('.'); { 1. Ziffer } KarlHeinz:= Karlheinz * 10; GibZeichenAus(chr(((Karlheinz shr 8) and 15) or '0')); KarlHeinz:= KarlHeinz and 255; { 2. Ziffer } KarlHeinz:= Karlheinz * 10; GibZeichenAus(chr(((Karlheinz shr 8) and 15) or '0')); KarlHeinz:= KarlHeinz and 255; Also Leute, ich bin ja nun längst nicht mehr der Allerjüngste und Schnellste im Denken, aber ich sehe mit einigem Erschrecken, wie begriffsstutzig ihr jungen Spunde so seid. Lernt doch um Himmelswillen zuerst das logische Denken, bevor ihr euch ans Programmieren macht. Es ist wirklich viel viel wichtiger, logisch und strategisch denken zu können, als irgendeine Programmiersprache gelernt oder den Umgang mit irgendeiner IDE/Toolchain geübt zu haben. Die obigen Vorschläge, an der Refrenz zu drehen, eine Tabelle zu basteln oder sonstwie das eigentliche Problem nicht zu lösen sondern zu umschleichen, sind allesamt OBERMURKS, der nur daraus rührt, daß die Schreiber eben noch nicht zu denken gelernt haben. Deshalb empfehle ich hier mal ein steinaltes Buch, das sich zwar auf den ebenso steinalten Z80 bezieht, aber an Aktualität nichts eingebüßt hat: Lampe, B./Jorke, G./Wengel, H., Algorithmen der - Wiley Online Library (http://www.hood.de/angebot/45547775/lampe-jorke-wengel-algorithmen-der-mikrorechentechnik.htm) Lest das und lernt damit, Algorithmen zu verstehen und zu begreifen, wie man Probleme angeht und löst. Daß im Buch als Hardware der alte Z80 herangezogen wurde, ist gut, denn das verhindert, daß Unbedarfte das Buch lediglich als ein Kochbuch für Copy&Paste ansehen. Stattdessen sieht man sich genötigt, den Sinn zu begreifen um die Algorithmen für heutige uC zu formulieren. W.S.
Hi >Lampe, B./Jorke, G./Wengel, H., Algorithmen der - Wiley Online Library >(http://www.hood.de/angebot/45547775/lampe-jorke-we...) oder den Nachfolger: http://www.ebay.de/itm/Arithmetische-Algorithmen-Mikrorechentechnik-Jorke-Lampe-Wengel-/250915667113 MfG Spess
W.S. schrieb: > Karl Heinz Buchegger schrieb: >> Zwischen dem, was er vom ADC bekommt und dem was er auf die Anzeige >> zaubern will, liegt ein Zwischenschritt. Wie berechnet er sich die (zb.) >> 8.8 Fixpunktzahl, die er dann schön ausgeben kann? > > Er berechnet sie überhaupt nicht, sondern setzt den ganzen Teil auf > Null und lädt den gebrochenen Teil mit dem Ergebnis aus dem ADC. Das ist > alles. Echt? Und das berechnet dann den Strom durch den Shunt, wenn er die Spannung über dem Shunt misst?
Karl Heinz Buchegger schrieb: > Echt? Es ist Sonntag, mieses Nieselwetter und ich war jetzt ne Weile im Garten um den elenden Kirschbaum zu verschneiden - ergo, hab momentan keinen Gefallen an solchen Bemerkungen. Also, du Moritator, wenn schon, dann trag was Nützliches zum Thema bei. W.S.
> Irgendwann verzweifle ich an euch allen!! > Lernt doch um Himmelswillen zuerst das logische Denken, > bevor ihr euch ans Programmieren macht. Vielleicht doch noch mal das Eröffnungsposting lesen, wo die Reise überhaupt hingehen soll. Die 5V sind nur Zwischenziel. Die endgültige Reise geht zu einer Strommessung und da bleibt es nicht aus, dass der Widerstand des Shunts in die Rechnung eingeht.
Oh, du KarlHeinz, lies doch mal: Manuel schrieb: > Vorgabe ist ein Messbereich von 0-5V also hab die looUp.. Darum drehte sich das Ganze: 0 bis 5 Volt. Über den Shunt und etwaige weitere Bauteile vor dem ADC hat er sich nicht ausgelassen. Ist ja auch seine Schulaufgabe. Mir ist schon klar, daß man für andere Meßbereiche auch andere Skalierungsfaktoren benötigt. Ich zitiere mich ausnahmsweise mal selber: W.S. schrieb: > Wir sehen also, daß > die Wertigkeiten aller Bits von der Eingangsbeschaltung und der Referenz > abhängt. Oder formal Resultat:= HardwareabhängigerFaktor * ADCErgebnis; Jetzt haben wir das Umwandeln eines ADC-Ergebnisses in einen Text 0.00 bis 4.99 exemplarisch geübt und zwar ohne irgendwelche Tabellen, die bei einem linearen Problem grundsätzlich überflüssig sind. Wer das kapiert hat, sollte ab jetzt kein Problem haben, diesen Algorithmus auf andere Bereiche umzusetzen. Allerdings ist dazu wenigstens einmal eine Multiplikation nötig.
W.S. schrieb: > Oh, du KarlHeinz, > > lies doch mal: > > Manuel schrieb: >> Vorgabe ist ein Messbereich von 0-5V also hab die looUp.. >> ich hab vollgendes Problem Ich muss für meine schule > ein Strommessgerät entwickeln. ! > Darum drehte sich das Ganze: 0 bis 5 Volt. Er misst im 5V Bereich seines ADC! Das heißt aber nicht, dass auf seiner Anzeige zum Schluss ein Wert zwischen 0 und 5 stehen soll. Schau dir die Tabellen an, die er bisher benutzt hat. Ich sag ja nicht, dass deine Ausgabefunktion schlecht ist. Überhaupt nicht. Aber sie ist nur Teil seiner Lösung. Und ob er in der Lage ist, die notwendigen Änderungen da mit einzuarbeiten .... wage ich zu bezweifeln.
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.