コード例 #1
0
ファイル: i2c.c プロジェクト: Liambeguin/openlab
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);
}
コード例 #2
0
ファイル: i2c.c プロジェクト: VincentLade/openlab
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);
}