/** * I2C BSP — STM32 Standard Peripheral Library implementation * * I2C1: PB6(SCL), PB7(SDA) * Speed: 400kHz standard mode */ #include "i2c_bsp.h" /*=========================================================================== * Pin definitions *===========================================================================*/ #define I2Cx I2C1 #define I2C_GPIO_PORT GPIOB #define I2C_SCL_PIN GPIO_Pin_6 #define I2C_SDA_PIN GPIO_Pin_7 #define I2C_GPIO_CLK RCC_APB2Periph_GPIOB #define I2C_CLK RCC_APB1Periph_I2C1 #define I2C_SPEED 400000 /*=========================================================================== * Private: wait for flag with timeout *===========================================================================*/ static int wait_flag(FlagStatus flag, uint32_t timeout_us) { while (timeout_us--) { if (I2C_GetFlagStatus(I2Cx, flag) == SET) { return 0; } /* ~1us at 72MHz */ uint32_t dly = 12; while (dly--) { __NOP(); } } return -1; } /*=========================================================================== * Init *===========================================================================*/ void I2C_BSP_Init(void) { GPIO_InitTypeDef gpio; I2C_InitTypeDef i2c; RCC_APB2PeriphClockCmd(I2C_GPIO_CLK | RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(I2C_CLK, ENABLE); GPIO_StructInit(&gpio); gpio.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN; gpio.GPIO_Speed = GPIO_Speed_10MHz; gpio.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_Init(I2C_GPIO_PORT, &gpio); I2C_StructInit(&i2c); i2c.I2C_Mode = I2C_Mode_I2C; i2c.I2C_DutyCycle = I2C_DutyCycle_2; i2c.I2C_OwnAddress1 = 0x00; i2c.I2C_Ack = I2C_Ack_Enable; i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; i2c.I2C_ClockSpeed = I2C_SPEED; I2C_Init(I2Cx, &i2c); I2C_Cmd(I2Cx, ENABLE); } /*=========================================================================== * Write *===========================================================================*/ int I2C_BSP_Write(uint8_t slave_addr, const uint8_t *pdata, uint16_t len) { /* START */ I2C_GenerateSTART(I2Cx, ENABLE); if (wait_flag(I2C_FLAG_SB, 10000) != 0) return -1; /* Address + write direction */ I2C_Send7bitAddress(I2Cx, slave_addr, I2C_Direction_Transmitter); if (wait_flag(I2C_FLAG_ADDR, 10000) != 0) return -1; /* Clear ADDR */ (void)I2Cx->SR1; (void)I2Cx->SR2; /* Send data bytes */ for (uint16_t i = 0; i < len; i++) { if (wait_flag(I2C_FLAG_TXE, 10000) != 0) return -1; I2C_SendData(I2Cx, pdata[i]); } /* Wait for last byte to be sent */ if (wait_flag(I2C_FLAG_BTF, 10000) != 0) return -1; /* STOP */ I2C_GenerateSTOP(I2Cx, ENABLE); return 0; } /*=========================================================================== * Read (register address first, then repeated-start + read) *===========================================================================*/ int I2C_BSP_Read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *pbuf, uint16_t len) { if (len == 0) return 0; /* Phase 1: Write register address */ I2C_GenerateSTART(I2Cx, ENABLE); if (wait_flag(I2C_FLAG_SB, 10000) != 0) return -1; I2C_Send7bitAddress(I2Cx, slave_addr, I2C_Direction_Transmitter); if (wait_flag(I2C_FLAG_ADDR, 10000) != 0) return -1; (void)I2Cx->SR1; (void)I2Cx->SR2; if (wait_flag(I2C_FLAG_TXE, 10000) != 0) return -1; I2C_SendData(I2Cx, reg_addr); if (wait_flag(I2C_FLAG_BTF, 10000) != 0) return -1; /* Phase 2: Repeated start + read */ I2C_GenerateSTART(I2Cx, ENABLE); if (wait_flag(I2C_FLAG_SB, 10000) != 0) return -1; I2C_Send7bitAddress(I2Cx, slave_addr, I2C_Direction_Receiver); if (wait_flag(I2C_FLAG_ADDR, 10000) != 0) return -1; (void)I2Cx->SR1; (void)I2Cx->SR2; /* Read bytes: ACK for all except last */ for (uint16_t i = 0; i < len; i++) { if (i == (len - 1)) { /* Last byte: NACK before reading */ I2C_AcknowledgeConfig(I2Cx, DISABLE); } if (wait_flag(I2C_FLAG_RXNE, 10000) != 0) return -1; pbuf[i] = I2C_ReceiveData(I2Cx); } /* STOP */ I2C_GenerateSTOP(I2Cx, ENABLE); I2C_AcknowledgeConfig(I2Cx, ENABLE); /* restore */ return 0; }