欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > 基于realtek 解决iic 时钟拉伸问题

基于realtek 解决iic 时钟拉伸问题

2025/2/12 7:50:03 来源:https://blog.csdn.net/qq_28851611/article/details/145570774  浏览:    关键词:基于realtek 解决iic 时钟拉伸问题

**

解决 realtek 库函数方式实现出现的 iic clock strech 时钟拉伸问题

**
很多小伙伴应该都用过 iic 但是接触过时钟拉伸这个细节的估计不多
简单的说就是通信过程中主机每次控制时钟线的电平需要判断从机是否准备好
在拉高时钟脚时需先切换成输入状态判断从机是否拉低时钟脚
如果从机拉住时钟脚 说明从机没有准备就绪 主机不能强行拉高 需等待从机释放

用realtek当主控和某器件通信 发现偶现一些不正常的现象 抓取逻辑分析仪看数据有时钟脉冲不均匀的情况
在这里插入图片描述

于是用示波器抓取发现有时钟线半高的电平
在这里插入图片描述
realtek的初始化函数并没有一个给用户设置时钟拉伸最大等待从机就绪超时的地方
但是 iic 写函数和读函数都包含了一个变量I2C_TimeOut 从代码看就是起这个作用的

/*** \brief  Send data in master mode through the I2Cx peripheral.* \param  I2Cx: Select the I2C peripheral. \ref I2C_Declaration* \param  pBuf: Byte to be transmitted.* \param  len: Data length to send.* \return I2C_Status: The status of I2Cx. \ref I2C_Status*/
I2C_Status I2C_MasterWrite(I2C_TypeDef *I2Cx, uint8_t *pBuf, uint16_t len)
{uint16_t cnt = 0;uint32_t time_out = I2C_TimeOut;I2C_Status abort_status = I2C_Success;/* Check the parameters */assert_param(IS_I2C_ALL_PERIPH(I2Cx));/* Write in the DR register the data to be sent */for (cnt = 0; cnt < len; cnt++){if (cnt >= len - 1){/*generate stop signal*/I2Cx->IC_DATA_CMD = (*pBuf++) | I2C_0X10_STOP;}else{I2Cx->IC_DATA_CMD = *pBuf++;}/* wait for flag of I2C_FLAG_TFNF */time_out = I2C_TimeOut;while (((I2Cx->IC_STATUS & I2C_FLAG_TFNF) == 0) && (time_out != 0)){/* Check abort status */abort_status = I2C_CheckAbortStatus(I2Cx);if (abort_status != I2C_Success){return abort_status;}time_out--;if (time_out == 0){return I2C_ERR_TIMEOUT;}}/* Check abort status */abort_status = I2C_CheckAbortStatus(I2Cx);if (abort_status != I2C_Success){return abort_status;}}while (((I2C_GetFlagState(I2Cx, I2C_FLAG_ACTIVITY) == SET) ||   \(I2C_GetFlagState(I2Cx, I2C_FLAG_TFE) != SET)) && (time_out != 0)){abort_status = I2C_CheckAbortStatus(I2Cx);if (abort_status != I2C_Success){return abort_status;}time_out--;if (time_out == 0){return I2C_ERR_TIMEOUT;}}return abort_status;
}
I2C_Status I2C_RepeatRead(I2C_TypeDef *I2Cx, uint8_t *pWriteBuf, uint16_t Writelen,uint8_t *pReadBuf, uint16_t Readlen)
{uint16_t cnt = 0;uint32_t reg_value = 0;uint32_t time_out = I2C_TimeOut;I2C_Status abort_status = I2C_Success;/* Check the parameters */assert_param(IS_I2C_ALL_PERIPH(I2Cx));/*------------------------------ write data section ------------------------------*//* write data in the IC_DATA_CMD register */for (cnt = 0; cnt < Writelen; cnt++){I2Cx->IC_DATA_CMD = *pWriteBuf++;/*wait for I2C_FLAG_TFNF flag that Tx FIFO is not full*/time_out = I2C_TimeOut;while (((I2Cx->IC_STATUS & I2C_FLAG_TFNF) == 0) && (time_out != 0)){/* Check abort status */abort_status = I2C_CheckAbortStatus(I2Cx);if (abort_status != I2C_Success){return abort_status;}time_out--;if (time_out == 0){return I2C_ERR_TIMEOUT;}}/* Check abort status */abort_status = I2C_CheckAbortStatus(I2Cx);if (abort_status != I2C_Success){return abort_status;}}/*------------------------------ read data section ------------------------------*/for (cnt = 0; cnt < Readlen; cnt++){if (cnt >= Readlen - 1){/*generate stop singal in last byte which to be sent*/I2Cx->IC_DATA_CMD = reg_value | I2C_0X10_CMD | I2C_0X10_STOP;}else{I2Cx->IC_DATA_CMD = reg_value | I2C_0X10_CMD;}/*wait for I2C_FLAG_RFNE flag*/time_out = I2C_TimeOut;while (((I2Cx->IC_STATUS & I2C_FLAG_RFNE) == 0) && (time_out != 0)){/* Check abort status */abort_status = I2C_CheckAbortStatus(I2Cx);if (abort_status != I2C_Success){return abort_status;}time_out--;if (time_out == 0){return I2C_ERR_TIMEOUT;}}*pReadBuf++ = (uint8_t)I2Cx->IC_DATA_CMD;}return abort_status;
}

realtek官方原生的 iic 库默认写的0xFFFFF 我们加一个 f 改成6个f 验证正常

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com