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.
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.
@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.
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.
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:
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
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?
"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.
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.
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.
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 ?!?
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)
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.
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.
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.
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.
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.