Grüß euch, folgende Situation. Ein bestehender "Master" Mikrocontroller der Reihe AtXmega soll ersetzt werden durch einen STM32F107 (hauptsächlich aufgrund von Ethernet). Die "Slaves" bleiben aber (ebenfalls Controller der AtXmega Reihe) und es können auch keine Anpassungen an der Firmware durchgeführt werden. Die Kommunikation läuft eigentlich. Aber nicht immer. Das Problem ist, dass die SCL Leitung von einem Gerät runter gezogen wird und nicht mehr freigegeben wird. Im aktuellen Test habe ich einen Master und zwei Slaves. Nach bisheriger Recherche scheint der Master das Problem zu sein, denn starte ich nur die Slaves neu, bleibt SCL low. Starte ich den Master hingegen neu, geht SCL wieder hoch. Ein Reintialisieren der I2C Peripherie im STM32 bringt nix, da bleibt SCL low. Das gibt für mich eigentlich keinen Sinn, da es nach einem Neustart ja wieder geht? Wirklich debuggen und mitloggen wann genau der Fehler auftritt kann ich nicht, da er eher willkürlich passiert. Manchmal tritt er erst nach Stunden auf, manchmal bereits nach einer Minute. Zum teste setze ich permanent Werte auf dem Slave. Beim STM32 habe ich den Error Interrupt für I2C aktiviert, jedoch tritt keiner auf. Auch die ganzen I2C Register weisen keine Auffälligkeit auf. Im I2C_SR1 Register sind die Bits BTF (Byte Transfer Finished) und TxE (Data Register Empty) gesetzt und im I2C_SR2 Register sind die Bits MSL (Master mode), BUSY (da SCL low) und TRA (Data Bytes Transmitted) gesetzt. Die Kommunikation läuft mit 400 kHz und ich nutze auf dem STM32 HAL. Jemand eine Idee was ich noch probieren könnte?
Nutzen deine I2C Slaves Clock-Streching? Ich habe irgendwo mal gelesen, dass der STM32 Probleme mit Clock-Stretching hat (bei Timeout)...
Lona schrieb: > Schaltplan Beim Schaltplan gibt es nicht viel zu sehen, was hier relevant wäre. An jedem SCL und SDA Pin befindet sich ein 100 Ohm Widerstand in Reihe. Und dann gibts noch einen Pull Up bei SCL und SDA mit jeweils 4k7 Ohm. Lona schrieb: > Sourcecode Wie schon erwähnt, nutze ich die HAL von STM.
1 | /* transmit the command */
|
2 | if(HAL_I2C_Master_Transmit(&hi2c1, (slv_nr<<1) & ~0x01, i2c_tx_buffer, tx_len, 100) != HAL_OK) |
3 | {
|
4 | response_error("Invalid Slave Number or Bus Error."); |
5 | }
|
6 | |
7 | /* receive the command */
|
8 | if(HAL_I2C_Master_Receive(&hi2c1, (slv_nr<<1) & ~0x01, i2c_rx_buffer, rx_len, 100) != HAL_OK) |
9 | {
|
10 | response_error("Receiving failed.") |
11 | }
|
response_error() ist ein Macro, des gleichzeitig ein return enthält. Und die Initialisierung von I2C:
1 | /* I2C1 init function */
|
2 | void MX_I2C1_Init(void) |
3 | {
|
4 | |
5 | hi2c1.Instance = I2C1; |
6 | hi2c1.Init.ClockSpeed = 400000; |
7 | hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; |
8 | hi2c1.Init.OwnAddress1 = 0; |
9 | hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; |
10 | hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; |
11 | hi2c1.Init.OwnAddress2 = 0; |
12 | hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; |
13 | hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; |
14 | if (HAL_I2C_Init(&hi2c1) != HAL_OK) |
15 | {
|
16 | _Error_Handler(__FILE__, __LINE__); |
17 | }
|
18 | |
19 | }
|
20 | |
21 | void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle) |
22 | {
|
23 | |
24 | GPIO_InitTypeDef GPIO_InitStruct; |
25 | if(i2cHandle->Instance==I2C1) |
26 | {
|
27 | /* USER CODE BEGIN I2C1_MspInit 0 */
|
28 | |
29 | /* USER CODE END I2C1_MspInit 0 */
|
30 | |
31 | /**I2C1 GPIO Configuration
|
32 | PB6 ------> I2C1_SCL
|
33 | PB7 ------> I2C1_SDA
|
34 | */
|
35 | GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; |
36 | GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; |
37 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; |
38 | HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); |
39 | |
40 | /* I2C1 clock enable */
|
41 | __HAL_RCC_I2C1_CLK_ENABLE(); |
42 | |
43 | /* I2C1 interrupt Init */
|
44 | HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0); |
45 | HAL_NVIC_EnableIRQ(I2C1_EV_IRQn); |
46 | HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0); |
47 | HAL_NVIC_EnableIRQ(I2C1_ER_IRQn); |
48 | /* USER CODE BEGIN I2C1_MspInit 1 */
|
49 | |
50 | /* USER CODE END I2C1_MspInit 1 */
|
51 | }
|
52 | }
|
Selbstverständlich ist das nicht der vollständige Quellcode. Den kann ich hier aber auch nicht posten da es mehrer tausend Zeilen Code verteilt über dutzende Dateien sind. Aber das ist der relevante I2C Teil.
Joe F. schrieb: > Nutzen deine I2C Slaves Clock-Streching? Ja tut er. Da such ich gleich mal ob ich was zu dem Thema finde.
Flo schrieb: > Und dann gibts noch einen Pull Up bei SCL und SDA mit jeweils 4k7 Ohm. Für 400 KHz werden 2.2K empfohlen (bei 3.3V). Und du kannst ja mal ein Clock-Stretching Timeout provozieren, indem du mit einem Draht SCL eine Weile auf GND ziehst. Wenn dann nach dem Loslassen das Problem da ist, wird's wohl damit zusammenhängen.
:
Bearbeitet durch User
Flo schrieb: > Lona schrieb: >> Schaltplan > > Beim Schaltplan gibt es nicht viel zu sehen, was hier relevant wäre. > An jedem SCL und SDA Pin befindet sich ein 100 Ohm Widerstand in Reihe. > Und dann gibts noch einen Pull Up bei SCL und SDA mit jeweils 4k7 Ohm. > Dann funktioniert das Ganze! Ausser du hast doch nicht die korrekte Hardware. Schaltplan und Foto bitte! > Selbstverständlich ist das nicht der vollständige Quellcode. Den kann > ich hier aber auch nicht posten da es mehrer tausend Zeilen Code > verteilt über dutzende Dateien sind. Aber das ist der relevante I2C > Teil. Doch das geht! Du kannst die Dateien direkt anhängen!
Schau mal in die Errata, beim F4 war da irgendwas nicht in Ordnung. Prüf das sicherheitshalber mal
Joe F. schrieb: > Und du kannst ja mal ein Clock-Stretching Timeout provozieren, indem du > mit einem Draht SCL eine Weile auf GND ziehst. Wenn dann nach dem > Loslassen das Problem da ist, wird's wohl damit zusammenhängen. Zu welche Zeitpunkt soll ich das am besten machen? Ingo Less schrieb: > Schau mal in die Errata, beim F4 war da irgendwas nicht in Ordnung. Prüf > das sicherheitshalber mal Ich habe einen F1. Aber ja, ins Errata habe ich schon geschaut und da gibts einige Probleme beim F1. Aber keiner der Fehler trifft auf meine Situation zu.
Flo schrieb: > Joe F. schrieb: >> Und du kannst ja mal ein Clock-Stretching Timeout provozieren, indem du >> mit einem Draht SCL eine Weile auf GND ziehst. Wenn dann nach dem >> Loslassen das Problem da ist, wird's wohl damit zusammenhängen. > > Zu welche Zeitpunkt soll ich das am besten machen? Der Zeitpunkt sollte eigentlich keine Rolle spielen. Du strechest die Clock dadurch einfach künstlich per Hand. Es muss während dessen natürlich ständig Traffic auf dem Bus sein. Den 100R in Reihe finde ich auch nicht so dolle, der LOW Pegel wird damit schon recht hoch. Ich würde es mal mit 2.2K Pullups und max. 33R in Reihe (oder 0R) probieren.
:
Bearbeitet durch User
Falls du ein Softwareproblem vermutest, probiere mal den Beispielcode von dieser Seite: http://stefanfrings.de/stm32/stm32f1.html#i2c Ich habe ihn bisher nur auf einem STM32F103 ausprobiert, sollte aber auch bei Dir gehen. Zumindest compiliert er fehlerfrei.
Joe F. schrieb: > Der Zeitpunkt sollte eigentlich keine Rolle spielen. Du strechest die > Clock dadurch einfach künstlich per Hand. Es muss während dessen > natürlich ständig Traffic auf dem Bus sein. Habe ich jetzt mal probiert. Da scheint es ein Problem zu geben. Denn manchmal stört das ganze gar nicht, die Kommunikation geht nach einer kurzen Unterbrechung weiter. Aber manchmal setzt er wieder das BUSY Flag und eine weitere Kommunikation ist nicht möglich (obwohl beide Leitungen wieder High sind). Jedoch hilft hier eine Neuintialisierung der I2C Schnittstelle. Joe F. schrieb: > Ich würde es mal mit 2.2K Pullups und max. 33R in Reihe (oder 0R) > probieren. Hab die Pullups mal getauscht, ebenso auf denn 33R in Reihe gewechselt. Aber die Fehler treten dennoch auf. Mittlerweile kann ich allerdings den Fehler reproduzieren. Und zwar tritt der Fehler nach 3-4 erfolgreich übertragenen Nachrichten auf. Also Master will etwas vom Slave lesen, das klappt 3-4 mal ohne Probleme. Dann gehts nicht mehr. Allerdings nur in dem Fall, wenn der Slave frisch bestromt wurde. Daher konnte ich jetzt auch das ganze mittels Logicanalyzer festhalten. Der Slave braucht über 10 ms nach jedem Byte, bevor er ein ACK schickt. Nach dem letzten Byte der Nachricht vom Master kommt auch noch ein ACK, aber SCL bleibt danach Low und der Slave verschickt nichts mehr. Das spricht jetzt erstmal für einen Fehler vom Slave. Jetzt kommt jedoch das aber. Starte ich den Master neu, und am Slave wird nichts gemacht, funktioniert die Kommunikation anschließend ohne Probleme. Ein einfaches neu initialisieren der I2C Peripherie reicht nicht... Stefan F. schrieb: > Falls du ein Softwareproblem vermutest, probiere mal den Beispielcode > von dieser Seite: Ich weiß grad ehrlich gesagt nicht ob es SW oder HW ist. Werde es aber mal im Hinterkopf behalten.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.