Forum: Mikrocontroller und Digitale Elektronik LM75 Temperatur von bin auf dec für LCD ausgeben??


von Tim M. (astarot)


Lesenswert?

Hallo,

Ich habe da n kleines Zahlenproblem. Ich bekomme vom meinem LM75 die 
Temperatur im Binären Format geliefert.

Sowohl TWI wie auch Display laufen schon.

Nun will ich die Temperatur in Dezimal auf einem LCD ausgeben. Wer kann 
mir dabei helfen wie ich die Binäre Zahl so umwandeln kann damit ich Sie 
an das Display schicken kann ??

ICH HABE DIE FAQ gelesen und nichts gefunden was mir geholfen hat, NEIN 
ich will keinen Fertigen Code auf dem Silbertablett serviert bekommen 
und NEIN, die Suche durch das Forum hat keinen für mich verständlichen 
Erfolg gebracht.

Ich brauche eine Lösung die in Assembler umgesetzt werden kann. In C 
Hilft mir das leider alles nichts.

Danke im Voraus für die Hilfe :-)

Mfg

Tim

von Remote O. (remote1)


Lesenswert?

entweder schaust du dir itoa mal etwas genauer an, oder die nachfolgende 
Funktion:
1
/**
2
* Wandelt übergebene Vor- und Nachkommastellen durch Festkommaarithmetik in eine Zeichenkette um.
3
* @param vork Angabe der Vorkommastelle
4
* @param nachk Angabe der Nachkommastelle
5
* @param tstring Pointer der Zeichenkette, in welche Ergebnis gespeichert werden soll (muss mind 10Bytes beinhalten, z.B. '-125.1250'+'Stringende')
6
*/
7
void temptoa(int8_t vork, int8_t nachk, char* tstring)
8
{
9
  uint8_t i; 
10
  int16_t tmp;
11
12
  tstring[9]='\0';      //Stringende-Zeichen
13
  tmp=nachk>>4;      //laut Datenblatt nur ersten 4 Bit für Nachkomma
14
  if( vork < 0 ) {    //Vorzeichen hinzufügen
15
      tstring[0] = '-';              
16
      vork = -vork;
17
    //1 auffüllen geaschieht automatisch wenn msb=1
18
    //tmp|=0xFFF0;    //wenn negativ, dann durch >>4 entstandenen 0 mit 1 ersetzen, damit noch negative Zahl
19
    tmp=-tmp; 
20
  }
21
  else {
22
    tstring[0] = ' ';
23
    tmp&=~(0xFFF0);    //falls pos Temp, aber nachk=0b10000000 --> durch msb=1 und >>4 wird nach vorne automatisch mit 1 aufgefüllt, da µC denkt dass neg. Zahl
24
  }
25
 
26
  for(i=3; i>=1; i--) {
27
    tstring[i]=(vork % 10) +'0';  //Schleife rückwärts wegen modulo, '0' Addieren um ASCII-Wert für Zahl zu erhalten
28
    vork /= 10;            //nächste Stelle (kein Komma, da variable 'vork' kein float)
29
    }
30
31
  tstring[4]=',';
32
33
  tmp=tmp*625;            //eigentlich *0,0625, aber *625 um float zu vermeiden
34
  for(i=4; i>=1; i--) {
35
    tstring[4+i]=(tmp % 10) +'0';  //Schleife rückwärts wegen modulo, '0' Addieren um ASCII-Wert für Zahl zu erhalten
36
    tmp /= 10;            //nächste Stelle (kein Komma, da vork kein float)
37
    }
38
}

Ich muss dazu sagen, dass die Funktion bei meinem DS7505 genutzt wird. 
Der hat ein paar mehr Nachkommastellen (12Bit Auflösung). Deswegen hatte 
ich mich für eine programmierung der Festkommaarithmetik entschieden um 
dem Problem aus dem Weg zu gehen ständig mit 0,0625 zu multiplizieren.

von Tim M. (astarot)


Lesenswert?

Danke für die schnelle Antwort,
kann man den Code auch in Assembler portieren?? Die Funktion in C  sieht 
schon sehr komfortabel aus aber ich MUSS das Problem vorerst in 
Assembler lösen ;-))

Grüße

Tim

von Michael U. (amiga)


Lesenswert?

Hallo,

schau ins Tutorial unter ADC, ziemlich am Ende gibt es auch eine 
Int_to_ASCII in ASM.

http://www.mikrocontroller.net/articles/AVR-Tutorial:_ADC#Ausgabe_als_Spannungswert

Gruß aus Berlin
Michael

von Remote O. (remote1)


Lesenswert?

Ich bin in Assambler nicht so fit, aber ein paar Schleifen, If 
bedingungen, Shifts etc. solltest du doch hinkriegen. Im Endeffekt wird 
ja nichts gemacht, als die "binäre" Zahl modulo 10 zu dividieren um die 
einzelnen Stellen zu erhalten und dann mit ASCII '0' zu addieren.
Sonderfall ist hier nur, dass bei den Nachkommastellen diese im 
vordersten Nibble  stehen und ich da um 4 shiften muss. Deswegen musste 
ich auch  aufpassen, dass ich mir dadurch nicht eine "negative" Zahl 
erstelle (also noch einmal Maskieren)

von Tim M. (astarot)


Lesenswert?

Danke für den Tip,
lerne gerade erst mit den uC´s umzugehen und am Anfang ist alles immer 
ziemlich verwirrend.

Warum muss man mit ASCII '0' addieren ??

mfg
Tim

von holger (Gast)


Lesenswert?

>Warum muss man mit ASCII '0' addieren ??

Weil '0' 0x30 ist. Und 0x30 + 0 ist '0'
Weil '1' 0x31 ist. Und 0x30 + 1 ist '1'
...

Und wenn man sich mal die Mühe macht nach
ASCII Code zu suchen, dann findet man das in 0.3s.

Aber manche sind einfach nur zu faul.

von Tim M. (astarot)


Lesenswert?

Hallo Holger,

danke für deine Hilfe.

Es tut mir leid dich enttäuschen zu müssen.

ETWAS NICHT ZU VERSTEHEN heißt nicht FAUL zu sein.

Mich nervt es echt immer wieder in Foren auf KLUGSCHEI?ER zu stoßen die 
anscheinend auf nichts anderes warten als ihren Frust an Leuten 
auszulassen die FREUNDLICH nach Hilfe Fragen.

Wenn ich zu FAUL gewesen WÄRE dann hätte ich geschrieben das ich keinen 
BOCK habe selber nach einer Lösung zu suchen und jemanden brauche der 
MEIN Problem löst.

Wie du aber sicherlich lesen kannst habe ich darum geben mich auf den 
Richtigen Weg zu bringen weil ich selber nicht auf die Lösung komme.

Es hat halt nich jeder der mit dem Thema uC anfängt schon profundes 
Wissen aus der Weltraumforschung parat.

Und ich habe nunmal gelernt, das wenn ich etwas nicht weiss nunmal 
Fragen muss damit es einem jemand erkährt !!

Wenn doofe Kommentare ernten wollte dann hätte ich den Thread wohl eher 
:"Haltet mir für doof und Faul" bennen sollen.

Nichts gegen dich persönlich aber ich hab die Nase voll in Foren immer 
wieder nur zu lesen :"DU DEPP MUSST DIE SUCHE BENUTZEN", dann bräuchte 
man nämlich kein Forum mehr sondern nur noch ein WIKI....

Und wie bereits geschrieben nutzt einem die beste Hilfe nichts, wenn man 
Sie nicht versteht oder eindfach nur ne Denkblockade hat...

mfg

Tim

von Draco (Gast)


Lesenswert?

Da stimme ich Tim völlig überein!!! Manchmal ist es echt graußig 
geworden hier, viele denken sie seien Gott und man müsste ihnen die 
Füsse lecken.

Sehr schade eigentlich :/

Aber es gibt hier zum Glück genauso viele, die sehr hilfreich zur Seite 
stehen, auch blutigen Anfängern - denen gillt auch hier mein Dank!

Und WARUM man zu 0x30 nochmal ne 0 addieren muß hast du noch nicht mal 
beantworten können holger.

von Stephan H. (stephan-)


Lesenswert?

weil 30 Hex eine 0 Dezimal ist. Laut ASCII Tabelle.

von Stephan H. (stephan-)


Lesenswert?

in Assembler ganz grob so, ( einfache Methode)

Zähler (B) mit 30h vorladen (wegen ASCII)
dann Ausgangswert (A) von LM 75 in Hex minus 64h (100dez)
 und den Zähler (B) plus eins
Wenn kein Überlauf dann wieder minus 64h und Zähler plus eins.
das ganze so lange bis überlauf ist ( als Schleife )
Wenn Überlauf dann Zähler (B) minus eins und Ausgangswert (A) plus 64h

jetzt das ganze mit 0Ah (10 dez) (als schleife)
und dann noch mit 1 (als Schleife )

gilt allerdings erstmal für 8 Bit Zahlen. Bei 16 Bit entsprechend 
größer.

zB. mal für 16 Bit...8051
geht aber auch anders...

************************************************************
; 16 bit Binär zu Dez /ASCI   16 Bit wert in R2 high, R3 Low
;************************************************************
asci1  equ  30h
asci2  equ  31h
asci3  equ  32h
asci4  equ  33h
asci5  equ  34h



  mov  asci1,#30h               ; 00 für Dez / 30h für ASCII
  mov  asci2,#30h
  mov  asci3,#30h


  mov  r2,#0h
  mov  r3,#09h
  clr  c
  ;mov  b,#10000
div10000:  mov  a,r3        ; Zehntausender
    subb  a,#10h
    mov  r3,a
    mov  a,r2
    subb  a,#27h
    mov  r2,a
    jc  end_zt
    inc  asci1
    jmp  div10000
end_zt:          mov  a,r3
          add  A,#10h
          mov  r3,a
          mov  a,r2
          addc  a,#27h
          mov  r2,a
div1000:        clr  c
    mov  a,r3       ; Tausender
          subb  a,#0E8h
          mov  r3,a
          mov  a,r2
          subb  a,#03h
          mov  r2,a
          jc  end_t
          inc  asci2
          jmp  div1000
end_t:    mov  a,r3
    add  a,#0E8h
    mov  r3,a
    mov  a,r2    ; Hunderter
    addc  a,#03h
          mov  r2,a
div100:    clr  c
    mov  a,r3
    subb  a,#64h
    mov  r3,a
    mov  a,r2
    subb  a,#0
    mov  r2,a
    jc  end_h
    inc  asci3
    jmp  div100
end_h:    mov  a,r3       ; Zehner und Einer
    add  a,#64h
    mov  b,#0Ah
      div  ab
      add  a,#30h
      mov  asci4,a
      mov  a,b
      add  a,#30h
      mov  asci5,a
      mov  a,asci1    ; Vornullunterdrückung
      cjne  a,#30h,null4
      mov  asci1,#20h
null1:    mov  a,asci2
    cjne  a,#30h,null4
    mov  asci2,#20h
null2:    mov  a,asci3
    cjne  a,#30h,null4
    mov  asci3,#20h
null3:    mov  a,asci4
    cjne  a,#30h,null4
    mov  asci4,#20h
null4:

          end

von Tim M. (astarot)


Lesenswert?

Also muss ich das Register (z.B. R16)= 00011111 durch Modulo 10 Teilen,

mag jetzt wieder ne Anfänger Frage sein, aber der Befehlssatz sieht 
keine Modulo Operation vor......

Werde aber sicherheitshalber (bevor ich wieder angeraunzt werde) das AVR 
Arithmetic Tutorial durchforsten ob ich da was finde.

Aber davon mal abgesehen. Ich Teile die Zahl durch 10 und der "Modulo" 
Rest gibt dann die erste Dezimalstelle an, die nächste Modulo 10 
Operation gibt dann den "Rest" also die 2.te Dezimalstelle aus usw.

Würde es funktionieren das ich diese Schleife unterbrechen kann wenn ich 
das Register auf "o" überprüfe ??

Also tst R16 oder ist das zu einfach gedacht??

mfg

Tim

von Stephan H. (stephan-)


Lesenswert?

ich denke Du willst Assembler ?? Module gibts da nicht.

von Tim M. (astarot)


Lesenswert?

Oh, da war Stephan ein kleines bisschen schneller als ich mit meinen 
Fingern.

Werde mir das Listing mal genauer anschauen. Ich Danke dir schonmal 
dafür.

Wenn ich Dazu Fragen habe, wende ich mich vertrauensvoll an dich ;-))

Gruß
Tim

von Tim M. (astarot)


Lesenswert?

Ich meinte ja auch die MODULO Operation. Tschuldigung wenn ich da was 
falsch geschrieben habe.

Ich bezog mich mit der MODULO Operation auf Remote1

mfg

Tim

von Georg (Gast)


Lesenswert?

@stephan

Das ist 8051-Assembler.

Ich fürchte der TO hat einen AVR (zumindest ist "tst R16" ein 
AVR-Befehl).

von Stephan H. (stephan-)


Lesenswert?

war nen Schreibfehler von mir. Aber die MODULO gibts in ASM nicht.
Auf nem 8051 kannst Du DIV AB machen und mit nem AVR halt die 
Schleifenmethode mit Subtraktion (Urmethode).
Der AVR kann nicht dividieren (in Hardware).
(Außer zu Schieben damit die Profis nicht raunen)

von Tim M. (astarot)


Lesenswert?

Mit dem Überlauf ist das CARRY Flag gemeint?? geht das auch auf "1" wenn 
eine Rechenoperation negativ geworden ist??

Ich ging bis jetzt davon aus, das ein Carry nur kommt wenn ich einen 
positiven Überlauf habe..

mfg

Tim

von Stephan H. (stephan-)


Lesenswert?

@georg,
jep richtig erkannt. MODULO ist aber auch kein ASM :-)
Mal schauen was er aus dem DIV AB beim Zehner macht !

von old-school (Gast)


Lesenswert?

Hallo Tim,

der LM75 ist doch über I2C angeschlossen ?

da solltest du aber 2 Byte in denen die benötigten 9Bit sind) bekommen 
...

das 1. Byte Bit(7) Polarität  Bit 6-0 und vom 2. Byte Bit(7) für Komma 
(5) Wert.

------
1.Byte   2.Byte

00000001 0xxxxxxx =   1,0
00000000 1xxxxxxx =   0,5
00000000 0xxxxxxx =   0,0 Grad
11111111 1xxxxxxx = - 0,5
11111110 0xxxxxxx = - 1,0


usw.

Gruss Ralf

von Georg (Gast)


Lesenswert?

Zu schade, daß der AVR keinen DA (decimal adjust) Befehl hat, dann wärs 
ganz einfach (alles andere könnte man übersetzen).

16 Bit binär nach packedBCD für 8051:

        BIN to BCD:

    For R2=#16d      ;Bit-Anzahl
      mov R0, #Integer  ;LSB
      clr C
      for R3=#2    ;Byte-Anzahl=2
        mov A, @R0
        rlc A
        mov @R0, A
        inc R0
      next
      mov R0, #BCD_Wert
      for R3=#2    ;Byte-Anzahl=2
        mov A, @R0
        addc A, @R0
        da A
        mov @R0, A
        inc R0
      next
    Next
  ret

von Tim M. (astarot)


Lesenswert?

@old school

Jepp da haste Recht. Ist in 2 Byte untergebracht.

Ich habe mir folgenden Ansatz ausgedacht (wenn ich auch noch nicht weiss 
wie das Umsetzen kann):
Ich Maskiere mit einer Bitmaske das erste Byte aus ob ich eine führende 
1 habe (>> neg Zahl). Wenn "ja" dann das 2.er Komplement bilden und 
schonmal ein "-" ans Display, wenn "nein" kein 2.er Komplement bilden 
und "+" ans Display senden.

Im nächsten Schritt würde ich im ersten Byte die Umwandlung von Bin in 
Ascii durchführen um den Temp Wert "Betrag" zu haben.

Zuletzt würde ich im 2.ten Byte das MSB auf 0 oder 1 überprüfen um zu 
wissen ob ich ,5 oder nicht ,5 Anzeigen muss.

Zu guter letzt würde ich (von hinten nach Vorne) die Zahlen ans Display 
ausgeben. Alternativ könnte man doch auch nach jeder "Umwandlung" die 
entsprechende Zahl an das Display senden, da ich ja mit "-100" anfange 
also die 100.er Stelle auslote ???

Mfg

Tim

von Tim M. (astarot)


Angehängte Dateien:

Lesenswert?

Also, habe gerade mal einen Test gemacht und in AVR Studio Simuliert.

Zum guten Schluss muss ich noch temp1-temp3 mit "30h" addieren um das 
entsprechende ASCII Zeichen für die Zahl zu erhalten.

Anschließen muss ich "nur noch" temp1-3 an das Display übergeben und 
hätte schon mal in Dezimal die Temperatur dort stehen.

Negative Temperaturen und Nachkommastellen sind noch nicht 
berücksichtigt !!!

Es geht dabei lediglich um die Umwandlung in ASCII.

Ist das so Richtig wie ich das gemacht habe ??
Mfg

Tim

von holger (Gast)


Lesenswert?

>Es geht dabei lediglich um die Umwandlung in ASCII.
>Ist das so Richtig wie ich das gemacht habe ??

Schon mal selber ausprobiert?

von Stephan H. (stephan-)


Lesenswert?

>Zum guten Schluss muss ich noch temp1-temp3 mit "30h" addieren um das
>entsprechende ASCII Zeichen für die Zahl zu erhalten.

und genau deswegen wurde der Zähler bei mir mit 30h vorher geladen.
tricky !!

von Tim M. (astarot)


Lesenswert?

Stephan Henning schrieb:
> und genau deswegen wurde der Zähler bei mir mit 30h vorher geladen.
> tricky !!

Da haste recht, warum einfach wenn´s auch schwer geht grins.

Werde mal nach der Arbeit versuchen das ganze einzubinden. Ich danke 
euch für die Tips. Ihr habt mir wirklich weitergeholfen.

Jetzt habe ich es verstanden was da passieren muss damit es klappt.

mfg

Tim

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
Noch kein Account? Hier anmelden.