Forum: Mikrocontroller und Digitale Elektronik STM32F103RFT6 I2C2 keine Funktion


von Bernd S. (soundgott)


Lesenswert?

Hallo auch,
ich brüte schon seit ein paar Tagen an der I2C Kommunikation (mit 
EEPROM, Display) an einem STM32F103RFT6. Die Pins PB10/11 führen die 
Signale SCL/SDA des 2. I2C Interfaces (I2C2). Pullups 3.6k sind dran. 
Selbst in einem minimalsten Testprogramm regt sich an den Leitungen 
nichts, dauerhafter Highpegel. Im Debugger sind alle notwendigen 
Register der RCC, GPIOB und I2C2 korrekt gesetzt. Gleiches Testprogramm 
für I2C1 konfiguriert, läuft ohne Probleme. Ich habe schon sämtliche 
Errata's und "googles" durch, nichts gefunden. Meine Hoffnung liegt nun 
hier. Hat jemand eine evtl Lösung?

von Patrick (dereine)


Lesenswert?

Moinsen,

wurde auch beim richtigen Package für die physischen Pins geguckt?

Laut Datenblatt liegen I2C2 SCL/SDA an Pin 29/30 für LQFP-64.
Nicht, das versehentlich bei LQFP-100 geguckt wurde und 47/48 vewendet 
wird.

Grüße,
derEine

von Kilo S. (kilo_s)


Lesenswert?

Sollen wir Hellsehen?

Zeig deinen CODE!

von Bernd S. (soundgott)


Lesenswert?

Patrick schrieb:
> Laut Datenblatt liegen I2C2 SCL/SDA an Pin 29/30 für LQFP-64.
> Nicht, das versehentlich bei LQFP-100 geguckt wurde und 47/48 vewendet
> wird.

Einwand berechtigt, ist aber korrekt angeschlossen (SCL: pin 29, PB10 
und SDA: pin 30, PB11)
Getestet wurde auf 2 verschiedenen Boards mit dem gleichen negativen 
Ergebnis.

Kilo S. schrieb:
> Sollen wir Hellsehen?
>
> Zeig deinen CODE!

Der Code für die Initialisierung, Nutzung der I2C-Schnittstellen dürfte 
den Wissenden bekannt sein. Es wurde mit verschiedenen Tests geprüft: 
Bare-Metal, HAL, StdPeripherie, auch mit STMCube erzeugter Code, alles 
mit gleichem Ergebnis. Das Ding rührt sich nicht.

von Patrick (dereine)


Lesenswert?

Gibt es sonst eventuell ein Konflikt mit einer aktivierten USART3 
Schnittstelle?

von Stefan S. (chiefeinherjar)


Lesenswert?

Bernd S. schrieb:
> Patrick schrieb:
>> Laut Datenblatt liegen I2C2 SCL/SDA an Pin 29/30 für LQFP-64.
>> Nicht, das versehentlich bei LQFP-100 geguckt wurde und 47/48 vewendet
>> wird.
>
> Einwand berechtigt, ist aber korrekt angeschlossen (SCL: pin 29, PB10
> und SDA: pin 30, PB11)
> Getestet wurde auf 2 verschiedenen Boards mit dem gleichen negativen
> Ergebnis.


Gut, an der Hardware liegt es nicht.

Bernd S. schrieb:
> Kilo S. schrieb:
>> Sollen wir Hellsehen?
>>
>> Zeig deinen CODE!
>
> Der Code für die Initialisierung, Nutzung der I2C-Schnittstellen dürfte
> den Wissenden bekannt sein. Es wurde mit verschiedenen Tests geprüft:
> Bare-Metal, HAL, StdPeripherie, auch mit STMCube erzeugter Code, alles
> mit gleichem Ergebnis. Das Ding rührt sich nicht.

Gut, die Software ist auch ausgeschlossen.

Also muss der Bug im Silizium des Chips sitzen - denn an dir bzw. 
deiner Schaltung (die du geheim hältst) und deinem Code (den du 
ebenfalls geheim hältst) kann es schließlich nicht liegen. Beides ist 
schließlich garantiert fehlerfrei - es stammt ja schließlich von dir.
Ergo können wir dir hier nicht weiterhelfen.

: Bearbeitet durch User
von Kilo S. (kilo_s)


Lesenswert?

Ah, der fehlerfreie perfekte Mensch erbarmt sich zu uns ins niedere 
Forum auf der Suche nach Hilfe die ja unmöglich auf einen seiner Fehler 
zurückzuführen sind!

Langsam aber sicher sind doch 90% der Menschheit noch zu doof einen 
Schuh vol pisse auszuleeren, bei dem die Anleitung dazu auf der Sohle 
steht!

Goodbye, TROLL!

von Bernd S. (soundgott)


Angehängte Dateien:

Lesenswert?

Stefan S. schrieb:
> Gut, die Software ist auch ausgeschlossen.
>
> Also muss der Bug im Silizium des Chips sitzen - denn an dir bzw.
> deiner Schaltung (die du geheim hältst) und deinem Code (den du
> ebenfalls geheim hältst) kann es schließlich nicht liegen. Beides ist
> schließlich garantiert fehlerfrei - es stammt ja schließlich von dir.
> Ergo können wir dir hier nicht weiterhelfen.
 Dabei ist der Code garnicht von mir (CubeMX)

Beitrag #8010552 wurde vom Autor gelöscht.
von Bernd S. (soundgott)


Angehängte Dateien:

Lesenswert?

Kilo S. schrieb:
> Ah, der fehlerfreie perfekte Mensch erbarmt sich zu uns ins niedere
> Forum auf der Suche nach Hilfe die ja unmöglich auf einen seiner Fehler
> zurückzuführen sind!

Schwachsinn, habe ich nie behauptet. Warscheinlich ist mein Ersuchen 
doch nur für Leute mit entsprechendem Wissen geeignet!

hier noch ein weiterer Test , nutzt die StdPeriph lib.

von Kilo S. (kilo_s)


Lesenswert?

Kein clock keine Pin Definitionen!

Geräteadresse?...

: Bearbeitet durch User
von Alex R. (geneo)


Lesenswert?

Du sprichst von Pin 10/11, ich sehe aber nur Pin 6/7 konfiguriert.

: Bearbeitet durch User
von Kilo S. (kilo_s)


Lesenswert?

1
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
2
{
3
  GPIO_InitTypeDef GPIO_InitStruct = {0};
4
5
  if(hi2c->Instance == I2C2)
6
  {
7
    /* Clocks */
8
    __HAL_RCC_GPIOB_CLK_ENABLE();
9
    __HAL_RCC_I2C2_CLK_ENABLE();
10
    __HAL_RCC_AFIO_CLK_ENABLE();
11
12
    /* I2C2 GPIO Configuration: PB10=SCL, PB11=SDA */
13
    GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11;
14
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
15
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
16
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
17
  }
18
}

falsch initialisiert!

F1 benutzt keine Alternate-Function Nummern (GPIO_AF4_I2C2 existiert 
hier nicht)

von Bernd S. (soundgott)


Lesenswert?

Alex R. schrieb:
> Du sprichst von Pin 10/11, ich sehe aber nur Pin 7/8 konfiguriert.

Mist, falsches File. Du hast Recht, ändert aber nix.

Beitrag #8010567 wurde vom Autor gelöscht.
von Kilo S. (kilo_s)


Lesenswert?

Thomas W. schrieb im Beitrag #8010567:
> Eigentlich haette der Compiler auch eine Warnung schicken sollen (16-bit
> vs. 8-Bit).

Daher meine Frage bezüglich der Adresse...

von Kilo S. (kilo_s)


Lesenswert?

Bernd S. schrieb:
> Warscheinlich ist mein Ersuchen doch nur für Leute mit entsprechendem
> Wissen geeignet!

Vorsicht, so hochtrabenden können tief Fallen!

von Bernd S. (soundgott)


Lesenswert?

Kilo S. schrieb:
> __HAL_RCC_AFIO_CLK_ENABLE();

ist auch richtig, kann weggelassen werden, ändert aber ebenfalls nix.
Damit auch die letzten Zweifel ausgeräumt werden:
Testumgebung: Visual Studio mit Extension VisualDGB (Compiler GCC)
Wie schon gesagt: in der Hardware-Registeransicht sind alle Register von 
I2C2, GPIOB, RCC korrekt gesetzt, aber es passiert nichts. Ich kan 
sehen, dass beim Sendeversuch, d.h. I2C2->DR das zu sendende Datum 
erhält, es bleibt jedoch beim nächsten Singlestep stehen (im Gegenzug 
zum Test mit I2C1)

von Bernd S. (soundgott)


Lesenswert?

Kilo S. schrieb:
> Thomas W. schrieb im Beitrag #8010567:
>> Eigentlich haette der Compiler auch eine Warnung schicken sollen (16-bit
>> vs. 8-Bit).
>
> Daher meine Frage bezüglich der Adresse...

???

von Jük P. (tik-tak)


Lesenswert?

Bernd S. schrieb:
> aber es passiert nichts.

STM32F103RFT6 bestimmt original?

von Kilo S. (kilo_s)


Lesenswert?

CubeMX setzt CR2 oft nur für I2C1 korrekt.

1
RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;
2
3
I2C2->CR2 = 36;   // APB1 Clock in MHz

I2C2 kann mit JTAG/SWD Pins kollidieren, wenn AFIO falsch konfiguriert 
ist.
1
__HAL_RCC_AFIO_CLK_ENABLE();
2
3
//und ob irgendwo remapped wurde
4
AFIO->MAPR

teste mal:
1
printf("CR2=%lu\n", I2C2->CR2);
2
printf("APB1=%lu\n", HAL_RCC_GetPCLK1Freq());

Wenn du mir diese drei Werte gibst, sag ich dir sofort den Fehler:

RCC->CFGR
I2C2->CR2
GPIOB->CRH

: Bearbeitet durch User
von Kilo S. (kilo_s)


Lesenswert?

Bernd S. schrieb:
> ???
1
uint16_t devAddr = 0x50 << 1;   // korrekt

von Bernd S. (soundgott)


Lesenswert?

Kilo S. schrieb:
> RCC->CFGR
> I2C2->CR2
> GPIOB->CRH

RCC->CFGR: 0x001d040a
I2C2->CR2: 0x00000024
GPIOB->CRH: 0x2848ff42 (CNF/MODE 10,11 = 0x11)

von Kilo S. (kilo_s)


Lesenswert?

Prüfe:
1
uint32_t busy = I2C2->SR2 & I2C_SR2_BUSY;

Wenn ≠0 → Ursache gefunden.

Typische Gründe:

Slave hält SDA

Pull-ups fehlen / zu schwach

vorheriger Reset mitten im Transfer

Debugger Stop während I2C aktiv.

Fix (offizieller ST Workaround)
1
I2C2->CR1 |= I2C_CR1_SWRST;
2
I2C2->CR1 &= ~I2C_CR1_SWRST;

Vor Init Bus freitakten:
1
// SCL manuell toggeln wenn SDA LOW
2
for(int i=0;i<9;i++)
3
{
4
   SCL_HIGH();
5
   delay();
6
   SCL_LOW();
7
   delay();
8
}

Direkt nach Init:
1
printf("SR2 = %04X\n", I2C2->SR2);
Ausgabe:
1
SR2 = 0002
BUSY Flag gesetzt, Ursache bestätigt.

Füge direkt nach Init ein:(Schnelllösung)
1
if(I2C2->SR2 & I2C_SR2_BUSY)
2
{
3
   I2C2->CR1 |= I2C_CR1_SWRST;
4
   I2C2->CR1 &= ~I2C_CR1_SWRST;
5
}

das sollte selbst mit kaputten slaves laufen:
1
void I2C2_Robust_Init(void)
2
{
3
    GPIO_InitTypeDef GPIO_InitStruct = {0};
4
5
    /* 1. Clocks aktivieren */
6
    __HAL_RCC_GPIOB_CLK_ENABLE();
7
    __HAL_RCC_I2C2_CLK_ENABLE();
8
    __HAL_RCC_AFIO_CLK_ENABLE();
9
10
    /* 2. Pins erstmal als GPIO OpenDrain (manuelle Bus Recovery) */
11
    GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11;
12
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
13
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
14
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
15
16
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10|GPIO_PIN_11, GPIO_PIN_SET);
17
    HAL_Delay(1);
18
19
    /* 3. Bus freitakten falls Slave hängt */
20
    if(!HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_11)) // SDA LOW?
21
    {
22
        for(int i=0;i<9;i++)
23
        {
24
            HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
25
            HAL_Delay(1);
26
            HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
27
            HAL_Delay(1);
28
        }
29
    }
30
31
    /* STOP Condition erzwingen */
32
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);
33
    HAL_Delay(1);
34
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
35
    HAL_Delay(1);
36
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET);
37
    HAL_Delay(1);
38
39
    /* 4. I2C Hardware Reset */
40
    I2C2->CR1 |= I2C_CR1_SWRST;
41
    HAL_Delay(1);
42
    I2C2->CR1 &= ~I2C_CR1_SWRST;
43
44
    /* 5. Pins auf I2C Alternate Function */
45
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
46
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
47
48
    /* 6. Peripheral Disable */
49
    I2C2->CR1 &= ~I2C_CR1_PE;
50
51
    /* 7. Timing konfigurieren */
52
    I2C2->CR2 = 36;        // APB1 MHz
53
    I2C2->CCR = 180;       // 100kHz @36MHz
54
    I2C2->TRISE = 37;      // laut Datenblatt
55
56
    /* 8. Peripheral Enable */
57
    I2C2->CR1 |= I2C_CR1_PE;
58
59
    /* 9. Dummy Read SR2 → Flags reset */
60
    (void)I2C2->SR2;
61
62
    /* 10. BUSY prüfen */
63
    if(I2C2->SR2 & I2C_SR2_BUSY)
64
    {
65
        /* letzter Rettungsversuch */
66
        I2C2->CR1 &= ~I2C_CR1_PE;
67
        HAL_Delay(1);
68
        I2C2->CR1 |= I2C_CR1_PE;
69
    }
70
}

von Bernd S. (soundgott)


Lesenswert?

Kilo S. schrieb:
> Prüfe:

Danke schonmal, werde es ausgiebig checken und berichten

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.