搜索
查看: 2755|回复: 2

[已解决] STM32F103CB----I2C读取错误

[复制链接]

该用户从未签到

1

主题

2

帖子

0

蝴蝶豆

新手上路

最后登录
1970-1-1
发表于 2014-2-8 10:37:17 | 显示全部楼层 |阅读模式
刚入手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;
}
 
回复

使用道具 举报

该用户从未签到

1

主题

2

帖子

0

蝴蝶豆

新手上路

最后登录
1970-1-1
 楼主| 发表于 2014-2-8 11:16:28 | 显示全部楼层

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

STM32的I2C总线通过硬件I2C的方式一次数据传输是不是最大只支持8个字节????
回复 支持 反对

使用道具 举报

该用户从未签到

133

主题

4688

帖子

239

蝴蝶豆

版主

最后登录
2021-4-10
发表于 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你赋值是多少?
回复 支持 反对

使用道具 举报

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

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|论坛-意法半导体STM32/STM8技术社区

GMT+8, 2024-4-28 07:59 , Processed in 0.153548 second(s), 31 queries .

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

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