[技术问答] HC32F005 I2C问题

[复制链接]
2419|7
 楼主| tottionly 发表于 2022-11-17 11:07 | 显示全部楼层 |阅读模式
HC32F005, 参考hc32f005_ddl_Rev1.9.0 Lite的i2c_bl24c08_poll, 请教个问题:
如果往BL24C08写一个字节,时序是这样的: 934086375a1935f69e.png

我理解的状态跳转是从0x08 => 0x18=>0x28=>产生stop位,对吗?
如果理解正确,那么产生stop位是在哪里实现的?代码中I2C_SetFunc(I2CX,I2cStop_En)执行条件:
1. 进入0x30状态。但进入0x30的条件是收到从机NACK,这里不满足。
2. 满足u8i>u32Len。但只写了1个字节,u8i=1, u32Len=1,不满足。
  1. en_result_t I2C_MasterWriteData(M0P_I2C_TypeDef* I2CX,uint8_t u8Addr,uint8_t *pu8Data,uint32_t u32Len)
  2. {
  3.     en_result_t enRet = Error;
  4.     uint8_t u8i=0,u8State;
  5.     I2C_SetFunc(I2CX,I2cStart_En);
  6.     while(1)
  7.     {
  8.         while(0 == I2C_GetIrq(I2CX))
  9.         {;}
  10.         u8State = I2C_GetState(I2CX);
  11.         switch(u8State)
  12.         {
  13.             case 0x08:                               ///< 已发送起始条件
  14.                 I2C_ClearFunc(I2CX,I2cStart_En);
  15.                 I2C_WriteByte(I2CX,I2C_SLAVEADDR);   ///< 从设备地址发送
  16.                 break;
  17.             case 0x18:                               ///< 已发送SLA+W,并接收到ACK
  18.                 I2C_WriteByte(I2CX,u8Addr);          ///< 从设备内存地址发送
  19.                 break;
  20.             case 0x28:                               ///< 上一次发送数据后接收到ACK
  21.                 I2C_WriteByte(I2CX,pu8Data[u8i++]);  ///< 继续发送数据
  22.                 break;
  23.             case 0x20:                               ///< 上一次发送SLA+W后,收到NACK
  24.             case 0x38:                               ///< 上一次在SLA+读或写时丢失仲裁
  25.                 I2C_SetFunc(I2CX,I2cStart_En);       ///< 当I2C总线空闲时发送起始条件
  26.                 break;
  27.             case 0x30:                               ///< 已发送I2Cx_DATA中的数据,收到NACK,将传输一个STOP条件
  28.                 I2C_SetFunc(I2CX,I2cStop_En);        ///< 发送停止条件
  29.                 break;
  30.             default:
  31.                 break;
  32.         }
  33.         if(u8i>u32Len)
  34.         {
  35.             I2C_SetFunc(I2CX,I2cStop_En);            ///< 此顺序不能调换,出停止条件
  36.             I2C_ClearIrq(I2CX);
  37.             break;
  38.         }
  39.         I2C_ClearIrq(I2CX);                          ///< 清除中断状态标志位
  40.     }
  41.     enRet = Ok;
  42.     return enRet;
  43. }


9363563759bca9a4f5.png
1920463759bf74103c.png
毛大人跟班 发表于 2022-11-17 13:48 | 显示全部楼层
加我聊下  877378012
 楼主| tottionly 发表于 2022-11-17 16:09 | 显示全部楼层
测试后发现,即使只发一个data, 0x28这个状态也会进入两次。但0x28中的 I2C_WriteByte(I2CX,pu8Data[u8i++])并非真正将数据输出到SDA上,只有I2C_ClearIrq(I2CX)动作后,总线上才有数据输出。因此是满足u8i>u32Len后,发送了I2cStop_En。
yizushijie 发表于 2022-11-21 09:59 | 显示全部楼层
他这里是有点问题的。
fengyun2023 发表于 2023-4-26 11:33 | 显示全部楼层
请问我从设备内存地址是16位要怎么做呢?
lisn3188 发表于 2023-4-28 09:20 | 显示全部楼层
用IO模拟吧
Henryko 发表于 2023-5-12 23:41 | 显示全部楼层
可以用软件模拟的iic
Jane0 发表于 2023-9-22 16:54 | 显示全部楼层
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

35

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部