datasheet

怎样用STM32 中的 I2C读写EEPROM(二)

2019-07-11来源: eefocus关键字:STM32  I2C读写  EEPROM

假设硬件电路如下图


EEPROM芯片的设备地址一共有 7 位,其中高 4 位固定为:1010 b,低 3 位则由 A0/A1/A2 信号线的

电平决定,图中的 R/W是读写方向位,与地址无关。



按照我们此处的连接,A0/A1/A2均为0,所以EEPROM的7位设备地址是:101 0000b ,

即 0x50。由于 I2C 通讯时常常是地址跟读写方向连在一起构成一个 8 位数,且当 R/W 位为

0 时,表示写方向,所以加上 7 位地址,其值为“0xA0”,常称该值为 I2C 设备的“写地

址”;当 R/W 位为 1 时,表示读方向,加上 7 位地址,其值为“0xA1”,常称该值为“读地址”。


EEPROM 芯片中还有一个 WP 引脚,具有写保护功能,当该引脚电平为高时,禁止写

入数据,当引脚为低电平时,可写入数据,我们直接接地,不使用写保护功能。

关于 EEPROM 的更多信息,可参考其数据手册《AT24C02》来了解。若您使用的实验

板 EEPROM 的型号、设备地址或控制引脚不一样,只需根据我们的工程修改即可,程序的


控制原理相同。


编程要点

(1) 配置通讯使用的目标引脚为开漏模式;

(2) 使能 I2C外设的时钟;

(3) 配置 I2C外设的模式、地址、速率等参数并使能 I2C外设;

(4) 编写基本 I2C按字节收发的函数;

(5) 编写读写 EEPROM 存储内容的函数;

(6) 编写测试程序,对读写数据进行校验。


 

#include "stm32f10x.h"

 

 

/**************************I2C参数定义,I2C1或I2C2********************************/

#define             EEPROM_I2Cx                                I2C1

#define             EEPROM_I2C_APBxClock_FUN                   RCC_APB1PeriphClockCmd

#define             EEPROM_I2C_CLK                             RCC_APB1Periph_I2C1

#define             EEPROM_I2C_GPIO_APBxClock_FUN              RCC_APB2PeriphClockCmd

#define             EEPROM_I2C_GPIO_CLK                        RCC_APB2Periph_GPIOB     

#define             EEPROM_I2C_SCL_PORT                        GPIOB   

#define             EEPROM_I2C_SCL_PIN                         GPIO_Pin_6

#define             EEPROM_I2C_SDA_PORT                        GPIOB 

#define             EEPROM_I2C_SDA_PIN                         GPIO_Pin_7

 

 

 

/* STM32 I2C 快速模式 */

#define I2C_Speed              400000  //*

 

/* 这个地址只要与STM32外挂的I2C器件地址不一样即可 */

#define I2Cx_OWN_ADDRESS7      0X0A   

 

/* AT24C01/02每页有8个字节 */

#define I2C_PageSize           8

 

/* AT24C04/08A/16A每页有16个字节 */

//#define I2C_PageSize           16

 

/*等待超时时间*/

#define I2CT_FLAG_TIMEOUT         ((uint32_t)0x1000)

#define I2CT_LONG_TIMEOUT         ((uint32_t)(10 * I2CT_FLAG_TIMEOUT))

 

 

/*信息输出*/

#define EEPROM_DEBUG_ON         0

 

#define EEPROM_INFO(fmt,arg...)           printf("<<-EEPROM-INFO->> "fmt"n",##arg)

#define EEPROM_ERROR(fmt,arg...)          printf("<<-EEPROM-ERROR->> "fmt"n",##arg)

#define EEPROM_DEBUG(fmt,arg...)          do{

                                          if(EEPROM_DEBUG_ON)

                                          printf("<<-EEPROM-DEBUG->> [%d]"fmt"n",__LINE__, ##arg);

                                          }while(0)

 

 

/* 

 * AT24C02 2kb = 2048bit = 2048/8 B = 256 B

 * 32 pages of 8 bytes each

 *

 * Device Address

 * 1 0 1 0 A2 A1 A0 R/W

 * 1 0 1 0 0  0  0  0 = 0XA0

 * 1 0 1 0 0  0  0  1 = 0XA1 

 */

 

/* EEPROM Addresses defines */

#define EEPROM_Block0_ADDRESS 0xA0   /* E2 = 0 */

//#define EEPROM_Block1_ADDRESS 0xA2 /* E2 = 0 */

//#define EEPROM_Block2_ADDRESS 0xA4 /* E2 = 0 */

//#define EEPROM_Block3_ADDRESS 0xA6 /* E2 = 0 */

 

 

void I2C_EE_Init(void);

void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite);

uint32_t I2C_EE_ByteWrite(u8* pBuffer, u8 WriteAddr);

uint32_t I2C_EE_PageWrite(u8* pBuffer, u8 WriteAddr, u8 NumByteToWrite);

uint32_t I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead);

void I2C_EE_WaitEepromStandbyState(void);

/**

  ******************************************************************************

  * @file    bsp_i2c_ee.c

  * @author  STMicroelectronics

  * @version V1.0

  * @date    2013-xx-xx

  * @brief   i2c EEPROM(AT24C02)应用函数bsp

  ******************************************************************************

  * @attention

  *

  * 实验平台:秉火 F103-指南者 STM32 开发板 

  * 论坛    :http://www.firebbs.cn

  * 淘宝    :https://fire-stm32.taobao.com

  *

  ******************************************************************************

  */ 

 

#include "./i2c/bsp_i2c_ee.h"

#include "./usart/bsp_usart.h"

 

 

 

 

uint16_t EEPROM_ADDRESS;

 

static __IO uint32_t  I2CTimeout = I2CT_LONG_TIMEOUT;   

 

 

static uint32_t I2C_TIMEOUT_UserCallback(uint8_t errorCode);

 

 

/**

  * @brief  I2C I/O配置

  * @param  无

  * @retval 无

  */

static void I2C_GPIO_Config(void)

{

  GPIO_InitTypeDef  GPIO_InitStructure; 

 

/* 使能与 I2C 有关的时钟 */

EEPROM_I2C_APBxClock_FUN ( EEPROM_I2C_CLK, ENABLE );

EEPROM_I2C_GPIO_APBxClock_FUN ( EEPROM_I2C_GPIO_CLK, ENABLE );

    

  /* I2C_SCL、I2C_SDA*/

  GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SCL_PIN;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;        // 开漏输出

  GPIO_Init(EEPROM_I2C_SCL_PORT, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SDA_PIN;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;        // 开漏输出

  GPIO_Init(EEPROM_I2C_SDA_PORT, &GPIO_InitStructure);

}

 

 

/**

  * @brief  I2C 工作模式配置

  * @param  无

  * @retval 无

  */

static void I2C_Mode_Configu(void)

{

  I2C_InitTypeDef  I2C_InitStructure; 

 

  /* I2C 配置 */

  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

/* 高电平数据稳定,低电平数据变化 SCL 时钟线的占空比 */

  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

  I2C_InitStructure.I2C_OwnAddress1 =I2Cx_OWN_ADDRESS7; 

  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;

 

/* I2C的寻址模式 */

  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

/* 通信速率 */

  I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;

  

/* I2C 初始化 */

  I2C_Init(EEPROM_I2Cx, &I2C_InitStructure);

  

/* 使能 I2C */

  I2C_Cmd(EEPROM_I2Cx, ENABLE);   

}

 

 

/**

  * @brief  I2C 外设(EEPROM)初始化

  * @param  无

  * @retval 无

  */

void I2C_EE_Init(void)

{

 

  I2C_GPIO_Config(); 

 

  I2C_Mode_Configu();

 

/* 根据头文件i2c_ee.h中的定义来选择EEPROM的设备地址 */

#ifdef EEPROM_Block0_ADDRESS

  /* 选择 EEPROM Block0 来写入 */

  EEPROM_ADDRESS = EEPROM_Block0_ADDRESS;

#endif

 

#ifdef EEPROM_Block1_ADDRESS  

/* 选择 EEPROM Block1 来写入 */

  EEPROM_ADDRESS = EEPROM_Block1_ADDRESS;

#endif

 

#ifdef EEPROM_Block2_ADDRESS  

/* 选择 EEPROM Block2 来写入 */

  EEPROM_ADDRESS = EEPROM_Block2_ADDRESS;

#endif

 

#ifdef EEPROM_Block3_ADDRESS  

/* 选择 EEPROM Block3 来写入 */

  EEPROM_ADDRESS = EEPROM_Block3_ADDRESS;

#endif

}

 

 

/**

  * @brief   将缓冲区中的数据写到I2C EEPROM中

  * @param   

  * @arg pBuffer:缓冲区指针

  * @arg WriteAddr:写地址

  *     @arg NumByteToWrite:写的字节数

  * @retval  无

  */

void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)

{

  u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;

 

  Addr = WriteAddr % I2C_PageSize;

  count = I2C_PageSize - Addr;

  NumOfPage =  NumByteToWrite / I2C_PageSize;

  NumOfSingle = NumByteToWrite % I2C_PageSize;

 

  /* If WriteAddr is I2C_PageSize aligned  */

if(Addr

[1] [2] [3]

关键字:STM32  I2C读写  EEPROM

编辑:什么鱼 引用地址:http://www.eeworld.com.cn/mcu/ic467443.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM32F4 内部flash驱动(寄存器操作)
下一篇:STM32学习笔记001:点亮RGB

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

STM32开发笔记20: STM32L053R8T6的keil配置

单片机型号:STM32L053R8T6    使用STM32CubeMX生成STM32L053R8T6相关的应用程序代码后,使用Keil开发环境第1次下载的时候,提示如下错误,我使用F0和F4的单片机,没有遇到过。    仔细查看工程设置,原因在工程设置中,我们需加入相应的Flash配置信息,如下图所示,具体的选择,要根据单片机的类型,我们可以仔细查看数据手册。    但下载的时候,偶尔还会提示如下错误:    这件事情网上说了很多的解决方法,我自己测试,更改2处Keil的设置既可以解决,如下图所示。    此2处更改后,反复
发表于 2019-07-16
STM32开发笔记20: STM32L053R8T6的keil配置

STM32开发笔记21: USB驱动的移植

单片机型号:STM32L053R8T6    现在使用的STM32L053R8T6单片机带有USB接口,原先一直使用UART转USB芯片来完成USB功能的支持,现在这款单片机带了就希望使用以下。由于已经建立了自己的工程目录,再重新使用STM32CubeMX生成的工程文件,重新建立是不显示的,所以本文探索将USB驱动文件移植到自己项目中的方法,我使用的是USB的CDCD类,步骤如下:    1、使用STM32CubeMX使能USB,如下图所示:    2、设置时钟,USB需要48M时钟,使用内部和外部均可,我这里使用外部时钟。    3、生成工程文件
发表于 2019-07-16
STM32开发笔记21: USB驱动的移植

STM32开发笔记22: 手动添加驱动文件

单片机型号:STM32L053R8T6    我们可以通过STM32CubeMX生成工程代码,但是如果我们的工程已经建立完毕了,或者说我们在原有的工程上,开始新的项目设计,此时又需加入新的驱动,该如何呢?本文探讨其解决方法。    1、STM32CubeMX的驱动路径如下图所示,我们希望加入什么驱动,就直接将其对应的.c文件加入到工程中即可。    2、为了使该模块生效,我们还学将其使能。其使能宏,在stm32l0xx_hal_conf.h中,如下图所示。    3、上述工作完成后,我们就可以对工程进行编译了,至于驱动的具体调用方法,我们可以参看ST
发表于 2019-07-16
STM32开发笔记22: 手动添加驱动文件

STM32开发笔记23: 使用__weak修饰符

单片机型号:STM32L053R8T6在 HAL 库中,很多回调函数前面使用__weak 修饰符。 weak 顾名思义是“弱”的意思,所以如果函数名称前面加上__weak 修饰符,我们一般称这个函数为“弱函数”。加上了__weak 修饰符的函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,那么编译器就会执行__weak 声明的函数,并且编译器不会报错。 举个例子:我们打开工程模板,找到并打开文件stm32f4xx_hal.c 文件,里面定义了一个函数 HAL_MspInit,定义如下:__weak void 
发表于 2019-07-16

STM32开发笔记24:STM32L0低功耗设计——需求概述

单片机型号:STM32L053R8T6    这几篇日志将详细记录,自己应用stm32进行低功耗设计的全过程。    使用芯片:STM32L053R8T6    运行模式:        Range 1:电源电压限制在1.71-3.6V,CPU最大运行频率为32MHz。        Range 2:CPU最大运行频率为16MHz。        Range 3:CPU最大运行频率4.2MHz    低功耗模式: 
发表于 2019-07-16
STM32开发笔记24:STM32L0低功耗设计——需求概述

STM32开发笔记25:STM32L0低功耗设计-使用Keil和ST-Link下载程序

单片机型号:STM32L053R8T6    继续项目的开发工作,突然发现,程序不能够正常下载到单片机中了,提示如下图所示的错误,我使用的是keil和ST-Link。    这个问题在我第1次调试的时候发生过1次,我认为是我误操作将芯片烧坏了,因为当时又反复的焊接了一下芯片,也没有修好,就把这件事情放下了。    今天再次出现,自己感觉可能和低功耗有关,仔细查看刚刚下载的程序,里面上来程序就进入低功耗,没有任何退出语句,所以应该是CPU不响应下载命令了。    按照这种思路,先将单片机的复位引脚接地,然后点击下载按钮的同时,放开复位引脚,居然成功
发表于 2019-07-16
STM32开发笔记25:STM32L0低功耗设计-使用Keil和ST-Link下载程序

小广播

何立民专栏

单片机及嵌入式宝典

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

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved