找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5651|回复: 2
打印 上一主题 下一主题
收起左侧

stm32f3的i2c使用小结

[复制链接]
跳转到指定楼层
楼主
ID:417196 发表于 2018-10-29 13:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
stm32f3的i2c使用小结
这几天拿到了stm32f3discovery,拿到手的第一件事就是测试了硬件i2c,使用stm32cube生成库,测试对象为AD5934与ADG715。经过两天的调试,完美调通。中间也碰到了些问题。
1、一开始用的I2C1,一仿真就会出现死机的情况。
        由于I2C1与swd接口重合,所以调用HAL_I2C_Init()函数后就死机,改成I2C2后问题解决。
2、无法访问指定地址的设备
        库函数中的入口地址并不是7bit地址,需要输入8bit。我的设备地址为13,始终无法访问设备,改为26后解决。
3、可以读写单个地址的数据,但是不能多字节读写。
       (1)、对于多字节写, 库函数中的
        HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_tMemAddSize, uint8_t*pData, uint16_t Size, uint32_t Timeout)
       其中MemAddSize表示地址的位数,0表示7bit地址,1表示10bit地址。我误认为这个写的字节数,所以导致在写多字节的时候出错。
       (2)、对于多字节读,由于AD5934的读操作与库函数的读操作有些出入,所以导致一直读错误。在库函数中写完读的内存地址就开始读,而AD5934中写完block read后接着还要再写一个number bytes read然后才开始读。所以需要对库函数进行修改,新增一个函数,以适合AD5934的block read.
        stm32f3的i2c有三种模式:Reload、AutoEnd、SoftEnd模式。
        i2c每发送完一个字节,就会产生TXIS标志,当发送完最后一个字节时:
        对于Reload模式,当字节大于255字节时,必须使用此模式,此模式下发送结束后,会产生tcr标志。
        对于AutoEnd模式,发送后最后一个字节时,会自动产生STOP。
        对于SoftEnd模式,发送完最后一个字节时,会产生tc标志,对于发送过程中需要Restart的需要使用此模式。
        对于AD5934的读操作,可以事先工作在SoftEnd模式,发送完block read与number bytes read字节后,再转入AutoEnd模式进行Restart,读取完指定的字节后自动产生STOP。操作流程如下:






HAL_StatusTypeDef HAL_I2C_Mem_Read_AD5934_Block(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
  uint32_t Sizetmp = 0;

  assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
  
  if(hi2c->State == HAL_I2C_STATE_READY)
  {   
    if((pData == NULL) || (Size == 0))
    {
      return  HAL_ERROR;                                 
    }

    if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
    {
      return HAL_BUSY;
    }

    /* Process Locked */
    __HAL_LOCK(hi2c);
   
    hi2c->State = HAL_I2C_STATE_MEM_BUSY_RX;
    hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
    /*
    //Send Slave Address and Memory Address
    if(I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize,Timeout) != HAL_OK)
    {
      if(hi2c->ErrorCode== HAL_I2C_ERROR_AF)
      {
        // Process Unlocked
        __HAL_UNLOCK(hi2c);
        return HAL_ERROR;
      }
      else
      {
        // Process Unlocked
        __HAL_UNLOCK(hi2c);
        return HAL_TIMEOUT;
      }
    }*/
   
    I2C_TransferConfig(hi2c,DevAddress,MemAddSize+1, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE);
      
    /* Wait until TXIS flag is set */
    if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout) != HAL_OK)
    {
      if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
      {
        return HAL_ERROR;
      }
      else
      {
        return HAL_TIMEOUT;
      }
    }
   
    /* If Memory address size is 8Bit */
    if(MemAddSize == I2C_MEMADD_SIZE_8BIT)
    {
      /* Send Memory Address */
      hi2c->Instance->TXDR = __HAL_I2C_MEM_ADD_LSB(MemAddress);   
    }      
    /* If Mememory address size is 16Bit */
    else
    {
      /* Send MSB of Memory Address */
      hi2c->Instance->TXDR = __HAL_I2C_MEM_ADD_MSB(MemAddress);
      
      /* Wait until TXIS flag is set */
      if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout) != HAL_OK)
      {
        if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
        {
          return HAL_ERROR;
        }
        else
        {
          return HAL_TIMEOUT;
        }
      }
      
      /* Send LSB of Memory Address */
      hi2c->Instance->TXDR = __HAL_I2C_MEM_ADD_LSB(MemAddress);  
    }
   
    /* Wait until TXIS flag is set */
    if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout) != HAL_OK)
    {
      if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
      {
        return HAL_ERROR;
      }
      else
      {
        return HAL_TIMEOUT;
      }
    }
   
    hi2c->Instance->TXDR = Size;
   
    /* Wait until TC flag is set */
    if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, RESET, Timeout) != HAL_OK)     
    {
      return HAL_TIMEOUT;
    }   
   
    /* Send Slave Address */
    /* Set NBYTES to write and reload if size > 255 andgenerate RESTART */
    /* Size > 255, need to set RELOAD bit */
    if(Size > 255)
    {
      I2C_TransferConfig(hi2c,DevAddress,255, I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
      Sizetmp = 255;
    }
    else
    {
      I2C_TransferConfig(hi2c,DevAddress,Size, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
      Sizetmp = Size;
    }
   
    do
    {  
      /* Wait until RXNE flag is set */
      if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, Timeout) != HAL_OK)     
      {
        return HAL_TIMEOUT;
      }
         
      /* Read data from RXDR */
      (*pData++) = hi2c->Instance->RXDR;

      /* Decrement the Size counter */
      Sizetmp--;
      Size--;   

      if((Sizetmp == 0)&&(Size!=0))
      {
        /* Wait until TCR flag is set */
        if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout) != HAL_OK)     
        {
          return HAL_TIMEOUT;
        }
        
        if(Size > 255)
        {
          I2C_TransferConfig(hi2c,DevAddress,255, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
          Sizetmp = 255;
        }
        else
        {
          I2C_TransferConfig(hi2c,DevAddress,Size, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
          Sizetmp = Size;
        }
      }

    }while(Size > 0);

    /* No need to Check TC flag, with AUTOEND mode the stop isautomatically generated */
    /* Wait until STOPF flag is reset */
    if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF) != HAL_OK)
    {
      if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
      {
        return HAL_ERROR;
      }
      else
      {
        return HAL_TIMEOUT;
      }
    }

    /* Clear STOP Flag */
    __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
   
    /* Clear Configuration Register 2 */
    __HAL_I2C_RESET_CR2(hi2c);
   
    hi2c->State = HAL_I2C_STATE_READY;
   
    /* Process Unlocked */
    __HAL_UNLOCK(hi2c);
   
    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}


http://blog.csdn.net/xiaoxiongli/article/details/49637785

http://blog.csdn.net/xiaoxiongli/


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:64451 发表于 2019-10-14 17:24 | 只看该作者
真心感谢楼主帮了我大忙,谢谢!
回复

使用道具 举报

板凳
ID:64451 发表于 2019-10-14 17:25 | 只看该作者
楼主,我今天也用pca9535,发现上电后Int引脚总是为低电平
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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