I2C @ STM32L476RG

OP #7491818
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?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren