野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 15533|回复: 9

f429中关于I2C协议层发送地址,等待ADDR置位后ADDR清零的问题

[复制链接]
发表于 2016-7-21 10:22:39 | 显示全部楼层 |阅读模式
在玩转stm32的书中这样说
QQ图片20160721093836.png
在实际例程中
  /* Send EEPROM address for write */
  I2C_Send7bitAddress(EEPROM_I2C, EEPROM_ADDRESS, I2C_Direction_Transmitter);
  I2CTimeout = I2CT_FLAG_TIMEOUT;
  /* Test on EV6 and clear it */(这边有个clear it,这边这个clear it是怎么实现的呢?
  while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(1);
  }

ADDR有两种清零方式,参考手册中这样说:
QQ图片20160721100239.png
在I2C_CheckEvent()函数中
ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
{
  uint32_t lastevent = 0;
  uint32_t flag1 = 0, flag2 = 0;
  ErrorStatus status = ERROR;

  /* Check the parameters */
  assert_param(IS_I2C_ALL_PERIPH(I2Cx));
  assert_param(IS_I2C_EVENT(I2C_EVENT));

  /* Read the I2Cx status register */
  flag1 = I2Cx->SR1;
  flag2 = I2Cx->SR2;                                //这两句话这样算不算软件序列清零呢?这边读取了SR1寄存器后,读取了SR2寄存器,ADDR位清零,
  flag2 = flag2 << 16;                               在外面的判断函中//如果条件不成立,将一直循环,一直清零,然后与EV6比较,直到ADDR=1,跳出循环。那么置1的时间也只有在清零到比较之间
                                                                如果是这样,那么下一次比较事件的时候就能将ADDR位清零,但是倘若在软件序列清零之前置1,就循环就死在这了,从实验来看,是不可能的。
  /* Get the last event value from I2C status register */          如果不是这样,那么什么时候清零呢?还是这边就是纯粹的赋值比较?        不要说我钻牛角尖,逻辑上有点不明白,指点指点!!!
  lastevent = (flag1 | flag2) & FLAG_MASK;

  /* Check whether the last event contains the I2C_EVENT */
  if ((lastevent & I2C_EVENT) == I2C_EVENT)
  {
    /* SUCCESS: last event is equal to I2C_EVENT */
    status = SUCCESS;
  }
  else
  {
    /* ERROR: last event is different from I2C_EVENT */
    status = ERROR;
  }
  /* Return status */
  return status;
}



回复

使用道具 举报

发表于 2016-7-21 10:23:54 | 显示全部楼层
用硬件iic卡死的话就改用软件iic,参考电容触摸章节的视频教程
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-7-21 10:27:26 | 显示全部楼层
flyleaf 发表于 2016-7-21 10:23
用硬件iic卡死的话就改用软件iic,参考电容触摸章节的视频教程

没卡死,我就是对ADDR清零有点疑问,不知道哪里清零了
回复 支持 反对

使用道具 举报

发表于 2016-7-21 10:38:12 | 显示全部楼层
望蓝天 发表于 2016-7-21 10:27
没卡死,我就是对ADDR清零有点疑问,不知道哪里清零了

  flag1 = I2Cx->SR1;
  flag2 = I2Cx->SR2;

这两句清零,顺便把标志读取到变量flag1和flag2,这个时候寄存器的数据先被暂存到变量,再清零

后面再判断flag1和flag2可以检测addr位是否为1
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-7-21 10:46:06 | 显示全部楼层
flyleaf 发表于 2016-7-21 10:38
flag1 = I2Cx->SR1;
  flag2 = I2Cx->SR2;

哦~~~,先保存变量再清零,这个顺序就能理解了,,谢谢大神解答疑惑
回复 支持 反对

使用道具 举报

发表于 2016-7-21 10:48:15 | 显示全部楼层
楼主研究得真仔细
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-7-21 11:24:01 | 显示全部楼层
鲁合乐 发表于 2016-7-21 10:48
楼主研究得真仔细

我一开始都没有清零的概念,然后看到书上写了,然后问题就来了。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-7-21 12:32:52 | 显示全部楼层
flyleaf 发表于 2016-7-21 10:38
flag1 = I2Cx->SR1;
  flag2 = I2Cx->SR2;

大神!!!!我还有个问题想不明白。。。。发帖感觉有点重复了,,就在这问下你。还请见谅。。

在I2C发送起始信号之后,等待SB位置1,然后SB位怎么清除呢,想不明白。。。

手册中这样说的:—由软件在读取 SR1 寄存器后写入 DR 寄存器来清零,或在 PE=0 时由硬件清零。

I2C_CheckEvent()里面没有写入DR这一步啊!感觉不能清零啊。
回复 支持 反对

使用道具 举报

发表于 2016-7-21 13:56:38 | 显示全部楼层
望蓝天 发表于 2016-7-21 12:32
大神!!!!我还有个问题想不明白。。。。发帖感觉有点重复了,,就在这问下你。还请见谅。。

在I2C ...

后面写入数据send的时候就有了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-7-21 14:23:06 | 显示全部楼层
flyleaf 发表于 2016-7-21 13:56
后面写入数据send的时候就有了

也是哦,,多谢
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-23 07:42 , Processed in 0.048799 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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