历史上的今天
返回首页

历史上的今天

今天是:2025年04月02日(星期三)

正在发生

2019年04月02日 | stm32f3的i2c使用小结

2019-04-02 来源:eefocus

这几天拿到了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;

  }

}


推荐阅读

史海拾趣

意普(ESPE)公司的发展小趣事

作为一家有社会责任感的企业,意普(ESPE)公司始终关注环保和可持续发展。公司采用环保材料和生产工艺,减少了对环境的污染。同时,公司还积极参与社会公益活动,为社会做出了积极贡献。这些举措不仅提升了公司的社会形象,也为企业的长期发展奠定了良好的社会基础。

Display Elektronik GmbH公司的发展小趣事

随着环保意识的日益增强,Display Elektronik GmbH将绿色环保理念融入到了公司的发展中。公司采用环保材料和生产工艺,减少了对环境的污染。同时,Display Elektronik GmbH还积极推广绿色显示技术,为客户提供更加环保、节能的显示解决方案。这种对环保的关注和投入,让Display Elektronik GmbH在行业中树立了良好的形象。

Datalogic公司的发展小趣事

随着电动汽车行业的兴起,汽车行业对零部件的标记和追踪要求也日益严格。Datalogic凭借其强大的技术实力,成功开发出3W固态激光打标机Vlase UV 3,该产品能够在橙色部件上实现高度可见、稳定和持久的对比度标记,解决了电动汽车生产中的一大难题。这一创新不仅展示了Datalogic的技术实力,也进一步巩固了其在电子行业中的领先地位。

Amphenol Thermometrics公司的发展小趣事

随着公司业务的不断发展,Datalogic意识到全球市场的巨大潜力。从2000年代开始,公司加快了全球化步伐,通过设立销售和服务中心,覆盖了全球100多个国家。这种全球布局不仅使Datalogic能够更好地服务全球客户,还为公司带来了更多的市场机会。

EXCELTA公司的发展小趣事

随着科技的不断进步和市场的不断变化,Excelta始终将技术创新作为公司发展的核心驱动力。公司投入大量资金和资源进行技术研发和产品创新,不断推出具有竞争力的新产品。其中,一款高性能的微型连接器产品凭借其出色的性能和稳定性在市场上取得了巨大成功。此外,Excelta还积极探索新的应用领域和市场机会,为公司的持续发展注入了新的活力。

CINTERION公司的发展小趣事

2010年,电子支付与身份识别技术领域的领军企业金雅拓,全资收购了CINTERION。这一资本动作不仅为CINTERION带来了更多的资金支持,更使其在金雅拓的物联网事业部中获得了更广阔的发展空间。收购完成后,CINTERION继续保持其技术领先地位,并在金雅拓的推动下,进一步拓宽了产品线和应用领域。

问答坊 | AI 解惑

仪器仪表相关知识(转帖)

仪器仪表相关产品包括:温度仪表,流量仪表,压力仪表,机械仪表(称重,转速,测厚),液位仪表,料位仪表,显示仪表,有纸/无纸记录仪,分析仪表,校验仪表等。   仪器功能在于物理、化学或生物的方法,获取被检测对象运动或变化的信息。在科 ...…

查看全部问答>

经典的C51学习教程

可是不知道怎么上传 [ 本帖最后由 xclfang 于 2009-2-4 17:30 编辑 ]…

查看全部问答>

通过NFS方式,开发板共享主机Redhat一个目录下的内容,ls出现问题

通过mount将Redhat的一个目录到开发板上,也就是NFS共享,可在两种情况下ls出现异常 /usr/arm/hello> ls hello.c /usr/arm/hello> ls Unhandled fault: external abort on linefetch (F4) at 0x00000001 fault-common.c(97): start_code=0x816 ...…

查看全部问答>

为AMD硬件平台定制一个wince平台想实现下面几个东西

为AMD硬件平台定制一个wince平台想实现下面几个东西 1.创建一个桌面快捷方式。 2.在WINDOWS目录下默认创建一个文件夹。 3.添加额外的文件到NK,并且开机运行 请问如何实现…

查看全部问答>

求做模拟键盘鼠标动作驱动,过NP。急,急,急

求做模拟键盘鼠标动作驱动,过NP。 不要按一次键出发那种键盘驱动,鼠标定位要准,稳定(韩文系统) 报酬丰厚。 急,急,急 TELL ME: 13406738163 pass86@gmail.com…

查看全部问答>

ucos的问题

uc/os的堆栈初始化函数(OSTaskInit())似乎没什么实质性的作用,这个函数返回的是栈顶的位置,那么后来如果发生任务切换或中断而需要保存寄存器,肯定是从这个栈顶开始的,而先前初始化过的堆栈不就没用了吗?…

查看全部问答>

【设计工具】Spartan-3 FPGA 系列中高效PCB 布局的LVDS 信号倒相设计技巧

  本应用指南说明 Spartan- 3 FPGA 系列如何仅通过在接收器数据通路中加入一个倒相器即可避免大量使用过孔,并且在不要求 PCB 重新设计的情况下即可解决意外的 PCB 迹线交换问题。   在比较简单的未大量使用过孔的四层或六层 PCB 上,可能很难 ...…

查看全部问答>

i2c实验

从网上下载了i2c的ip核,是Richard Herveille上传的,引文没有很好的参考例程,自己写的nios程序一直不通,有没有写好的例程,对照一下,我写的程序,还请看看哪里有问题,卡在这里两天了,操作的是PCF8563实时时钟,main函数是我自己写的,其他的 ...…

查看全部问答>

求教:keil编译大于64KB的程序

[img]最近为这个问题很头疼,虽然网上也有资料,但总讲的也不详细,而且有些提到的东西找不到。有两个问题很烦恼,一、只要程序超过64KB,编译就出错,二、可不可以不指定bank,keil就能自己自动划分呢,对于写程序的人来说,写个C文件就指定一个ba ...…

查看全部问答>