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?