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我没调试, 我调试KF8AI2C 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

为啥这么多单片机都存在这样的问题
页: [1]
查看完整版本: 醉了,又卡I2C上了,有空帮忙看看,谢谢了...