Forum: Mikrocontroller und Digitale Elektronik LM75A reagiert nicht, I2C funktioniert


von Heinz M. (subi)


Lesenswert?

Hallo,

ich bin mal wieder ratlos.

Den I²C nutze ich inzwischen ohne nennenswerte Probleme. Nur der LM75 
will iregndwie nicht.

Es handelt sich um diesen:
https://docs-emea.rs-online.com/webdocs/14e5/0900766b814e5831.pdf

Momentan wird nichts weiter gemacht, als 0x00 über die Adresse 0x90 
(alle Adresspins auf GND) zu senden und dann sollen 2 Bytes über 0x91 
empfangen werden. Aber schon beim Senden reagiert der LM75 nicht. Mir 
ist bewusst, dass ich die 0x00 nicht senden müsste um die Temperatur zu 
lesen.

Ich habe probiert:
- Zwei weitere LM75
- Pinbelegung schon 10x kontrolliert
- Lange und kurze Kabel
- Am gleichen Bus laufen noch andere Geräte ohne Probleme (2 Displays 
und ein Portexpander)
- GY-511 (Gyro) ebenfalls an den gleichen Bus, nur Adressen und Register 
gewechselt, ansonsten identischer Code wie für den LM75 und er 
antwortet.
- Pullup Widerstände (1K und 10K)
- Kondensator laut Datenblatt an die Versorgungspins
- Pegelwandler um von den knappen 2,82 auf 4,2 V zu kommen. Ebenfalls 
mit Pullup und Kondensator
- SDA und SCL getauscht
- Was ich nicht testen kann ist die Geschwindigkeit des I²C Busses 
ändern, weil er sich aufhängt, wenn sich zu viel Arbeit anstaut, die er 
über I²C nicht weg bekommt. Laut Datenblatt 2,5 µs für einen Takt, was 
400 MHz (Fast Mode) entspricht. Diese sind bei mir eingestellt.

Bus ist in Ordnung und Hardware wüsste ich nicht was ich sonst noch 
versuchen soll.

Der Code ist unspektakulär und wie gesagt, funktioniert mit dem Gyro.
1
if(i2c1.useSendewunschFlag(temp1.readDeviceID(),true) == 1 && tempAuswertung == 0) //darf ich?
2
{
3
4
  i2c1.setTxRxSperre(temp1.readDeviceID()); //Sperrt Zugriff auf i2c1, damit dma nicht unterbrochen wird.
5
6
  //funktioniert: Portexpander
7
  //buffer[0] = 0x12;
8
  //HAL_I2C_Master_Transmit_DMA(&hi2c1,0x40,buffer,1);
9
10
  //funktioniert: Gyro
11
  //buffer[0] = 0x28;
12
  //HAL_I2C_Master_Transmit_DMA(&hi2c1,0x32,buffer,1);
13
14
  //funktioniert nicht: LM75
15
  buffer[0] = 0x00;
16
  HAL_I2C_Master_Transmit_DMA(&hi2c1,0x90,buffer,1);
17
18
  tempAuswertung = 20;
19
}
20
21
if (tempAuswertung == 20 && i2c1.readBusyTxFlag() == false) //gesendet?
22
{
23
  //funktioniert: Portexpander
24
  //HAL_I2C_Master_Receive_DMA(&hi2c1,0x41,RxBuffer,2); 
25
26
  //funktioniert: Gyro
27
  //HAL_I2C_Master_Receive_DMA(&hi2c1,0x33,RxBuffer,2); 
28
29
  //funktioniert nicht: LM75
30
  HAL_I2C_Master_Receive_DMA(&hi2c1,0x91,RxBuffer,2);
31
32
  tempAuswertung = 30;
33
}
34
35
if (tempAuswertung == 30 && i2c1.readBusyRxFlag() == false) //empfangen?
36
{
37
  i2c1.resetTxRxSperre(); //Gibt Zugriff wieder frei
38
  temperatur[0] = RxBuffer[0];
39
  temperatur[1] = RxBuffer[1];
40
  tempAuswertung = 0;
41
}

von Stefan F. (Gast)


Lesenswert?

Welchen Wert liefert HAL_I2C_Master_Transmit_DMA(&hi2c1,0x90,buffer,1) 
zurück?

Oder: Antwortet der Sensor nach der Adresse mit einem ACK? Antwrotet er 
nach dem einen Byte mit einem ACK? Das kannst du mit einem Logic 
Analyzer oder Oszilloskop prüfen.

von Crazy Harry (crazy_h)


Lesenswert?

Schaltplan/Layout?

von Heinz M. (subi)


Lesenswert?

@Stefanus:

Hätte ich vielleicht noch schreiben sollen. Nach erfolgreicher 
Kommunikation springt er in eine dieser beiden Funktionen. Macht er aber 
nicht. Als wenn unter der Adresse niemand anzutreffen ist.
1
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c1)
2
{
3
  i2c1.resetBusyTxFlag();
4
}
5
6
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c1)
7
{
8
  i2c1.resetBusyRxFlag();
9
}

Logic Analyzer und Oszi sind nicht zur Hand.

Wie kann ich das machen mit Wert zurückgeben lassen? Über die Error 
Handler?

@Crazy: Siehe Beschreibung.

von Stefan F. (Gast)


Lesenswert?

Heinz M. schrieb:
> Wie kann ich das machen mit Wert zurückgeben lassen?

Die Funktionliefer einen Rpckgabewert zurpck, den musst du nur in eine 
Variable speichern und kontrollieren. Die Funktion ist so deklariert:

HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, 
uint16_t DevAddress, uint8_t *pData, uint16_t Size);

Wenn die Funktion nicht HAL_OK zurück liefert, kannst du 
HAL_I2C_GetError(I2C_HandleTypeDef *hi2c) aufrufen, um Details zum 
Fehler zu erhalten.

> Logic Analyzer und Oszi sind nicht zur Hand.

Dann kaufe Dir mal ganz schnell wenigstens so einen billigen "8ch Logic 
Analyzer" für 8€, denn Analysieren ist besser als Raten.

von Harry L. (mysth)


Lesenswert?

Heinz M. schrieb:
>
>
> void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c1)
> {
>   i2c1.resetBusyRxFlag();
> }

ic2c1.resetBusy... ist vollkommen überflüssig, aber dafür fehlt die 
Abfrage, ob der Callback auch wirklich zu deinem i2c-Port gehört.

Ausserdem sollte der i2c-Handle in der Funktion nicht den selben Namen 
haben wie das tatsächlich genutzte (globale) i2c-Handle.

So sollte das aussehen:
1
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
2
 {
3
   if(hi2c == &hi2c1)
4
   {
5
       // do something
6
   }
7
 }

: Bearbeitet durch User
von Heinz M. (subi)


Lesenswert?

@Stefanus:
1
buffer[0] = 0x00;
2
test=HAL_I2C_Master_Transmit_DMA(&hi2c1,0x90,buffer,1);
3
HAL_Delay(30);
4
if (test == 0)
5
  HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
Er liefert 0 zurück. Egal ob bei funktionierendem Gyro oder nicht 
funktionierendem LM75. Nur mit dem Unterschied, dass er bei dem Gyro in 
den Callback reinspringt und beim LM75 nicht. Bei Adressen wo definitiv 
nichts dran hängt liefert er auch 0. Sollte er da nicht eine 3 liefern?


@Harry: Danke, da wäre ich wohl später drüber gestolpert. An dem 
resetBusy hängt noch mehr dran, was aber nichts mit dem aktuellen 
Problem mit dem LM75 zu tun hat. Wollte euch nicht zumuten den ganzen 
Code durchzuakkern, da er ja mit den anderen I²C Geräten funktioniert. 
Und bevor ihr noch mehr Fehler findet :-X

von Stefan F. (Gast)


Lesenswert?

Heinz M. schrieb:
> Bei Adressen wo definitiv
> nichts dran hängt liefert er auch 0. Sollte er da nicht eine 3 liefern?

So genau kenne ich die HAL nicht. Dein Ergebnis überrascht mich 
jedenfalls. Was sagt den die Doku der HAL dazu?

von Harry L. (mysth)


Lesenswert?

Häng mal nen Logic-Analyser dran!
Das sagt mehr als 1000 Worte.

von Heinz M. (subi)


Lesenswert?

"HAL_OK       = 0x00U,
HAL_ERROR    = 0x01U,
HAL_BUSY     = 0x02U,
HAL_TIMEOUT  = 0x03U"

Quelle: 
https://community.st.com/s/question/0D50X00009XkXjvSAF/halstatustypedef

Daher wenn eine Adresse angeschrieben wird, wo kein Gerät antworten 
könnte, müsste eigentlich 3 kommen. Es kommt aber 0. Im Gegensatz dazu 
reagiert er aber richtig, dass er nicht in den Callback springt. 
Vielleicht hab ich auch was bei der Fehlerabfrage falsch, weil er immer 
0 ausspuckt.

von Stefan F. (Gast)


Lesenswert?

Da gibt es doch so eine HAL_I2C_IsDeviceReady Funktion (ohne DMA). 
Liefert die den richtigen Return Code zurück?

Siehe Beitrag "Re: Problem mit I2C scan auf Adresse von HTU21D"
Zumindest beim User M.G. tut sie, was man von ihr erwartet.

von Heinz M. (subi)


Lesenswert?

Hab die Funktion so eingebaut:
1
test=HAL_I2C_IsDeviceReady(&hi2c1,0x32,1,10);

Dann bleibt er komplett stecken. Mainloop wird nicht weiter ausgeführt. 
Habe es mit dem Portexpander gegengeprüft, der definitiv funktioniert.

Auch wenn ich die Adresspins alle auf High mache und OS offen lassen das 
gleiche.

von Stefan F. (Gast)


Lesenswert?

Heinz M. schrieb:
> Dann bleibt er komplett stecken

Messe mal die Pegel an den Leitungen SCL und SDA in diesem hängenden 
Zustand. Wenn eine der beiden Leitungen auf Low hängt, trenne den Sensor 
im laufenden Betrieb ab. Bleibt sie dann immer noch auf Low?

Auf diese Weise findest du heraus, ob der Sensor oder der 
Mikrocontroller hängt.

Pull-Up Widerstände sind noch vorhanden, hoffe ich ?!?

von Heinz M. (subi)


Lesenswert?

Aktuell sieht es so aus.

µC
|
- 1 kOhm Pull-Up
|
- Portexpander (funktioniert)
- Display1 (funktioniert)
- Display2 (funktioniert)
|
Levelshifter TXB0104
|
- 1 kOhm Pull-Up
|
- LM75

Auf LM75 Seite:
4,26 V VCC
1,75 V bzw. 1,74 V wenn er hängt
0,67 V wenn ich die Datenleitung abziehe
µC hört auf zu senden (mit LEDs an Leitung getestet)

Wenn ich mein normales Programm nehme, dann arbeitet der µC ganz normal 
weiter. (ohne den Levelshifter -> Pegel high)

Mit dem IsDeviceReady bleibt er jedoch stehen. (Ohne den Levelshifter -> 
Pegel low)

von Stefan F. (Gast)


Lesenswert?

Heinz M. schrieb:
> 1,75 V bzw. 1,74 V wenn er hängt
> 0,67 V wenn ich die Datenleitung abziehe

Das sind beide unerwartete Werte.

Im Ruhezustand sollen beide Leitungen High Pegel haben. Ich denke, du 
solltest da weiter forschen, am Besten mit einem Oszilloskop. ielleicht 
passen die recht niederohmigen Pull-Up Widerstände nicht oder der 
Pegelwandler funktioniert nicht.

Warum betreibst du den LM75 nicht einfach mit 3,3V und ohne 
Pegelwandler? Ich würde das wenigstens mal ausprobieren, um Probleme 
durch den Pegelwandler auszuschließen.

von Heinz M. (subi)


Lesenswert?

Diese LM 75 sind mit 2,8 bis 5,5 V spezifiziert. Das Discovery Board, 
welches ich als Programmer nehme liefert ~2,91 V.

Über 10 cm 0,75 mm² kommen auf dem Breadboard nur noch 2,78 V an.

Daher der Versuch mit dem Pegelwandler.

Ohne Pegelwandler sind es 2,53 V bzw. 2,62 V wenn er bei dem 
IsDeviceReady hängen bleibt.

Wechsle ich auf HAL_I2C_Master_Transmit_DMA sind es 0,37 V (SCL) und 
2,85 V. VCC ist in dem Fall auf 2,82 V angestiegen.

Edit: Displays und Portexpander funktionieren auch "ohne" Pull-Up. Ich 
vermute auf den Display Baords sind schon welche drauf. Beim LM75 habe 
ich mit denen von den Displays, als auch die separaten 1k versucht.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Heinz M. schrieb:
> Wechsle ich auf HAL_I2C_Master_Transmit_DMA sind es 0,37 V (SCL) und
> 2,85 V. VCC ist in dem Fall auf 2,82 V angestiegen.

Messungen am I²C Bus mit dem Multimeter müssten im Ruhezustand fast VCC 
(höchstens 0,1V darunter) und im Fehlerfall wenn ein Gerät hängt fast 0V 
(maximal 0,1V) ergeben. Deine Messwerte deuten für mich auf eine 
Hardwareproblem hin, dass du wie gesagt mit einem Oszilloskop weiter 
untersuche kannst.

Alternativ kannst du ein Testprogramm schreiben, dass die beiden Pins im 
10 Sekunden Takt (im Open-Drain Modus!) auf High/Low umschaltet und dann 
man die Pegel Messen.

Und den LM75 kannst du durch Taster (nach GND hin) ersetzen und dann man 
die Spannungen vor und hinter dem Pegelwandler messen (bei High und 
Low).

Möglicherweise fließen da zu hohe Ströme: Kann man auch messen.

von Harry L. (mysth)


Lesenswert?

Heinz M. schrieb:
> Hab die Funktion so
> eingebaut:test=HAL_I2C_IsDeviceReady(&hi2c1,0x32,1,10);
>
> Dann bleibt er komplett stecken. Mainloop wird nicht weiter ausgeführt.

Den aktuellen Status bekommst du mit:
1
Result = HAL_I2C_GetState(&hi2c);

Wenn alles gut gegangen ist, enthält Result:

HAL_I2C_STATE_READY

Andere mögliche Stati findest du in der Doku.

von Wolfgang (Gast)


Lesenswert?

Heinz M. schrieb:
> Momentan wird nichts weiter gemacht, als 0x00 über die Adresse 0x90
> (alle Adresspins auf GND) zu senden und dann sollen 2 Bytes über 0x91
> empfangen werden. Aber schon beim Senden reagiert der LM75 nicht.

Bist du sicher, dass deine I2C-Receive und -Transmit Funktionen nicht 
die I2C-Adresse entsprechend Tab. 4 im Datenblatt erwarten?

Evtl. hast du mit der dort für A0..2=0 angegeben Adresse 0x48 mehr 
Glück. Sonst lasse einfach mal einen I2C-Scanner den gesamten 7-Bit 
Adressraum absuchen.

von Harry L. (mysth)


Lesenswert?

Die I2C-Adresse steckt bei allen HAL-Funktionen in den oberen 7bit.
Bit0 ist R/W

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.