打印

香版,STM32 I2C疑惑

[复制链接]
2784|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
myfaith|  楼主 | 2010-5-21 10:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
问题一:STM32的I2C里那个BUSY位,置1的条件是SDA或SCL为低,是包括自己发起传输时将SDA和SCL拉低吗,是否意思是,不管这两条线是谁拉低的,只要有一根线出现低电平就置位BUSY?清除的条件是检测到STOP,那这个STOP是包括自己发出的STOP的还是总线上其它器件产生的?
Bit 1 BUSY: Bus busy
0: No communication on the bus
1: Communication ongoing on the bus
–Set by hardware on detection of SDA or SCL low
–cleared by hardware on detection of a Stop condition.
It indicates a communication in progress on the bus. This information is still updated when
the interface is disabled (PE=0).

问题二:STM32108PKT I2C-E2PROM例程里,I2C_Comm_MasterSend函数里发送完数据后最后有一段   "/* launch check write status procedure */"的代码,又等待1s,等待总线空闲,发start,address,stop什么的,有什么用?我去掉这一段的话,在发送函数之后需要加一段延时才能跟接收函数,否则返回ADDR_MATCH_ERR错误,这又是为什么,因为本身接收函数里就有一等待/判断总线空闲代码



I2C_Result  I2C_Comm_MasterSend(I2C_TypeDef* I2Cx, uint16_t slaveaddr, uint8_t offset, uint8_t* pBuffer, uint32_t length)
{
__IO uint32_t check_time = 0;
    /*wait 5us min for bus free time limitation for later transaction*/
    *(uint32_t *)0xe000e014 = one_us_unit*5;     //SysTick_SetReload(one_us_unit*5);
    *(uint32_t *)0xe000e018 = 0;                 //SysTick_CounterCmd(SysTick_Counter_Clear);
    *(uint32_t *)0xe000e010 |= 1;                //SysTick_CounterCmd(SysTick_Counter_Enable);
    while(!I2C_OT);
    *(uint32_t *)0xe000e010 &= 0xfffffffe;       //SysTick_CounterCmd(SysTick_Counter_Disable);
    I2C_OT = FALSE;   
   
   
    /*wait bus free*/
    *(uint32_t *)0xe000e014 = BUS_BUSY_TIMEOUT;  //SysTick_SetReload(BUS_BUSY_TIMEOUT);
    *(uint32_t *)0xe000e018 = 0;                 //SysTick_CounterCmd(SysTick_Counter_Clear);
    *(uint32_t *)0xe000e010 |= 1;                //SysTick_CounterCmd(SysTick_Counter_Enable);
    while((I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY))&&(!I2C_OT));
    *(uint32_t *)0xe000e010 &= 0xfffffffe;       //SysTick_CounterCmd(SysTick_Counter_Disable);
    if (I2C_OT)
    {
      I2C_OT = FALSE;
      return BUS_BUSY;
    }
   
   
    /*send start and wait*/
    I2C_GenerateSTART(I2Cx, ENABLE);
    *(uint32_t *)0xe000e014 = SEND_START_TIMEOUT;  //SysTick_SetReload(SEND_START_TIMEOUT);
    *(uint32_t *)0xe000e018 = 0;                   //SysTick_CounterCmd(SysTick_Counter_Clear);
    *(uint32_t *)0xe000e010 |= 1;                  //SysTick_CounterCmd(SysTick_Counter_Enable);
    while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT) || I2C_OT));
    *(uint32_t *)0xe000e010 &= 0xfffffffe;         //SysTick_CounterCmd(SysTick_Counter_Disable);
    if (I2C_OT)
    {
      I2C_OT = FALSE;
      return SEND_START_ERR;
    }  
   
   
    /* send 7-bit slave address and wait */
    I2C_Send7bitAddress(I2Cx, (u8)(slaveaddr & 0xFF), I2C_Direction_Transmitter);
    *(uint32_t *)0xe000e014 = SEND_ADDR7_TIMEOUT;  //SysTick_SetReload(SEND_ADDR7_TIMEOUT);
    *(uint32_t *)0xe000e018 = 0;                   //SysTick_CounterCmd(SysTick_Counter_Clear);
    *(uint32_t *)0xe000e010 |= 1;                  //SysTick_CounterCmd(SysTick_Counter_Enable);
    while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) || I2C_OT));  
    *(uint32_t *)0xe000e010 &= 0xfffffffe;         //SysTick_CounterCmd(SysTick_Counter_Disable);
    if (I2C_OT)
    {
      I2C_OT = FALSE;
      I2C_GenerateSTOP(I2Cx, ENABLE);
      while ((I2Cx->CR1 & 0x200) == 0x200);   //wait while stop bit not cleared
      if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF))
        I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
      return ADDR_MATCH_ERR;
    }   
        
    /* send offset if needed */
    if (offset != 0xff)
    {
      I2C_SendData(I2Cx, offset);
      *(uint32_t *)0xe000e014 = SEND_DATA_TIMEOUT; //SysTick_SetReload(SEND_DATA_TIMEOUT);
      *(uint32_t *)0xe000e018 = 0;                 //SysTick_CounterCmd(SysTick_Counter_Clear);
      *(uint32_t *)0xe000e010 |= 1;                //SysTick_CounterCmd(SysTick_Counter_Enable);
      while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED) || I2C_OT));
      *(uint32_t *)0xe000e010 &= 0xfffffffe;       //SysTick_CounterCmd(SysTick_Counter_Disable);
      if (I2C_OT)
      {
        I2C_OT = FALSE;
        I2C_GenerateSTOP(I2Cx, ENABLE);
        while ((I2Cx->CR1 & 0x200) == 0x200);   //wait while stop bit not cleared
        if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF))
          I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
        return DATA_TIMEOUT;
      }
    }
  
    I2C_SendData(I2Cx, *pBuffer++);
    length--;
    while (length--)
    {
        *(uint32_t *)0xe000e014 = SEND_DATA_TIMEOUT;
        *(u32 *)0xe000e018 = 0;                 
        *(uint32_t *)0xe000e010 |= 1;               
        while (((I2C_GetLastEvent(I2Cx) & 0x04) != 0x04)&&(!I2C_OT));  
        *(uint32_t *)0xe000e010 &= 0xfffffffe;  
        if (I2C_OT)
        {
          I2C_OT = FALSE;
          I2C_GenerateSTOP(I2Cx, ENABLE);
          while ((I2Cx->CR1 & 0x200) == 0x200);
          if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF))
            I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
          return DATA_TIMEOUT;
        }
        I2C_SendData(I2Cx, *pBuffer++);
    }
    *(uint32_t *)0xe000e014 = SEND_DATA_TIMEOUT;
    *(uint32_t *)0xe000e018 = 0;                 
    *(uint32_t *)0xe000e010 |= 1;
    while (!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED) || I2C_OT));
    *(uint32_t *)0xe000e010 &= 0xfffffffe;
    if (I2C_OT)
    {
      I2C_OT = FALSE;
      I2C_GenerateSTOP(I2Cx, ENABLE);
      while ((I2Cx->CR1 & 0x200) == 0x200);
      if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF))
        I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
      return DATA_TIMEOUT;
    }

    /* send stop to close communication */
    I2C_GenerateSTOP(I2Cx, ENABLE);
  
   
    /* launch check write status procedure */能力 //以下代码毛用?
    while(check_time != 1000000/5)
    {
      /*wait 5us min for bus free time limitation for later transaction : check phase*/
      *(uint32_t *)0xe000e014 = one_us_unit*5;     //SysTick_SetReload(one_us_unit*5);
      *(uint32_t *)0xe000e018 = 0;                 //SysTick_CounterCmd(SysTick_Counter_Clear);
      *(uint32_t *)0xe000e010 |= 1;                //SysTick_CounterCmd(SysTick_Counter_Enable);
      while(!I2C_OT);
      *(uint32_t *)0xe000e010 &= 0xfffffffe;       //SysTick_CounterCmd(SysTick_Counter_Disable);
      I2C_OT = FALSE;  
   
      /* wait bus for free */
      *(uint32_t *)0xe000e014 = CHECK_TIMEOUT;
      *(uint32_t *)0xe000e018 = 0;
      *(uint32_t *)0xe000e010 |= 1;
      while((I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY))&&(!I2C_OT));
      *(uint32_t *)0xe000e010 &= 0xfffffffe;
      I2C_OT = FALSE;
      if (I2C_OT)         //上面这句都已经赋为FALSE了,还判断它的真假????
      {
        I2C_OT = FALSE;
        /* during 1s, bus is occupied by other i2c comm */  
        /* after check_timeout(1s), target's internal must complete */
        return NO_ERR;     //如果I2C_OT为真都已经超时了,还返回NO_ERR??
      }      
      
      I2C_GenerateSTART(I2Cx, ENABLE);
      while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
      I2C_Send7bitAddress(I2Cx, slaveaddr, I2C_Direction_Transmitter);
      
       /* wait for 10 I2C clock pulse period and then check ADDR set or not*/
      *(uint32_t *)0xe000e014 = one_us_unit*i2c_10clk_us;
      *(uint32_t *)0xe000e018 = 0;
      *(uint32_t *)0xe000e010 |= 1;
      while(!I2C_OT);
      *(uint32_t *)0xe000e010 &= 0xfffffffe;
      I2C_OT = FALSE;
      if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR))
      {
        break;
      }
      I2C_ClearFlag(I2Cx, I2C_FLAG_AF);   
      I2C_GenerateSTOP(I2Cx, ENABLE);
      while ((I2Cx->CR1 & 0x200) == 0x200);    //STOP bit
   
      check_time++;
    }
    if (check_time ==1000000/5)
      return WRITE_FAILURE;
    I2C_ClearFlag(I2Cx, I2C_FLAG_AF);   
    I2C_GenerateSTOP(I2Cx, ENABLE);
    while ((I2Cx->CR1 & 0x200) == 0x200);   

    return NO_ERR;
}
沙发
香水城| | 2010-5-21 10:56 | 只看该作者
1)按总线信号为准。
2)这个问题与EEPROM的时序有关,你要看看EEPROM的手册。

使用特权

评论回复
板凳
myfaith|  楼主 | 2010-5-21 12:42 | 只看该作者
本帖最后由 myfaith 于 2010-5-21 12:48 编辑

2# 香水城
1.总线信号包不包括自己在总线上产生的信号?
2.明白,这应该是在写操作之后一直试探EEPROM是否能够对地址应答,以确定它内部编程完成.

使用特权

评论回复
地板
香水城| | 2010-5-21 13:35 | 只看该作者
1)总线信号当然包括自己在总线上产生的信号。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

68

主题

468

帖子

0

粉丝