#include "i2c.h" #include "stm32f10x_i2c.h" #include "stm32f10x_gpio.h" #include "porting.h" void i2cInit(I2C_TypeDef* I2Cx) { if (I2Cx == I2C1) { i2c1Init(); } else { THROW_ERROR(E_I2C_NON_EXISTANT); } } void i2c1Init(void) { // Initialization structs GPIO_InitTypeDef i2c_gpio; I2C_InitTypeDef i2c; // Turn on clocks RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); //Configure I2C module i2c.I2C_ClockSpeed = 100000; i2c.I2C_Mode = I2C_Mode_I2C; i2c.I2C_DutyCycle = I2C_DutyCycle_2; i2c.I2C_OwnAddress1 = 0x15; i2c.I2C_Ack = I2C_Ack_Enable; i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_Init(I2C1, &i2c); //Additionally we need to initialize corresponding GPIOs i2c_gpio.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; i2c_gpio.GPIO_Mode = GPIO_Mode_AF_OD; // Open drain only if you have pull-up resistors i2c_gpio.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &i2c_gpio); // Enable I2C 1 I2C_Cmd(I2C1, ENABLE); DEBUG_MSG("I2C1 initialized."); } uint8_t i2cPing(I2C_TypeDef* I2Cx, uint8_t slave_addr) { DEBUG_MSG("Searching for: %d\n", slave_addr); // Wait until I2Cx is not busy anymore while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)); // Generate start condition I2C_GenerateSTART(I2Cx, ENABLE); while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); // Send slave address I2C_Send7bitAddress(I2Cx, slave_addr<<1, I2C_Direction_Transmitter); // Wait for I2C EV5. volatile uint32_t timeout = 0xFFFF; while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if (timeout == 0) { break; } else { timeout--; } } I2C_GenerateSTOP(I2Cx, ENABLE); if (timeout > 0) { DEBUG_MSG("Slave found\n\r"); return 1; } else { DEBUG_MSG("Slave not found\n\r"); } return 0; } void i2cStartTransmission(I2C_TypeDef* I2Cx, uint8_t dir, uint8_t slave_addr) { // Wait for I2C module to become ready while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)); // Generate I2C start condition I2C_GenerateSTART(I2Cx, ENABLE); // Waiting for EV5 while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); // The 7 bit address needs to be shifted by 1 I2C_Send7bitAddress(I2Cx, slave_addr<<1, dir); // Depending on whether the master is reading or writing another event is triggered if(dir== I2C_Direction_Transmitter) { while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); } if(dir== I2C_Direction_Receiver) { while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); } } void i2cWrite(I2C_TypeDef* I2Cx, uint8_t* data, uint16_t len, uint32_t timeout) { if(len-- >= 1) { I2C_SendData(I2Cx, *data++); } while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED) && timeout) { timeout--; } } void i2cAckOn(I2C_TypeDef* I2Cx) { I2C_AcknowledgeConfig(I2Cx, ENABLE); } void i2cAckOff(I2C_TypeDef* I2Cx) { I2C_AcknowledgeConfig(I2Cx, DISABLE); } uint8_t i2cRead(I2C_TypeDef* I2Cx) { while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); uint8_t data = I2C_ReceiveData(I2Cx); return data; } void i2cEndTransmission(I2C_TypeDef* I2Cx) { I2C_GenerateSTOP(I2Cx, ENABLE); while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF)); }