/********************************************************************** * Copyright: (C)2024 LingYun IoT System Studio * Author: GuoWenxue * * Description: The purpose of this code is to provide a simple C library, * which providing software bit-bang of the I2C protocol on * any GPIO pins for ISKBoard. * * ChangeLog: * Version Date Author Description * V1.0.0 2024.08.29 GuoWenxue Release initial version * ***********************************************************************/ #ifndef __I2C_BITBANG_H #define __I2C_BITBANG_H #include "stm32l4xx_hal.h" #include #include #define I2C_DELAY_US 5 /* I2C timing delay in microseconds */ #define I2C_TIMEOUT_COUNT 100 /* Timeout counter for waiting ACK */ /* GPIO port for I2C typedef */ typedef struct i2c_gpio_s { GPIO_TypeDef *group; /* GPIO group */ uint16_t pin; /* GPIO pin */ } i2c_gpio_t; /* I2C bus typedef */ typedef struct i2c_bus_s { volatile atomic_bool lock; /* Bus lock flag */ uint8_t addr; /* 7-bits slave address */ i2c_gpio_t scl; /* SCL GPIO pin */ i2c_gpio_t sda; /* SDA GPIO pin */ } i2c_bus_t; /* GPIO level enum */ enum { LOW = 0, HIGH = 1, }; /* I2C ACK/NACK enum */ typedef enum { I2C_ACK = 0, I2C_NACK = 1 } i2c_ack_t; /* I2C status enum */ typedef enum { I2C_OK = 0, I2C_ERROR = 1, I2C_TIMEOUT = 2, I2C_BUSY = 3 } i2c_status_t; /* *+---------------------------------+ *| I2C bus control function | *+---------------------------------+ */ /* I2C1 bus instance for SHT20, RTC, OLED on board */ extern i2c_bus_t i2c1_bus; /* I2C2 bus instance on MikroBUS */ extern i2c_bus_t i2c2_bus; /** * @brief Initialize I2C GPIO pins * @param bus: pointer to I2C bus structure * @retval None */ extern void i2c_init(i2c_bus_t *bus); /** * @brief Deinitialize I2C GPIO pins * @param bus: pointer to I2C bus structure * @retval None */ extern void i2c_deinit(i2c_bus_t *bus); /** * @brief 通用 I2C 设备属性结构体 */ typedef struct { i2c_bus_t *bus; /* 绑定的 I2C 物理总线实例 */ uint8_t dev_addr; /* 7位设备物理从机地址 */ } i2c_dev_t; /** * @brief 绑定设备及地址到 I2C 总线上 * @param dev: I2C 设备结构体指针 * @param bus: 物理总线指针 * @param dev_addr: 7位从机地址 * @retval 0: 成功; -1: 失败 */ extern int i2c_bind_dev(i2c_dev_t *dev, i2c_bus_t *bus, uint8_t dev_addr); /** * @brief 将I2C总线加锁让设备独占总线 * @param dev: I2C 设备结构体指针 * @retval 0: 成功; -1: 失败 */ extern int i2c_lock_dev(i2c_dev_t *dev); /** * @brief 释放设备的 I2C 总线锁 * @param dev: I2C 设备结构体指针 * @retval 无 */ extern void i2c_free_dev(i2c_dev_t *dev); /** * @brief Lock I2C bus for exclusive access (bare metal mutex) * @param bus: pointer to I2C bus structure * @retval I2C_OK if success, I2C_BUSY if bus is locked */ extern i2c_status_t i2c_lock(i2c_bus_t *bus); /** * @brief Unlock I2C bus * @param bus: pointer to I2C bus structure * @retval None */ extern void i2c_unlock(i2c_bus_t *bus); /** * @brief Scan I2C bus for connected devices * @param bus: pointer to I2C bus structure * @retval none */ extern void i2c_scan(i2c_bus_t *bus); /* *+---------------------------------+ *| I2C timing sequence function | *+---------------------------------+ */ /** * @brief Generate I2C start condition * @param bus: pointer to I2C bus structure * @retval None */ extern void i2c_start(i2c_bus_t *bus); /** * @brief Generate I2C stop condition * @param bus: pointer to I2C bus structure * @retval None */ extern void i2c_stop(i2c_bus_t *bus); /** * @brief Wait for ACK from slave * @param bus: pointer to I2C bus structure * @retval I2C_ACK or I2C_NACK */ extern i2c_ack_t i2c_wait_ack(i2c_bus_t *bus); /** * @brief Send ACK to slave * @param bus: pointer to I2C bus structure * @retval None */ extern void i2c_send_ack(i2c_bus_t *bus); /** * @brief Send NACK to slave * @param bus: pointer to I2C bus structure * @retval None */ extern void i2c_send_nack(i2c_bus_t *bus); /** * @brief Write one byte to I2C bus * @param bus: pointer to I2C bus structure * @param byte: byte to write * @retval None */ extern void i2c_write_byte(i2c_bus_t *bus, uint8_t byte); /** * @brief Read one byte from I2C bus * @param bus: pointer to I2C bus structure * @retval received byte */ extern uint8_t i2c_read_byte(i2c_bus_t *bus); /* *+-----------------------------------+ *| I2C read/write function | *+-----------------------------------+ */ /** * @brief Write data to I2C slave device * @param bus: pointer to I2C bus structure * @param addr: 7-bit slave address * @param reg: register address * @param data: pointer to data buffer * @param len: data length * @retval I2C status */ extern i2c_status_t i2c_write(i2c_bus_t *bus, uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len); /** * @brief Read data from I2C slave device * @param bus: pointer to I2C bus structure * @param addr: 7-bit slave address * @param reg: register address * @param data: pointer to data buffer * @param len: data length * @retval I2C status */ extern i2c_status_t i2c_read(i2c_bus_t *bus, uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len); /** * @brief Write data to I2C slave device without register address * @param bus: pointer to I2C bus structure * @param addr: 7-bit slave address * @param data: pointer to data buffer * @param len: data length * @retval I2C status */ extern i2c_status_t i2c_write_no_reg(i2c_bus_t *bus, uint8_t addr, uint8_t *data, uint16_t len); /** * @brief Read data from I2C slave device without register address * @param bus: pointer to I2C bus structure * @param addr: 7-bit slave address * @param data: pointer to data buffer * @param len: data length * @retval I2C status */ extern i2c_status_t i2c_read_no_reg(i2c_bus_t *bus, uint8_t addr, uint8_t *data, uint16_t len); /* *+-----------------------------------+ *| Linux I2C API–compatible function | *+-----------------------------------+ */ #define I2C_M_WR 0x0000 /* 写控制标志 */ #define I2C_M_RD 0x0001 /* 读控制标志 */ typedef struct { uint8_t addr; /* 7位从机地址 */ uint16_t flags; /* I2C_M_WR 或 I2C_M_RD */ uint16_t len; /* 数据长度 */ uint8_t *buf; /* 数据指针 */ } i2c_msg_t; /* Functions compatible with the Linux I2C adapter API */ extern i2c_status_t i2c_transfer(i2c_bus_t *bus, i2c_msg_t *msgs, int num); #endif /* __I2C_BITBANG_H */