野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 2032|回复: 9

STM32 i2c写eeprom再读等待eeprom写完成代码部分

[复制链接]
发表于 2024-8-31 19:04:10 | 显示全部楼层 |阅读模式
本帖最后由 我不理解 于 2024-9-2 22:16 编辑

如下是野火给出的i2c驱动c程序的等待检测代码
void I2C_EE_WaitEepromStandbyState(void)      
{
  vu16 SR1_Tmp = 0;

  do
  {
    /* Send START condition */
    I2C_GenerateSTART(EEPROM_I2Cx, ENABLE);
    /* Read I2C1 SR1 register */
    SR1_Tmp = I2C_ReadRegister(EEPROM_I2Cx, I2C_Register_SR1);
    /* Send EEPROM address for write */
    I2C_Send7bitAddress(EEPROM_I2Cx, EEPROM_ADDRESS, I2C_Direction_Transmitter);
  }while(!(I2C_ReadRegister(EEPROM_I2Cx, I2C_Register_SR1) & 0x0002));        
<- 此处,在上一句给了发送7地址指令后,i2c此时是必定还没有发完这些地址的。那么直接判断i2c 的ADDR有没有发送完成是否是个合理的行为,虽然我不知道为什么程序可以跑,我猜测硬件层面状态机可能混乱阴差阳错导致程序运行成功了?可能在某次eeprom可以接到start信号后即使stm32发了好几次start eeprom也是                                                                                           一直接按内部状态机运行,然后给了个ack信号?然后被stm32捕捉到了?
非常费解好吧!!!!


  /* Clear AF flag */
  I2C_ClearFlag(EEPROM_I2Cx, I2C_FLAG_AF);
    /* STOP condition */   
    I2C_GenerateSTOP(EEPROM_I2Cx, ENABLE);   
}

回复

使用道具 举报

发表于 2024-9-2 08:58:58 | 显示全部楼层
你怎么判断他一定没发送完地址的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-2 22:15:00 | 显示全部楼层
菠萝片 发表于 2024-9-2 08:58
你怎么判断他一定没发送完地址的

i2c的速度400K,cpu主频72M,刚给出的发送地址指令然后直接判断有没有发完,这难道发完了吗
回复 支持 反对

使用道具 举报

发表于 2024-9-3 09:42:07 | 显示全部楼层
为什么不能发完,他本身流程先运行完指令再运行下一句判断,没问题啊
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-12 00:12:47 | 显示全部楼层
菠萝片 发表于 2024-9-3 09:42
为什么不能发完,他本身流程先运行完指令再运行下一句判断,没问题啊

不是 i2c的速度是400k,你运行完一条指令后下条指令就是判断有没有发完,你指令是在72M时钟域运行的 a
回复 支持 反对

使用道具 举报

发表于 2024-9-13 09:31:37 | 显示全部楼层
是软件模拟的IIC的话一般会加延时来降低频率,也就是到达你所谓的400K.可以看看软件模拟IIC的相关网页和代码,你会更好理解.
硬件IIC的话逻辑是将发送数据放入寄存器后,在程序中只需要等到对应寄存器中标志位,标志位变化表示硬件发送完成或是ACK收到,这个时候去读取就可以了.
不论硬件还是软件IIC,都建议你看一下函数内部是怎么实现的.
野火论坛202409130920352976..png
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-17 14:50:30 | 显示全部楼层
Nalimca 发表于 2024-9-13 09:31
是软件模拟的IIC的话一般会加延时来降低频率,也就是到达你所谓的400K.可以看看软件模拟IIC的相关网页和代码 ...

你说的和我问的有联系吗?我不知道要检测ack信号吗??
我在说 为什么给完i2c发送指令后直接检测这个ack信号,你这里肯定是检测不到的,检测不到不是重新跑一遍循环再重新发送?再立即检测?
能不能看下问题理解下啊
回复 支持 反对

使用道具 举报

发表于 2024-9-25 10:32:04 | 显示全部楼层
我不理解 发表于 2024-9-12 00:12
不是 i2c的速度是400k,你运行完一条指令后下条指令就是判断有没有发完,你指令是在72M时钟域运行的 a ...

你这个你跳转去看看程序,你I2C_Send7bitAddress是一个函数,程序运行到这就会进入里面执行代码,又不是就只有一句话。程序最底层的都是操作寄存器,前面那人说的没问题
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-25 18:51:09 | 显示全部楼层
菠萝片 发表于 2024-9-25 10:32
你这个你跳转去看看程序,你I2C_Send7bitAddress是一个函数,程序运行到这就会进入里面执行代码,又不是 ...

对啊,是操作寄存器啊,一句话就够了啊,1/72Mhz的时间就发完了啊
void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction)
{
  /* Check the parameters */
  assert_param(IS_I2C_ALL_PERIPH(I2Cx));
  assert_param(IS_I2C_DIRECTION(I2C_Direction));
  /* Test on the direction to set/reset the read/write bit */
  if (I2C_Direction != I2C_Direction_Transmitter)
  {
    /* Set the address bit0 for read */
    Address |= OAR1_ADD0_Set;
  }
  else
  {
    /* Reset the address bit0 for write */
    Address &= OAR1_ADD0_Reset;
  }
  /* Send the address */
  I2Cx->DR = Address;     <<<<<<<-
}
回复 支持 反对

使用道具 举报

发表于 2024-9-29 10:54:03 | 显示全部楼层
do while 第一次执行 生成起始信号,清除SR1寄存器数据,发送地址,进入while判断,判断读取SR1寄存器bit1,bit1为0循环继续,bit1为1循环结束.
假设发送未结束,因为地址发送需要时间,此时SR1->bit1为0,进入循环,因为总线占用,生成起始信号不起作用(在本字节传递完成后起作用),清除SR1寄存器数据,发送地址(此步同样不起作用),接着进入while判断直到发送结束.
假设发送结束,NACK,此时SR1->bit1为0,进入循环,重新发送起始信号等开始新一次通讯.继续循环.
假设发送结束,ACK,此时SR1->bit1为1,退出循环.软件清除AF标志位,发送结束信号完成I2C通讯.
告诉你了看标志位,看标志位,看标志位!!!!
这么简单的逻辑理解不了????我上个回答有什么问题,非得按行给你讲代码你才能看懂吗?一点脑子不带的?给你免费回答个问题,给你还装起来了.
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-10-15 08:47 , Processed in 0.121014 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表