Forum: Mikrocontroller und Digitale Elektronik LM75 funktioniert nicht


von Kai M. Tegtmeier (Gast)


Lesenswert?

Ich habe ein Problem mit einem Mega32 und einem LM75. Ich versuche, ihn
auszulesen, bekomme aber immer nur 0 als Ergebnis. Zum Auslesen benutze
ich die Bibliotheksfunktionen, die mit dem Codevision-Compiler
mitgeliefert werden. Angeschlossen wird der LM75 an irgendeinen Port,
der nur ganz vorne im Programm definiert werden muß. Das habe ich auch
gemacht. Kann es eventuell sein, daß der I2C-Bus in Verbindung mit
dieser Programmbibliothek externe Pull-up-Widerstände braucht?!? Oder
gibt es noch irgendwelche anderen Dinge, die schiefgelaufen sein
könnten?

Vielen Dank für Eure Hinweise!
Gruß
KMT

von Sebastian Wille (Gast)


Lesenswert?

Hi,

also ohne Source ist sowas natürlich immer schwer...

Ich habe meine I2C-Schaltung immer (!) mit externen PullUps, und das
muß auch so sein. Denn die internen PullUps gehen ja nur bei
Port-Eingang, ohne externe PullUps gibts Chaos.

Probier's mal und wenn's immer noch nicht geht, poste Deinen Code.

Sebastian

von Kai M. Tegtmeier (Gast)


Lesenswert?

Vielen Dank für die schnelle Antwort. Die schlausten Programme scheitern
ja fast immer an den dümmsten Problemen. Habe jetzt externe Pull-ups
eingebaut, jetzt läuft es. Ich bin aus welchem Grund auch immer davon
ausgegangen, daß der AVR die Pull-ups selber zur Verfügung stellt (ich
glaub, ich hab sowas in der Beschreibung vom TWI gelesen - aber das
waren ja auch andere Pins...)

Nochmals vielen Dank und viele Grüße
Kai Markus

von Sebastian Wille (Gast)


Lesenswert?

Hi Kai,

schön, daß es nun klappt!

TWI ist ja auch was anderes... Codevision ignoriert TWI und läßt Dir
freie Hand bei der Wahl der beiden I2C-Pins, oder?

Wie gesagt, PullUps gibt's nur beim Port-Eingang. Der Port für den
I2C-Datenkanal ist abwechselnd Ein- und Ausgang. Und bei den
"Umschaltungen" zwischen Ein- und Ausgang gibt's ohne externe
PullUps Probleme.

Als PullUp rate ich Dir ca. 10 kOhm.

Noch 'ne Frage von mir: Wo hast Du denn den LM75 bekommen? Danke!

Sebastian

von Kai M. Tegtmeier (Gast)


Lesenswert?

Hi, Sebastian!

Ich hab auch zunächst gerätselt, ob ich am AVR überhaupt TWI
einschalten muß oder nicht. Habs einfach mal aus gelassen - geht
genauso. Anscheinend hat also die I2C-Bibliothek von Codevision nix mit
dem TWI-Interface am AVR zu tun. Ich hab jetzt als Pull-ups 3k3
genommen, weil ich die gerade zur Hand hatte. Tuts genauso.

Den LM75 hab ich, weil ich in der Nähe von Sande wohne, von Reichelt.
Ist doch ne Menge billiger als Conrad, selbst wenn man sich das
schicken läßt. Außerdem ist das IC-Sortiment wesentlich größer:
www.reichelt.de

Viele Grüße
Kai Markus

von Stefan G. (Gast)


Lesenswert?

Hallo Kai Markus,
mal kurz ne andere Frage: ich bastel ja auch gerade mit dem LM75 rum.
Ich möchte erstmal nur einen anschliessen. Benötige ich da alle Adress
input pins? Also A0, A1 und A2?
Gruß,
Stefan

von Kai M. Tegtmeier (Gast)


Lesenswert?

Hallo, Stefan!

Yup, du benötigst alle Adress-Pins. An den Adress-Pins wird digital
eingestellt, welche Subadresse der LM75 auf dem I2C-Bus hat. Codiert
wird das ganze folgendermaßen:

A0 A1 A2
0  0  0   Adresse=0
1  0  0   Adresse=1
0  1  0   Adresse=2
1  1  0   Adresse=3
0  0  1   Adresse=4
1  0  1   Adresse=5
0  1  1   Adresse=6
1  1  1   Adresse=7

wobei 0 bedeutet, daß der entsprechende Pin mit Masse verbunden ist und
1 bedeutet, daß er mit der positiven Versorgungsspannung (je nach Chip
3,3V oder 5V) verbunden ist.

Wenn Du erstmal nur einen LM75 abfragen willst, würde ich Dir
empfehlen, über die Pins 5 bis 8 (A0-A2 und Vcc) eine Lötbrücke zu
legen. Damit liegen alle Adreßpins auf 1 und die Adresse ist 7. So hab
ich es gemacht.

Hoffe, das hilft Dir weiter. Ansonsten bin ich für Fragen immer offen.

Gruß
Kai Markus

von Stefan G. (Gast)


Lesenswert?

Hallo Kai Markus,
da unsere Programme sicher ziemlich ähnlich aussehen (ich benutze
ebenfalls Codevision und DS75) frage ich dich nochmal. Das mit den
Adresspins habe ich kapiert, habe sie ebenfalls miteinander und mit
V_cc verbunden und beim Wizard Adresse 7 ausgewählt.
Nun habe ich nochmal eine Frage zu den Pullups: Hast du da nun 10kOhm
genommen? Wo zwischen wird der Pullup genau geschaltet, zwischen V_cc
und Datenleitung?
Hast du auch einen Kondensator zwischen GND und V_cc oder ist der nicht
so wichtig?
Was genau bedeutet Open Drain (das steht öfter im Datenblatt), was muß
ich da beachten?
Liegt das Temperaturergebnis dann am O.S. Pin? Nur frage ich mich wie
ich das dann auslese, ist ja nur ein Bit.
Bei mir ist´s auch das ersten mal mit I2C, was mache ich mit dem SDA
Pin?

Meine Güte, eine Menge Fragen.
Vielleicht mache ich´s auch zu kompliziert, und Codevision nimmt mir
schon z.T. die Arbeit ab, aber durch die Verkabelung steige ich
nochnicht ganz durch.
Gruß,
Stefan

ps: und wie funktioniert das eigentlich genau mit T_OS und T_HYST?

von Kai M. Tegtmeier (Gast)


Lesenswert?

Hallo, Stefan!

Also, gehen wir die Fragen mal der Reihe nach durch.

1. Die Pull-up-Widerstände (10 kOhm sind ok) werden zwischen Vcc und
I2C-Busleitungen (SDA und SCL) geschaltet. Du benötigst also 2 Stück.

2. Den Kondensator habe ich schnöderweise einfach weggelassen. Wenn der
LM75 dicht am Prozessor sitzt, geht das auch; bei größerer
Leitungslänge empfiehlt es sich aber, den Kondensator zu benutzen.

3. Open drain ist eine Typenbezeichnung für einen Anschluß am IC. Es
bedeutet, daß der Ausgang selbst keine Spannung führt, sondern
lediglich im IC gegen Masse (in der Regel) geschaltet wird Das kann man
sich wie ein Relais vorstellen, wo der eine Anschluß des Schaltkontakts
offen liegt und am Pin des ICs abgegriffen werden kann. Der andere
Anschluß des Schaltkontakts ist mit Masse verbunden. Man bekommt also
bei einem open drain Anschluß nur eine Verbindung mit Masse. Um hier
ein verwertbares Logik-Signal abgreifen zu können, braucht man
Pull-up-Widerstände. Der I2C-Bus z.B. ist in open drain-Technik
ausgeführt.

4. Nej, das Temperaturergebnis mußt Du über den I2C-Bus auslesen. Dazu
schickt der AVR über die Leitungen SDA bzw. SCL ein Lese-Kommando mit
der Subadresse des LM75 an den Chip. Der wiederum antwortet mit der
9-bit breiten Temperaturinformation. Klingt alles sehr kompliziert; zum
Glück übernimmt der Codevision-Compiler die meiste Ablaufsteuerung. Du
mußt nur den I2C-Bus und den LM75 initialisieren und die Temperatur
auslesen. Bei Bedarf schicke ich Dir gerne meinen Quellcode zu.

5. Der O.S. Pin hat eine ganz andere Funktion. Er wirkt quasi wie ein
programmierbarer Temperatur-Alarm. Man kann für den LM75 eine
Temperaturschwelle (z.B. 60 Grad) programmieren, oberhalb derer dieser
Ausgang auf logisch 1 geht (Temperatur-Alarm). Des weiteren kann man
eine untere Temperaturschwelle programmieren (z.B. 55 Grad), die
unterschritten werden muß, damit diese logische 1 wieder gelöscht wird.
Wie genau der O.S. Pin sich verhält, hängt von der Programmierung ab
(sh. Datenblatt LM75)

6. SCL und SDA sind die Clock- bzw. Datenleitungen des I2C-Busses. Sie
müssen beide mit dem AVR verbunden sein und Pull-up-Widerstände
besitzen. O.S. kann man, wenn man ihn nicht braucht, offen lassen.

Soweit erstmal von mir; falls noch Fragen sind oder Du den Quellcode
haben möchtest, melde dich einfach.

Viele Grüße aus Buchholz in der Nordheide
Kai Markus

von Kai M. Tegtmeier (Gast)


Lesenswert?

Sorry, hab das jetzt gerade erst gesehen:

Beim Wizard brauchst Du die Adresse nicht auszuwählen; der Wizard
bedient sich des im AVR eingebauten TWI (two wire interface = I2C). Die
im Codevision eingebauten Bibliotheksfunktionen (lm75_init usw.)
pfeifen aber auf das TWI und nehmen ihr eigenes Protokoll. Schau mal in
die Codevision-Hilfe unter dem Stichwort LM75 (?), da ist ein
Beispiel-Programm, wie man den LM75 ansteuert. SDA und SCL können mit 2
beliebigen unbenutzten Portleitungen verbunden werden; es muß nur VOR
der Zeile #include <lm75.h> definiert werden, welcher Port und welche
Leitungen es sind. Bei Bedarf kannst Du gerne meinen Quelltext haben.

7. T_OS und T_HYST sind diese beiden programmierbaren
Temperaturschwellen, von denen ich geschrieben hatte. T_OS ist meines
Wissens die obere, T_Hyst die untere.

Nochmals viele Grüße aus Buchholz
Kai Markus

von Stefan G. (Gast)


Lesenswert?

Hallo Kai Markus,
erstmal vielen Dank für deine Ausführliche Antwort. Hat mir auf jedem
Fall weitergeholfen.
Ich habe nun alles angeschlossen, und einfach probiert mir die
Temperatur (bisher wohl noch als 9 bit 2er Komplement) auf dem Terminal
ausgeben zu lassen. Aber es tut sich einfach nichts. Irgendwo steckt
offenbar noch ein Fehler.
Hier erstmal was ich gemacht habe:
Lötbrücke über Adressleitungen und V_cc gelegt -> Sensor hat Adresse
7.
Einen Pullup Widerstand direkt vom SDA Pin des Sensors zum V_cc Knoten
gelegt, den anderen Pullup Widerstand vom SDL Pin des Sensors auf den
V_cc Knoten.
Laut meinem uC Datenblatt entspricht SDA Port C Pin1 und SDL Port C Pin
0. Ich habe also die entsprechenden Pins des Sensors direkt mit den
Pins  von Port C verbunden. Dann habe ich noch V_cc und GND man Masse
und Versorgungsspannung meines STK500 verbunden (Spannung habe ich auch
gemessen -> 5 V).
Den Programmcode hänge ich nochmal unten an, vielleicht siehst du da ja
noch einen Fehler oder hast sonst noch irgendeine Idee.
Gruß, Stefan

ps: Was verstehst du denn unter "dicht am Prozessor sitzen"?
Vieolleicht bräuchte ich ja doch einen Kondensator. Die Leitungen sind
bei mir ca. 20 cm lang.

Hier das Programm:

#include <mega323.h>
#include <delay.h>

// I2C Bus functions
#asm
   .equ __i2c_port=0x15
   .equ __sda_bit=1
   .equ __scl_bit=0
#endasm
#include <i2c.h>

// LM75 Temperature Sensor functions
#include <lm75.h>

// Standard Input/Output functions
#include <stdio.h>

// Declare your global variables here

void main(void)
{
// Declare your local variables here

int t;

// Input/Output Ports initialization
// Port A initialization
// Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In
Func7=In
// State0=T State1=T State2=T State3=T State4=T State5=T State6=T
State7=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In
Func7=In
// State0=T State1=T State2=T State3=T State4=T State5=T State6=T
State7=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In
Func7=In
// State0=T State1=T State2=T State3=T State4=T State5=T State6=T
State7=T
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In
Func7=In
// State0=T State1=T State2=T State3=T State4=T State5=T State6=T
State7=T
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
GICR|=0x00;
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud rate: 115200
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x01;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
// Analog Comparator Output: Off
ACSR=0x80;
SFIOR=0x00;

// I2C Bus initialization
i2c_init();

// LM75 Temperature Sensor initialization
// thyst: 75°C
// tos: 80°C
// O.S. polarity: 0
lm75_init(7,75,80,0);

while (1)
      {
      // Temperatur lesen vom Sensor mit Adresse 7:
      t = lm75_temperature_10(7);

      // Temperatur auf Terminal ausgeben:
      putchar(t);
      delay_ms(50);
      };
}

von Kai M. Tegtmeier (Gast)


Lesenswert?

Hmm, ich denke, Du solltest erst einmal versuchen, den Fehler
einzugrenzen, ob er am Messen des LM75 liegt oder an der
Terminalausgabe. Ich schicke Dir im Anhang mal meinen Sourcecode mit;
der liest das Temperatursignal vom LM75 und gibt es (unter schnöder
Mißachtung des 9. Bits - sehr unsauber programmiert ;-) auf PORTC aus,
wo ich LEDs angeschlossen habe. Meine Routine ist allerdings auf Port B
(0x18) gemünzt, läßt sich aber ja durch 0x15 sehr schnell auf PortC
umstellen. Du mußt dann nur die LED-Ausgabe auf einem anderen Port
machen (DDRC und PORTC nicht vergessen!). So kannst Du zunächst erstmal
eingrenzen, ob an deinem Meßvorgang oder am Terminal irgendwas nicht
stimmt.

Ich würde auch vor und nach dem Aufruf von lm75_init eine längere
Warteschleife einfügen, damit der Chip und der Bus Zeit haben, sich zu
initialisieren.

Des weiteren weiß ich nicht, wie dein Terminal darauf reagiert, wenn Du
ihm einen integer-Wert rüberschickst. Ich vermute mal, das geht auch
nicht so ohne weiteres. Wenn ich die Temperatur auf einem Display
angezeigt bekommen möchte, schreibe ich

printf ("%-i . %-u",t/10,abs(t%10));

Mit dieser Zeile statt der Putchar-Zeile müßte auch Dein Terminal
zurechtkommen, weil Codevision soweit ich weiß printf auch an die
USART-Schnittstelle schickt.

Gruß
Kai Markus

von Stefan G. (Gast)


Lesenswert?

Hallo Kai Markus,
irgendwie ist der Anhang nicht mitgekommen....

von Stefan G. (Gast)


Lesenswert?

Hi Kai Markus,
es tut sich was. Ich hatte da tatsächlich ein par Sachen vergessen und
habe das Programm nun nochmal folgendermaßen umgeändert:

int t;
char t_char[9];

while (1)
      {
      // Temperatur lesen vom Sensor mit Adresse 7:
      t = lm75_temperature_10(7);

      // int t in char umrechnen:
      itoa(t,t_char);

      // Temperatur auf Terminal ausgeben:
      puts(t_char);
      delay_ms(50);
      };

Ich hatte nun eigentlich damit gerechnet, daß ich jeweils 9 Zeichen
ausgegeben bekomme, ich bekomme aber immer nur 3. Zimmertemperatur
entspricht nun dem Wert 270 auf dem Terminal. Auch ändern sich die
Werte immer nur in 5er Schritten. Etwas merkwürdig. Ich werde nochmal
ein bischen suchen. Falls du noch eine Idee hast, her damit :-)

achja, diese Zeile hatte ich schon im Codevision Handbuch gelesen, mit
den Zeichen kann ich aber irgendwie nichts anfangen:
printf ("%-i . %-u",t/10,abs(t%10));
Kannst du mir sagen was da passiert?
Gruß,
Stefan

von Kai M. Tegtmeier (Gast)


Angehängte Dateien:

Lesenswert?

Oops, da hab ich doch glatt den Sourcecode vergessen. Aber diesmal dann.
Schön, daß sich jetzt bei Dir schon mal was tut.
Deine Annahme, daß aus dem LM75 9 Zeichen rauskommen, ist leider nicht
ganz richtig (wenn Du mit 9 Zeichen 9 character meinst). Es kommen aus
dem LM75 9 bit Temperaturinformation raus, verpackt in 2 Byte. Diese 2
Byte werden dann von der lm75_temperature Routine bereits in einen
°C-Wert umgerechnet und in einen Integer-Wert gepackt. Und diesen
Integer-Wert mußt Du dann als Zeichenkette auf das Terminal geben.
Gibst Du ihn mit putchar aus, sendet der Prozessor das ASCII-Zeichen 14
an das Terminal (270 = 256+14, das 9.Bit = 256 wird ignoriert). Das
ASCII-Zeichen 14 kann vom Terminal nicht dargestellt werden. Deshalb
hast Du auf dem Terminal nichts gesehen.
Die Zeile printf wandelt den Integer-Wert in eine Komma-Zahl um und
gibt sie auf dem Terminal aus, dabei wird das "%-i" in den
Anführungsstrichen durch den Wert t/10 ersetzt, das "%-u" durch den
Wert abs(t%10) - dafür wird übrigens die Header-Datei #include <math.h>
gebraucht.

Das Problem mit den 0.5-Sprüngen tritt bei mir auch auf; das liegt aber
daran, daß der LM75 nur eine Auflösung von 0.5 Grad hat. Ich gehe mal
davon aus, daß die lm75_temperature-Routine den Zahlenwert schon soweit
aufbereitet, daß nur noch 0.5-Sprünge vorkommen können.
Heißt, der nächste gültige Temperaturwert, den die Routine ausspuckt,
ist entweder 275 oder 265, entsprechend 27.5° oder 26.5° Die Tabelle
aus dem Datenblatt vom LM75 gilt also dafür nicht.

BTW, 270 (=27°C) Zimmertemperatur ist ja schon lekker warm...

Was die Art des Messens angeht, so steht im Datenblatt, daß der LM75
seine eigene Prozessortemperatur, nicht die Temperatur seines Gehäuses
mißt. Die beste thermische Kopplung mit dem Prozessor besteht laut
Datenblatt über den GND-Pin.

In der Hoffnung, etwas Licht ins Dunkel gebracht zu haben
Gruß
Kai Markus

von Stefan G. (Gast)


Lesenswert?

Hallo Kai Markus,
du hast mir auf jedem Fall schonmal geholfen. Nun weiß ich auch was
diese blöden %-i und %-u Befehle machen. Hatte ich nirgends gefunden
bzw. bin ich nie draus schlau geworden.
Dann hat´s bei mir ja eignetlich schon halbwegs funktioniert. Ich
dachte nur am Faktor 10 könnte es nicht liegen, da mir 27 Grad etwas
hoch vorkamen. Ich habe nun aber mal auf der Oberfläche meines DS75
gemessen, da waren es 25 Grad. Kommt also doch ganz gut hin. Aber was
meinst du mit "Die beste thermische Kopplung mit dem Prozessor besteht
laut Datenblatt über den GND-Pin"?

Nur was du oben geschrieben hattest mit 270=256+14 habe ich nicht ganz
verstanden. Warum meinst du, daß der uP probiert das ASCII Zeichen 14
zu senden?

Daß die 0,5 Sprünge an der 9 bit Auflösung liegen, ist mir dann auch
eingefallen. Meinen DS75 (hatte ich mir als Sample von Maxim bestellt)
kann man aber auch mit bis zu 12 bit Auflösung laufen lassen, aber da
muß man in irgendwelche Register des Sensors schreiben, von denen ich
noch nicht genau weiß, wie ich sie ansprechen kann.
Gruß,
Stefan

von Kai M. Tegtmeier (Gast)


Lesenswert?

Hallo, Stefan!

Die Aussage mit der thermischen Kopplung will meinen, daß in der Regel
der Prozessor im Inneren des LM75 die gleiche Temperatur hat wie sein
GND-Pin, das heißt also, die Wärme oder Kälte wird am schnellsten über
den GND-Pin zum Prozessor geleitet, noch schneller als über das
Plastik-Gehäuse (ist ja auch irgendwie logisch: zum GND-Pin hat der
Prozessor eine Verbindung aus Metall, zum Gehäuse nur eine aus Plastik,
was ja doch die Wärme schlechter leitet...)

Was ich mit dem ASCII-Zeichen 14 meine, ist folgendes:

Du bekommst als Ergebnis der Routine den Integer-Wert 270 raus.
Binär ausgedrückt wäre das 0000 0001 0000 1110 = 270
und in seine 2 Bytes zerlegt:    256+       14 = 270

Diesen Wert hast Du versucht, über putchar rauszugeben. Putchar
ignoriert bestenfalls die ersten 8 Bit vom Integer-Wert und gibt nur
das zweite Byte = 14 raus. Und das ASCII-Zeichen 14 ist auf jeden Fall
kein sichtbares Zeichen auf dem Terminal.

Viele Grüße
Kai Markus

von Stefan G. (Gast)


Lesenswert?

Hallo,
nun habe ich verstanden was du meintest. Danke.

Eine Frage habe ich aber noch :-)  :
Ich möchte letztendlich mit Hilfe des Tempsensors eine Heizungsregelung
realisieren (ein Metallblock mittels einer 24 Volt Heizpatrone
erwärmt).  Dazu benötige ich einen "vernünftigen" Temperaturwert, mit
dessen Hilfe ich dann Stellgröße etc. meines PID Reglers berechnen
kann. Was ich nun auf dem Terminal ausgebe sind ja Characters, oder?
Mir ist nicht ganz klar, was genau die Funktion lm75_temperature_10(7)
für einen Integer Wert rausgibt, bzw. wie ich mit diesem Wert arbeiten
kann. Meinetwegen auch erstmal (statt eines PID Reglers) mit einfachen
if - else Anweisungen und Ungleichungen (z.B. if (t_neu > 28){...} )

Hast du rausgefunden was diese Tempfunktion genau erzeugt?
Grüsse,
Stefan

von Stefan G. (Gast)


Lesenswert?

Ach ja, ich hatte gerade nochmal in das Library File gesehen (lm75.lib).
Dort wird die Funktion folgendermaßen programmiert:

int lm75_temperature_10(unsigned char chip)
{
union lm75_temp tt;
unsigned char i2c_addr;
i2c_addr=0x90|(chip<<1);
i2c_start();
i2c_write(i2c_addr);
i2c_write(0);
i2c_start();
i2c_write(++i2c_addr);
tt.b[1]=i2c_read(1);
tt.b[0]=i2c_read(0);
i2c_stop();
return (tt.w>>7)*5;
}

Verstehst du was da passiert?
Stefan

von Kai M. Tegtmeier (Gast)


Lesenswert?

So ungefähr überblicke ich schon, was da passiert. Meines Wissens nach
gibt die Funktion lm_temperature einfach nur den Temperaturwert mal 10
genommen als Integer raus. Diesen Wert kannst Du auch ohne weiteres in
Deinen Programm-Routinen abfragen. Die Umrechnung nach ASCII bzw. Char
wird ja nur durch den printf-Befehl gemacht und verändert den Inhalt
von temp nicht.

Was die Routine angeht, so geh ich mal Zeile für Zeile durch:


1. Funktion lm75_temperature_10 gibt integer zurück, bekommt char
übergeben.

2. Variable tt als Union-Typ lm75_temp deklarieren (was eine Union ist
--> siehe C-Handbücher)

3. i2caddr als char-Variable ohne Vorzeichen (d.h. 0-255) deklarieren

4. i2caddr (=Adresse vom LM75 auf dem I2C-Bus) ist gleich
0x90+(chip*2), also bei unserem Chip = 0x90+(2*7)= 0x9E. Chip ist die
Nummer des LM75, die man bei dem Aufruf der Funktion übergibt. Das
Multiplizieren mit 2 verschiebt die Chipnummer im Adressbyte um ein Bit
nach links, weil die Chip-Nummer im Adressbyte nicht in den letzten 3
Bits steht, sondern eine Position weiter links. Raus kommt dann
folgendes: i2caddr= 1 0 0 1 A2 A1 A0 0 mit A2,A1,A0 =1
Diese Zeile sagt dem Chip folgendes: ich will mit Chip 7 einen
Schreibzugriff (nämlich Pointer setzen) durchführen.

5. i2c-Start-Bedingung auf den Bus ausgeben.

6. i2c-Adresse auf den Bus ausgeben und damit den LM75 ansprechen.

7. "0" auf den i2c-Bus ausgeben, d.h. Register 0 auf dem LM75 soll
angesprochen werden. (im Datenblatt nennen die das "Pointer Byte").

8. wieder i2c-start-Bedingung ausgeben (sog. Repeated start condition)

9. i2caddr= 1 0 0 1 A2 A1 A0 1 heißt die nächste Zeile in Binär
übersetzt. Sie sagt dem Chip: ich will mit Chip 7 einen Lesezugriff
(nämlich auf das vorher festgelegte Register 0=temperaturinformation)
durchführen.

10. +11. die beiden folgenden Zeilen lesen die 2 Datenbytes der
Temperaturinformation vom Bus und schreiben sie in die Variable tt.

12. i2c-Stop-Bedingung senden.

13. als Ergebnis den 16-Bit-Wert in der Variable tt, aber um 7 Bits
nach rechts verschoben und mit 5 multipliziert, ausgeben. Das ist
nötig, um aus dem zweier-Komplement-Wert, den der Chip liefert, einen
einigermaßen handlebaren Integer-Wert zu machen.

Wenn Du dir das Datenformat ganz genau anschauen willst, empfehle ich
Dir S. 11 im Datenblatt vom LM75 (www.nsc.com). In der Zeile 1.12
(Temperature register) sieht man auch sehr gut, warum das Ergebnis um 7
Stellen nach rechts verschoben werden muß.

Viele Grüße einstweilen und viel Spaß beim Lesen!

Kai Markus

von Peter Scholz (Gast)


Lesenswert?

Hallo,


ich habe probleme mit dem beschreiben der Register im LM75.
Das Lesen aller Register klappt einwandfrei.
Bin nach dem Datenblattvorgrgangen.

Kann mir da jemand helfen?
Vielen Dank im voraus.
PS

von Noname (Gast)


Lesenswert?

Hallo

Brauche Hillllfeeeeeeeeeeee!!

Habe seit kuzem LM75, der auch nicht funktioniert!
Das Lesen des Temperaturregisters funktioniert, aber ich bekomme immer
die gleichen Werte (nur blödsinn)!

Es ändert sich nicht. Weder durch erhitzen noch durch abkühlen!! Habe
sogar kurtzzeitig Eisspray eingezetzt (-50 C°). Wenn es kaputt wäre,
würde doch die Kommunikation mit ATMega8 nicht funktionieren. Oder???

Ich benutze die SCK und SDA Leitungen der C-Ports mit 2,2k Ohm Pull-
ups.

Woher bekomme ich die Werte für die Pull- ups des I2C Busses?
Wie berechne ich es?? In Spezifikation der i2c nichts gefunden.

An Pin O.S des LM75 habe ich nicht angeschlossen, es hängt da ich es
nicht brauche. Ich will nur die aktuellen Temperaturen lesen können.

Kann es sein, dass man LM75 konfigurieren muss vorher? (Temperatur
lesen ist doch Voreinstellung im Config Register oder???)

Brauche auch die Libs II2C.lib und lm75.lib!! Wie kann ich sehen, was
die Funktionen i2c_start() usw. genau machen?



Jungs hilft mir!!!!

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.