mirror of
https://github.com/Arthur-cai/Soft_I2C_Driver.git
synced 2025-06-17 04:52:05 +00:00
fix(软件模拟I2C):修改停止信号和起始信号,修改延展计数为用户可设置
1. 修改停止信号函数为void型,且超时不会return 2. 起始信号函数增加时钟延展判断 3. I2C驱动结构体增加延展计数 4. I2C驱动初始化函数增加传参,设置延展计数 Signed-off-by: ArthurCai <arthurcai_c@163.com>
This commit is contained in:
parent
b85cb7c4bb
commit
8d6fbce170
@ -45,10 +45,8 @@ SOFT_I2C_STATIC_INLINE void soft_i2c_gpio_clk_enable(P_SOFT_I2C_GPIO_COMM_T p_gp
|
||||
*/
|
||||
static void soft_i2c_set_od_mode(P_SOFT_I2C_GPIO_COMM_T p_gpio) {
|
||||
#if defined(SOFT_I2C_GD32F3_USED)
|
||||
// GD32F30x芯片
|
||||
gpio_init(p_gpio->gpioPort, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, p_gpio->gpioPin);
|
||||
#elif defined(SOFT_I2C_STM32F1_USED)
|
||||
// STM32F10x芯片
|
||||
GPIO_InitTypeDef initStruct;
|
||||
initStruct.GPIO_Pin = (uint16_t)p_gpio->gpioPin;
|
||||
initStruct.GPIO_Mode = GPIO_Mode_Out_OD;
|
||||
@ -170,6 +168,10 @@ static void soft_i2c_start(P_SOFT_I2C_T p_i2c) {
|
||||
soft_i2c_delay_800ns();
|
||||
soft_i2c_write_gpio(&p_i2c->sda, SOFT_I2C_LEVEL_HIGH);
|
||||
soft_i2c_write_gpio(&p_i2c->scl, SOFT_I2C_LEVEL_HIGH);
|
||||
#if defined(__SOFT_I2C_CLOCK_STRECH_EN__)
|
||||
uint32_t waitCnt = p_i2c->waitCnt; ///< 等待计数
|
||||
SOFT_I2C_WAIT_SCL_RELEASE(p_i2c, waitCnt); // 等待SCL释放
|
||||
#endif
|
||||
soft_i2c_delay_us();
|
||||
soft_i2c_write_gpio(&p_i2c->sda, SOFT_I2C_LEVEL_LOW);
|
||||
soft_i2c_delay_us();
|
||||
@ -181,29 +183,23 @@ static void soft_i2c_start(P_SOFT_I2C_T p_i2c) {
|
||||
*
|
||||
* @param [in] p_i2c I2C结构体指针
|
||||
*
|
||||
* @return soft_i2c_err_t
|
||||
* @retval 0 成功, 其他值 失败 @ref SOFT_I2C_ERR_CODE
|
||||
* @details 特殊说明:
|
||||
* @par eg:
|
||||
* @code
|
||||
*
|
||||
* @endcode
|
||||
*/
|
||||
static soft_i2c_err_t soft_i2c_stop(P_SOFT_I2C_T p_i2c) {
|
||||
static void soft_i2c_stop(P_SOFT_I2C_T p_i2c) {
|
||||
soft_i2c_write_gpio(&p_i2c->scl, SOFT_I2C_LEVEL_LOW);
|
||||
soft_i2c_write_gpio(&p_i2c->sda, SOFT_I2C_LEVEL_LOW);
|
||||
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 = SOFT_I2C_WAIT_CNT; ///< 等待计数
|
||||
uint32_t waitCnt = p_i2c->waitCnt; ///< 等待计数
|
||||
SOFT_I2C_WAIT_SCL_RELEASE(p_i2c, waitCnt); // 等待SCL释放
|
||||
if (waitCnt == 0) {
|
||||
return SOFT_I2C_ERR_TIMEOUT;
|
||||
}
|
||||
#endif
|
||||
soft_i2c_delay_us();
|
||||
soft_i2c_write_gpio(&p_i2c->sda, SOFT_I2C_LEVEL_HIGH);
|
||||
return SOFT_I2C_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -220,10 +216,11 @@ 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 = SOFT_I2C_WAIT_CNT; ///< 等待计数
|
||||
uint32_t waitCnt = 100;
|
||||
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__)
|
||||
waitCnt = p_i2c->waitCnt; ///< 等待计数
|
||||
SOFT_I2C_WAIT_SCL_RELEASE(p_i2c, waitCnt); // 等待SCL释放
|
||||
if (waitCnt == 0) {
|
||||
return SOFT_I2C_ERR_TIMEOUT;
|
||||
@ -281,8 +278,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 = SOFT_I2C_WAIT_CNT; ///< 等待计数
|
||||
bool isFirstBit = true; ///< 是否第一位
|
||||
uint32_t waitCnt = p_i2c->waitCnt; ///< 等待计数
|
||||
bool isFirstBit = true; ///< 是否第一位
|
||||
#endif
|
||||
for (loopCnt = 0; loopCnt < 8; loopCnt++) {
|
||||
soft_i2c_write_gpio(&p_i2c->sda, SOFT_I2C_GET_MSB_BIT(byte)); // 写入数据
|
||||
@ -322,8 +319,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 = SOFT_I2C_WAIT_CNT; ///< 等待计数
|
||||
bool isFirstBit = true; ///< 是否第一位
|
||||
uint32_t waitCnt = p_i2c->waitCnt; ///< 等待计数
|
||||
bool isFirstBit = true; ///< 是否第一位
|
||||
#endif
|
||||
soft_i2c_write_gpio(&p_i2c->sda, SOFT_I2C_LEVEL_HIGH); // 开启线与
|
||||
for (loopCnt = 0; loopCnt < 8; loopCnt++) {
|
||||
@ -368,6 +365,7 @@ static soft_i2c_err_t soft_i2c_comm(P_SOFT_I2C_T p_i2c, P_SOFT_I2C_MSG_T p_msg)
|
||||
// 1. 判忙
|
||||
if (soft_i2c_is_busy(p_i2c)) {
|
||||
p_i2c->i2cSta = SOFT_I2C_BUSY;
|
||||
soft_i2c_stop(p_i2c);
|
||||
return SOFT_I2C_ERR_BUSY;
|
||||
}
|
||||
// 2. 发送开始信号
|
||||
@ -435,6 +433,7 @@ static soft_i2c_err_t soft_i2c_comm(P_SOFT_I2C_T p_i2c, P_SOFT_I2C_MSG_T p_msg)
|
||||
* @brief 软件模拟 I2C 初始化
|
||||
*
|
||||
* @param [in] p_i2c I2C结构体指针
|
||||
* @param [in] waitCnt 超时计数(时钟延展使能时有意义)
|
||||
*
|
||||
* @return uint32_t
|
||||
* @retval 0 成功, 其他值 失败 @ref SOFT_I2C_ERR_CODE
|
||||
@ -444,7 +443,7 @@ static soft_i2c_err_t soft_i2c_comm(P_SOFT_I2C_T p_i2c, P_SOFT_I2C_MSG_T p_msg)
|
||||
*
|
||||
* @endcode
|
||||
*/
|
||||
soft_i2c_err_t soft_i2c_init(P_SOFT_I2C_T p_i2c) {
|
||||
soft_i2c_err_t soft_i2c_init(P_SOFT_I2C_T p_i2c, uint32_t waitCnt) {
|
||||
// 1. 参数检查
|
||||
if (p_i2c == NULL) {
|
||||
return SOFT_I2C_ERR_PARAM;
|
||||
@ -467,6 +466,10 @@ soft_i2c_err_t soft_i2c_init(P_SOFT_I2C_T p_i2c) {
|
||||
soft_i2c_set_od_mode(&p_i2c->sda);
|
||||
soft_i2c_write_gpio(&p_i2c->scl, SOFT_I2C_LEVEL_HIGH);
|
||||
soft_i2c_write_gpio(&p_i2c->sda, SOFT_I2C_LEVEL_HIGH);
|
||||
#if defined(__SOFT_I2C_CLOCK_STRECH_EN__)
|
||||
// 4. 修改超时计数
|
||||
p_i2c->waitCnt = waitCnt;
|
||||
#endif
|
||||
p_i2c->isInit = true;
|
||||
return SOFT_I2C_ERR_OK;
|
||||
}
|
||||
|
@ -63,6 +63,16 @@ typedef uint32_t soft_i2c_err_t; ///< 返回值类型
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief 软件模拟 I2C 默认超时计数
|
||||
* @addtogroup SOFT_I2C_WAITCNT
|
||||
* @{
|
||||
*/
|
||||
#define SOFT_I2C_DEFAULT_WAITCNT (0xFFFFU) ///< 默认超时计数
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief 软件模拟 I2C 寄存器地址长度
|
||||
* @addtogroup SOFT_I2C_REG_ADDR_LEN
|
||||
@ -87,6 +97,26 @@ typedef uint32_t soft_i2c_err_t; ///< 返回值类型
|
||||
#endif
|
||||
|
||||
#if defined(SOFT_I2C_GD32F3_USED)
|
||||
#if defined(__SOFT_I2C_CLOCK_STRECH_EN__)
|
||||
/**
|
||||
* @brief 软件模拟 I2C 定义结构体
|
||||
*
|
||||
* @param [in] name I2C结构体名称
|
||||
* @param [in] scl_port 时钟线端口, A ~ G
|
||||
* @param [in] scl_pin 时钟线引脚, 0 ~ 15
|
||||
* @param [in] sda_port 数据线端口, A ~ G
|
||||
* @param [in] sda_pin 数据线引脚, 0 ~ 15
|
||||
*/
|
||||
#define SOFT_I2C_DEF(name, scl_port, scl_pin, sda_port, sda_pin) \
|
||||
SOFT_I2C_T soft_i2c_##name = { \
|
||||
false, false, SOFT_I2C_DEFAULT_WAITCNT, \
|
||||
{GPIO##scl_port, GPIO_PIN_##scl_pin, SOFT_I2C_GPIO##scl_port##_CLK}, \
|
||||
{GPIO##sda_port, GPIO_PIN_##sda_pin, SOFT_I2C_GPIO##sda_port##_CLK}, \
|
||||
SOFT_I2C_IDLE \
|
||||
}; \
|
||||
void *const name = &soft_i2c_##name \
|
||||
|
||||
#else
|
||||
/**
|
||||
* @brief 软件模拟 I2C 定义结构体
|
||||
*
|
||||
@ -105,7 +135,28 @@ typedef uint32_t soft_i2c_err_t; ///< 返回值类型
|
||||
}; \
|
||||
void *const name = &soft_i2c_##name \
|
||||
|
||||
#endif
|
||||
#elif defined(SOFT_I2C_STM32F1_USED)
|
||||
#if defined(__SOFT_I2C_CLOCK_STRECH_EN__)
|
||||
/**
|
||||
* @brief 软件模拟 I2C 定义结构体
|
||||
*
|
||||
* @param [in] name I2C结构体名称
|
||||
* @param [in] scl_port 时钟线端口, A ~ G
|
||||
* @param [in] scl_pin 时钟线引脚, 0 ~ 15
|
||||
* @param [in] sda_port 数据线端口, A ~ G
|
||||
* @param [in] sda_pin 数据线引脚, 0 ~ 15
|
||||
*/
|
||||
#define SOFT_I2C_DEF(name, scl_port, scl_pin, sda_port, sda_pin) \
|
||||
SOFT_I2C_T soft_i2c_##name = { \
|
||||
false, false, SOFT_I2C_DEFAULT_WAITCNT, \
|
||||
{GPIO##scl_port##_BASE, GPIO_Pin_##scl_pin, SOFT_I2C_GPIO##scl_port##_CLK}, \
|
||||
{GPIO##sda_port##_BASE, GPIO_Pin_##sda_pin, SOFT_I2C_GPIO##sda_port##_CLK}, \
|
||||
SOFT_I2C_IDLE \
|
||||
}; \
|
||||
void *const name = &soft_i2c_##name \
|
||||
|
||||
#else
|
||||
/**
|
||||
* @brief 软件模拟 I2C 定义结构体
|
||||
*
|
||||
@ -124,6 +175,7 @@ typedef uint32_t soft_i2c_err_t; ///< 返回值类型
|
||||
}; \
|
||||
void *const name = &soft_i2c_##name \
|
||||
|
||||
#endif
|
||||
#else
|
||||
#define SOFT_I2C_DEF(name, scl_port, scl_pin, sda_port, sda_pin)
|
||||
#endif
|
||||
@ -172,6 +224,9 @@ typedef struct _SOFT_I2C_GPIO_COMM_T {
|
||||
typedef struct _SOFT_I2C_T {
|
||||
bool isValid; ///< 芯片是否有效
|
||||
bool isInit; ///< 是否初始化
|
||||
#if defined(__SOFT_I2C_CLOCK_STRECH_EN__)
|
||||
uint32_t waitCnt; ///< 超时计数(时钟延展使用)
|
||||
#endif
|
||||
SOFT_I2C_GPIO_COMM_T scl; ///< 时钟线
|
||||
SOFT_I2C_GPIO_COMM_T sda; ///< 数据线
|
||||
SOFT_I2C_STA_E i2cSta; ///< I2C监控状态
|
||||
@ -203,16 +258,30 @@ SOFT_I2C_STATIC_INLINE SOFT_I2C_STA_E soft_i2c_get_sta(P_SOFT_I2C_T p_i2c) {
|
||||
* @brief 软件模拟 I2C 初始化
|
||||
*
|
||||
* @param [in] p_i2c I2C结构体指针
|
||||
* @param [in] waitCnt 超时计数(时钟延展使能时有意义)
|
||||
*
|
||||
* @return uint32_t
|
||||
* @retval 0 成功, 其他值 失败 @ref SOFT_I2C_ERR_CODE
|
||||
* @details 特殊说明:
|
||||
* @par eg:
|
||||
* @code
|
||||
* // 注册I2C驱动
|
||||
* SOFT_I2C_DEF(I2C_DEV, A, 8, A, 9);
|
||||
*
|
||||
* // 如果跨文件注册, 则需要在其头文件中声明驱动, 并在使用驱动的文件中包含其头文件
|
||||
* SOFT_I2C_EXT(I2C_DEV);
|
||||
*
|
||||
* // 开启时钟延展初始化时, 设置延展的超时计数为1000, 该传参会修改默认计数值
|
||||
* soft_i2c_init(I2C_DEV, 1000);
|
||||
*
|
||||
* // 开启时钟延展初始化时, 如果第二个传参为 SOFT_I2C_DEFAULT_WAITCNT, 则不会修改默认计数值
|
||||
* soft_i2c_init(I2C_DEV, SOFT_I2C_DEFAULT_WAITCNT);
|
||||
*
|
||||
* // 未开启时钟延展时, 传参waitCnt不会起作用
|
||||
* soft_i2c_init(I2C_DEV, 1000);
|
||||
* @endcode
|
||||
*/
|
||||
extern soft_i2c_err_t soft_i2c_init(P_SOFT_I2C_T p_i2c);
|
||||
extern soft_i2c_err_t soft_i2c_init(P_SOFT_I2C_T p_i2c, uint32_t waitCnt);
|
||||
|
||||
/**
|
||||
* @brief 软件模拟 I2C 写数据
|
||||
|
@ -44,7 +44,6 @@
|
||||
#define SOFT_I2C_NACK SOFT_I2C_LEVEL_HIGH ///< I2C非应答信号(高电平)
|
||||
#define SOFT_I2C_WRITE (0U) ///< 写操作
|
||||
#define SOFT_I2C_READ (1U) ///< 读操作
|
||||
#define SOFT_I2C_WAIT_CNT (0xFFFU) ///< 等待计数(用于时钟延展)
|
||||
/*
|
||||
* @}
|
||||
*/
|
||||
|
@ -38,7 +38,7 @@ int main(void) {
|
||||
led_on();
|
||||
|
||||
// 初始化结构体对象
|
||||
ret = soft_i2c_init(I2C_DEV);
|
||||
ret = soft_i2c_init(I2C_DEV, SOFT_I2C_DEFAULT_WAITCNT);
|
||||
|
||||
while (1) {
|
||||
/* turn on LED1 */
|
||||
|
@ -71,13 +71,14 @@ int main(void) {
|
||||
led_init();
|
||||
led_on();
|
||||
|
||||
ret = soft_i2c_init(I2C_DEV);
|
||||
ret = soft_i2c_init(I2C_DEV, SOFT_I2C_DEFAULT_WAITCNT);
|
||||
|
||||
while (1) {
|
||||
led_on();
|
||||
block_delay();
|
||||
{
|
||||
memset(r_buf, 0, 8);
|
||||
|
||||
if (flag) {
|
||||
ret = soft_i2c_write(I2C_DEV, SLAVE_ADDR, REG_ADDR, 1, w_buf, 8);
|
||||
// if (ret != SOFT_I2C_ERR_OK) {
|
||||
|
Loading…
Reference in New Issue
Block a user