stm32f3的i2c使用小结

最新更新时间:2019-04-02来源: eefocus关键字: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_t MemAddSize, 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;


  /* Check the parameters  http://tiyubisai.com/video_news/news_135585.html */

  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 and generate 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 is automatically 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;

  }

}


关键字:stm32f3  i2c 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/2019/ic-news040243701.html

上一篇:STM32驱动温湿度传感器HTU21D
下一篇:STM32 I2C 死锁问题

推荐阅读

STM32F3的ADC使用DMA模式传输转换数据
本文使用ADC转换电位器输出的电压值,并用DMA模式传输转换的结果,每8次采样转换取平均值,做一个简单的数字滤波。ADC的详细配置与使用见之前的日记STM32中ADC的使用,只是最后增加一步配置DMA:DMA for ADC channels features configuration To enable the DMA mode for ADC channels group, use the ADC_DMACmd() function. To configure the DMA transfer request, use ADC_DMAConfig() function.DMA的配置(摘自STM32F3官方用户手册
发表于 2017-09-30
STM32F3硬件I2C与LSM303DLHC通信
I2C(Inter-Integrated Circuit)总线是一种两线式串行总线,用于连接微控制器及其外围设备。和SPI一样,也是一种常用的串行通信方式。STM32微控制器提供硬件I2C,对它进行相应配置就可以用来进行多个设备之间的通信。使用步骤:1. Enable peripheral clock 2. Enable SDA, SCL and SMBA (when used) GPIO clocks 3. Peripherals alternate function: Call GPIO_Init() function.4. Program the Mode, Timing , Own address, A
发表于 2017-09-30
STM32F3实时时钟RTC-闹钟和唤醒中
STM32RTC使用步骤:打开PWR时钟和Backup区数据访问若使用外部低速时钟(LSE),打开LSE并等待起振选择和打开RTC时钟,等待时钟同步配置时间格式,分频系数等根据需要配置时钟,日期,闹钟,唤醒,输出,时间戳,备份寄存器等模块根据需要配置和打开中断,其中 RTC Alarm ——EXTI line 17  RTC tamper and Timestamps——EXTI line 19  RTC wakeup——EXTI line 20 下面的代码配置日期,时间,当前时间设置为 15年05月31日,星期日(7),15:50:40,打开闹钟A和唤醒中断,每一秒钟来一
发表于 2017-09-30
STM32F3—CAN通信自发自收
CAN通信是STM32中比较复杂的东西之一,它的初始化主要分为两个部分,一个是CAN的初始化,一个是过滤器的初始化。自发自收只需要一个器件,CAN的模式选择回环(Loopback)模式,这种模式下发出的数据也会被CAN本身接收回来,只需要检查接收到的数据和发送的数据是否一样,就能测试发送是否成功。代码:void CAN_Config(void){        CAN_InitTypeDef CAN_InitStructure;        CAN_FilterInitTy
发表于 2017-09-30
ST推出闪存容量高达512KB的STM32F3微控制器
    中国,2015年2月9日 —— 意法半导体 (STMicroelectronics,简称ST;纽约证券交易所代码:STM) 的STM32F3系列微控制器再添新产品,满足市场对高性能、创新功能和价格实惠的需求。新微控制器的片上存储容量增至512KB闪存 (Flash) 以及80KB静态随机存取记忆体 (SRAM),并集成丰富的外设接口,其中包括电机高转速控制器及片外 (off-chip) 存储器接口。         STM32F3系列是意法半导体ARM® Cortex®-M4微控制器产品组合的入门级产品。经过市场
发表于 2015-02-10
ST推出闪存容量高达512KB的<font color='red'>STM32F3</font>微控制器
S3C2440裸机------I2C_S3C2440的I2C控制器控制时序
1.寄存器S3C2440的I2C主要由以下四个寄存器来控制。 2.数据传输流程 
发表于 2022-02-11
S3C2440裸机------I2C_S3C2440的<font color='red'>I2C</font>控制器控制时序
小广播
设计资源 培训 开发板 精华推荐

何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved