Forum: Mikrocontroller und Digitale Elektronik I2C @ STM32L476RG


von Christian (christian_m346)


Lesenswert?

Ich versuche auf einem STM32L476RG ein EEPROM via I2C anzusprechen. 
Leider scheitere ich aber offenbar bereits an der grundsätzlichen 
Konfig. der I2C-Schnittstelle:
1
void config_i2c(void) {
2
  //Initialize PB13 and PB14 as SCL and SDA respectively:
3
  {
4
    RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;
5
6
    //Configure PB13 as SCL:
7
    {
8
      GPIOB->AFR[1] &= ~(GPIO_AFRH_AFRH5);
9
      GPIOB->AFR[1] |= ((uint32_t)GPIO_AF4_I2C2) << GPIO_AFRH_AFSEL13_Pos;
10
      GPIOB->MODER |= GPIO_MODER_MODER13_1;
11
      GPIOB->OTYPER |= GPIO_OTYPER_OT13;
12
      GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR13;
13
    }
14
15
    //Configure PB14 as SDA:
16
    {
17
      GPIOB->AFR[1] &= ~(GPIO_AFRH_AFRH6);
18
      GPIOB->AFR[1] |= ((uint32_t)GPIO_AF4_I2C2) << GPIO_AFRH_AFSEL14_Pos;
19
      GPIOB->MODER |= GPIO_MODER_MODER14_1;
20
      GPIOB->OTYPER |= GPIO_OTYPER_OT14;
21
      GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR14;
22
    }
23
  }
24
25
  //Initialize the I2C interface for master mode:
26
  {
27
    //Make sure HSI16 clock is turned on.
28
    RCC->CR |= RCC_CR_HSION;
29
    while(!(RCC->CR & RCC_CR_HSIRDY));
30
31
    //Select HSI16 clock as I2C2 clock.
32
    RCC->CCIPR |= RCC_CCIPR_I2C2SEL_1;
33
34
    //Enable the clock for the I2C interface.
35
    RCC->APB1ENR1 |= RCC_APB1ENR1_I2C2EN;
36
37
    //Disable the I2C peripheral.
38
    I2C2->CR1 &= ~(I2C_CR1_PE);
39
40
    //Configure timing for "Fast-mode".
41
    //(See Table 236 of the Reference Manual "RM0351, Rev 9" for the values.)
42
    I2C2->TIMINGR =
43
      (0x1u << I2C_TIMINGR_PRESC_Pos) +
44
      (0x9u << I2C_TIMINGR_SCLL_Pos) +
45
      (0x3u << I2C_TIMINGR_SCLH_Pos) +
46
      (0x2u << I2C_TIMINGR_SDADEL_Pos) +
47
      (0x3u << I2C_TIMINGR_SCLDEL_Pos);
48
49
    //"Stop" and "Restart" will be generated by software.
50
    I2C2->CR2 &= ~(I2C_CR2_AUTOEND);
51
52
    //Configure 7-bit addressing and set slave address.
53
    I2C2->CR2 &= ~(I2C_CR2_ADD10);
54
    I2C2->CR2 &= ~(I2C_CR2_SADD);
55
    I2C2->CR2 |= (NV_RAM_DEVICE_ADDRESS << 1)&0xFEul;
56
57
    //Enable the I2C peripheral.
58
    I2C2->CR1 |= I2C_CR1_PE;
59
  }
60
}
Wenn ich dann versuche, erst einmal einfach eine "Start Condition" zu 
generieren, passiert genau gar nichts. Das heisst, ich sehe auf dem 
Oszi. rein gar nichts auf den zwei Leitungen.
1
void do_some_magic(void) {
2
  //Set transfer dir. "write".
3
  I2C2->CR2 &= ~(I2C_CR2_RD_WRN);
4
5
  //Configure number of bytes to be written.
6
  I2C2->CR2 |= 1 << I2C_CR2_NBYTES_Pos;
7
8
  //Generate "Start Condition".
9
  I2C2->CR2 |= I2C_CR2_START;
10
  while(I2C2->CR2&I2C_CR2_START); //<-- HIER DREHT ES "FOREVER"
11
12
  return;
13
}
Was muss ich noch "enablen", "clearen" etc. oder was sonst ist falsch?

: Bearbeitet durch User
von Harry L. (mysth)


Lesenswert?

Su solltest HAL nutzen!

Funktioniert einfach und spart enorm Lebenszeit.

von Christian (christian_m346)


Lesenswert?

Harry L. schrieb:
> Su solltest HAL nutzen!
>
> Funktioniert einfach und spart enorm Lebenszeit.

Mit HAL funktioniert es übrigens. Hätte ja auch sein können, dass es an 
der Hardware, Verkabelung, Pull-ups etc. liegt. Das tut es aber nicht. 
Und ich will hier jetzt eben keinen HAL.

von Wilhelm M. (wimalopaan)


Lesenswert?

zumindest beim Setzen des MODER der GPIOB scheint mit ein "clear" vor 
dem "or" der Bits zu fehlen. Denn das "or" setzt zwar das schon gesetzte 
Bit. Jedoch musst Du aus dem "analog mode" raus.

Benutze das CMSIS Macro: MODIFY_REG (mit der richtigen Maske).

: Bearbeitet durch User
von Wilhelm M. (wimalopaan)


Lesenswert?

Christian schrieb:
> while(I2C2->CR2&I2C_CR2_START); //<-- HIER DREHT ES "FOREVER"

Falls das Senden mal geklappt hat, solltest Du hier I2C_ISR_TXIS 
verwenden.

von Christian (christian_m346)


Lesenswert?

Wilhelm M. schrieb:
> zumindest beim Setzen des MODER der GPIOB scheint mit ein "clear" vor
> dem "or" der Bits zu fehlen. Denn das "or" setzt zwar das schon gesetzte
> Bit. Jedoch musst Du aus dem "analog mode" raus.
>
> Benutze das CMSIS Macro: MODIFY_REG (mit der richtigen Maske).

Das löst das Problem. Vielen Dank.

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.