Forum: Mikrocontroller und Digitale Elektronik I2C auf STM32F103


von Richard M. (Gast)


Lesenswert?

Hallo zusammen,

ich habe hier ein Problem mit dem I2C und bekomm diesen einfach nicht 
zum laufen. Als Hardware habe ich hier einen STM32F103ZE mit einem 
Segger Ultra + und einem Saleae Logic Analyser zum auslesen der SCL und 
SDA Pins.

Der folgende Code ist unter embOS initialisiert:
1
void ConfigureI2CGPIO(void) 
2
{
3
  GPIO_InitTypeDef GPIO_InitStructure;
4
        I2C_InitTypeDef   I2C_InitStructure;
5
6
  RCC_AHBPeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
7
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
8
        SET_BIT(RCC->APB2ENR, RCC_APB2ENR_AFIOEN);
9
10
        GPIO_PinRemapConfig(AFIO_MAPR_I2C1_REMAP, ENABLE);
11
12
        GPIO_InitStructure.GPIO_Pin =  (GPIO_Pin_8) | (GPIO_Pin_9);     //SCL (PB6),SDA (PB7): Alternate Function, Open Drain
13
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
14
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // Open Drain, I2C bus pulled high externally  
15
        GPIO_Init(GPIOB, &GPIO_InitStructure);
16
                
17
        I2C_Cmd(I2C1, DISABLE);          
18
        
19
        I2C_InitStructure.I2C_ClockSpeed=100000;
20
        I2C_InitStructure.I2C_Mode=I2C_Mode_I2C;
21
        I2C_InitStructure.I2C_DutyCycle=I2C_DutyCycle_2;
22
        I2C_InitStructure.I2C_OwnAddress1=0;
23
        I2C_InitStructure.I2C_Ack=I2C_Ack_Enable;
24
        I2C_InitStructure.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit; 
25
        I2C_Init(I2C1, &I2C_InitStructure);
26
27
        I2C_Cmd(I2C1, ENABLE);
28
  //GPIO_PinRemapConfig(AFIO_MAPR_I2C1_REMAP, ENABLE);
29
30
        GPIOB->BSRR = I2C_SCL_PIN | I2C_SDA_PIN;
31
32
  GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN;
33
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
34
  GPIO_Init(I2C_SCL_GPIO_PORT, &GPIO_InitStructure);
35
36
  GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN;
37
  GPIO_Init(I2C_SDA_GPIO_PORT, &GPIO_InitStructure);
38
39
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
40
41
  RCC_APB2PeriphClockCmd(I2C_SCL_GPIO_CLK | I2C_SDA_GPIO_CLK | I2C_SMBUSALERT_GPIO_CLK, ENABLE);
42
43
  GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN;
44
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
45
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
46
  GPIO_Init(I2C_SCL_GPIO_PORT, &GPIO_InitStructure);
47
48
  GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN;
49
  GPIO_Init(I2C_SDA_GPIO_PORT, &GPIO_InitStructure);
50
}
51
52
void I2C_Eeprom_Write(int num, uint8_t *ptxbuf) 
53
{
54
        ConvertMessage(num, ptxbuf);
55
56
  I2C_GenerateSTART(I2C1, ENABLE);
57
58
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
59
  
60
  I2C_Send7bitAddress(I2C1, I2C_EEPROM_ADDRESS >> 1, I2C_Direction_Transmitter);
61
62
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
63
64
  I2C_SendData(I2C1, *ptxbuf);
65
66
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
67
68
  I2C_SendData(I2C1, *(++ptxbuf));
69
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
70
      
71
  I2C_GenerateSTOP(I2C1, ENABLE);
72
}

Das Problem ist, dass mir der Code beim senden an den EEPROM bei
1
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

hängen bleibt und gar nichts mehr geht... Mit dem Logic Analyser kann 
ich weder an SCL noch an SDA was erkennen... Die Pins bleiben einfach 
auf high. Pull-Ups sind vorhanden.

Ich weiß mir nicht mehr zu helfen woran es liegen könnte. Habe 
zahlreiche Versuche gestartet aber ich komm nicht mehr weiter.

Kann mir hier vielleicht einer einen Rat geben woran es liegen könnte?

Als Anmerkung:

Er geht in der I2C_CheckEvent in den ERROR-Fall... Also muss ein Bit 
nicht gesetzt worden sein, also nehm ich an.
1
ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
2
{
3
  uint32_t lastevent = 0;
4
  uint32_t flag1 = 0, flag2 = 0;
5
  ErrorStatus status = ERROR;
6
7
  /* Check the parameters */
8
  assert_param(IS_I2C_ALL_PERIPH(I2Cx));
9
  assert_param(IS_I2C_EVENT(I2C_EVENT));
10
11
  /* Read the I2Cx status register */
12
  flag1 = I2Cx->SR1;
13
  flag2 = I2Cx->SR2;
14
  flag2 = flag2 << 16;
15
16
  /* Get the last event value from I2C status register */
17
  lastevent = (flag1 | flag2) & FLAG_Mask;
18
19
  /* Check whether the last event contains the I2C_EVENT */
20
  if ((lastevent & I2C_EVENT) == I2C_EVENT)
21
  {
22
    /* SUCCESS: last event is equal to I2C_EVENT */
23
    status = SUCCESS;
24
  }
25
  else
26
  {
27
    /* ERROR: last event is different from I2C_EVENT */
28
    status = ERROR;
29
  }
30
  /* Return status */
31
  return status;
32
}

Ich danke schonmal,

liebe Grüße
Richard

: Verschoben durch User
von Milbe (Gast)


Lesenswert?

Sendet "I2C_GenerateSTART(I2C1, ENABLE);" das Startbit? Was ist als 
Slave angeschlossen?

von STM Apprentice (Gast)


Lesenswert?

Ich schweife vom Thema ab, aber:

Wieder mal, ich liebe meine Soft-I2C-Library!

Läuft ohne Probleme und ich kann mir im Debugger und am
Bus jedes Bit einzeln anschauen, ganz statisch unhektisch
und ohne Logikanalysator-Gefummel.

Aber da die Library so gut funktioniert musste ich schon
lange nicht mehr den Debugger dafür bemühen.

von Richard M. (Gast)


Lesenswert?

Milbe schrieb:
> Sendet "I2C_GenerateSTART(I2C1, ENABLE);" das Startbit? Was ist als
> Slave angeschlossen?

Wie man sieht ein EEPROM... Das Startbit wird auch nicht gesendet. Wenn 
ich die Messung starte ändert sich im Verlauf von 20 Sekunden nichts.

STM Apprentice schrieb:
> Wieder mal, ich liebe meine Soft-I2C-Library!

Ist die zu haben? Oder haben Sie eine Idee woran das liegen könnte? 
Könnte wirklich Hilfe gebrauchen.

von Dr. Sommer (Gast)


Lesenswert?

Richard M. schrieb:
> GPIO_PinRemapConfig(AFIO_MAPR_I2C1_REMAP, ENABLE);

Geprüft ob das stimmt? Welche Pins benutzt du? Die Pins sind ständig 
High und es tut sich gar nichts? Was passiert wenn du das EEPROM trennst 
und die Leitungen per LA anschaust?

von Richard M. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Geprüft ob das stimmt? Welche Pins benutzt du?

Pin 8 und 9, Das ist das Remapping des STM32F103ZE. Standard wären diese 
Pin 6 und 7.

Dr. Sommer schrieb:
> Die Pins sind ständig High und es tut sich gar nichts? Was passiert wenn du das 
EEPROM trennst und die Leitungen per LA anschaust?

Ebenfalls nichts, rein gar nichts. Beide Kanäle bleiben durchgehend auf 
HIGH

von Dr. Sommer (Gast)


Lesenswert?

Richard M. schrieb:
> RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

Warum ist das doppelt? Warum initialisierst du die Pins 3x?

von Richard M. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Warum ist das doppelt? Warum initialisierst du die Pins 3x?

Das kommt aus einer bestehenden Datei eines anderen RTOS.

Habe ich so übernommen, ändert ja nix an der eigentlichen init, wird 
eben nur wieder überschrieben oder nicht?

von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

Richard M. schrieb:
> Ist die zu haben?

Ist die denn wirklich so schwer selbst zu schreiben? Es sind doch bloß 2 
Leitungen. Ich selber verwende auch einen Software-Lowlevel-Treiber 
recht oft und ich hab den hier auch schon mal gepostet. Ich häng dir mal 
sowas dran, der war (wenn ich mich recht erinnere) damals für nen 
Kinetis. ist schon ne Weile her.

Und wenn du das Umschreiben auf STM32 nicht aus eigener Kraft zuwege 
bringst, dann werde Briefmarkensammler oder Tanzlehrer.

W.S.

von Richard M. (Gast)


Lesenswert?

W.S. schrieb:
> Und wenn du das Umschreiben auf STM32 nicht aus eigener Kraft zuwege
> bringst, dann werde Briefmarkensammler oder Tanzlehrer.
>
> W.S.

Klar, bist ja auf die Welt gekommen und warst allwissend. Bleib mal am 
Boden

von Dr. Sommer (Gast)


Lesenswert?

Richard M. schrieb:
> Habe ich so übernommen, ändert ja nix an der eigentlichen init, wird
> eben nur wieder überschrieben oder nicht?

Weiß nicht, es sieht irgendwie komisch aus. Und da es ja nicht 
funktioniert...

von Richard M. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Weiß nicht, es sieht irgendwie komisch aus. Und da es ja nicht
> funktioniert...

Hab jetzt eine init gemacht der GPIOs, änder nichts an dem Fehler dass 
er nicht mal das Startbit generiert. Ich finde den Fehler einfach nicht.

von Dr. Sommer (Gast)


Lesenswert?

Richard M. schrieb:
> Hab jetzt eine init gemacht der GPIOs, änder nichts an dem Fehler dass
> er nicht mal das Startbit generiert. Ich finde den Fehler einfach nicht.

Zeig den neuen Code, die Definition der Makros I2C_SCL_PIN etc. 
Irgendwas muss an der Pin Konfiguration falsch sein. Wird die vielleicht 
irgendwo von einem anderen Programmteil überschrieben?

von Richard M. (Gast)


Lesenswert?

1
/* STM32 Include files ******************************************************/
2
3
#include <stm32f10x_i2c.h>
4
5
/* Macro defintions  ********************************************************/
6
7
#define I2C_SCL_PIN                     GPIO_Pin_6
8
#define I2C_SCL_GPIO_PORT               GPIOB
9
#define I2C_SDA_PIN                     GPIO_Pin_7
10
#define I2C_SDA_GPIO_PORT               GPIOB
11
12
#define I2C_SCL_GPIO_CLK                RCC_APB2Periph_GPIOB
13
#define I2C_SDA_GPIO_CLK                RCC_APB2Periph_GPIOB
14
#define I2C_SMBUSALERT_GPIO_CLK         RCC_APB2Periph_GPIOB
15
16
/* EEPROM */
17
#define I2C_EEPROM_ADDRESS              0xA8
18
19
/* General information ******************************************************/
20
21
/* Types ********************************************************************/
22
23
/* Local Prototypes *********************************************************/
24
25
void ConfigureI2CGPIO(void);
26
27
/* Global variables *********************************************************/
28
29
/* Functions ****************************************************************/
30
31
void ConfigureI2CGPIO(void) 
32
{
33
  GPIO_InitTypeDef GPIO_InitStructure;
34
        I2C_InitTypeDef   I2C_InitStructure;
35
36
  RCC_AHBPeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
37
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
38
        SET_BIT(RCC->APB2ENR, RCC_APB2ENR_AFIOEN);
39
40
        //TODO: APB1 Reset Register
41
42
        GPIO_PinRemapConfig(AFIO_MAPR_I2C1_REMAP, ENABLE);
43
44
        GPIO_InitStructure.GPIO_Pin =  (GPIO_Pin_6) | (GPIO_Pin_7);     //SCL (PB6),SDA (PB7): Alternate Function, Open Drain
45
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
46
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // Open Drain, I2C bus pulled high externally  
47
        GPIO_Init(GPIOB, &GPIO_InitStructure);
48
                
49
        I2C_Cmd(I2C1, DISABLE);          
50
        
51
        I2C_InitStructure.I2C_ClockSpeed=100000;
52
        I2C_InitStructure.I2C_Mode=I2C_Mode_I2C;
53
        I2C_InitStructure.I2C_DutyCycle=I2C_DutyCycle_2;
54
        I2C_InitStructure.I2C_OwnAddress1=0;
55
        I2C_InitStructure.I2C_Ack=I2C_Ack_Enable;
56
        I2C_InitStructure.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit; 
57
        I2C_Init(I2C1, &I2C_InitStructure);
58
59
        I2C_Cmd(I2C1, ENABLE);
60
61
        GPIOB->BSRR = I2C_SCL_PIN | I2C_SDA_PIN;
62
63
  GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN;
64
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
65
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
66
  GPIO_Init(I2C_SCL_GPIO_PORT, &GPIO_InitStructure);
67
68
  GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN;
69
  GPIO_Init(I2C_SDA_GPIO_PORT, &GPIO_InitStructure);
70
}

Hier mit defines, die werden nirgends sonst definiert.

von Richard M. (Gast)


Lesenswert?

Pin 6 und 7 wurden wieder auf 8 und 9 geändert... Hab grad auf einem 
EVAL probiert... Funktionierte auch nicht

von Stefan F. (Gast)


Lesenswert?

Vielleicht kommst du ohne diese komische Abstraktions-Library besser 
zurecht. Hier ein kommentiertes Beispiel:

http://stefanfrings.de/stm32/index.html#i2c

von Richard M. (Gast)


Lesenswert?

Stefanus F. schrieb:
> Vielleicht kommst du ohne diese komische Abstraktions-Library besser
> zurecht. Hier ein kommentiertes Beispiel:
>
> http://stefanfrings.de/stm32/index.html#i2c

Hab ich auch schon probiert. Hat leider auch nicht funktioniert.. Ich 
verzweifle langsam daran....

von Dr. Sommer (Gast)


Lesenswert?

Richard M. schrieb:
> RCC_AHBPeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

Ist verkehrt... einmal AHB und einmal APB2. Die GPIO-Initialisierung ist 
immer noch doppelt. Steppe den Code im Debugger durch und schaue ob in 
den Registern die gewünschten Dinge landen.

von Stefan F. (Gast)


Lesenswert?

Was hat leider auch nicht funktioniert?
Welchen Pegel haben die beiden Leitungen SDA und SCL im Ruhezustand 
(nach der Initialisierung)?
Welchen Pegel haben sie nachdem der Fehler begonnen hat?
Welches Signal misst du mit deinem Logic Analyzer?
Bist du sicher, dass der Logic Analyzer funktioniert und dass du ihn 
richtig bedienst?
Hast du die GND Leitung vom EEprom mit dem STM32 verbunden?
Hast du anstelle des EEproms mal einen anderen Chip probiert? Der 
PCF8574 ist für erste Versuche immer gut.
Hast du mal versucht, einfach gar keinen Slave anzuschliessen, um nur 
die Ausgangs-Signale des STM32 zu prüfen? Zumindest die Adresse (also 
das erste Byte) müsste zu sehen sein.
Zeige mal deinen Schaltplan.
Zeige mal dein Programm, das auf meinem Code basiert.

Probiere das alles aus, beantworte die Fragen und dann sehen wir weiter.

von Dr. Sommer (Gast)


Lesenswert?

PS: absolut sicher dass kein Verdrahtungs-Fehler vorliegt? Kannst du die 
Pins normal als GPIO konfigurieren und auf Low schalten?

von Richard M. (Gast)


Lesenswert?

Stefanus F. schrieb:
> Was hat leider auch nicht funktioniert?
> Welchen Pegel haben die beiden Leitungen SDA und SCL im Ruhezustand
> (nach der Initialisierung)?
> Welchen Pegel haben sie nachdem der Fehler begonnen hat?
> ...

Ich werd dir da morgen eine ausreichende Diagnose geben und deinen Code 
nochmals verwenden. Auch bei entferntem EEPROM bleibt der Fehler 
bestehen. Die Signale sind stets auf HIGH

von Stefan F. (Gast)


Lesenswert?

Richard M. schrieb:
> Stefanus F. schrieb:
>> Was hat leider auch nicht funktioniert?
>> Welchen Pegel haben die beiden Leitungen SDA und SCL im Ruhezustand
>> (nach der Initialisierung)?
>> Welchen Pegel haben sie nachdem der Fehler begonnen hat?
>> ...
>
> Ich werd dir da morgen eine ausreichende Diagnose geben und deinen Code
> nochmals verwenden. Auch bei entferntem EEPROM bleibt der Fehler
> bestehen. Die Signale sind stets auf HIGH

Das mein Beispielprogramm erprobt ist und funktioniert sollte das (ohne 
EEprom) zumindest die Slave Adresse ausgeben. Tut es das nicht, ist 
möglicherweise dein µC defekt.

von Richard M. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> PS: absolut sicher dass kein Verdrahtungs-Fehler vorliegt? Kannst
> du die Pins normal als GPIO konfigurieren und auf Low schalten?

Verdrahtungsfehler liegt keiner vor, alles schon überprüft. Ich werd 
morgen mal alles nochmal durchtesten. Die Pins als einfache DO verwenden 
und dann Stefanus Init nochmals anwenden. Vll. seh ich den Wald vor 
lauter Bäumen nicht mehr...

von Richard M. (Gast)


Lesenswert?

Stefanus F. schrieb:

> Das mein Beispielprogramm erprobt ist und funktioniert sollte das (ohne
> EEprom) zumindest die Slave Adresse ausgeben. Tut es das nicht, ist
> möglicherweise dein µC defekt.

Ich werd das alles nochmal durchprobieren. Ich melde mich morgen 
nochmal. Danke vorab

von Richard M. (Gast)


Lesenswert?

Ich habe jetzt die Initialisierung nach Stefanus durchgeführt:
1
void i2c_init(I2C_TypeDef* registerStruct, bool fastMode, uint32_t apb1_clock)
2
{
3
    SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPBEN);
4
    SET_BIT(RCC->APB2ENR, RCC_APB2ENR_AFIOEN);
5
    
6
    // Enable clock
7
    if (registerStruct==I2C1)
8
    {
9
        SET_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C1EN);
10
    }
11
    else if (registerStruct==I2C2)
12
    {
13
        SET_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C2EN);
14
    }
15
    
16
    // Configure timing
17
    MODIFY_REG(registerStruct->CR2, I2C_CR2_FREQ, apb1_clock/1000000); 
18
    if (fastMode)
19
    {
20
        MODIFY_REG(registerStruct->CCR, I2C_CCR_CCR, apb1_clock/800000);
21
        MODIFY_REG(registerStruct->TRISE, I2C_TRISE_TRISE, apb1_clock/4000000+1);
22
    }
23
    else
24
    {
25
        MODIFY_REG(registerStruct->CCR, I2C_CCR_CCR, apb1_clock/200000);
26
        MODIFY_REG(registerStruct->TRISE, I2C_TRISE_TRISE, apb1_clock/1000000+1);
27
    }
28
    
29
    // Enable the peripheral
30
    SET_BIT(registerStruct->CR1, I2C_CR1_PE);
31
}
32
33
unsigned int i2c_communicate(I2C_TypeDef* registerStruct, uint8_t slave_addr, 
34
    void* send_buffer, unsigned int send_size, void* receive_buffer, unsigned int receive_size)
35
{
36
    unsigned int receive_count=0;
37
38
    // shift the 7bit address to the right position
39
    slave_addr=slave_addr<<1;
40
41
    // Send data
42
    if (send_size>0)
43
    {
44
        // Send START and slave address
45
        SET_BIT(registerStruct->CR1, I2C_CR1_START);                     // send START condition
46
        while (!READ_BIT(registerStruct->SR1, I2C_SR1_SB));              // wait until START has been generated
47
        WRITE_REG(registerStruct->DR,slave_addr);                        // send slave address
48
        while (!READ_BIT(registerStruct->SR1, I2C_SR1_ADDR))             // wait until address has been sent
49
        {
50
            if (READ_BIT(registerStruct->SR1, I2C_SR1_AF))
51
            {
52
                // did not receive ACK after address
53
                goto error;
54
            }
55
        }
56
57
        READ_REG(registerStruct->SR2);                                   // clear ADDR
58
        while (send_size>0)
59
        {
60
            WRITE_REG(registerStruct->DR,*((uint8_t*)send_buffer));      // send 1 byte from buffer
61
            while (!READ_BIT(registerStruct->SR1, I2C_SR1_TXE))          // wait until Tx register is empty
62
            {
63
                if (READ_BIT(registerStruct->SR1, I2C_SR1_AF))
64
                {
65
                    // did not receive ACK after data byte
66
                    goto error;
67
                }
68
            }
69
            send_buffer++;
70
            send_size--;
71
        }
72
        while (!READ_BIT(registerStruct->SR1, I2C_SR1_BTF))              // wait until last byte transfer has finished
73
        {
74
            if (READ_BIT(registerStruct->SR1, I2C_SR1_AF))
75
            {
76
                // did not receive ACK after data byte
77
                goto error;
78
            }
79
        }
80
    }
81
82
    CLEAR_BIT(registerStruct->CR1, I2C_CR1_POS);                         // POS=0
83
    SET_BIT(registerStruct->CR1, I2C_CR1_ACK);                           // acknowledge each byte
84
85
    // Receive data
86
    // The procedure includes workaround as described in AN2824
87
    if (receive_size>0)
88
    {
89
        // Send (RE-)START and slave address
90
        SET_BIT(registerStruct->CR1, I2C_CR1_START);                      // send START condition
91
        while (!READ_BIT(registerStruct->SR1, I2C_SR1_SB));               // wait until START has been generated
92
        WRITE_REG(registerStruct->DR,slave_addr+1);                       // send slave address + read mode
93
        while (!READ_BIT(registerStruct->SR1, I2C_SR1_ADDR))              // wait until address has been sent
94
        {
95
            if (READ_BIT(registerStruct->SR1, I2C_SR1_AF))
96
            {
97
                // did not receive ACK after address
98
                goto error;
99
            }
100
        }
101
102
        if (receive_size>2)
103
        {
104
            READ_REG(registerStruct->SR2);                                // clear ADDR
105
            while (receive_size>3)
106
            {
107
                while (!READ_BIT(registerStruct->SR1, I2C_SR1_RXNE));     // wait until a data byte has been received
108
                *((uint8_t*)receive_buffer)=READ_REG(registerStruct->DR); // read data
109
                receive_size--;
110
                receive_count++;
111
                receive_buffer++;
112
            }
113
            while (!READ_BIT(registerStruct->SR1, I2C_SR1_BTF));          // wait until 2 bytes are received
114
            CLEAR_BIT(registerStruct->CR1, I2C_CR1_ACK);                  // prepare to send a NACK
115
            *((uint8_t*)receive_buffer)=READ_REG(registerStruct->DR);     // read the penultimate data byte
116
            receive_size--;
117
            receive_count++;
118
            receive_buffer++;
119
            __disable_irq();
120
            {
121
                SET_BIT(registerStruct->CR1, I2C_CR1_STOP);               // prepare to send a STOP condition
122
                *((uint8_t*)receive_buffer)=READ_REG(registerStruct->DR); // read the last data byte
123
                receive_size--;
124
                receive_count++;
125
                receive_buffer++;
126
            }
127
            __enable_irq();
128
        }
129
        else if (receive_size==2)
130
        {
131
            SET_BIT(registerStruct->CR1, I2C_CR1_POS);                    // NACK shall be applied to the next byte, not the current byte
132
            __disable_irq();
133
            {
134
                READ_REG(registerStruct->SR2);                            // clear ADDR
135
                CLEAR_BIT(registerStruct->CR1, I2C_CR1_ACK);              // prepare to send a NACK
136
            }
137
            __enable_irq();
138
            while (!READ_BIT(registerStruct->SR1, I2C_SR1_BTF));          // wait until 2 bytes are received
139
            __disable_irq();
140
            {
141
                SET_BIT(registerStruct->CR1, I2C_CR1_STOP);               // prepare to send a STOP condition
142
                *((uint8_t*)receive_buffer)=READ_REG(registerStruct->DR); // read the penultimate data byte
143
                receive_size--;
144
                receive_count++;
145
                receive_buffer++;
146
             }
147
            __enable_irq();
148
        }
149
        else if (receive_size==1)
150
        {
151
            CLEAR_BIT(registerStruct->CR1, I2C_CR1_ACK);                  // prepare to send a NACK
152
            __disable_irq();
153
            {
154
                READ_REG(registerStruct->SR2);                            // clear ADDR
155
                SET_BIT(registerStruct->CR1, I2C_CR1_STOP);               // prepare to send a STOP condition
156
            }
157
            __enable_irq();
158
            while (!READ_BIT(registerStruct->SR1, I2C_SR1_RXNE));         // wait until a data byte has been received
159
        }
160
161
        *((uint8_t*)receive_buffer)=READ_REG(registerStruct->DR);         // read the last data byte
162
        receive_size--;
163
        receive_count++;
164
        receive_buffer++;
165
        while (READ_BIT(registerStruct->SR1, I2C_CR1_STOP));              // wait until STOP has been generated
166
    }
167
168
    else if (receive_size==0 && send_size>0)
169
    {
170
        SET_BIT(registerStruct->CR1, I2C_CR1_STOP);                       // send STOP condition
171
        while (READ_BIT(registerStruct->CR1, I2C_CR1_STOP));              // wait until STOP has been generated
172
    }
173
174
    return receive_count;
175
176
    error:
177
    SET_BIT(registerStruct->CR1, I2C_CR1_STOP);                           // send STOP condition
178
    while (READ_BIT(registerStruct->CR1, I2C_CR1_STOP));                  // wait until STOP has been generated
179
    CLEAR_BIT(registerStruct->CR1, I2C_CR1_PE);                           // restart the I2C interface clear all error flags
180
    SET_BIT(registerStruct->CR1, I2C_CR1_PE);
181
    //ITM_SendString("I2C bus error!\n");
182
    return receive_count;
183
}

Die Aufrufe der Funktionen ist hier zu erkennen:
1
        i2c_init(I2C1, false, 72000000)
2
                                                 
3
        AFIO->MAPR |= AFIO_MAPR_I2C1_REMAP;
4
5
        MODIFY_REG(GPIOB->CRL, GPIO_CRH_CNF8  + GPIO_CRH_MODE8,  GPIO_CRH_CNF8_0 + GPIO_CRH_CNF8_1 + GPIO_CRH_MODE8_1);
6
        MODIFY_REG(GPIOB->CRL, GPIO_CRH_CNF9  + GPIO_CRH_MODE9,  GPIO_CRH_CNF9_0 + GPIO_CRH_CNF9_1 + GPIO_CRH_MODE9_1);
7
8
        uint8_t send_buffer[4]={10,20,30,40};
9
        uint8_t receive_buffer[9];
10
11
        // Communicate with slave address 8: send 4 bytes, then receive 9 bytes
12
        int received=i2c_communicate(I2C1, 168, send_buffer, 4, receive_buffer, 9);

Remapping durchgeführt. CRL und CRH manipuliert und abgeändert. Leider 
dennoch kein I2C möglich. Bleibt wie bisher in
1
while (!READ_BIT(registerStruct->SR1, I2C_SR1_SB));              // wait until START has been generated

beim senden der Start Condition hängen...

Das Board ist in Ordnung. Hat vorher damit auch funktioniert. 
Verdrahtungsfehler ausgeschlossen. MCU ist in Ordnung. Die Pins sind als 
normale GPIOs zu benutzen.

von Stefan F. (Gast)


Lesenswert?

Richard M. schrieb:
> Die Pins als einfache DO verwenden
> und dann Stefanus Init nochmals anwenden. Vll. seh ich den Wald vor
> lauter Bäumen nicht mehr...

Ich wollte eigentlich, dass du das gesamte Programm erstmal 1:1 (als 
neues separates Projekt) probierst, um einen HW Fehler auszuschließen.

Du hast meinen Fragenkatalog noch nicht beantwortet.

von Richard M. (Gast)


Lesenswert?

Stefanus F. schrieb:
> Was hat leider auch nicht funktioniert?

Ihre Init

> Welchen Pegel haben die beiden Leitungen SDA und SCL im Ruhezustand
> (nach der Initialisierung)?

Permanent High

> Welchen Pegel haben sie nachdem der Fehler begonnen hat?

Immernoch High

> Welches Signal misst du mit deinem Logic Analyzer?

High?

> Bist du sicher, dass der Logic Analyzer funktioniert und dass du ihn
> richtig bedienst?

Ja

> Hast du die GND Leitung vom EEprom mit dem STM32 verbunden?

Ja

> Hast du anstelle des EEproms mal einen anderen Chip probiert? Der
> PCF8574 ist für erste Versuche immer gut.

Ja, keinen EEPROM aber einen US

> Hast du mal versucht, einfach gar keinen Slave anzuschliessen, um nur
> die Ausgangs-Signale des STM32 zu prüfen? Zumindest die Adresse (also
> das erste Byte) müsste zu sehen sein.

Ja, selbiges Problem

> Zeige mal deinen Schaltplan.

STM3210E-EVAL Board

> Zeige mal dein Programm, das auf meinem Code basiert.

embOS mit lediglicher Init des I2C.

von Richard M. (Gast)


Lesenswert?

> Welches Signal misst du mit deinem Logic Analyzer?

SDA und SCL wenn Sie das meinen.

von Mehmet K. (mkmk)


Lesenswert?

STM Apprentice schrieb:
> Wieder mal, ich liebe meine Soft-I2C-Library!

Dieselbe Liebeserklaerung hier aus meiner Ecke.
Nebst dem, dass man nicht behaupten kann, die Errata des STM32F103 
bezüglich I2C sei bescheiden ausgefallen, habe ich nie verstanden, wieso 
man für ein paar Bytes, die man per I2C hin- und herschieben will, nicht 
eine Software-Lösung mit ein paar überschau- und nachvollziehbaren 
Zeilen vorzieht. Eine Lösung, die auf einem STM8 genauso funktioniert, 
wie auf einem STM32. Oder einem EFM8. Oder was auch immer.

Okay, jetzt wird Dr. Sommer kommen und "im Hintergrund" in die Runde 
werfen. Konnte ich auch nie nachvollziehen.

von Stefan F. (Gast)


Lesenswert?

Klingt für mich so, als ob der Mikrocontroller defekt sei.
Andererseits kannst du die Pins als GPIO Nutzen. Sie sind also nicht 
defekt.

Dass die I²C Einheit im µC defekt ist, die I/O Pins aber nicht, kann 
eigentlich nicht sein.

von Richard M. (Gast)


Lesenswert?

Stefanus F. schrieb:
> Klingt für mich so, als ob der Mikrocontroller defekt sei.
> Andererseits kannst du die Pins als GPIO Nutzen. Sie sind also nicht
> defekt.
>
> Dass die I²C Einheit im µC defekt ist, die I/O Pins aber nicht, kann
> eigentlich nicht sein.

Das Board wurde vorher mit dem RTOS EUROS betrieben und es funktionierte 
stets I2C. Ich kann mir auch nicht erklären warum jetzt I2C nicht 
funktioniert

von STM Apprentice (Gast)


Lesenswert?

Mehmet K. schrieb:
> habe ich nie verstanden, wieso
> man für ein paar Bytes, die man per I2C hin- und herschieben will, nicht
> eine Software-Lösung mit ein paar überschau- und nachvollziehbaren
> Zeilen vorzieht.

Es gibt schon Gründe dagegen:

Man muss ja das I2C-Takten durch Delays im usec Bereich steuern
Wenn man eine Interrupt-intensive Anwendung hat kann ein oft
genutztes Delay die Performance stark ausbremsen bzw zum
erliegen bringen.

Einen Vorteil den ich sehr schätze: man kann praktisch jedes
beliebige Pin-Paar für SCL und SDA verwenden.

von Dr. Sommer (Gast)


Lesenswert?

Mehmet K. schrieb:
> Okay, jetzt wird Dr. Sommer kommen und "im Hintergrund" in die Runde
> werfen. Konnte ich auch nie nachvollziehen.

Das ist leicht zu erklären. Wenn du parallel noch andere zeitkritische 
Aufgaben laufen hast, möchte man keine Zeit in Warteroutinen des 
Soft-I²C verschwenden. "Den Not-Aus kann ich gerade leider nicht 
durchführen, ich muss noch Statusinformationen ans I²C-Display senden" 
wäre nicht so gut.

von Stefan F. (Gast)


Lesenswert?

Ich möchte nochmal anregen, mein Programm wirklich 1:1 zu verwenden. 
Soweit ich erkennen kann, hast du meinen Code irgendwie in deinen 
eingebettet. Die Problemursache könnte außerhalb der von Dir gezeigten 
Zeilen liegen.

Soll ich Dir ein *.bin File von meinem Programm schicken, meinst du das 
könnte helfen?

von STM Apprentice (Gast)


Lesenswert?

Allerdings lassen sich bei I2C die Delays ja durchaus "interuptible"
gestalten denn der Bus verlangt nicht eine strenge Taktung wie
(z.B. bei Soft-Serial), da er bei den meisten Bausteinen auch
pseudo-statisch funktioniert.

von Richard M. (Gast)


Lesenswert?

Stefanus F. schrieb:
> Soll ich Dir ein *.bin File von meinem Programm schicken, meinst du das
> könnte helfen?

Wäre vll nicht schlecht. Ich wär für jegliche Hilfe dankbar. Ich bastel 
hier ständig rum und versuche den Fehler zu finden. Nachdem die GPIOS 
gehen kann es nur anderweitig Komplikationen geben

von Stefan F. (Gast)


Lesenswert?

Richard M. schrieb:
>> Soll ich Dir ein *.bin File von meinem Programm schicken, meinst du das
>> könnte helfen?
>  Wäre vll nicht schlecht.

Ich melde mich heute Abend wieder, wenn ich zu hause bin. Dann mach ich 
das für dich fertig.

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Wie versprochen ist hier das Lauffähige Programm.

Ich habe es ein bisschen erweitert, damit eine LED an PCA5 oder PC13 
blinkt und damit die I²C Kommunikation endlos oft wiederholt wird.

Da kein Slave angeschlossen ist, wird die Adresse nicht mit ACK 
beantwortet, so dass die Kommunikation an dieser Stelle abgebrochen 
wird.

1
int main(void)
2
{
3
    // Configure PA5 and PC13 for blinking LED
4
    SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN);
5
    SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPCEN);
6
    MODIFY_REG(GPIOA->CRL, GPIO_CRL_CNF5 + GPIO_CRL_MODE5, GPIO_CRL_MODE5_0);
7
    MODIFY_REG(GPIOC->CRH, GPIO_CRH_CNF13 + GPIO_CRH_MODE13, GPIO_CRH_MODE13_0);
8
9
    // Enable Port B and alternate functions for I²C
10
    SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPBEN);
11
    SET_BIT(RCC->APB2ENR, RCC_APB2ENR_AFIOEN);
12
13
    // Initialize I2C1, no fast mode, APB1 clock is 8 MHz
14
    i2c_init(I2C1, false, 8000000);
15
16
    // I2C uses PB6=SCL, PB7=SDA, alternate function open-drain 2 MHz
17
    MODIFY_REG(GPIOB->CRL, GPIO_CRL_CNF6 + GPIO_CRL_MODE6, 
18
        GPIO_CRL_CNF6_0 + GPIO_CRL_CNF6_1 + GPIO_CRL_MODE6_1);
19
    MODIFY_REG(GPIOB->CRL, GPIO_CRL_CNF7 + GPIO_CRL_MODE7, 
20
        GPIO_CRL_CNF7_0 + GPIO_CRL_CNF7_1 + GPIO_CRL_MODE7_1);
21
22
    // Send and receive buffer
23
    uint8_t send_buffer[4] = { 10, 20, 30, 40 };
24
    uint8_t receive_buffer[9];
25
26
    for (;;)
27
    {
28
        delay(200);
29
30
        // Both LED HIGH
31
        WRITE_REG(GPIOA->BSRR, GPIO_BSRR_BS5);
32
        WRITE_REG(GPIOC->BSRR, GPIO_BSRR_BS13);
33
34
        // Communicate with slave address 8: send 4 bytes, then receive 9 bytes
35
        int received = i2c_communicate(I2C1, 8, send_buffer, 4, receive_buffer,    9);
36
37
        delay(200);
38
39
        // Both LED LOW
40
        WRITE_REG(GPIOA->BSRR, GPIO_BSRR_BR5);
41
        WRITE_REG(GPIOC->BSRR, GPIO_BSRR_BR13);
42
    }
43
44
}

von Mehmet K. (mkmk)


Lesenswert?

Dr. Sommer schrieb:
> "Den Not-Aus kann ich gerade leider nicht
> durchführen, ich muss noch Statusinformationen ans I²C-Display senden"
> wäre nicht so gut.

Also von Dir haette ich jetzt erwartet, dass Du den Not-Aus an ein 
Interrupt anbindest.

von Stefan F. (Gast)


Lesenswert?

Richard,
falls du mein Codebeispiel erneut von meiner Homepage herunter lädst, 
beachte bitte, dass ich inzwischen die Konfiguration der I/O Pins in die 
i2c_init() Funktion verschoben habe. Macht Sinn, oder?

von Dr. Sommer (Gast)


Lesenswert?

Mehmet K. schrieb:
> Also von Dir haette ich jetzt erwartet, dass Du den Not-Aus an ein
> Interrupt anbindest.

Und wenn es kein simpler Taster ist, sondern eine komplizierte 
Sensorauswertung? z.B. ein BMS welches regelmäßig alle Zelltemperaturen 
abfragt um Dinge wie Derating zu berechnen und manchmal eben auch 
Übertemperatur.

Ohne RTOS kann man nur einen Task haben der lange/blockierend läuft 
(main-Schleife). Alles andere muss dann in Interrupts. Wenn die Schleife 
schon blockiert ist (z.B. mit FAT32-und SD-Karten Ansteuerung oder 
Netzwerkanbindung) kann man die nicht auch noch mit I2C belegen.

Selbst wenn es nicht um Latenzen geht - vielleicht möchte man die 
Leistung des Prozessors komplett ausnutzen (z.B. DSP), wenn man da jede 
Menge Zeit in Warteschleifen vertrödelt kann das knapp werden.

Dann gibt es noch den Aspekt der Leistungsaufnahme - busy waiting 
Schleifen verbrauchen sinnlos Strom. Da kann man besser den Prozessor 
ständig schlafen legen und nur via Interrupt aufwecken wenn was 
passieren muss.

Oder eben doch mit RTOS. Aber auch da verwendet man eher nicht blinde 
Warteschleifen sondern weckt den Thread via Interrupt auf.

von Stefan F. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Ohne RTOS kann man nur einen Task haben der lange/blockierend läuft
> (main-Schleife).

Das stimmt nicht. Multitasking ist durchaus auch ohne RTOS (und ähnliche 
Konstrukte) möglich. Windows 3.11 und Android haben es uns jahrelang 
vorgemacht. Siehe https://www.mikrocontroller.net/articles/Statemachine 
und http://stefanfrings.de/multitasking_arduino/index.html

von Dr. Sommer (Gast)


Lesenswert?

Stefanus F. schrieb:
> Das stimmt nicht. Multitasking ist durchaus auch ohne RTOS (und ähnliche
> Konstrukte) möglich.

Leider kann man in State Machines nicht busy warten. Mit Interrupt 
basierten (Hardware) I2C würde man eben genau eine FSM implementieren - 
ohne Warten.

von Stefan F. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Leider kann man in State Machines nicht busy warten.

Korrekt. Mein Code-Beispiel ist in dieser Hinsicht also suboptimal.

von Dr. Sommer (Gast)


Lesenswert?

Stefanus F. schrieb:
> Windows 3.11 und Android haben es uns jahrelang vorgemacht.

Windows 3.11 hatte kooperatives Multitasking. Ob der Kontextwechsel 
aktiv oder per Timer Interrupt ausgelöst wird ist an der Stelle egal. 
Wie Android mit Linux etwas anderes als präemptives Multithreading 
gemacht haben soll weiß ich nicht.

von Stefan F. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Wie Android mit Linux etwas anderes als präemptives Multithreading
> gemacht haben soll weiß ich nicht.

Android Apps (die ganze Java VM) liefen lange Zeit Single-Threaded mit 
kooperativem Multitasking. Präemptives Multithreading gab es nur einen 
Layer darunter im nativen Code.

von Stefan F. (Gast)


Lesenswert?

Richard M. schrieb:
> i2c_init(I2C1, false, 72000000)

Ich denke, das kann nicht sein. Der APB1 Bus darf mit maximal 36Mhz 
getaktet werden. Hast du den AHB und APB1 Prescaler korrekt eingestellt?

Ich zitiere aus dem Referenzhandbuch:
"The FREQ bits must be configured with the APB clock frequency value 
(I2C peripheral connected to APB). The FREQ field is used by the 
peripheral to generate data setup and hold times compliant with the I2C 
specifications. The minimum allowed frequency is 2 MHz, the maximum 
frequency is limited by the maximum APB frequency and cannot exceed 50 
MHz (peripheral intrinsic maximum limit)."

Es wäre angenehm, zu erfahren, ob mein *.bin File bei Dir läuft (I2C1 
auf PB6 und PB7).

von Bene N. (klia)


Lesenswert?

Stefanus F. schrieb:
>
> Es wäre angenehm, zu erfahren, ob mein *.bin File bei Dir läuft (I2C1
> auf PB6 und PB7).

Leider nicht... Ich weiß nicht woran es liegt... Ich verzweifle langsam

von Stefan F. (Gast)


Lesenswert?

Benjamin N. schrieb:
>> Es wäre angenehm, zu erfahren, ob mein *.bin File bei Dir läuft (I2C1
>> auf PB6 und PB7).
>
> Leider nicht... Ich weiß nicht woran es liegt... Ich verzweifle langsam

Riecht nach Hardwarefehler. Blinkt denn wenigstens die LED an PA5 oder 
PC13?

von Bene N. (klia)


Lesenswert?

Stefanus F. schrieb:

> Riecht nach Hardwarefehler. Blinkt denn wenigstens die LED an PA5 oder
> PC13?

Wie beschrieben, nein, auch gar nicht möglich aufgrund unterschiedlicher 
Boards. Ich schreibe gerade das zip-File um, um es dann zu testen

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Benjamin N. schrieb:
> Leider nicht... Ich weiß nicht woran es liegt...

Blöde Frage: Pullups an SDA & SCL existieren aber, oder?

von Stefan F. (Gast)


Lesenswert?

Benjamin N. schrieb:
> Wie beschrieben, nein, auch gar nicht möglich aufgrund unterschiedlicher
> Boards.

Wie meinst du das? Weil er ein anderes Board hat kann es unmöglich 
defekt sein?

von Bene N. (klia)


Lesenswert?

Frank M. schrieb:
> Benjamin N. schrieb:
>> Leider nicht... Ich weiß nicht woran es liegt...
>
> Blöde Frage: Pullups an SDA & SCL existieren aber, oder?

Ja, 4,7k jeweils.

von Bene N. (klia)


Lesenswert?

Stefanus F. schrieb:
> Benjamin N. schrieb:
>> Wie beschrieben, nein, auch gar nicht möglich aufgrund unterschiedlicher
>> Boards.
>
> Wie meinst du das? Weil er ein anderes Board hat kann es unmöglich
> defekt sein?

Nein, defekt wie per Mail beschrieben kann es nicht sein!

Wenn ich das alte RTOS aufspiele funktioniert es tadellos

von Stefan F. (Gast)


Lesenswert?

Bene N. schrieb:
> Nein, defekt wie per Mail beschrieben kann es nicht sein!

Wenn aber weder die Hardware defekt ist, noch mein Beispielprogramm (was 
ich bewiesen habe), dann muss wohl ein Messfehler vorliegen.

Besorge Dir mal schleunigst ein Nucleo64-F103RB Board, damit du andere 
Hardware zum Vergleichen hast. Kostet nur ca 15€.

von Bene N. (klia)


Lesenswert?

Also ich hab jetzt einen kleinen Fortschritt. Er schickt zumindest 
schonmal ein Start-Bit... Das Signal geht von High auf Low aber das wars 
dann auch schon. Ich benutze das Programm von Stefanus.

Main wurde abgeändert in:
1
int main(void)
2
{
3
    // Enable Port B and alternate functions for I²C
4
    SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPBEN);
5
    SET_BIT(RCC->APB2ENR, RCC_APB2ENR_AFIOEN);
6
7
    // Initialize I2C1, no fast mode, APB1 clock is 8 MHz
8
    i2c_init(I2C1, false, 8000000);
9
10
    AFIO->MAPR |= AFIO_MAPR_I2C1_REMAP;
11
    // I2C uses PB6=SCL, PB7=SDA, alternate function open-drain 2 MHz
12
    // Must be done after the I2C initialization otherwise the I/O pins would start with wrong logic level
13
    MODIFY_REG(GPIOB->CRH, GPIO_CRH_CNF8 + GPIO_CRH_MODE8, GPIO_CRH_CNF8_0 + GPIO_CRH_CNF8_1 + GPIO_CRH_MODE8_1);
14
    MODIFY_REG(GPIOB->CRH, GPIO_CRH_CNF9 + GPIO_CRH_MODE9, GPIO_CRH_CNF9_0 + GPIO_CRH_CNF9_1 + GPIO_CRH_MODE9_1);
15
16
    uint8_t send_buffer[4] = { 10, 20, 30, 40 };
17
    uint8_t receive_buffer[9];
18
19
    for (;;)
20
    {
21
        delay(200);
22
23
        // Communicate with slave address 8: send 4 bytes, then receive 9 bytes
24
        int received = i2c_communicate(I2C1, 0xA8, send_buffer, 4, receive_buffer, 9);
25
26
        delay(200);
27
28
    }
29
30
}

Jetzt bleibt er hier hängen:
1
while (!READ_BIT(registerStruct->SR1, I2C_SR1_ADDR))             // wait until address has been sent
2
        {
3
            if (READ_BIT(registerStruct->SR1, I2C_SR1_AF))
4
            {
5
                // did not receive ACK after address
6
                goto error;
7
            }
8
        }

Liegt vermutlich an der falschen Adresse, aber immerhin ein Fortschritt. 
Was war der Fehler? Bisher keinen entdeckt. Plötzlich gigns...

von Stefan F. (Gast)


Lesenswert?

Bene N. schrieb:
> Liegt vermutlich an der falschen Adresse

Nein, er muss zumindest die ganze Adresse senden und das ACK (oder NAK) 
einlesen, so wie ich das weiter oben in meinem Screenshot von Logic 
Analyzer gezeigt habe.

Mit wie viel MHz wird denn dein ABP1 Bus konfiguriert?
Ich vermute, dass deine I²C Schnittstelle sich aufhängt, weil sie keine 
funktionierende Takt-Konfiguration hat. In meinem Beispielprogramm wird 
die Default-Vorgabe (nach Reset) verwendet, und das sind 8MHz.

In deinem umgeschriebenen Quelltext waren es zuerst 72MHz, dann 8MHz. 
Die meisten Leute benutzen hingegen das maximal mögliche, das wären 
36MHz. Ich denke, dass du die entscheidenden Code-Zeilen (die dafür 
verantwortlich sind) immer noch nicht gezeigt hast.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Bene N. schrieb:
> Liegt vermutlich an der falschen Adresse, aber immerhin ein Fortschritt.
> Was war der Fehler? Bisher keinen entdeckt. Plötzlich gigns...

 Man, probiere es doch mal mit HAL, dann weisst du wenigstens ob es
 ein Soft- oder Hardware Fehler ist.

von Bene N. (klia)


Lesenswert?

Stefanus F. schrieb:

> Mit wie viel MHz wird denn dein ABP1 Bus konfiguriert?
> Ich vermute, dass deine I²C Schnittstelle sich aufhängt, weil sie keine
> funktionierende Takt-Konfiguration hat. In meinem Beispielprogramm wird
> die Default-Vorgabe (nach Reset) verwendet, und das sind 8MHz.
>
Sind auf 36MHz und habe ich geändert. Die Init ist in stm32f10x_rcc.
1
static void SetSysClockTo72(void)
2
{
3
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
4
  
5
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
6
  /* Enable HSE */    
7
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
8
 
9
  /* Wait till HSE is ready and if Time out is reached exit */
10
  do
11
  {
12
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
13
    StartUpCounter++;  
14
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
15
16
  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
17
  {
18
    HSEStatus = (uint32_t)0x01;
19
  }
20
  else
21
  {
22
    HSEStatus = (uint32_t)0x00;
23
  }  
24
25
  if (HSEStatus == (uint32_t)0x01)
26
  {
27
    /* Enable Prefetch Buffer */
28
    FLASH->ACR |= FLASH_ACR_PRFTBE;
29
30
    /* Flash 2 wait state */
31
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
32
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    
33
34
 
35
    /* HCLK = SYSCLK */
36
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
37
      
38
    /* PCLK2 = HCLK */
39
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
40
    
41
    /* PCLK1 = HCLK */
42
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

: Bearbeitet durch User
von Bene N. (klia)


Angehängte Dateien:

Lesenswert?

Anbei mal ein Scope… Mehr macht er nicht :-(

Dabei war die Scope-Länge 20 Sekunden. Die Adresse 168 und das Byte 
10...

: Bearbeitet durch User
von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Was ist da los? Warum sind die Flanken so breit dargestellt? Ausserdem 
müsste SCL 5µs nach SDA auf Low gehen. Bei Dir ist der Zeitabstand viel 
zu gering. Das ist der dritte deutliche Hinweis auf fehlerhafte 
Takt-Konfiguration.

Es wäre wirklich hilfreich wenn du dein ganzes Programm zeigen 
würdest, damit das Raten aufhört. Die entscheidenden Zeilen fehlen schon 
wieder - ich kann nicht sehen, wie die PLL und der I2c Takt konfiguriert 
wurden.

Ich habe Dir erneut mein funktionierendes *.bin File angehängt, dieses 
mal mit Remapping auf PB8/9. Probiere es aus. (Der Kommentar "no pin 
remapping" ist falsch)

von Richard M. (Gast)


Lesenswert?

Ich habe es soeben auf den Controller geladen. Beide Ausgänge lediglich 
auf HIGH. Ich werde morgen mal das Programm hochladen

von Bene N. (klia)


Angehängte Dateien:

Lesenswert?

Anbei mein File

von Bene N. (klia)


Angehängte Dateien:

Lesenswert?

Anbei nochmal

von Stefan F. (Gast)


Lesenswert?

Bene N. schrieb:
> Anbei mein File

Was soll ich jetzt damit anfangen?

Ohne Quelltext kann ich es nicht analysieren und ohne eine Hardware kann 
ich es wahrscheinlich nicht ausführen. bzw: Um zu ermitteln, ob das 
Programm auf meiner Hardware ausführbar wäre, bräuchte ich den 
Quelltext.

Selbst wenn ich es auf meiner Hardware ausführen kann, kommt dabei nur 
eine Aussage wie "geht" oder "geht nicht" heraus. Beide Ergebnisse 
bringen Dich nicht weiter.

Langer Rede kurzer Sinn: Ich brauche immer noch deinen kompletten 
Quelltext.

von Bene N. (klia)


Angehängte Dateien:

Lesenswert?

Das ist mit dem obigen File aber auf Pins 6 und 7... Ich brauche aber 8 
und 9 und da funktioniert einfach gar nichts :-(

von Stefan F. (Gast)


Lesenswert?

Bene N. schrieb:
> Das ist mit dem obigen File aber auf Pins 6 und 7... Ich brauche
> aber 8
> und 9 und da funktioniert einfach gar nichts :-(

Junge Junge, ich habe Dir ein *.bin File gegeben, dass nachweislich auf 
Pin 8 und 9 kommuniziert. Hast du mein Foto und die Screenshots nicht 
gesehen?

von Bene N. (klia)


Lesenswert?

Stefanus F. schrieb:
> Bene N. schrieb:
>> Das ist mit dem obigen File aber auf Pins 6 und 7... Ich brauche
>> aber 8
>> und 9 und da funktioniert einfach gar nichts :-(
>
> Junge Junge, ich habe Dir ein *.bin File gegeben, dass nachweislich auf
> Pin 8 und 9 kommuniziert. Hast du mein Foto und die Screenshots nicht
> gesehen?

Natürlich hab ich das... Dennoch gibt er auf Pin 8 und 9 nichts aus!!!

von Stefan F. (Gast)


Lesenswert?

Bene N. schrieb:
> Stefanus F. schrieb:
>> Bene N. schrieb:
>>> Das ist mit dem obigen File aber auf Pins 6 und 7... Ich brauche
>>> aber 8
>>> und 9 und da funktioniert einfach gar nichts :-(
>>
>> Junge Junge, ich habe Dir ein *.bin File gegeben, dass nachweislich auf
>> Pin 8 und 9 kommuniziert. Hast du mein Foto und die Screenshots nicht
>> gesehen?
>
> Natürlich hab ich das... Dennoch gibt er auf Pin 8 und 9 nichts aus!!!

Dann musst du mal deine Dateien sortieren. Das kann unmöglich sein. Ein 
Programm, das bei mir auf PB8/9 Ausgaben macht*, kann unmöglich bei Dir 
stattdessen PB6/7 verwenden.

*) Was ich wieder anhand von Foto und Screenshot nachgewiesen habe

von Bene N. (klia)


Lesenswert?

Stefanus F. schrieb:
> Dann musst du mal deine Dateien sortieren. Das kann unmöglich sein. Ein
> Programm, das bei mir auf PB8/9 Ausgaben macht*, kann unmöglich bei Dir
> stattdessen PB6/7 verwenden.
>
> *) Was ich wieder anhand von Foto und Screenshot nachgewiesen habe

Ich habe auf dem EVAL Board Pin 6 und 7 überprüft und bekomme Daten 
siehe meinen Scope2. Ändere ich aber die Pins auf 8 und 9 wird nichts 
mehr ausgegeben. Das hat doch nichts mit den *.bin zu tun.

von Stefan F. (Gast)


Lesenswert?

Bene N. schrieb:
> Anbei nochmal

Na endlich!

Du hast also nun mein Programmbeispiel 1:1 übernommen und in deine IDE 
eingebaut. Irgendwelchen Fremden Code, der irgend etwas am Takt herum 
fummelt, habe ich da jetzt nicht mehr entdeckt.

Laut deinem Screenshot vom Logic Analyzer läuft es auch, aber auf den 
falschen Pins. Das kann bei dem Quelltext aber nicht sein. Hast du etwa 
vergessen, es nach Aktivierung des Remappings zu compilieren oder zu 
übertragen?

Mit deinem Projekt stimmt etwas nicht. Es scheint, als ob du die CMSIS 
Dateiena alle doppelt drin hast, einmal im Hauptverzeichnis und dann 
nochmal im CMSIS Verzeichnis. Ob dass die Fehlerursache ist, weiß ich 
nicht.

von Bene N. (klia)


Lesenswert?

Stefanus F. schrieb:
> Mit deinem Projekt stimmt etwas nicht. Es scheint, als ob du die CMSIS
> Dateiena alle doppelt drin hast, einmal im Hauptverzeichnis und dann
> nochmal im CMSIS Verzeichnis. Ob dass die Fehlerursache ist, weiß ich
> nicht.

Nein wird schon richtig kompiliert und wird auch geremapped aber es 
kommt einfach nix an den Pins an.

Ich entfernte CMSIS-Ordner aber ändert nichts.

von Stefan F. (Gast)


Lesenswert?

Es kann doch nicht sein, dass das Remapping trotz fehlerfreier Hardware 
nur auf deiner Hardware nicht funktioniert. Ich bin jetzt echt ratlos.

von Bene N. (klia)


Lesenswert?

Stefanus F. schrieb:
> Es kann doch nicht sein, dass das Remapping trotz fehlerfreier Hardware
> nur auf deiner Hardware nicht funktioniert. Ich bin jetzt echt ratlos.

Ich eben auch... Ich weiß nicht woran es liegt... Hab einen 4,7k an 
beiden Pins als PullUp. Es ist GENAU dein Programm. Pin 6 und 7 
funktionieren, sobald ich remappe geht nichts mehr

von Bene N. (klia)


Angehängte Dateien:

Lesenswert?

Das Startbit sendet er noch, aber nicht die Adresse... Und das versteh 
ich überhaupt nicht

von Stefan F. (Gast)


Lesenswert?

Bene N. schrieb:
> Das Startbit sendet er noch

Ja, aber mit falschem Timing (die beiden Flanken kommen zu schnell 
nacheinander). Und auch diese Messung zeigt wieder so einen auffällig 
breiten Balken bei der Zeitmarke +10µs. Also ob das Signal dort mehrfach 
ganz schnell zwischen High und Low hin und her wechselt.

Die Frage ist, ob das so vom µC kommt, oder von anderen Bauteilen, die 
am Bus hängen. Kannst du die Leitungen unterbrechen?

> Es ist GENAU dein Programm

Das sehe ich jetzt auch anhand deines ZIP Files. Ich dachte erst, dass 
deine IDE womöglich noch Code zur Takt-Konfiguration hinzu fügt, aber 
das ist ganz sicher nicht der Fall.

von Bene N. (klia)


Lesenswert?

Also es hing noch ein US dran... Ja. Habe jetzt die VErbindung getrennt. 
Allerdings liegen SCL und SDA jetzt nicht mehr auf HIGH sondern LOW. 
Jetzt kann ich mit LA nichts mehr messen

von Bene N. (klia)


Lesenswert?

Ok Stefanus... Ich glaub ich hab den Fehler gefunden... Ich berichte dir 
sobald sich das bestätigt hat...

von Stefan F. (Gast)


Lesenswert?

Bene N. schrieb:
> Allerdings liegen SCL und SDA jetzt nicht mehr auf HIGH sondern LOW.

Die Pull-Up Widerstände müssen dran bleiben. Das kannst du ja 
provisorisch machen.

> Ich glaub ich hab den Fehler gefunden
> Ich berichte dir sobald sich das bestätigt hat

Ich bin sehr neugierig auf des Rätsels Lösung.

von Stefan F. (Gast)


Lesenswert?

Ich habe in zwischen per Email die Information bekommen, dass doch ein 
HW Fehler vorliegt. Die Platine wurde falsch bestückt, so dass effektiv 
die Pull-Up Widerstände fehlten und ein Widerstand die Leitung SDA mit 
SCL verbunden hatte.

von Yo (Gast)


Lesenswert?

Nach 3 Tagen habe ich bei mir einen Fehler gefunden. Mag dieser hier 
auch sein. Die Lösung bei mir war ein Reset vom I2C Modul zu machen, 5ms 
warten, dann nochmal konfigurieren, warten nochmal 5ms, dann enable des 
Modules. Klingt  bescheuert, ist aber so.

von Stefan F. (Gast)


Lesenswert?

Yo schrieb:
> Die Lösung bei mir war ein Reset vom I2C Modul zu machen, 5ms
> warten, dann nochmal konfigurieren, warten nochmal 5ms, dann enable des
> Modules.

Ich würde dir einen Blick ins Errata Dokument zu werfen. Wenn du die 
Schnittstelle so benutzt, wir dort beschrieben ist, sind solche 
Wiederholungen nicht nötig.

> Klingt bescheuert, ist aber so.

Die Hardware ist halt ein bisschen buggy.

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.