Forum: Mikrocontroller und Digitale Elektronik Problem mit I2C scan auf Adresse von HTU21D


von M. G. (ixil96)


Lesenswert?

Hallo,

ich programmiere gerade die I2C-Schnittstelle (Controller = STM32L476RG) 
zum HTU21D Sensor. Als IDE verwende ich Atollic Truestudio.

Mit dem folgenden Codeschnippsel frage ich die Adresse (sollte lt. 
Datenblatt eigentlich 0x40 sein) ab.

Für die Abfrage verwende ich eine HAL-Funktion und übergebe als 
Parameter i für die Adresse. Die Variable i ist global und beginnt bei 
0:
1
  /**
2
    * @brief  Checks if target device is ready for communication.
3
    * @note   This function is used with Memory devices
4
    * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains the configuration information for the specified I2C.
5
    * @param  DevAddress Target device address: The device 7 bits address value in datasheet must be shifted to the left before calling the interface
6
    * @param  Trials Number of trials
7
    * @param  Timeout Timeout duration
8
    * @retval HAL status
9
    */
10
  for (; i<255; i++)
11
  {
12
    if(HAL_I2C_IsDeviceReady(&hi2c1, i, 1, 10) ==  HAL_OK)
13
    {
14
      HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
15
      break;
16
    }
17
  }

Das seltsame dabei ist, dass HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); nie 
ausgeführt wird (Das Programm bleibt hier auch bei einem Breakpoint 
nicht stehen). Die Abfrage wird aber bei i=128 (0x80) beendet.

von Stefan F. (Gast)


Lesenswert?

Welchen Typ hat i und mit welchem Startwert fängst du an?

Ist Dir bewusst, dass I²C Adressen normalerweise nur 7 Bits haben, also 
niemals den Wert 255 haben können?

Dass dein Pin nie getoggelt wird könnte schlicht daran liegen, dass dein 
Sensor nicht antwortet.

Ich würde Dir empfehlen, die Kommunikation mit einem "8ch logic 
analyzer" zu untersuchen. Was du auch noch ganz fix prüfen solltest, ist 
die Spannung an SDA und SCL. Beide Leitungen müssen vor und nach dem 
Programm-Ablauf auf High Pegel liegen, also deutlich mehr als 2 Volt.

von Thomas Z. (usbman)


Lesenswert?

M. G. schrieb:
> Die Variable i ist global und beginnt bei 0

eine Schleifenvariable i global zu machen darauf muss man erst mal 
kommen.

Thomas

von M. G. (ixil96)


Lesenswert?

Thomas Z. schrieb:
> M. G. schrieb:
>> Die Variable i ist global und beginnt bei 0
>
> eine Schleifenvariable i global zu machen darauf muss man erst mal
> kommen.
>
> Thomas

Ja genau....

Wie soll ich sie sonst beim Debuggen überwachen...?

von M. G. (ixil96)


Angehängte Dateien:

Lesenswert?

Ich habe SCK und SDA mit dem Oszi aufgenommen. Das ist die Übertragung 
der Adresse 0x40.

Ich interpretiere das als START - 0100 0000 ACK - STOP

Somit sollte das denke ich passen...

: Bearbeitet durch User
von Thomas Z. (usbman)


Lesenswert?

M. G. schrieb:
> Ja genau....
>
> Wie soll ich sie sonst beim Debuggen überwachen...?

Bedeutung man kann nur globale Variablen überwachen? Wenn das so sein 
sollte würde ich über eine alternative Toolchain nachdenken.

Thomas

von M. G. (ixil96)


Lesenswert?

Thomas Z. schrieb:
> M. G. schrieb:
>> Ja genau....
>>
>> Wie soll ich sie sonst beim Debuggen überwachen...?
>
> Bedeutung man kann nur globale Variablen überwachen? Wenn das so sein
> sollte würde ich über eine alternative Toolchain nachdenken.
>
> Thomas

Dann wäre ich dir sehr dankbar, wenn du es mir für Atollic TrueStudio 
zeigen könntest wie das geht!

von Thomas Z. (usbman)


Lesenswert?

nun eine Möglichkeit die immer gehen wird wäre z.B die Variable lokal 
als static zu definieren. Und ja mir ist durchaus bekannt dass so ein 
Konstrukt auch eine globale Var erzeugt die halt nur lokal sichtbar ist.

Beispiel:
1
char foo(void)
2
{
3
  char static i = 0;
4
  ...
5
  return i;
6
}

von Stefan F. (Gast)


Lesenswert?

M. G. schrieb:
> Wie soll ich sie sonst beim Debuggen überwachen...?

Lokale Variablen kannst du genau so überwachen. üge sie einfach zum 
Watch Fenster hinzu oder setze eine Haltepunkt innerhalb der Schleife 
und zeige dann mit der Maus drauf.

von Joachim B. (jar)


Lesenswert?

M. G. schrieb:
> Das ist die Übertragung
> der Adresse 0x40.

und mit 64d kleiner als 127 0x7f

also warum?

M. G. schrieb:
> for (; i<255; i++)

wenn es eh höhere Adressen gibt I2C Erweiterung muss man die oberhalb 
anders ansprechen.....
http://gedankenlyrik.bplaced.net/www/studium/seminararbeit_2008.pdf

nun gilt noch zu klären wie deine SW I2C ansprechen möchte,

entweder mit 7-bit
1
  for(address = 1; address < 127; address++ ) 
2
  { //The i2c_scanner uses the return value of
3
    //the Write.endTransmisstion to see if
4
    //a device did acknowledge to the address.
5
    Wire.beginTransmission(address);
6
    error = Wire.endTransmission();
7
8
    if (error == 0)
9
    { DEBUG_PRINT(F("I2C found at Add. 0x"));

oder mit 8-bit +R/W
1
if(!i2c_start(PCF8574A_0+I2C_READ))  //;  // set device address and write mode

von Stefan F. (Gast)


Lesenswert?

M. G. schrieb:
> Ich interpretiere das als START - 0100 0000 ACK - STOP

Das neunte Bit hat High Pegel, das ist ein NACK. Dein Sensor hat nicht 
geantwortet.

von M. G. (ixil96)


Lesenswert?

Stefanus F. schrieb:
> M. G. schrieb:
>> Ich interpretiere das als START - 0100 0000 ACK - STOP
>
> Das neunte Bit hat High Pegel, das ist ein NACK. Dein Sensor hat nicht
> geantwortet.

Danke für die Info! Das habe ich wohl falsch interpretiert... 1 = NACK, 
0 = ACK.

Die Initialisierung habe ich über CubeMX gemacht. Eingestellt ist eine 
7-Bit Adressierung.
1
  hi2c1.Instance = I2C1;
2
  hi2c1.Init.Timing = 0x10909CEC;
3
  hi2c1.Init.OwnAddress1 = 0;
4
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
5
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
6
  hi2c1.Init.OwnAddress2 = 0;
7
  hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
8
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
9
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

Ich habe jetzt 3 Sensoren mit unterschiedlichen Pull-up Widerständen 
(2k2, 4k7 und 10k) getestet.

von Stefan F. (Gast)


Lesenswert?

Bis auf das fehlende ACK sieht dein Oszilloskop-Bild gut aus. Am 
Programm kann es daher nicht liegen.

von M. G. (ixil96)


Lesenswert?

Wer lesen kann ist klar im Vorteil...

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

Naja, eine gemeine Falle

1
/**
2
  * @brief  Checks if target device is ready for communication.
3
  * @note   This function is used with Memory devices
4
  * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
5
  *                the configuration information for the specified I2C.
6
  * @param  DevAddress Target device address: The device 7 bits address value
7
  *         in datasheet must be shifted to the left before calling the interface
8
  * @param  Trials Number of trials
9
  * @param  Timeout Timeout duration
10
  * @retval HAL status
11
  */
12
HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout)

von Stefan F. (Gast)


Lesenswert?

M. G. schrieb:
> The device 7 bits address value in datasheet must be shifted to the left
> before calling the interface.

Guter Hinweis,
dann hätte der Sensor auf die Adresse 0x80 (128) reagieren müssen.

was zu dieser Aussage passt:

> Die Abfrage wird aber bei i=128 (0x80) beendet.

M.G. vielleicht musst du einfach noch ein bisschen üben, den Debugger zu 
bedienen!? Fange mal damit, die Optimierungsstufe des Compilers auf -Og 
oder -O0 zu ändern. Hat deine Projekt nicht genau dafür zwei 
unterschiedliche Konfigurationen vorbereitet? Zumindest bei der System 
Workbench wäre das standardmäßig der Fall.

Siehe 
http://blog.atollic.com/how-to-create-and-modify-a-build-configuration-video-tutorial

von M. G. (ixil96)


Angehängte Dateien:

Lesenswert?

Mit übergabe von 0x80 sieht die Sache schon besser aus...

jetzt noch den Rest mit Auslesen usw.

@ Stefanus F. Da hast du recht! Üben muss ich noch ganz viel. Ich 
arbeite mich erst in die ganze STM32 Geschichte und TrueStudio ein.

von Stefan F. (Gast)


Lesenswert?

M. G. schrieb:
> it übergabe von 0x80 sieht die Sache schon besser aus...

Na also, geht doch! Erste Hürde geschafft. Jetzt spiele mit dem Debugger 
herum, bevor du weiter programmierst. Denn den wirst du noch öfter 
benutzen wollen.

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.