From 3d500401a949d5859fd4129bd477a1747a89a830 Mon Sep 17 00:00:00 2001 From: ArthurCai Date: Mon, 29 Jan 2024 22:39:05 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E8=BD=AF=E4=BB=B6=E6=A8=A1=E6=8B=9FI2C)?= =?UTF-8?q?=EF=BC=9A=E4=BF=AE=E6=94=B9=E5=AE=8F=E5=AE=9A=E4=B9=89=EF=BC=8C?= =?UTF-8?q?=E6=96=B9=E4=BE=BF=E5=90=8E=E7=BB=AD=E5=85=BC=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 移动地址长度宏到 bsp_soft_i2c.h 文件内 2. 根据 GD32F30X_XX 和 STM32F10X_XX 生成对应的宏 SOFT_I2C_GD32F3_USED 和 SOFT_I2C_STM32F1_USED 3. 修改 bsp_soft_i2c_private.h 文件内的宏函数结构 4. 修改 bsp_soft_i2c.c 内时钟延展等待计数为可修改的宏 SOFT_I2C_WAIT_CNT Signed-off-by: ArthurCai --- software_i2c/bsp_soft_i2c.c | 40 ++++++++--------- software_i2c/bsp_soft_i2c.h | 39 +++++++++++++--- software_i2c/bsp_soft_i2c_private.h | 69 ++++++++++++++++++++++------- 3 files changed, 105 insertions(+), 43 deletions(-) diff --git a/software_i2c/bsp_soft_i2c.c b/software_i2c/bsp_soft_i2c.c index 2e99c2a..dd2e3ff 100644 --- a/software_i2c/bsp_soft_i2c.c +++ b/software_i2c/bsp_soft_i2c.c @@ -25,8 +25,7 @@ * @return void */ SOFT_I2C_STATIC_INLINE void soft_i2c_gpio_clk_enable(P_SOFT_I2C_GPIO_COMM_T p_gpio) { -#if defined(GD32F30X_HD) || defined(GD32F30X_CL) || defined(GD32F30X_XD) || \ - defined(STM32F10X_HD) || defined(STM32F10X_MD) || defined(STM32F10X_CL) +#if defined(SOFT_I2C_GD32F3_USED) || defined(SOFT_I2C_STM32F1_USED) SOFT_I2C_ENABLE_GPIO_CLK(p_gpio->gpioClk); #else return; @@ -45,10 +44,10 @@ SOFT_I2C_STATIC_INLINE void soft_i2c_gpio_clk_enable(P_SOFT_I2C_GPIO_COMM_T p_gp * @endcode */ static void soft_i2c_set_od_mode(P_SOFT_I2C_GPIO_COMM_T p_gpio) { -#if defined(GD32F30X_HD) || defined(GD32F30X_CL) || defined(GD32F30X_XD) +#if defined(SOFT_I2C_GD32F3_USED) // GD32F30x芯片 gpio_init(p_gpio->gpioPort, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, p_gpio->gpioPin); -#elif defined(STM32F10X_HD) || defined(STM32F10X_MD) || defined(STM32F10X_CL) +#elif defined(SOFT_I2C_STM32F1_USED) // STM32F10x芯片 GPIO_InitTypeDef initStruct; initStruct.GPIO_Pin = (uint16_t)p_gpio->gpioPin; @@ -71,8 +70,7 @@ static void soft_i2c_set_od_mode(P_SOFT_I2C_GPIO_COMM_T p_gpio) { * @return void */ SOFT_I2C_STATIC_INLINE void soft_i2c_write_gpio(P_SOFT_I2C_GPIO_COMM_T p_gpio, uint8_t val) { -#if defined(GD32F30X_HD) || defined(GD32F30X_CL) || defined(GD32F30X_XD) || \ - defined(STM32F10X_HD) || defined(STM32F10X_MD) || defined(STM32F10X_CL) +#if defined(SOFT_I2C_GD32F3_USED) || defined(SOFT_I2C_STM32F1_USED) if (val) { SOFT_I2C_SET_PIN(p_gpio->gpioPort, p_gpio->gpioPin); } else { @@ -92,8 +90,7 @@ SOFT_I2C_STATIC_INLINE void soft_i2c_write_gpio(P_SOFT_I2C_GPIO_COMM_T p_gpio, u * @retval 0 低电平, 1 高电平 */ SOFT_I2C_STATIC_INLINE uint8_t soft_i2c_read_gpio(P_SOFT_I2C_GPIO_COMM_T p_gpio) { -#if defined(GD32F30X_HD) || defined(GD32F30X_CL) || defined(GD32F30X_XD) || \ - defined(STM32F10X_HD) || defined(STM32F10X_MD) || defined(STM32F10X_CL) +#if defined(SOFT_I2C_GD32F3_USED) || defined(SOFT_I2C_STM32F1_USED) return (SOFT_I2C_READ_PIN(p_gpio->gpioPort, p_gpio->gpioPin)) ? 1 : 0; #else return 0xFF; @@ -119,17 +116,19 @@ static void soft_i2c_delay_us(void) { */ static void soft_i2c_delay_800ns(void) { uint32_t i = 0; -#if defined(GD32F30X_HD) || defined(GD32F30X_CL) || defined(GD32F30X_XD) +#if defined(SOFT_I2C_GD32F3_USED) uint32_t j = 0; for (i = 0; i < 2; i++) { for (j = 0; j < (SOFT_I2C_DELAY_CYCLE * 4) / 5; j++) { __asm("NOP"); } } -#elif defined(STM32F10X_HD) || defined(STM32F10X_MD) || defined(STM32F10X_CL) +#elif defined(SOFT_I2C_STM32F1_USED) for (i = 0; i < 2; i++) { __asm("NOP"); } +#else + return; #endif } #pragma pop @@ -196,7 +195,7 @@ static soft_i2c_err_t soft_i2c_stop(P_SOFT_I2C_T p_i2c) { soft_i2c_delay_us(); soft_i2c_write_gpio(&p_i2c->scl, SOFT_I2C_LEVEL_HIGH); #if defined(__SOFT_I2C_CLOCK_STRECH_EN__) - uint32_t waitCnt = 0xFFF; ///< 等待计数 + uint32_t waitCnt = SOFT_I2C_WAIT_CNT; ///< 等待计数 SOFT_I2C_WAIT_SCL_RELEASE(p_i2c, waitCnt); // 等待SCL释放 if (waitCnt == 0) { return SOFT_I2C_ERR_TIMEOUT; @@ -221,7 +220,7 @@ static soft_i2c_err_t soft_i2c_stop(P_SOFT_I2C_T p_i2c) { * @endcode */ static soft_i2c_err_t soft_i2c_wait_ack(P_SOFT_I2C_T p_i2c) { - uint32_t waitCnt = 0xFFF; ///< 等待计数 + uint32_t waitCnt = SOFT_I2C_WAIT_CNT; ///< 等待计数 soft_i2c_write_gpio(&p_i2c->sda, SOFT_I2C_LEVEL_HIGH); // 开启线与 soft_i2c_write_gpio(&p_i2c->scl, SOFT_I2C_LEVEL_HIGH); // 拉起SCL #if defined(__SOFT_I2C_CLOCK_STRECH_EN__) @@ -282,8 +281,8 @@ static void soft_i2c_ack_respond(P_SOFT_I2C_T p_i2c, uint8_t ackVal) { static soft_i2c_err_t soft_i2c_send_byte(P_SOFT_I2C_T p_i2c, uint8_t byte) { uint8_t loopCnt = 0; ///< 循环计数 #if defined(__SOFT_I2C_CLOCK_STRECH_EN__) - uint32_t waitCnt = 0xFFF; ///< 等待计数 - bool isFirstBit = true; ///< 是否第一位 + uint32_t waitCnt = SOFT_I2C_WAIT_CNT; ///< 等待计数 + bool isFirstBit = true; ///< 是否第一位 #endif for (loopCnt = 0; loopCnt < 8; loopCnt++) { soft_i2c_write_gpio(&p_i2c->sda, SOFT_I2C_GET_MSB_BIT(byte)); // 写入数据 @@ -323,8 +322,8 @@ static soft_i2c_err_t soft_i2c_send_byte(P_SOFT_I2C_T p_i2c, uint8_t byte) { static soft_i2c_err_t soft_i2c_read_byte(P_SOFT_I2C_T p_i2c, uint8_t *p_data) { uint8_t loopCnt = 0; ///< 循环计数 #if defined(__SOFT_I2C_CLOCK_STRECH_EN__) - uint32_t waitCnt = 0xFFF; ///< 等待计数 - bool isFirstBit = true; ///< 是否第一位 + uint32_t waitCnt = SOFT_I2C_WAIT_CNT; ///< 等待计数 + bool isFirstBit = true; ///< 是否第一位 #endif soft_i2c_write_gpio(&p_i2c->sda, SOFT_I2C_LEVEL_HIGH); // 开启线与 for (loopCnt = 0; loopCnt < 8; loopCnt++) { @@ -450,8 +449,7 @@ soft_i2c_err_t soft_i2c_init(P_SOFT_I2C_T p_i2c) { return SOFT_I2C_ERR_PARAM; } // 2. 初始化结构体内监控变量 -#if defined(GD32F30X_HD) || defined(GD32F30X_CL) || defined(GD32F30X_XD) || \ - defined(STM32F10X_HD) || defined(STM32F10X_MD) || defined(STM32F10X_CL) +#if defined(SOFT_I2C_GD32F3_USED) || defined(SOFT_I2C_STM32F1_USED) p_i2c->isValid = true; // 芯片有效 #else p_i2c->isValid = false; // 芯片无效 @@ -491,7 +489,8 @@ soft_i2c_err_t soft_i2c_init(P_SOFT_I2C_T p_i2c) { * @endcode */ soft_i2c_err_t soft_i2c_write(P_SOFT_I2C_T p_i2c, uint32_t slaveAddr, uint32_t regAddr, uint32_t regAddrLen, uint8_t *p_data, uint32_t dataLen) { - if (p_i2c == NULL || p_data == NULL || p_i2c->isValid == false || p_i2c->isInit == false || dataLen == 0) { + if (p_i2c == NULL || p_data == NULL || p_i2c->isValid == false || p_i2c->isInit == false || \ + dataLen == 0 || regAddrLen < SOFT_I2C_REG_ADDR_LEN_1 || regAddrLen > SOFT_I2C_REG_ADDR_LEN_2) { return SOFT_I2C_ERR_PARAM; } SOFT_I2C_DEF_MSG(w_msg, slaveAddr, regAddr, regAddrLen, p_data, dataLen, SOFT_I2C_WRITE); @@ -517,7 +516,8 @@ soft_i2c_err_t soft_i2c_write(P_SOFT_I2C_T p_i2c, uint32_t slaveAddr, uint32_t r * @endcode */ soft_i2c_err_t soft_i2c_read(P_SOFT_I2C_T p_i2c, uint32_t slaveAddr, uint32_t regAddr, uint32_t regAddrLen, uint8_t *p_data, uint32_t dataLen) { - if (p_i2c == NULL || p_data == NULL || p_i2c->isValid == false || p_i2c->isInit == false || dataLen == 0) { + if (p_i2c == NULL || p_data == NULL || p_i2c->isValid == false || p_i2c->isInit == false || \ + dataLen == 0 || regAddrLen < SOFT_I2C_REG_ADDR_LEN_1 || regAddrLen > SOFT_I2C_REG_ADDR_LEN_2) { return SOFT_I2C_ERR_PARAM; } SOFT_I2C_DEF_MSG(r_msg, slaveAddr, regAddr, regAddrLen, p_data, dataLen, SOFT_I2C_READ); diff --git a/software_i2c/bsp_soft_i2c.h b/software_i2c/bsp_soft_i2c.h index d04351b..f13d627 100644 --- a/software_i2c/bsp_soft_i2c.h +++ b/software_i2c/bsp_soft_i2c.h @@ -17,12 +17,18 @@ /* 根据不同的芯片包含不同的文件 */ #if defined(GD32F30X_HD) || defined(GD32F30X_CL) || defined(GD32F30X_XD) -#include "gd32f30x.h" +#define SOFT_I2C_GD32F3_USED ///< 使用GD32F3芯片 #elif defined(STM32F10X_HD) || defined(STM32F10X_MD) || defined(STM32F10X_CL) -#include "stm32f10x.h" +#define SOFT_I2C_STM32F1_USED ///< 使用STM32F1芯片 #else #error "Please select the target chip model!" #endif + +#if defined(SOFT_I2C_GD32F3_USED) +#include "gd32f30x.h" +#elif defined(SOFT_I2C_STM32F1_USED) +#include "stm32f10x.h" +#endif #include #include #include @@ -33,6 +39,8 @@ #define SOFT_I2C_STATIC_INLINE static __inline ///< 静态内联函数 #elif defined(__GNUC__) #define SOFT_I2C_STATIC_INLINE static inline ///< 静态内联函数 +#else +#define SOFT_I2C_STATIC_INLINE #endif /** @@ -55,6 +63,18 @@ typedef uint32_t soft_i2c_err_t; ///< 返回值类型 * @} */ +/** + * @brief 软件模拟 I2C 寄存器地址长度 + * @addtogroup SOFT_I2C_REG_ADDR_LEN + * @{ + */ +#define SOFT_I2C_REG_ADDR_LEN_1 (1U) ///< 1字节寄存器地址长度 +#define SOFT_I2C_REG_ADDR_LEN_2 (2U) ///< 2字节寄存器地址长度 +/** + * @} + */ + +#if defined(SOFT_I2C_GD32F3_USED) || defined(SOFT_I2C_STM32F1_USED) /** * @brief 软件模拟 I2C 外部声明 * @@ -62,8 +82,11 @@ typedef uint32_t soft_i2c_err_t; ///< 返回值类型 */ #define SOFT_I2C_EXT(name) \ extern void *const name +#else +#define SOFT_I2C_EXT(name) +#endif -#if defined(GD32F30X_HD) || defined(GD32F30X_CL) || defined(GD32F30X_XD) +#if defined(SOFT_I2C_GD32F3_USED) /** * @brief 软件模拟 I2C 定义结构体 * @@ -80,8 +103,9 @@ typedef uint32_t soft_i2c_err_t; ///< 返回值类型 {GPIO##sda_port, GPIO_PIN_##sda_pin, SOFT_I2C_GPIO##sda_port##_CLK}, \ SOFT_I2C_IDLE \ }; \ - void *const name = &soft_i2c_##name -#elif defined(STM32F10X_HD) || defined(STM32F10X_MD) || defined(STM32F10X_CL) + void *const name = &soft_i2c_##name \ + +#elif defined(SOFT_I2C_STM32F1_USED) /** * @brief 软件模拟 I2C 定义结构体 * @@ -98,7 +122,10 @@ typedef uint32_t soft_i2c_err_t; ///< 返回值类型 {GPIO##sda_port##_BASE, GPIO_Pin_##sda_pin, SOFT_I2C_GPIO##sda_port##_CLK}, \ SOFT_I2C_IDLE \ }; \ - void *const name = &soft_i2c_##name + void *const name = &soft_i2c_##name \ + +#else +#define SOFT_I2C_DEF(name, scl_port, scl_pin, sda_port, sda_pin) #endif #ifdef __cplusplus diff --git a/software_i2c/bsp_soft_i2c_private.h b/software_i2c/bsp_soft_i2c_private.h index c9e5603..7efacbe 100644 --- a/software_i2c/bsp_soft_i2c_private.h +++ b/software_i2c/bsp_soft_i2c_private.h @@ -22,17 +22,9 @@ * @addtogroup SOFT_I2C_COMM_DEF * @{ */ -#define SOFT_I2C_SET_PIN(port, pin) \ - (*(volatile uint32_t *)(uint32_t)((port) + 0x10U)) = (uint32_t)(pin) -#define SOFT_I2C_RESET_PIN(port, pin) \ - (*(volatile uint32_t *)(uint32_t)((port) + 0x14U)) = (uint32_t)(pin) -#define SOFT_I2C_READ_PIN(port, pin) \ - (*(volatile uint32_t *)(uint32_t)((port) + 0x08U)) & (uint32_t)(pin) -#define SOFT_I2C_ENABLE_GPIO_CLK(gpioClk) \ - (*(volatile uint32_t *)(uint32_t)(0x40021000U + 0x18U)) |= (uint32_t)(gpioClk) -#if defined(GD32F30X_HD) || defined(GD32F30X_CL) || defined(GD32F30X_XD) +#if defined(SOFT_I2C_GD32F3_USED) #define SOFT_I2C_DELAY_CYCLE (10U) ///< 延时周期数 -#elif defined(STM32F10X_HD) || defined(STM32F10X_MD) || defined(STM32F10X_CL) +#elif defined(SOFT_I2C_STM32F1_USED) #define SOFT_I2C_DELAY_CYCLE (1U) ///< 延时周期数 #else #define SOFT_I2C_DELAY_CYCLE (1U) ///< 延时周期数 @@ -43,22 +35,65 @@ #define SOFT_I2C_NACK SOFT_I2C_LEVEL_HIGH ///< I2C非应答信号(高电平) #define SOFT_I2C_WRITE (0U) ///< 写操作 #define SOFT_I2C_READ (1U) ///< 读操作 -#define SOFT_I2C_REG_ADDR_LEN_1 (1U) ///< 1字节寄存器地址长度 -#define SOFT_I2C_REG_ADDR_LEN_2 (2U) ///< 2字节寄存器地址长度 +#define SOFT_I2C_WAIT_CNT (0xFFFU) ///< 等待计数(用于时钟延展) /* * @} */ +/** + * @brief 软件模拟 I2C 引脚置高 + * + * @param [in] port 端口 + * @param [in] pin 引脚 + */ +#define SOFT_I2C_SET_PIN(port, pin) \ + (*(volatile uint32_t *)(uint32_t)((port) + 0x10U)) = (uint32_t)(pin) + +/** + * @brief 软件模拟 I2C 引脚置低 + * + * @param [in] port 端口 + * @param [in] pin 引脚 + */ +#define SOFT_I2C_RESET_PIN(port, pin) \ + (*(volatile uint32_t *)(uint32_t)((port) + 0x14U)) = (uint32_t)(pin) + +/** + * @brief 软件模拟 I2C 读引脚输入电平 + * + * @param [in] port 端口 + * @param [in] pin 引脚 + */ +#define SOFT_I2C_READ_PIN(port, pin) \ + (*(volatile uint32_t *)(uint32_t)((port) + 0x08U)) & (uint32_t)(pin) + +/** + * @brief 软件模拟 I2C 使能引脚时钟 + * + * @param [in] gpioClk 引脚时钟 @ref SOFT_I2C_GPIO_CLK_E + */ +#define SOFT_I2C_ENABLE_GPIO_CLK(gpioClk) \ + (*(volatile uint32_t *)(uint32_t)(0x40021000U + 0x18U)) |= (uint32_t)(gpioClk) + /** * @brief 软件模拟 I2C 位操作 * @addtogroup SOFT_I2C_BIT_OPERATION * @{ */ -#define SOFT_I2C_GET_MSB_BIT(data) (((data) >> 7) & 0x01) ///< 获取最高位 -#define SOFT_I2C_GET_LOW_BYTE(data) (uint8_t)((data) & 0xFF) ///< 获取低字节 -/* - * @} -*/ + +/** + * @brief 软件模拟 I2C 获取最高位 + * + * @param [in] data 数据 + */ +#define SOFT_I2C_GET_MSB_BIT(data) (((data) >> 7) & 0x01) + +/** + * @brief 软件模拟 I2C 获取最低字节 + * + * @param [in] data 数据 + */ +#define SOFT_I2C_GET_LOW_BYTE(data) (uint8_t)((data) & 0xFF) /** * @brief 软件模拟 I2C 等待 SCL 释放