I2C: add frequency support instead of just fast mode
This commit is contained in:
parent
944379fda9
commit
6e160c31af
|
@ -21,7 +21,6 @@
|
|||
|
||||
/* standard libraries */
|
||||
#include <stdint.h> // standard integer types
|
||||
//#include <stdio.h> // standard I/O facilities
|
||||
#include <stdlib.h> // general utilities
|
||||
|
||||
/* STM32 (including CM3) libraries */
|
||||
|
@ -61,6 +60,7 @@ static uint32_t RCC_I2C(uint32_t i2c)
|
|||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
/** get RCC for GPIO port for SCL pin based on I2C identifier
|
||||
* @param[in] i2c I2C base address
|
||||
* @return RCC GPIO address
|
||||
|
@ -76,6 +76,7 @@ static uint32_t RCC_GPIO_PORT_SCL(uint32_t i2c)
|
|||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
/** get RCC for GPIO port for SDA pin based on I2C identifier
|
||||
* @param[in] i2c I2C base address
|
||||
* @return RCC GPIO address
|
||||
|
@ -91,6 +92,7 @@ static uint32_t RCC_GPIO_PORT_SDA(uint32_t i2c)
|
|||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
/** get GPIO port for SCL pin based on I2C identifier
|
||||
* @param[in] i2c I2C base address
|
||||
* @return GPIO address
|
||||
|
@ -112,6 +114,7 @@ static uint32_t GPIO_PORT_SCL(uint32_t i2c)
|
|||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
/** get GPIO port for SDA pin based on I2C identifier
|
||||
* @param[in] i2c I2C base address
|
||||
* @return GPIO address
|
||||
|
@ -133,6 +136,7 @@ static uint32_t GPIO_PORT_SDA(uint32_t i2c)
|
|||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
/** get GPIO pin for SCL pin based on I2C identifier
|
||||
* @param[in] i2c I2C base address
|
||||
* @return GPIO address
|
||||
|
@ -154,6 +158,7 @@ static uint32_t GPIO_PIN_SCL(uint32_t i2c)
|
|||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
/** get GPIO pin for SDA pin based on I2C identifier
|
||||
* @param[in] i2c I2C base address
|
||||
* @return GPIO address
|
||||
|
@ -176,7 +181,7 @@ static uint32_t GPIO_PIN_SDA(uint32_t i2c)
|
|||
}
|
||||
}
|
||||
|
||||
void i2c_master_setup(uint32_t i2c, bool fast)
|
||||
void i2c_master_setup(uint32_t i2c, uint16_t frequency)
|
||||
{
|
||||
// check I2C peripheral
|
||||
if (I2C1!=i2c && I2C2!=i2c) {
|
||||
|
@ -194,15 +199,18 @@ void i2c_master_setup(uint32_t i2c, bool fast)
|
|||
rcc_periph_clock_enable(RCC_I2C(i2c)); // enable clock for I2C peripheral
|
||||
i2c_reset(i2c); // reset configuration
|
||||
i2c_peripheral_disable(i2c); // I2C needs to be disable to be configured
|
||||
if (frequency>400) { // limit frequency to 400 kHz
|
||||
frequency = 400;
|
||||
}
|
||||
i2c_set_clock_frequency(i2c, rcc_apb1_frequency/1000000); // configure the peripheral clock to the APB1 freq (where it is connected to)
|
||||
if (fast) {
|
||||
i2c_set_fast_mode(i2c);
|
||||
i2c_set_ccr(i2c, rcc_apb1_frequency/(400000*2)); // set Thigh/Tlow to generate frequency of 400 kHz
|
||||
i2c_set_trise(i2c, (300/(1000/(rcc_apb1_frequency/1000000)))+1); // max rise time for 300 kHz is 300 ns
|
||||
if (frequency>100) { // use fast mode for frequencies > 100 kHz
|
||||
i2c_set_fast_mode(i2c); // set fast mode
|
||||
i2c_set_ccr(i2c, rcc_apb1_frequency/(frequency*1000*2)); // set Thigh/Tlow to generate frequency (fast duty not used)
|
||||
i2c_set_trise(i2c, (300/(1000/(rcc_apb1_frequency/1000000)))+1); // max rise time for Fm mode (< 400) kHz is 300 ns
|
||||
} else {
|
||||
i2c_set_standard_mode(i2c); // the DS1307 has a maximum I2C SCL freq if 100 kHz (corresponding to the standard mode)
|
||||
i2c_set_ccr(i2c, rcc_apb1_frequency/(100000*2)); // set Thigh/Tlow to generate frequency of 100 kHz
|
||||
i2c_set_trise(i2c, (1000/(1000/(rcc_apb1_frequency/1000000)))+1); // max rise time for 100 kHz is 1000 ns (~1 MHz)
|
||||
i2c_set_ccr(i2c, rcc_apb1_frequency/(frequency*1000*2)); // set Thigh/Tlow to generate frequency of 100 kHz
|
||||
i2c_set_trise(i2c, (1000/(1000/(rcc_apb1_frequency/1000000)))+1); // max rise time for Sm mode (< 100 kHz) is 1000 ns (~1 MHz)
|
||||
}
|
||||
i2c_peripheral_enable(i2c); // enable I2C after configuration completed
|
||||
|
||||
|
@ -212,11 +220,7 @@ void i2c_master_setup(uint32_t i2c, bool fast)
|
|||
timer_reset(TIM(I2C_MASTER_TIMER)); // reset timer state
|
||||
timer_set_mode(TIM(I2C_MASTER_TIMER), TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); // set timer mode, use undivided timer clock, edge alignment (simple count), and count up
|
||||
timer_one_shot_mode(TIM(I2C_MASTER_TIMER)); // stop counter after update event (we only need to one timeout and reset before next operation)
|
||||
if (fast) {
|
||||
timer_set_prescaler(TIM(I2C_MASTER_TIMER), rcc_ahb_frequency/400000-1); // set the prescaler so one tick is also one I2C bit (used I2C frequency)
|
||||
} else {
|
||||
timer_set_prescaler(TIM(I2C_MASTER_TIMER), rcc_ahb_frequency/100000-1); // set the prescaler so one tick is also one I2C bit (used I2C frequency)
|
||||
}
|
||||
timer_set_prescaler(TIM(I2C_MASTER_TIMER), rcc_ahb_frequency/(frequency*1000)-1); // set the prescaler so one tick is also one I2C bit (used I2C frequency)
|
||||
timer_set_period(TIM(I2C_MASTER_TIMER), I2C_MASTER_TIMEOUT*9); // use factor to wait for all 9 bits to be transmitted
|
||||
timer_update_on_overflow(TIM(I2C_MASTER_TIMER)); // only use counter overflow as UEV source (use overflow as timeout)
|
||||
|
||||
|
@ -239,6 +243,11 @@ void i2c_master_setup(uint32_t i2c, bool fast)
|
|||
|
||||
void i2c_master_release(uint32_t i2c)
|
||||
{
|
||||
// check I2C peripheral
|
||||
if (I2C1!=i2c && I2C2!=i2c) {
|
||||
while (true);
|
||||
}
|
||||
|
||||
i2c_reset(i2c); // reset I2C peripheral configuration
|
||||
i2c_peripheral_disable(i2c); // disable I2C peripheral
|
||||
rcc_periph_clock_disable(RCC_I2C(i2c)); // disable clock for I2C peripheral
|
||||
|
@ -259,6 +268,11 @@ void i2c_master_release(uint32_t i2c)
|
|||
|
||||
bool i2c_master_check_signals(uint32_t i2c)
|
||||
{
|
||||
// check I2C peripheral
|
||||
if (I2C1!=i2c && I2C2!=i2c) {
|
||||
while (true);
|
||||
}
|
||||
|
||||
return (0!=gpio_get(GPIO_PORT_SCL(i2c), GPIO_PIN_SCL(i2c)) && 0!=gpio_get(GPIO_PORT_SDA(i2c), GPIO_PIN_SDA(i2c)));
|
||||
}
|
||||
|
||||
|
@ -300,7 +314,7 @@ bool i2c_master_select_slave(uint32_t i2c, uint8_t slave, bool write)
|
|||
return false; // could not send start condition
|
||||
}
|
||||
}
|
||||
if (!(I2C_SR2(i2c) & I2C_SR2_MSL)) { // I2C device is already not master mode
|
||||
if (!(I2C_SR2(i2c) & I2C_SR2_MSL)) { // I2C device is not in master mode
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,10 @@
|
|||
|
||||
/** setup I2C peripheral
|
||||
* @param[in] i2c I2C base address
|
||||
* @param[in] fast use standard (100 kHz) or fast (400 kHz) mode
|
||||
* @param[in] frequency frequency to use in kHz (1-400)
|
||||
* @note Standard mode (Sm) is used for frequencies up to 100 kHz, and Fast mode (Fm) is used for frequencies up to 400 kHz
|
||||
*/
|
||||
void i2c_master_setup(uint32_t i2c, bool fast);
|
||||
void i2c_master_setup(uint32_t i2c, uint16_t frequency);
|
||||
/** release I2C peripheral
|
||||
* @param[in] i2c I2C base address
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue