你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F103CB----I2C读取错误

[复制链接]
bei_ji 提问时间:2014-2-8 10:37 /
刚入手STM32的开发板,最近调试I2C时碰到难点,在读取0-8个字节时正常,在读取大于8个字节的数据时,实际读出的数据是第九个和之后的字节会将前面的数据覆盖,然后补齐0xff,比如"STM32F103CB",直接读取11个字节的结果是字符“03CB2F10”+“0xff,0xff,0xff,0xff”,这是怎么回事?
读取函数是使用的固件库函数
I2C_Result  I2C_Comm_MasterReceive(I2C_TypeDef* I2Cx, uint16_t slaveaddr, uint8_t offset, uint8_t* pBuffer, uint32_t length)
{   
  /* wait 5us max for bus free time limitation for later transaction */
  *(uint32_t *)0xe000e014 = one_us_unit*5;
  *(uint32_t *)0xe000e018 = 0;
  *(uint32_t *)0xe000e010 |= 1;
  while(!I2C_OT);
  *(uint32_t *)0xe000e010 &= 0xfffffffe; 
  I2C_OT = FALSE;  
 
  /* wait bus free */
  *(uint32_t *)0xe000e014 = BUS_BUSY_TIMEOUT;
  *(uint32_t *)0xe000e018 = 0;
  *(uint32_t *)0xe000e010 |= 1;
  while((I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY))&&(!I2C_OT));
  *(uint32_t *)0xe000e010 &= 0xfffffffe; 
  if (I2C_OT)
  {
    I2C_OT = FALSE;
    return BUS_BUSY;
  }
  
  /* send start and wait */
  I2C_GenerateSTART(I2Cx, ENABLE);
  *(uint32_t *)0xe000e014 = SEND_START_TIMEOUT;
  *(uint32_t *)0xe000e018 = 0;
  *(uint32_t *)0xe000e010 |= 1;
  while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT) || I2C_OT)); 
  *(uint32_t *)0xe000e010 &= 0xfffffffe; 
  if (I2C_OT)
  {
    I2C_OT = FALSE;
    return SEND_START_ERR;
  }
        
  /*
  if offset needed:
  (1) slave address with write direction
  (2) offset
  (3) re-start
  */
  if (offset!=0xff)
  {
    /* (1) */
    I2C_Send7bitAddress(I2Cx, (uint8_t)(slaveaddr & 0xFF), I2C_Direction_Transmitter);
    *(uint32_t *)0xe000e014 = SEND_ADDR7_TIMEOUT;
    *(uint32_t *)0xe000e018 = 0;
    *(uint32_t *)0xe000e010 |= 1;
    while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) || I2C_OT));  
    *(u32 *)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 ADDR_MATCH_ERR;
    }
      
    
    /* (2) */
    I2C_SendData(I2Cx, offset); 
    *(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;
    }
      
    
    /* (3) */
    I2C_GenerateSTART(I2Cx, ENABLE);
    *(uint32_t *)0xe000e014 = SEND_START_TIMEOUT;
    *(uint32_t *)0xe000e018 = 0;
    *(uint32_t *)0xe000e010 |= 1;
    while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT) || I2C_OT)); 
    *(uint32_t *)0xe000e010 &= 0xfffffffe; 
    if (I2C_OT)
    {
      I2C_OT = FALSE;
      return SEND_START_ERR;
    }   
  } 
 
  
  /* send addr with read direction */
  I2C_Send7bitAddress(I2Cx, (uint8_t)(slaveaddr & 0xFF), I2C_Direction_Receiver);
  
  
  /*
  different implementation of receive data 
  depends on communication length
  (1) length >=3
  (2) length = 2
  (3) length = 1
  */
  if (length >=3)
  {
    *(uint32_t *)0xe000e014 = SEND_ADDR7_TIMEOUT;  
    *(uint32_t *)0xe000e018 = 0;
    *(uint32_t *)0xe000e010 |= 1;
    while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) || 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 ADDR_MATCH_ERR;
    }    
    
    /* receive data */
    /* use another safe procedure to receive data */
    while(length)
    {
      if (length !=3)
      {
        *(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT;   
        *(uint32_t *)0xe000e018 = 0;
        *(uint32_t *)0xe000e010 |= 1;
        while(((I2C_GetLastEvent(I2Cx)&0x04) != 0x04)&& !I2C_OT); // poll on BTF
        *(uint32_t *)0xe000e010 &= 0xfffffffe;     
        if (I2C_OT)
        {
          I2C_OT = FALSE;
          I2C_GenerateSTOP(I2Cx, ENABLE);
          return DATA_TIMEOUT;
        }    
        *pBuffer++ = I2C_ReceiveData(I2Cx);
        length--;
      }
      
      if (length == 3)
      {
        /* D(n-2) in DR; D(n-1) in shift register */
        *(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT;   
        *(uint32_t *)0xe000e018 = 0;
        *(uint32_t *)0xe000e010 |= 1;
        while(((I2C_GetLastEvent(I2Cx)&0x04) != 0x04)&& !I2C_OT); // poll on BTF
        *(uint32_t *)0xe000e010 &= 0xfffffffe;     
        if (I2C_OT)
        {
          I2C_OT = FALSE;
          I2C_GenerateSTOP(I2Cx, ENABLE);
          return DATA_TIMEOUT;
        }        
        /* clear ACK */
        I2C_AcknowledgeConfig(I2Cx, DISABLE);     
        __disable_irq();       //NVIC_SETPRIMASK();
        /* read D(n-2) */
        *pBuffer++ = I2C_ReceiveData(I2Cx);      
        /* program stop */
        I2C_GenerateSTOP(I2Cx, ENABLE);    
        /* read D(n-1) */
        *pBuffer++ = I2C_ReceiveData(I2Cx);
        __enable_irq();      //NVIC_RESETPRIMASK();
        
        *(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT;   
        *(uint32_t *)0xe000e018 = 0;
        *(uint32_t *)0xe000e010 |= 1;
        while(((I2C_GetLastEvent(I2Cx)&0x40) != 0x40)&& !I2C_OT); // poll on RxNE
        *(uint32_t *)0xe000e010 &= 0xfffffffe;     
        if (I2C_OT)
        {
          I2C_OT = FALSE;
          I2C_GenerateSTOP(I2Cx, ENABLE);
          return DATA_TIMEOUT;
        }
        *pBuffer = I2Cx->DR;
        length = 0;
      }
    }
 
 
    *(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT;   
    *(uint32_t *)0xe000e018 = 0;
    *(uint32_t *)0xe000e010 |= 1;    
    while (((I2Cx->CR1 & 0x200) == 0x200)&&(!I2C_OT)); 
    *(uint32_t *)0xe000e010 &= 0xfffffffe;     
    if (I2C_OT)
    {
      I2C_OT = FALSE;
      return SEND_STOP_ERR;
    }
    
    
    
    I2C_AcknowledgeConfig(I2Cx, ENABLE);
  }
  else if (length == 2)
  {
    vu32 tmp;
    /* ACK=1,POS=1 */
    I2Cx->CR1 = 0xc01; 
    
    *(uint32_t *)0xe000e014 = SEND_ADDR7_TIMEOUT;   
    *(uint32_t *)0xe000e018 = 0;
    *(uint32_t *)0xe000e010 |= 1;
    while((!I2C_GetFlagStatus(I2Cx,I2C_FLAG_ADDR))&& !I2C_OT); //wait for ADDR event
    *(uint32_t *)0xe000e010 &= 0xfffffffe;     
    if (I2C_OT)
      {
        I2C_OT = FALSE;
        I2C_GenerateSTOP(I2Cx, ENABLE);
        return ADDR_MATCH_ERR;
      } 
    __disable_irq();  //NVIC_SETPRIMASK();
    /* clear ADDR */
    tmp = I2Cx->SR2;    
    /* disable ACK */
    I2C_AcknowledgeConfig(I2Cx, DISABLE);
 
    __enable_irq();   //NVIC_RESETPRIMASK();     
    
    *(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT;   
    *(uint32_t *)0xe000e018 = 0;
    *(uint32_t *)0xe000e010 |= 1;
    while(((I2C_GetLastEvent(I2Cx)&0x0004) != 0x0004)&& !I2C_OT); // poll on BTF
    *(uint32_t *)0xe000e010 &= 0xfffffffe;     
    if (I2C_OT)
      {
        I2C_OT = FALSE;
        I2C_GenerateSTOP(I2Cx, ENABLE);
        return DATA_TIMEOUT;
      } 
    __disable_irq();  //NVIC_SETPRIMASK();   
    I2C_GenerateSTOP(I2Cx, ENABLE); 
    *pBuffer++ = I2Cx->DR;
    *pBuffer = I2Cx->DR;
    __enable_irq();   //NVIC_RESETPRIMASK();
    length = 0;
    /* POS=0; ACK=PE=1 */
    I2Cx->CR1 = 0x0401; 
  }
  else if (length == 1)
  {
    __IO uint32_t tmp;
    
    *(uint32_t *)0xe000e014 = SEND_ADDR7_TIMEOUT;   
    *(uint32_t *)0xe000e018 = 0;
    *(uint32_t *)0xe000e010 |= 1;
    while((!I2C_GetFlagStatus(I2Cx,I2C_FLAG_ADDR))&& !I2C_OT); //wait for ADDR event
    *(uint32_t *)0xe000e010 &= 0xfffffffe;     
    if (I2C_OT)
      {
        I2C_OT = FALSE;
        I2C_GenerateSTOP(I2Cx, ENABLE);
        return ADDR_MATCH_ERR;
      }   
    /* disable ACK */
    I2C_AcknowledgeConfig(I2Cx, DISABLE);
 
    __disable_irq();  //NVIC_SETPRIMASK();   
    /* clear ADDR */
    tmp = I2Cx->SR2;   
    I2C_GenerateSTOP(I2Cx, ENABLE);
    __enable_irq();   //NVIC_RESETPRIMASK();
    
    
    
    *(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT;   
    *(uint32_t *)0xe000e018 = 0;
    *(uint32_t *)0xe000e010 |= 1;
    while(((I2C_GetLastEvent(I2Cx)&0x40) != 0x40)&& !I2C_OT); // poll on RxNE
    *(uint32_t *)0xe000e010 &= 0xfffffffe;     
    if (I2C_OT)
      {
        I2C_OT = FALSE;
        I2C_GenerateSTOP(I2Cx, ENABLE);
        return DATA_TIMEOUT;
      } 
    
    *pBuffer = I2Cx->DR;
    length = 0;
    while ((I2Cx->CR1 & 0x200) == 0x200); 
    I2C_AcknowledgeConfig(I2Cx, ENABLE);
  }
      
  return NO_ERR;
}
 
收藏 评论2 发布时间:2014-2-8 10:37

举报

2个回答
bei_ji 回答时间:2014-2-8 11:16:28

RE:STM32F103CB----I2C读取错误

STM32的I2C总线通过硬件I2C的方式一次数据传输是不是最大只支持8个字节????
废鱼 回答时间:2014-2-10 10:16:54

RE:STM32F103CB----I2C读取错误

I2C_Result  I2C_Comm_MasterReceive(I2C_TypeDef* I2Cx, uint16_t slaveaddr, uint8_t offset, uint8_t* pBuffer, uint32_t length)
length你赋值是多少?

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版