21ic电子技术开发论坛

标题: 醉了,又卡I2C上了,有空帮忙看看,谢谢了... [打印本页]

作者: fydabcd    时间: 2022-6-22 18:35
标题: 醉了,又卡I2C上了,有空帮忙看看,谢谢了...
本帖最后由 fydabcd 于 2022-6-22 18:38 编辑

        主机模式,从机为24C04,24C04的随机读写,需要发完器件地址和子地址后,重新发送起始位和器件地址才能读。
      调试调用函数I2c_Buffer_Read(I2C0_SFR, 0xA0, i2c_read_buffer, 10);
      另外比较疑惑的是官方的里程中,读和写的函数都没有子地址的参数,这个不应该是I2C的标配吗?
/*发送起始位*/void I2c_Buffer_Read(I2C_SFRmap* I2Cx, uint16_t Read_I2C_Addr, uint8_t *p_buffer, uint16_t number_of_byte)
{

        I2Cx->SR = 0;
        I2C_Cmd(I2Cx, TRUE);
        I2C_Clear_INTERRUPT_Flag(I2Cx);
        I2C_Generate_START(I2Cx, TRUE);
        while (!I2C_Get_INTERRUPT_Flag(I2Cx));
        /*发送器件地址*/
        I2C_SendData8(I2Cx, Read_I2C_Addr | 0x01);
        I2C_Clear_INTERRUPT_Flag(I2Cx);
        while (!I2C_Get_INTERRUPT_Flag(I2Cx));
        I2c_Wait_Ack_Flag(I2Cx);
        if(AckTimeoutFlag == 1)
        {
                return (void)0;
        }
        /*发送子地址*/
    I2C_SendData8(I2Cx, 0x0);/*此处调试中,子地址固定为0*/
    I2C_Clear_INTERRUPT_Flag(I2Cx);
    while (!I2C_Get_INTERRUPT_Flag(I2Cx));
    I2C_Clear_INTERRUPT_Flag(I2Cx);
        I2c_Wait_Ack_Flag(I2Cx);
        if(AckTimeoutFlag == 1)
        {
                return (void)0;
        }
        /*重发起始位*/
        I2C_Clear_Start_Flag(I2Cx);
        I2C_Clear_INTERRUPT_Flag(I2Cx);
        I2C_Generate_START(I2Cx, TRUE);
        while (!I2C_Get_INTERRUPT_Flag(I2Cx));
        /*重发器件地址*/
        I2C_SendData8(I2Cx, Read_I2C_Addr | 0x01);
        I2C_Clear_INTERRUPT_Flag(I2Cx);
        while (!I2C_Get_INTERRUPT_Flag(I2Cx));
        I2c_Wait_Ack_Flag(I2Cx);
        if(AckTimeoutFlag == 1)
        {
                return (void)0;
        }
        /*读取数据*/
         while (number_of_byte)
         {
                 while (!I2C_Get_INTERRUPT_Flag(I2Cx));
                 if (I2C_Get_Receive_Buff_Flag(I2Cx))
                 {
                         I2C_Ack_DATA_Config(I2Cx, I2C_ACKDATA_ACK);
                         *p_buffer = I2C_ReceiveData(I2Cx);
                         I2C_Clear_INTERRUPT_Flag(I2Cx);
                         p_buffer++;
                 }
                 number_of_byte--;
         }
        
         /* Stop bit */
         I2C_Generate_STOP(I2Cx, TRUE);
        
         /* Clear the ISIF bit of the I2C interrupt flag */
         I2C_Clear_INTERRUPT_Flag(I2Cx);
         /* Wait for the stop to complete */
         while (!I2C_Get_INTERRUPT_Flag(I2Cx));
        //           ;
        
         /* Clear the ISIF bit of the I2C interrupt flag */
         I2C_Clear_INTERRUPT_Flag(I2Cx);
         /* Clear the I2C stop flag PIF bit */
         I2C_Clear_Stop_Flag(I2Cx);
         /* Turn off the I2C module */
         I2C_Cmd(I2Cx, FALSE);
}



作者: 树上的小鸟    时间: 2022-6-23 07:57
这个没有针对特定外围器件去做例程,主要是体现操作方法和流程,可以根据实际的应用去修改嘛
作者: 树上的小鸟    时间: 2022-6-23 08:00
例程代码仅仅提供的这个外设模块的操作方法示例,没有针对特定的应用场景或者外围器件做应用,可以直接在代码上重构适合自己应用的代码。
作者: lvben5d    时间: 2022-6-23 09:15
本帖最后由 lvben5d 于 2022-6-23 09:19 编辑

官网 KF32A得 I2C我没调试, 我调试KF8A  I2C OK。  你注意下I2C的基本规范,我有GD32的I2C,也是按照GD32官网,自己需要按照I2C 读写外部器件规范,整合了下。 要认真去看I2C 读写外部器件的特性,有一个需要注意的点: I2C 从机地址  可能需要 <<1 。 我的GD32E103 是需要<<1位才对。 从机地址 比如是 0xA0 ,我实际填写的从机地址是   (0xA0<<1)  ,卡了我1星期,我才发现是从机地址不对。     不管是哪家MCU,  I2C驱动时序中按照各家MCU的寄存器对照手册进行,前期如果会用示波器(让硬件协助),可以拉到SDA引脚,把I2C时钟控制在400KHZ + (慢一点便于抓波)
作者: ayb_ice    时间: 2022-6-23 13:08
GPIO模拟比这不知道好多少,我从不用硬件的IIC,SPI
作者: nongshengjiang    时间: 2022-6-23 13:42
你们都什么专业的呵呵
作者: tpgf    时间: 2022-7-6 14:16
我发现很多型号的单片机都有iic的问题存在啊
作者: kxsi    时间: 2022-7-6 14:23
终端电阻都加上了吗
作者: daichaodai    时间: 2022-7-7 08:34
又是硬件IIC?
作者: 七毛钱    时间: 2022-7-11 15:00
为啥这么多单片机都存在这样的问题




欢迎光临 21ic电子技术开发论坛 (https://bbs.21ic.com/) Powered by Discuz! X3.5