Forum: Compiler & IDEs I2C Scanner / STM32 Adressproblem..


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Daniel S. (sany)


Lesenswert?

Moin Zusammen,

Habe einen STM32F407VET6 und programmiere in C++

Aktuell habe ich mich gewundert, warum mein Slave mit der I2C Adresse 
0x01 nicht von meinem Scanner gefunden wird.

Der Fehler war über den Logicanalyzer schnell gefunden.
Mein Scanner scannt in 2er Schritten die I2C Adressen bis 128...
Aber warum? Für meinen I2C Bus nutze ich das 7-Bit Addressing..
1
int i2c_RailScanner()
2
{
3
  uint8_t i = 0;
4
  int found = 0;
5
6
  for(i=1; i<128; i++)
7
  {
8
    if(HAL_I2C_IsDeviceReady(&hi2c2, (uint16_t)(i<<1), 2, 50) == HAL_OK)
9
    {
10
      if(i2c_deviceFound(i))
11
      {
12
        found++;
13
      }
14
    }
15
  }
16
17
  if(found == 0)
18
    error = true;
19
20
  return found;
21
}

Scannt dann jewels 0x02, 0x04, 0x06,0x08,0xA0,0xC0 etc...

von N. M. (mani)


Lesenswert?

1
HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout);

Und warum genau machst du DevAddress*2?

1
if(HAL_I2C_IsDeviceReady(&hi2c2, (uint16_t)(i<<1), 2, 50) == HAL_OK)
2
    {
3
}

von Hmmm (hmmm)


Lesenswert?

Daniel S. schrieb:
> (uint16_t)(i<<1)

Da wird die 7-Bit-Adresse ein Bit nach links geschoben, die sieht dann 
also so aus, wie sie auf dem Bus übertragen wird (Bit 7-1 I2C-Adresse, 
Bit 0 R/!W).

Welche Variante (nackte 7-Bit-Adresse oder 1 Bit nach links geschoben) 
HAL_I2C_IsDeviceReady() haben will, musst Du in der Dokumentation 
nachlesen.

von Daniel S. (sany)


Lesenswert?

Wo steht denn DevAddress*2 ?
Die Adresse wird eigentlich nur verschoben...

von Hmmm (hmmm)


Lesenswert?

Daniel S. schrieb:
> Die Adresse wird eigentlich nur verschoben...

Binärsystem, Schieben nach links = Multiplikation mit 2.

Aber nach dem, was ich spontan finde, ist der Aufruf schon korrekt. Hast 
Du vielleicht das Slave-Device vermurkst? Zeig doch mal, was der Logic 
Analyzer ausspuckt.

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Daniel S. schrieb:
> Wo steht denn DevAddress*2 ?
> Die Adresse wird eigentlich nur verschoben...

Dann solltest Du Dich vielleicht noch einmal mit Grundschulmathematik 
beschäftigen.

von Daniel S. (sany)


Angehängte Dateien:

Lesenswert?

> Dann solltest Du Dich vielleicht noch einmal mit Grundschulmathematik
> beschäftigen.

Na wenn du das sagst..! :)

> Binärsystem, Schieben nach links = Multiplikation mit 2.
Ah okay, wusste ich nicht, muss selten etwas schieben.

Generell funktioniert mein Slave, der Master hat die Adresse 0x00, und 
der Slave hat die 0x01.

Wenn ich dem Slave die Adresse 0x02 gebe, wir er auch gefunden...
Mich wundert eben nur, warum bei meinem STM32 in 2er Schritten gezählt 
wird, selbst wenn ich die Schiebung nach links weg lasse..

von Hmmm (hmmm)


Lesenswert?

Daniel S. schrieb:
> Mich wundert eben nur, warum bei meinem STM32 in 2er Schritten gezählt
> wird, selbst wenn ich die Schiebung nach links weg lasse..

Weil Du die I2C-Adressierung nicht begreifst?

Zeig doch endlich mal, was der Logic Analyzer anzeigt. Und zwar das rohe 
Signal, nicht nur das Log des Decoders.

Nochmal zur Verdeutlichung: Bit 0 ist R/!W. Wenn Dein Slave die 
7-Bit-Adresse 0x01 hat, wird er auf dem Bus mit 0x02 (write) und 0x03 
(read) angesprochen.

: Bearbeitet durch User
von Daniel S. (sany)


Angehängte Dateien:

Lesenswert?

> Weil Du die I2C-Adressierung nicht begreifst?
Scheinbar, arbeite jedoch öfters mit I2C, auch erfolgreich.. scheinbar 
verstehe ich Sie wohl wirklich nicht... Warum aber, zählt der selbige 
Code auf einem ESP32 die Adressen von 1 bis 128 durch?

>Zeig doch endlich mal, was der Logic Analyzer anzeigt. Und zwar das rohe
>Signal, nicht nur das Log des Decoders.

Im Anhang, da findest du nicht viel, da der Slave mit 0x01 beim Scannen 
nicht gefunden wird, da:

i=1 ... Mein Master hat die Adresse 0x00 und mein Slave hat die Adresse 
1, also 0x01 (Steht so auch im I2C Register des Slaves)..

von Hmmm (hmmm)


Lesenswert?

Daniel S. schrieb:
> Warum aber, zählt der selbige
> Code auf einem ESP32 die Adressen von 1 bis 128 durch?

Weil es wie gesagt zwei Schreibweisen von I2C-Adressen gibt, die rohe 
7-Bit-Adresse und die um 1 Bit nach links verschobene, wie man sie auf 
dem Bus findet.

Bei fremden Libraries musst Du immer darauf achten, welche benötigt 
wird.

Daniel S. schrieb:
> Im Anhang, da findest du nicht viel, da der Slave mit 0x01 beim Scannen
> nicht gefunden wird

Da wird 0x01 (7-Bit-Adresse) zum Schreiben angesprochen (-> 0x02) und 
liefert kein ACK.

Dein Problem ist der Slave.

von Clemens L. (c_l)


Lesenswert?

Daniel S. schrieb:
> der Master hat die Adresse 0x00, und der Slave hat die 0x01.

Die STM-Hardware unterstützt das, damit die Firmware solche Sachen wie 
General Call implementieren kann. Aber du solltest trotzdem keine 
ungültigen Adressen verwenden.
https://www.i2c-bus.org/addressing/

von Mario P. (mario_71950c)


Lesenswert?

Ein Problem sind die reservierten Bereiche bei der Adressierung beim 
I2C. Gültige Slave-Adressen sind größer als 0x07 und kleiner als 0x78.
Die Adresse 0x01 ist als CBUS Addresse reserviert. Die CBUS-Adresse 
wurde reserviert, um das Mischen von CBUS-kompatiblen und 
I2C-Bus-kompatiblen Geräten im selben System zu ermöglichen. 
I2C-Bus-kompatible Geräte dürfen beim Empfang dieser Adresse nicht 
antworten.

von Daniel S. (sany)


Lesenswert?

Moin,

Hm okay... verstehen tu ich es immer noch nicht ganz.

Zu meinem Verständnis, der HAL I2C Treiber erwartet ja eine geshiftete 
Adresse 8-Bit.

Ich stelle nun im Master also die Adresse 0x10 ein. (Ohne <<1 ?)
In meinem Slave stelle ich dann nun die Adresse 0x20 ein (Ohne <<1 ?)

Beim Transmit vom Master gebe ich dann als Adresse 0x20<<1 an? Der HAL 
Treiber macht ja somit daraus "0x40" also das doppelte, aber der Slave 
hat ja dann nur die Adresse "0x20"... oder denke ich falsch?

vielen lieben Dank.

von Harald K. (kirnbichler)


Lesenswert?

Daniel S. schrieb:
> Zu meinem Verständnis, der HAL I2C Treiber erwartet ja eine geshiftete
> Adresse 8-Bit.

Tut er das? Steht das irgendwo, oder reimst Du Dir das irgendwie 
zusammen?
Woher stammt der Code, den Du am Anfang gezeigt hast? Hast Du den selbst 
geschrieben, oder hast Du den irgendwo im Internet gefunden, oder wird 
explizit darauf hingewiesen, daß der für genau den von Dir verwendeten 
HAL-Treiber passt?

von Clemens L. (c_l)


Lesenswert?

Daniel S. schrieb:
> Ich stelle nun im Master also die Adresse 0x10 ein. (Ohne <<1 ?)
> In meinem Slave stelle ich dann nun die Adresse 0x20 ein (Ohne <<1 ?)

Die 7-Bit-Adresse muss die selbe sein. Ob mit oder ohne Shift, musst du 
in der jeweiligen Dokumentation nachschauen (wenn sie denn existiert und 
auffindbar ist).

Soweit ich sehe, will der STM32-HAL eine geshiftete Adresse.

von Harald K. (kirnbichler)


Lesenswert?

Die Dokumentation 
(https://www.disca.upv.es/aperles/arm_cortex_m3/llibre/st/STM32F439xx_User_Manual/group__i2c__exported__functions__group2.html#gade6a669a25f0e99ef7fd52724acb3dec)

schreibt bei allen Funktionen, denen eine Geräteadresse übergeben wird, 
dies hier:

> DevAddress  Target device address The device 7 bits address value
> in datasheet must be shifted to the left before calling the interface

Die einzige Ausnahme ist die Funktion  HAL_I2C_IsDeviceReady. Da steht 
nur:

> DevAddress  Target device address

Absicht oder Versehen?

: Bearbeitet durch User
von Daniel S. (sany)


Lesenswert?

>> DevAddress  Target device address The device 7 bits address value
>> in datasheet must be shifted to the left before calling the interface

So stehts auch in den Funktionen.. nichts neues?

> Die einzige Ausnahme ist die Funktion  HAL_I2C_IsDeviceReady. Da steht
> nur:

>> DevAddress  Target device address
>
> Absicht oder Versehen?

Stimmt für die HAL_I2C_IsDeviceReady funktioniert.

Leider wurden meine Fragen aber nicht beantwortet.
>> https://controllerstech.com/stm32-as-i2c-slave-part-1/

Hier wird der STM32 Slave lediglich mit 0x12 Adresse eingerichtet,

Master-Code:
1
  /* USER CODE BEGIN 2 */
2
3
  uint16_t slaveADDR = 0x12<<1;
4
  uint8_t TxData[6] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6};
5
  while (1)
6
  {
7
    HAL_I2C_Master_Transmit(&hi2c1, slaveADDR, TxData, 6, 1000);
8
    HAL_Delay (1000);
9
  }

Hier wird die Adresse mit 0x12<<1 geshiftet... Aber der Slave wird gar 
nicht erreicht, selbst wenn ich den Code Original nachbaue, sagt mir 
mein Saleae Analyzer das beim Transmit die Adresse 0x24 angesprochen 
wird (Verdoppelt) aber er kann die Adresse 0x24 garnicht erreichen, weil 
der Slave hat die Adresse 0x12 hat...!

Wenn ich nun den Master Code um die Funktion HAL_I2C_IsDeviceReady 
erweitere und die 0x12 prüfe, erhalte ich vom Slave ein ACK.

Prüfe ich mit 0x12<<1 wird die 0x24 geprüft und es folgt ein NAK.

Welche Adresse wäre denn nun korrekt?

Ich bin mittelmäßig verwirrt...

von Oliver S. (oliverso)


Lesenswert?

Daniel S. schrieb:
> Welche Adresse wäre denn nun korrekt?
>
> Ich bin mittelmäßig verwirrt...

Das ist dabei üblich. Die offizielle Spec nennt für die Adresse 7 Bits, 
die im Telegramm ein Bit links geschiftet übertragen wird, mit dem 
red/write-Bit hinten dran.

99% aller Libs implementieren den Shift aber nicht, die erwarten die 
Adresse als linksgeschifteten 8-Bit-wert.

Insofern hilft da RTFM, oder einfach ausprobieren.

Oliver

von Steve van de Grens (roehrmond)


Lesenswert?

Oliver S. schrieb:
> Insofern hilft da RTFM, oder einfach ausprobieren.

Ich würde in den Quelltext schauen, wenn es nicht dokumentiert ist.

: Bearbeitet durch User
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.