Forum: Mikrocontroller und Digitale Elektronik STM32F4 I2C immer busy


von Patrick B. (p51d)


Lesenswert?

Hallo miteinander

Ich möchte ein wenig mit dem I2C der STM-Familie herumspielen, aber 
bisher leider ohne Erfolg. Beim Versuch etwas zu senden oder Empfangen 
ist das Modul immer busy, ohne das etwas gemacht wird.
Ich habe mich nun schon seit 3 Tagen an diesem ding generft. Vieleicht 
fällt einem ja auf, was falsch ist:
1
void HMC5883L_init(void)
2
{
3
    GPIO_InitTypeDef GPIO_InitStructure;
4
    I2C_InitTypeDef I2C_InitStructure;
5
6
    // write CONFIG_A register
7
    uint8_t tmp = (HMC5883L_AVERAGING_8 << (HMC5883L_CRA_AVERAGE_BIT - HMC5883L_CRA_AVERAGE_LENGTH + 1)) |
8
                  (HMC5883L_RATE_15 << (HMC5883L_CRA_RATE_BIT - HMC5883L_CRA_RATE_LENGTH + 1)) |
9
                  (HMC5883L_BIAS_NORMAL << (HMC5883L_CRA_BIAS_BIT - HMC5883L_CRA_BIAS_LENGTH + 1)) ;
10
11
    // Enable clock
12
    RCC_APB1PeriphClockCmd(HMC5883L_I2C_RCC_Periph, ENABLE);
13
    RCC_AHB1PeriphClockCmd(HMC5883L_I2C_RCC_Port, ENABLE);
14
15
    // Performing a Reset
16
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
17
    RCC_APB1PeriphResetCmd(HMC5883L_I2C_RCC_Periph, ENABLE);
18
    RCC_APB1PeriphResetCmd(HMC5883L_I2C_RCC_Periph, DISABLE);
19
20
    // Connect Pins to AF function
21
    GPIO_PinAFConfig(HMC5883L_I2C_Port, HMC5883L_I2C_SCL_Pin, HMC5883L_I2C_SCL_AF);
22
    GPIO_PinAFConfig(HMC5883L_I2C_Port, HMC5883L_I2C_SDA_Pin, HMC5883L_I2C_SDA_AF);
23
24
    // Configure I2C SCL Pin(Pin10), SDA Pin (pin11)
25
    GPIO_InitStructure.GPIO_Pin = HMC5883L_I2C_SCL_Pin | HMC5883L_I2C_SDA_Pin;
26
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
27
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
28
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
29
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
30
    GPIO_Init(HMC5883L_I2C_Port, &GPIO_InitStructure);
31
32
    // Configure I2C
33
    I2C_DeInit(HMC5883L_I2C);
34
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;                  // I2C mode
35
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;              // 50% duty cycle -> standard
36
    I2C_InitStructure.I2C_OwnAddress1 = 0;                    // not relevant in master mode
37
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
38
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;  // Set address length to 7 bit addresses
39
    I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;
40
    I2C_Init(HMC5883L_I2C, &I2C_InitStructure);
41
42
    /*ENABLE*/
43
    I2C_Cmd(HMC5883L_I2C, ENABLE);
44
45
    HMC5883L_I2C_ByteWrite(HMC5883L_DEFAULT_ADDRESS, &tmp ,HMC5883L_RA_CONFIG_A); // <== Hier hängt er sich auf
46
}
1
void HMC5883L_I2C_ByteWrite(uint8_t slaveAddr, uint8_t* pBuffer, uint8_t WriteAddr)
2
{
3
// Diese Schlaufe wird nie verlassen
4
  while(I2C_GetFlagStatus(HMC5883L_I2C, I2C_FLAG_BUSY));      // wait until I2C is not busy anymore
5
6
  /* Send START condition */
7
  I2C_GenerateSTART(HMC5883L_I2C, ENABLE);
8
9
  /* Test on EV5 and clear it */
10
  while(!I2C_CheckEvent(HMC5883L_I2C, I2C_EVENT_MASTER_MODE_SELECT));
11
12
  /* Send HMC5883 address for write */
13
  I2C_Send7bitAddress(HMC5883L_I2C, slaveAddr, I2C_Direction_Transmitter);
14
15
  /* Test on EV6 and clear it */
16
  while(!I2C_CheckEvent(HMC5883L_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
17
18
  /* Send the HMC5883L internal address to write to */
19
  I2C_SendData(HMC5883L_I2C, WriteAddr);
20
21
  /* Test on EV8 and clear it */
22
  while(!I2C_CheckEvent(HMC5883L_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
23
24
  /* Send the byte to be written */
25
  I2C_SendData(HMC5883L_I2C, *pBuffer);
26
27
  /* Test on EV8 and clear it */
28
  while(!I2C_CheckEvent(HMC5883L_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
29
30
  /* Send STOP condition */
31
  I2C_GenerateSTOP(HMC5883L_I2C, ENABLE);
32
}

Testweise habe ich die I2C-Lib etwas angepasst:
1
FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG)
2
{
3
  FlagStatus bitstatus = RESET;
4
  __IO uint32_t i2creg = 0, i2cxbase = 0;
5
uint32_t SR1 = 0, SR2 = 0;
6
  /* Check the parameters */
7
  assert_param(IS_I2C_ALL_PERIPH(I2Cx));
8
  assert_param(IS_I2C_GET_FLAG(I2C_FLAG));
9
10
  /* Get the I2Cx peripheral base address */
11
  i2cxbase = (uint32_t)I2Cx;
12
  
13
  /* Read flag register index */
14
  i2creg = I2C_FLAG >> 28;
15
  
16
  /* Get bit[23:0] of the flag */
17
  I2C_FLAG &= FLAG_MASK;
18
  
19
  if(i2creg != 0)
20
  {
21
    /* Get the I2Cx SR1 register address */
22
    i2cxbase += 0x14;
23
  }
24
  else
25
  {
26
    /* Flag in I2Cx SR2 Register */
27
    I2C_FLAG = (uint32_t)(I2C_FLAG >> 16);
28
    /* Get the I2Cx SR2 register address */
29
    i2cxbase += 0x18;
30
  }
31
SR1 = (*(__IO uint32_t *) (i2cxbase - 0x18 + 0x14));
32
SR2 = (*(__IO uint32_t *)i2cxbase);
33
  if(((*(__IO uint32_t *)i2cxbase) & I2C_FLAG) != (uint32_t)RESET)
34
  {
35
    /* I2C_FLAG is set */
36
    bitstatus = SET;
37
  }
38
  else
39
  {
40
    /* I2C_FLAG is reset */
41
    bitstatus = RESET;
42
  }
43
  
44
  /* Return the I2C_FLAG status */
45
  return  bitstatus;
46
}
SR1 = 0;
SR2 = 2; -> Busy Flag ist gesetzt

Was habe ich falsch gemacht?

Besten Dank für die Hilfe
MFG
Patrick

von dein Lehrer (Gast)


Lesenswert?

Patrick B. schrieb:
> ding generft. Vieleicht
> fällt einem ja auf, was falsch ist:

richtig wäre
Ding genervt. Vielleicht

von frame (Gast)


Lesenswert?

Hast du schon einmal nachgemessen, was auf dem Bus passiert ?
Ein Oszilloskop ist hier sehr hilfreich.

Zumindest statisch sollten die Pegel stimmen. I2C ist ein Open-Drain 
Bus, das ist dir schon bewußt. Sprich, du brauchst einen 
Pullup-Widerstand. Fehlt der, ist der Bus auch immer "busy".
Und wenn das alles in Ordnung ist: manchmal starten diverse I2C-Slaves 
nicht korrekt, weil sie irgendeine Störung als Bussignal bewerten. Dann 
kann es helfen, auf SCL 9 Taktimpulse auszugeben, damit der Slave SDA 
wieder freigibt. Dazu müßtest du die I2C-Pins als GPIO betreiben.

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.