历史上的今天
返回首页

历史上的今天

今天是:2024年12月22日(星期日)

2021年12月22日 | STM32F429--I2C通信(读写EEPROM,串口返回测试数据)

2021-12-22 来源:eefocus

一、I2C介绍

I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息,SDA数据线和SCL时钟信号线。

  

主器件用于启动总线传送数据,并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件.在总线上主和从、发和收的关系不是恒定的,而取决于此时数据传送方向。


如果主机要发送数据给从器件,则主机首先寻址从器件,然后主动发送数据至从器件,最后由主机终止数据传送;

如果主机要接收从器件的数据,首先由主器件寻址从器件.然后主机接收从器件发送的数据,最后由主机终止接收过程。在这种情况下.主机负责产生定时时钟和终止数据传送。


二、I2C的通信状态

总线空闲—SDA和SCL都为高电平


数据的有效位规定


SCL为高电平期间,数据线SDA上必须保持稳定

只有SCL为低电平期间,数据线SDA才允许变化

在这里插入图片描述

I2C的起始和终止信号


SCL线为高电平期间,SDA线由高电平—>低电平,表示起始信号

SCL线为高电平期间,SDA线由低电平—>高电平,表示终止信号

在这里插入图片描述

3.I2C字节的传送与应答


每一个字节是8位,先传最高位(MSB),每传一个字节后面必须跟随一个应答位(即一帧有9位)。

在这里插入图片描述

三、须知

下面代码用到了串口返回读取的数据信息,此处用到了串口一

在这里插入图片描述

用到的库函数

在这里插入图片描述
在这里插入图片描述

主发送器通讯过程

在这里插入图片描述

主接收器

在这里插入图片描述

四、程序部分

bsp_i2c_eeprom.h


#ifndef __BSP_I2C_EEPROM_H

#define __BSP_I2C_EEPROM_H


#include "stm32f4xx.h"


#define I2C_OWN_ADDR 0x77 /*主机的八位地址,只要不和从机重复*/


#define I2C_SPEED 400000  /*快速模式最高400khz*/


#define EEPROM_ADDR (0x50<<1)   //0xA0,



//引脚定义,移植时修改此处即可,野火的I2C口为PB6和PB7

/*******************************************************/

#define EEPROM_I2C                              I2C1

#define EEPROM_I2C_CLK                         RCC_APB1Periph_I2C1


#define EEPROM_SCL_GPIO_PORT                    GPIOB

#define EEPROM_SCL_GPIO_CLK                     RCC_AHB1Periph_GPIOB

#define EEPROM_SCL_PIN                          GPIO_Pin_6

#define EEPROM_SCL_AF                           GPIO_AF_I2C1

#define EEPROM_SCL_SOURCE                       GPIO_PinSource6


#define EEPROM_SDA_GPIO_PORT                GPIOB

#define EEPROM_SDA_GPIO_CLK                 RCC_AHB1Periph_GPIOB

#define EEPROM_SDA_PIN                       GPIO_Pin_7

#define EEPROM_SDA_AF                        GPIO_AF_I2C1

#define EEPROM_SDA_SOURCE                   GPIO_PinSource7


/************************************************************/

void EEPROM_GPIO_Config(void);

void EEPROM_I2C_ModeConfig(void);

void EEPROM_Byte_Write(uint8_t* pData,uint8_t addr);

uint8_t EEPROM_Byte_Read(uint8_t addr);


#endif /* __BSP_I2C_EEPROM_H */


bsp_i2c_eeprom.c


#include "./i2c/bsp_i2c_eeprom.h"


void Wait_for_EEPROM(void);

//1.初始化GPIO

void EEPROM_GPIO_Config(void)

{


  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(EEPROM_SCL_GPIO_CLK|EEPROM_SDA_GPIO_CLK,ENABLE);

    

 /* 连接SCL*/

  GPIO_PinAFConfig(EEPROM_SCL_GPIO_PORT,EEPROM_SCL_SOURCE,EEPROM_SCL_AF);

  /*  连接 SDA*/

  GPIO_PinAFConfig(EEPROM_SDA_GPIO_PORT,EEPROM_SDA_SOURCE,EEPROM_SDA_AF);

  

  

  /* GPIO初始化 */

  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;  

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  

  /* 配置SCL引脚为复用功能  */

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_Pin = EEPROM_SCL_PIN  ;  

  GPIO_Init(EEPROM_SCL_GPIO_PORT, &GPIO_InitStructure);


  /* 配置SDA引脚为复用功能 */

  GPIO_InitStructure.GPIO_Pin = EEPROM_SDA_PIN;

  GPIO_Init(EEPROM_SDA_GPIO_PORT, &GPIO_InitStructure);

  


}


//2.初始化I2C模式

void EEPROM_I2C_ModeConfig(void)

{

  I2C_InitTypeDef I2C_InitStruct;

    

  /* 使能 I2C时钟 */

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

  

  I2C_InitStruct.I2C_Ack =  I2C_Ack_Enable;

  I2C_InitStruct.I2C_AcknowledgedAddress =  I2C_AcknowledgedAddress_7bit;

  I2C_InitStruct.I2C_ClockSpeed =  I2C_SPEED; 

  I2C_InitStruct.I2C_DutyCycle =  I2C_DutyCycle_2 ;

  I2C_InitStruct.I2C_Mode =  I2C_Mode_I2C ;

  I2C_InitStruct.I2C_OwnAddress1 = I2C_OWN_ADDR;

  

  I2C_Init(EEPROM_I2C,&I2C_InitStruct);

  

  I2C_Cmd(EEPROM_I2C,ENABLE);


}



//3.byte write 函数

void EEPROM_Byte_Write(uint8_t* pData,uint8_t addr)

{

  I2C_GenerateSTART(EEPROM_I2C,ENABLE);

  

  while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS )

  {

     //....

  }

    

  I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Transmitter);

  

  

  while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS )

  {

  

  }

  

  

  I2C_SendData(EEPROM_I2C,addr);

  

  

  while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS )

  {

  

  }

  

  

  I2C_SendData(EEPROM_I2C,*pData);

  

  

  

  while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS )

  {

  

  }

  

  

  I2C_GenerateSTOP(EEPROM_I2C,ENABLE);


}



//4.random read

uint8_t EEPROM_Byte_Read(uint8_t addr)

{

  uint8_t readTemp;


  Wait_for_EEPROM();

  

  

  I2C_GenerateSTART(EEPROM_I2C,ENABLE);

  

  while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS )

  {

     //....

  }

    

  I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Transmitter);

  

  

  while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS )

  {

  

  }

  

  

  I2C_SendData(EEPROM_I2C,addr);

  

  

  while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS )

  {

  

  }

  

  

  I2C_GenerateSTART(EEPROM_I2C,ENABLE);

  

  while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS )

  {

     //....

  }


  

  I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Receiver);

  

  

  while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS )

  {

  

  }

  

  I2C_AcknowledgeConfig(EEPROM_I2C,DISABLE);

  

  while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS )

  {

  

  }

  

  readTemp = I2C_ReceiveData(EEPROM_I2C);

   

  

  I2C_GenerateSTOP(EEPROM_I2C,ENABLE);

  

  return readTemp;


}


//5.等待EEPROM内部写完毕

void Wait_for_EEPROM(void)

{

  do

  {

    I2C_GenerateSTART(EEPROM_I2C,ENABLE);

  

//    while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS )

//    {

//       //....

//    }

      

    I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Transmitter);  

  

  }while(I2C_GetFlagStatus(EEPROM_I2C,I2C_FLAG_ADDR) == RESET);

  

  //等待ADDR = 1 才执行下面的语句

  

  I2C_ClearFlag(EEPROM_I2C,I2C_FLAG_AF);

    

  I2C_GenerateSTOP(EEPROM_I2C,ENABLE);


  while(I2C_GetFlagStatus(EEPROM_I2C,I2C_FLAG_BUSY) == SET);

  

  //总线空闲,执行下面的语句


}  


bsp_debug_usart.h


#ifndef __DEBUG_USART_H

#define __DEBUG_USART_H


#include "stm32f4xx.h"

#include



//引脚定义

/*******************************************************/

#define DEBUG_USART                             USART1

#define DEBUG_USART_CLK                         RCC_APB2Periph_USART1

#define DEBUG_USART_BAUDRATE                    115200  //串口波特率


#define DEBUG_USART_RX_GPIO_PORT                GPIOA

#define DEBUG_USART_RX_GPIO_CLK                 RCC_AHB1Periph_GPIOA

#define DEBUG_USART_RX_PIN                      GPIO_Pin_10

#define DEBUG_USART_RX_AF                       GPIO_AF_USART1

#define DEBUG_USART_RX_SOURCE                   GPIO_PinSource10


#define DEBUG_USART_TX_GPIO_PORT                GPIOA

#define DEBUG_USART_TX_GPIO_CLK                 RCC_AHB1Periph_GPIOA

#define DEBUG_USART_TX_PIN                      GPIO_Pin_9

#define DEBUG_USART_TX_AF                       GPIO_AF_USART1

#define DEBUG_USART_TX_SOURCE                   GPIO_PinSource9


#define DEBUG_USART_IRQHandler                  USART1_IRQHandler

#define DEBUG_USART_IRQ                  USART1_IRQn

/************************************************************/


void Debug_USART_Config(void);

void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch);

void Usart_SendString( USART_TypeDef * pUSARTx, char *str);


void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch);


#endif /* __USART1_H */


bsp_debug_usart.c


#include "./usart/bsp_debug_usart.h"



 /**

  * @brief  配置嵌套向量中断控制器NVIC

  * @param  无

  * @retval 无

  */

static void NVIC_Configuration(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

  

  /* 嵌套向量中断控制器组选择 */

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

推荐阅读

史海拾趣

台湾富晶(FORTUNE)公司的发展小趣事
确保电源供电稳定,无电压波动或断电现象。
AR RF/Microwave Instrumentation公司的发展小趣事

面对未来的发展,AR RF/Microwave Instrumentation制定了明确的战略规划。他们将继续加大在研发和创新方面的投入,推出更多具有创新性和竞争力的产品。同时,公司还将积极拓展新的应用领域和市场,寻求更多的合作机会,以实现更加广泛的发展。

请注意,以上仅为概述性的故事框架,并非具体的事实描述。如果你需要更详细、具体的故事内容,建议查阅AR RF/Microwave Instrumentation公司的官方资料、新闻报道或行业分析报告等,以获取更准确的信息。

DATEL Inc公司的发展小趣事

随着公司业务的不断扩展,DATEL Inc.开始实施全球化战略。公司积极开拓国际市场,与全球各地的合作伙伴建立了紧密的合作关系。通过引进国际先进技术和管理经验,DATEL Inc.的产品质量和服务水平得到了进一步提升。同时,公司还加强了对海外市场的营销和推广力度,成功将DATEL Inc.的品牌推向了全球。

岑科(CENKER)公司的发展小趣事

岑科公司成立于2001年,初期主要从事电子元器件的贸易业务。在创始人蔡旌章的带领下,岑科以优质的服务和灵活的运营策略,在国内外市场上赢得了良好的口碑。这一时期,岑科的服务对象主要是海内外的电子元器件需求商,通过精准把握市场需求和优质的产品供应,逐渐在电子元器件贸易领域站稳了脚跟。随着业务的不断拓展,岑科开始思考如何进一步提升自身的竞争力,以实现更长远的发展。

Bomar Interconnect公司的发展小趣事

在供应链管理方面,Bomar Interconnect公司也进行了一系列优化措施。公司与供应商建立了长期稳定的合作关系,确保原材料的稳定供应和质量可控。同时,公司还加强了对供应链的监控和管理,通过信息化手段提高了供应链的透明度和效率。这些努力不仅降低了公司的采购成本,也提高了供应链的响应速度和灵活性。

Amkor公司的发展小趣事

在电子行业的激烈竞争中,Bomar Interconnect公司凭借持续的技术创新,逐渐崭露头角。公司研发团队不断深入研究新型连接技术,成功推出了一系列高性能、高可靠性的连接器产品。这些产品在市场上获得了广泛认可,为公司带来了稳定的收入来源。同时,公司还积极投入资源,加强与其他企业的技术合作,不断拓宽产品应用领域,进一步提升了公司的市场竞争力。

问答坊 | AI 解惑

再议Linux与WinCE

Linux是单体内核,即将图形、驱动及文件系统等功能全在操作系统内核中实现,运行在内核状态和同一地址空间,其优点是减少了进程间通信和状态切换的系统开销,获得较高的运行效率;缺点是内核比较庞大! WinCE是微内核,即在内核中实现基本功能, ...…

查看全部问答>

ad783怎么用?

本帖最后由 paulhyde 于 2014-9-15 09:40 编辑 我实在是不知道这个东东怎么用啊,大家帮一下我吧!  …

查看全部问答>

AVR辅助开发工具

有助于写显示驱动和通信程序…

查看全部问答>

请问这个是怎么理解的设置定时器定时时间

void vSetMotorTimer(unsigned short uiTime)// uiTime us   {      RCAP2LH = uiTime;  }  //重新载入定时数据   void vUpdateMotorTimer(void)  {      T2LH=RCAP2L ...…

查看全部问答>

有没有人研究过mini2440的BSP,其BSP是如何识别128M/256M等flash的?

因为我使用的是QQ2440,但是我发现最新的mini2440的BSP更新了很多驱动,我想移进去QQ2440使用,但是可惜烧写进去后不能启动。 我觉得想搞好这个bsp必须先知道如何使用其他flash时需要修改的代码,哪位高手知道的,麻烦指导下。…

查看全部问答>

求介绍一些wince编程书籍

求介绍一些wince编程书籍…

查看全部问答>

C#如何捕获inputPanel输入法改变的事件

我是初学,最近被此问题困扰了好多天, 打开inputPanel后,改变输入法,inputPanel的高度会改变,此时如何捕获该事件。 我使用C#,开发环境vs   2005,.net   CF   2.0。 希望解释能详细些,我是初学。 还有我的 ...…

查看全部问答>

PG128128A资料

研究了N就,PG128128A资料到底怎么驱动,谁有能提供详细资料 12864及以下的我会,就是不会PG128128A的 邮箱 zoujun224@qq.com…

查看全部问答>

惭愧啊,st网站上想找点东西太难了

                                 也不知道是自己笨还是网站不太合理,反正在他官网上从来都没找到自己想要的东西,搜到的许多野都是指向其官网,可 ...…

查看全部问答>

DSP2812 5V和3.3V接口电压转换芯片

请教大家有没有用过 5V和3.3V接口电压转换芯片,我需要DSP2812外接DS18B20和其他几个5V峰值的转速信号,需要做电平转换,但是不知道使用什么样的接口电压转换芯片,需要方向控制的就不要介绍了,比如:SN74LVC164245。我需要的是自动双向转换电平的 ...…

查看全部问答>