STM32, i2c Daten verarbeiten..

OP #7549147
Lesenswert?

Moin!

Ich arbeite derzeit an einer Kommunikation zwischen einem STM32F407 (Master) und 6x STM32F103 (Slave) die über I2C im Interrupt / DMA Betrieb und einer RJ45 Verbindung kommunizieren sollen.

Der Master erkennt an den RJ45 Ports wo ein Slave angeschlossen wurde, da ein Pin auf 3.3V gezogen wird und somit ein Interrupt für den RJ45 Port ausgelöst wird.

Da die Slave Platinen alle gleich sind, wird beim einstecken jedem Slave eine neue I2C Adresse zugewiesen, funktioniert auch prima.

Nun mache ich mir über die Kommunikation gedanken.

Der Master schickt einen Abragebefehl für die Softwareversion an den Slave, der Slave soll den Befehl erkennen und entsprechend mit der Softwareversion antworten.

Leider hängt mein Hirn etwas...

Um die Daten auf dem Slave zu empfangen nutze ich folgenden Code:

1
#define GET_VERSION 0x01
2
#define GET_VOLTAGE 0x02
3

4
uint8_t txData[6];
5
uint8_t RxData[6];
6

7
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
8
{
9
  if(TransferDirection == I2C_DIRECTION_TRANSMIT)
10
  {
11
    HAL_I2C_Slave_Seq_Receive_IT(hi2c, RxData, 6, I2C_FIRST_AND_NEXT_FRAME);
12
  }
13
  else
14
  {
15
    HAL_I2C_Slave_Seq_Transmit_IT(hi2c, txData, 6, I2C_FIRST_AND_LAST_FRAME);
16
  }
17
}
18

19
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
20
{
21
  rxCount++;
22
        process_data();
23
}
24

25
void process_data()
26
{
27
 switch(RxData[0])
28
 {
29
   case GET_VERSION:
30
     txData[0] = 0x1;
31
     txData[1] = 0x2;
32
     txData[2] = 0x3;
33
   break;
34
   case GET_VOLTAGE:
35
      txData[0] = 0x6;
36
      txData[1] = 0x7;
37
      txData[2] = 0x8;
38
      txData[3] = 0x9;
39
   break;
40
   default:
41
    break;
42
 }
43
}

So nun habe ich diverse Probleme, mit dem jetzigen Code kommt beim Master lediglich 6x 0x0 an.

Ich hatte auch schon die Variante,

1
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
2
{
3
  rxCount++;
4
        process_data();
5
        HAL_I2C_Slave_Seq_Transmit_IT(hi2c, txData, 6, I2C_FIRST_AND_LAST_FRAME);
6
}

Leider empfängt der Master dann null komma garnix, über den Analyzer sehe ich eben nur das auf den Slave geschrieben wird, aber kein Read...

Weiß jemand zufällig rat, oder stelle ich mich doof an?

OP #7549232
Lesenswert?

Ouh Sorry, hats nicht angehängt.

Bild 1: Ist die Variante 1 mit: Hier Empfängt der Master das vom Slave, schickt aber seltsamer weiße noch ein NACK mit hinterher.. ?!

1
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
2

3
{
4

5
  if(TransferDirection == I2C_DIRECTION_TRANSMIT)
6

7
  {
8

9
    HAL_I2C_Slave_Seq_Receive_IT(hi2c, RxData, 6, I2C_FIRST_AND_NEXT_FRAME);
10

11
  }
12

13
  else
14

15
  {
16

17
    HAL_I2C_Slave_Seq_Transmit_IT(hi2c, txData, 6, I2C_FIRST_AND_LAST_FRAME);
18

19
  }
20

21
}

Bild 2 ist die Variante 2:

1
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
2

3
{
4

5
  rxCount++;
6

7
        process_data();
8

9
        HAL_I2C_Slave_Seq_Transmit_IT(hi2c, txData, 6, I2C_FIRST_AND_LAST_FRAME);
10

11
}

Man sieht, der Master versucht zu lesen, erhält aber nix bei Bild 2... und der Mastercode bleibt stehen...

Angehängte Dateien:
OP #7549248
Lesenswert?

Ali K. schrieb:

Fürs Lesen sendet man normalerweise erstmal die Slave Adresse und danach ein Write auf die Registeradresse, danach ein Repeated Start, danach folgt direkt ein Read.

Bitte?

Ich nutze die HAL-Bibliothek, warum sollte das bitte falsch sein?

Der Code für den Master:

1
uint16_t slaveADDR = 0x18<<1;
2
uint8_t TxData[6] = {0x2,0x2,0x3,0x4,0x5,0x6};
3

4
......
5

6
  /* USER CODE BEGIN WHILE */
7
  while (1)
8
  {
9
    /* USER CODE END WHILE */
10

11
    /* USER CODE BEGIN 3 */
12

13
    HAL_I2C_Master_Transmit(&hi2c2, slaveADDR, TxData, 6,1000);
14
    uint8_t rxData[6];
15
    while(HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY) {}
16

17
    HAL_I2C_Master_Receive(&hi2c2, slaveADDR, rxData, 6, 1000);
18
    HAL_Delay(1000);
19
  }
20
  /* USER CODE END 3 */

Es wird zu erst an den Slave geschrieben und dann die Daten vom Slave abgeholt, was soll denn bitte da nicht passen?

Gast #7549569
Lesenswert?

Mit der HAL kenne ich ich nicht aus, aber I²C habe ich öfters benutzt und debuggt.

Dein Bild von Variante 1 zeigt, dass der Master nach dem Read 0x18 Kommando 6 Bytes liest. Danach beendet er die Übertragung mit NACK und STOP. Soweit alles gut.

In der zweiten Variante bestätigt der Slave das Read 0x18 Kommando ebenfalls ordentlich mit ACK. Doch danach hält jemand die Taktleitung auf LOW, gibt des Bus nicht mehr frei. Die Spannende Frage ist, wer den Bus blockiert: Master oder Slave?

Trenne den Master oder den Slave vom Bus, der Pull-Up Widersdtand soll aber bleiben. Wenn der SCL Pegel dabei auf High wechselt, dann hat der abgetrennte Busteilnehmer den Bus blockiert. Ansonsten war es der andere.

Für eine etwas schnellere Analyse von Blockaden kann die angehängte Schaltung als Bus-Ersatz hilfreich sein. Wenn du magst, kannst du sie 2x aufbauen so dass du auch an SDA so eine Anzeige hast. Die flackernde LED signalisiert Aktivität auf dem Bus. Eine dauerhaft leuchtende signalisiert eine Blockierung. Damit kannst du das Programm Zeile für Zeile durch steppen und siehst sofort, ab wo der Bus hängt.

Im blockierten Zustand sagt dir der Spannungsabfall an den 47Ω Widerständen der SCL Leitung, welche Seite der Bösewicht ist. Auf der Seite wo Spannung am Widerstand abfällt ist die Blockade.

Was du auch tun kannst:

Prüfe im Debugger, wo deine Code-Ausführung hängen bleibt. Ich vermute in der Zeile

while(HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY) {}

Schaue im Quelltext nach, was da genau abgefragt wird und vergleiche das mit der Doku im Datenblatt.

Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren