历史上的今天
返回首页

历史上的今天

今天是:2025年08月09日(星期六)

2019年08月09日 | stm32f030 硬件I2C配置

2019-08-09 来源:eefocus

使用硬件I2C的说明

STM32F0使用硬件I2C作为master,与外设通信,code步骤如下:


配置GPIO引脚功能

初始化I2C外设

调用I2C的外设库函数进行读写I2C

下面是详细代码: 

1. 配置GPIO引脚功能


RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_1);

GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_1);


这里外设控制时钟使用了AHB总线时钟,PB8、9脚复用了I2C功能GPIO_AF_1,注意使用了开漏的脚位设置,实际电路上8、9两脚上要上拉10K电阻


2. 初始化I2C外设


I2C_InitTypeDef I2C_InitStructure;

RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;

I2C_InitStructure.I2C_DigitalFilter = 0x00;

I2C_InitStructure.I2C_OwnAddress1 = 0x00;

I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

I2C_InitStructure.I2C_Timing = 0x30E32E44;

I2C_Init(I2C1, &I2C_InitStructure);

I2C_Cmd(I2C1, ENABLE);


这里工作时钟使用了系统时钟RCC_I2C1CLK_SYSCLK,注意I2C_Timing时钟寄存器的值需要使用ST官方工具来计算


3. 调用I2C的外设库函数进行读写I2C 

可以使用查询状态寄存器方式 

主要库函数有: 

(1).void I2C_TransferHandling(I2C_TypeDef* I2Cx, uint16_t Address, uint8_t Number_Bytes, uint32_t ReloadEndMode, uint32_t StartStopMode)


(2)uint8_t I2C_ReceiveData ( I2C_TypeDef * I2Cx )


(3)void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data) 

详细说明可看标准外设库帮助文档


I2C读设备数据


/**

  * @brief  从I2C1总线上的某一器件的某一起始地址中读取一定字节的数据到数组中

  * @param  driver_Addr:I2C器件地址

  * @param  start_Addr:起始字节地址

  * @param  number_Bytes:要读取的字节数量(小于一页)

  * @param  read_Buffer:存放读取数据的数组指针

  * @retval 是否读取成功

  */

I2C_Status I2C1_Read_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer)

{

  uint8_t read_Num;


  I2C_Timeout = I2C_TIMEOUT;

  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)

  {

    if((I2C_Timeout--) == 0)

    {

      return I2C_FAIL;

    }

  }


  I2C_TransferHandling(I2C1, driver_Addr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);


  I2C_Timeout = I2C_TIMEOUT;

  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)

  {

    if((I2C_Timeout--) == 0)

    {

      return I2C_FAIL;

    }

  }


  I2C_SendData(I2C1, start_Addr);


  I2C_Timeout = I2C_TIMEOUT;

  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TC) == RESET)

  {

    if((I2C_Timeout--) == 0)

    {

      return I2C_FAIL;

    }

  }


  I2C_TransferHandling(I2C1, driver_Addr, number_Bytes,  I2C_AutoEnd_Mode, I2C_Generate_Start_Read);


  for(read_Num = 0; read_Num < number_Bytes; read_Num++)

  {

    I2C_Timeout = I2C_TIMEOUT;

    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET)

    {

      if((I2C_Timeout--) == 0)

      {

        return I2C_FAIL;

      }

    }


    read_Buffer[read_Num] = I2C_ReceiveData(I2C1);

  }


  I2C_Timeout = I2C_TIMEOUT;

  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET)

  {

    if((I2C_Timeout--) == 0)

    {

      return I2C_FAIL;

    }

  }


  return I2C_OK;

}


I2C写设备数据


/**

  * @brief  从I2C1的总线上的某一器件的某一起始地址中读取一定字节的数据到数组中

  * @param  driver_Addr:I2C器件地址

  * @param  start_Addr:起始字节地址

  * @param  number_Bytes:要读取的字节数量(小于一页)

  * @param  write_Buffer:存放读取数据的数组指针

  * @retval 是否读取成功

  */

I2C_Status I2C1_Write_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer)

{

  uint8_t write_Num;


  I2C_Timeout = I2C_TIMEOUT;

  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)

  {

    if((I2C_Timeout--) == 0)

    {

      return I2C_FAIL;

    }

  }


  I2C_TransferHandling(I2C1, driver_Addr, 1, I2C_Reload_Mode, I2C_Generate_Start_Write);


  I2C_Timeout = I2C_TIMEOUT;

  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)

  {

    if((I2C_Timeout--) == 0)

    {

      return I2C_FAIL;

    }

  }


  I2C_SendData(I2C1, start_Addr);


  I2C_Timeout = I2C_TIMEOUT;

  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TCR) == RESET)

  {

    if((I2C_Timeout--) == 0)

    {

      return I2C_FAIL;

    }

  }


  I2C_TransferHandling(I2C1, driver_Addr, number_Bytes, I2C_AutoEnd_Mode, I2C_No_StartStop);


  for(write_Num = 0; write_Num < number_Bytes; write_Num++)

  {

    I2C_Timeout = I2C_TIMEOUT;

    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)

    {

      if((I2C_Timeout--) == 0)

      {

        return I2C_FAIL;

      }

    }


    I2C_SendData(I2C1, write_Buffer[write_Num]);

  }


  I2C_Timeout = I2C_TIMEOUT;

  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET)

  {

    if((I2C_Timeout--) == 0)

    {

      return I2C_FAIL;

    }

  }


  return I2C_OK;

}


推荐阅读

史海拾趣

台湾远翔(Feeling Technology)公司的发展小趣事

乔光电子在技术创新方面始终走在行业前列。面对压敏电阻产品技术方面的挑战,如产品失效引发的起火问题,公司在苏州设立了专门的实验室,由7名成员组成研发团队,专注于材料研发。经过不懈努力,乔光电子成功解决了这一难题,并在全球范围内率先大批量使用刷铜技术,进一步提升了产品的性能和质量。此外,公司还不断引入新技术、新设备,提高产品的生产效率和品质,确保在全球市场中保持领先地位。

帝特(DTECH)公司的发展小趣事

帝特在国内市场取得一定成绩后,开始积极拓展国际市场。公司在中国区开设了广州、深圳分公司,并在泰国和马来西亚等地设立了分公司和专卖店。通过全球化的战略布局,帝特的产品销售网络遍布东南亚、中东、非洲和美洲等国家和地区,公司的知名度和市场份额均得到了显著提升。

Anritsu公司的发展小趣事

面对日益激烈的市场竞争和不断变化的市场需求,帝特始终坚持创新驱动的发展战略。公司不断投入研发资源,加强技术创新和产品升级,力求在保持传统业务优势的同时,开拓新的增长点。此外,帝特还积极布局电子专用材料项目,加强半导体芯片封装浆料研发推广,进一步优化产业结构,提升公司的综合竞争力。

以上五个故事概述了帝特(DTECH)公司在电子行业发展的主要历程和关键节点,展现了公司从创立到成长为行业领军企业的艰辛与辉煌。

AAEON公司的发展小趣事

2007年,帝特成功获得迪士尼形象授权(泰国),这一里程碑事件标志着帝特品牌在国际市场上的认可度和影响力得到了显著提升。随后,帝特又获得了国内悠嘻猴授权,进一步丰富了其产品线。2008年,帝特荣获“守合同、重信用企业”荣誉称号,这一荣誉不仅是对帝特过去努力的肯定,也为公司的未来发展奠定了坚实基础。

Embedded Planet公司的发展小趣事

Embedded Planet公司自成立之初就注重技术创新和与业界领导者的合作。通过持续研发,公司成功开发出一款革命性的嵌入式系统解决方案,这一解决方案能够显著提升设备的性能和效率。同时,Embedded Planet积极与卓联半导体公司合作,共同推出了一款伪线模块,该模块能够大幅度降低通过分组网络传送TDM业务的网络设备的复杂性,并缩短开发时间。这一创新产品得到了市场的广泛认可,也为公司赢得了更多的合作机会。

Crouzet公司的发展小趣事

Crouzet一直致力于产品创新和技术研发。公司的产品线不断丰富,涵盖了自动控制元件、智能控制器、可编程逻辑控制器、触摸屏、测量传感器、模拟和数字电子元件等多种产品。这些产品广泛应用于汽车、化工、电力、机械、消费电子、空调和冷库、石油和天然气等多个行业,为客户提供了高效、可靠的自动化解决方案。

问答坊 | AI 解惑

智能温控器使居家采暖更舒适

时值装修旺季,许多家庭在经历去年雪灾严寒之后开始将采暖设备优先采购,而目前一项精确采暖和高效节能相结合的高科技产品——碳晶平面发热材料正式登陆南京,作为拥有三项国家发明专利的新产品,碳晶地暖已经在上海成功实践,并被南极科考队采纳使 ...…

查看全部问答>

FSA4157模拟开关

大家有谁知道什么产品上还在使用FSA4157模拟开关,希望知道的能够帮帮我!谢谢…

查看全部问答>

ADI SHARC处理器的起源和演进

说到要求超高性能的前沿应用,就不得不提起ADI公司的SHARC处理器。随着更高动态范围、更高性能和更低成本等市场压力的与日俱增,各种应用对浮点处理器的需求也在不断增加。本文将介绍第一款SHARC处理器背后的历史,并讨论其架构的创新,这使得这款 ...…

查看全部问答>

向今天已开始工作的表示敬意

今天是初七,按国家规定已经要上班了。不过EEWORLD明天才上班,所以还有一天的轻松。不过,要向今天已开始紧张工作的坛友们表示崇高的敬意,并由衷地说一声“你们辛苦了”!!!…

查看全部问答>

基于NiosⅡ的硬盘存储系统的研究与设计

本帖最后由 paulhyde 于 2014-9-15 09:33 编辑 信息 技 术 的快速发展,电子产品广泛地进入生产和生活领域,使得数据存储需求日益增强。本文研究设计了一种基于Nios I处理器的硬盘存储系统。首先,本文介绍了论文选题的背景及国内外相关研究的进展 ...…

查看全部问答>

贵求毕业设计 单片机方面的 谢谢

本人想做个单片机的毕业设计 不是很懂 所以不希望太难 但是又怕简单了学校不给通过 所以希望大家给点意见 最好能提供点设计资料 谢谢大家了…

查看全部问答>

急求用MATLAB实现频率提取(FFT) 代码

急求用MATLAB实现频率提取(FFT) 代码…

查看全部问答>

问几个驱动模型的问题

1,写了一个SPI的驱动,使用的是驱动模型框架,probe,remove等,现在要给上层应用程序提供接口,以实现读,写,打开,关闭等功能,是不是要向字符驱动那样实现write,read等函数? 2,如果不使用字符驱动的那些接口,那要怎么实现以提供接口给上 ...…

查看全部问答>

招驱动开发方面的兼职人员

本公司现在招驱动开发方面书籍的作者 待遇丰厚 有兴趣的可以和我联系  进行详谈 QQ878298915 请注明  驱动 Email pyq_1985@163.com…

查看全部问答>

如何实现自动清理(WINCE做服务器)

程序运行一段时间,占用内存会不断增大,最小化以后window会自动清理,有没有编程的方法实现自动清理 …

查看全部问答>