void i2c_enable(i2c_t i2c, i2c_clock_mode_t mode) { uint32_t pclk, freq; const _i2c_t *_i2c = i2c; // Disable the I2C EV and ERR interrupt lines in the NVIC nvic_disable_interrupt_line(_i2c->irq_line_ev); nvic_disable_interrupt_line(_i2c->irq_line_er); // Enable the clock for this peripheral rcc_apb_enable(_i2c->apb_bus, _i2c->apb_bit); // Reset the peripheral *i2c_get_CR1(_i2c) = I2C_CR1__SWRST; // Clear all registers *i2c_get_CR2(_i2c) = 0; *i2c_get_CCR(_i2c) = 0; *i2c_get_TRISE(_i2c) = 0; *i2c_get_SR1(_i2c) = 0; *i2c_get_SR2(_i2c) = 0; *i2c_get_OAR1(_i2c) = 0; *i2c_get_OAR2(_i2c) = 0; // Release SWRST *i2c_get_CR1(_i2c) = 0; /* Step 1: program the peripheral input clock in CR2 */ // Compute clock frequency pclk = rcc_sysclk_get_clock_frequency( _i2c->apb_bus == 1 ? RCC_SYSCLK_CLOCK_PCLK1 : RCC_SYSCLK_CLOCK_PCLK2); freq = pclk / 1000000; *i2c_get_CR2(_i2c) = freq & I2C_CR2__FREQ_MASK; /* Step 2: configure the clock control registers */ if (mode == I2C_CLOCK_MODE_FAST) { // Set Fast Speed mode and bitrate: ~400kHz uint32_t ccr = freq * 10; ccr = ccr / 12 + (ccr % 12 ? 1 : 0); *i2c_get_CCR(_i2c) = I2C_CCR__FS | ccr; } else { // Set Standard Speed mode and bitrate: 100kHz *i2c_get_CCR(_i2c) = (freq * 5) & I2C_CCR__CCR_MASK; } /* Step 3: configure the rise time registers */ if (mode == I2C_CLOCK_MODE_FAST) { // Configure maximum rise time *i2c_get_TRISE(_i2c) = (freq * 3 / 10 + 1) & I2C_TRISE__TRISE_MASK; } else { // Configure maximum rise time *i2c_get_TRISE(_i2c) = (freq + 1) & I2C_TRISE__TRISE_MASK; } /* Step 4: program the CR1 register to enable the peripheral */ // Enable I2C *i2c_get_CR1(_i2c) = I2C_CR1__PE; // Enable EVT and ERR interrupt // Note: do not enable BUF to avoid stm32f problem *i2c_get_CR2(_i2c) |= I2C_CR2__ITEVTEN | I2C_CR2__ITERREN; // Initialize I2C state _i2c->data->state = I2C_IDLE; _i2c->data->len_send = 0; _i2c->data->len_recv = 0; _i2c->data->cpt_send = 0; _i2c->data->cpt_recv = 0; _i2c->data->transfer_handler = NULL; // Enable I2C EV and ERR interrupt line in the NVIC nvic_enable_interrupt_line(_i2c->irq_line_ev); nvic_enable_interrupt_line(_i2c->irq_line_er); }
void i2c_enable(i2c_t i2c, i2c_clock_mode_t mode) { uint32_t pclk, freq; _i2c_t *_i2c = i2c; // Disable the I2C EV and ERR interrupt lines in the NVIC nvic_disable_interrupt_line(_i2c->irq_line_ev); nvic_disable_interrupt_line(_i2c->irq_line_er); // Enable the clock for this peripheral rcc_apb_enable(_i2c->apb_bus, _i2c->apb_bit); // Reset the peripheral *i2c_get_CR1(_i2c) = I2C_CR1__SWRST; // Clear all registers *i2c_get_CR1(_i2c) = 0; *i2c_get_CR2(_i2c) = 0; *i2c_get_CCR(_i2c) = 0; *i2c_get_TRISE(_i2c) = 0; *i2c_get_SR1(_i2c) = 0; *i2c_get_SR2(_i2c) = 0; /* Step 1: program the peripheral input clock in CR2 */ // Compute clock frequency pclk = rcc_sysclk_get_clock_frequency( _i2c->apb_bus == 1 ? RCC_SYSCLK_CLOCK_PCLK1 : RCC_SYSCLK_CLOCK_PCLK2); freq = pclk / 1000000; *i2c_get_CR2(_i2c) = freq & I2C_CR2__FREQ_MASK; /* Step 2: configure the clock control registers */ if (mode == I2C_CLOCK_MODE_FAST) { // Set Fast Speed mode and bitrate: 400kHz with duty t_low/t_high = 16/9 *i2c_get_CCR(_i2c) = I2C_CCR__FS | I2C_CCR__DUTY | (freq / 10 * 25); } else { // Set Standard Speed mode and bitrate: 100kHz *i2c_get_CCR(_i2c) = (freq * 5) & I2C_CCR__CCR_MASK; } /* Step 3: configure the rise time registers */ if (mode == I2C_CLOCK_MODE_FAST) { // Configure maximum rise time *i2c_get_TRISE(_i2c) = (freq * 3 / 10 + 1) & I2C_TRISE__TRISE_MASK; } else { // Configure maximum rise time *i2c_get_TRISE(_i2c) = (freq + 1) & I2C_TRISE__TRISE_MASK; } /* Step 4: program the CR1 register to enable the peripheral */ // Set I2C mode, enable ACK and enable I2C *i2c_get_CR1(_i2c) = I2C_CR1__ACK | I2C_CR1__PE; // Enable EV and BUF interrupt *i2c_get_CR2(_i2c) |= I2C_CR2__ITEVTEN | I2C_CR2__ITBUFEN | I2C_CR2__ITERREN; // Initialize I2C state state = I2C_IDLE; // Enable I2C EV and ERR interrupt line in the NVIC nvic_enable_interrupt_line(_i2c->irq_line_ev); nvic_enable_interrupt_line(_i2c->irq_line_er); }