EEPROM芯片(24c02)使用详解(I2C通信时序分析、操作源码分析、原理图分析)
创始人
2025-05-30 17:43:13

1、前言

(1)本文主要是通过24c02芯片来讲解I2C接口的EEPROM操作方法,包含底层时序和读写的代码;
(2)大部分代码是EEPROM芯片通用的,但是其中关于某些时间的要求,是和具体芯片相关的,和主控芯片和外设芯片都有关系,需要具体分析,但是逻辑顺序是不变的;

2、EEPROM介绍

(1)在嵌入式开发中,EEPROM的实际场景比闪存flash少很多。EEPROM芯片容量小,flash容量大,并且flash价格便宜;
(2)EEPROM的读写速度一般比flash慢;
(3)EEPROM大多是I2C接口,占用的引脚比flash少;
(4)EEPROM比flash掉电保存数据的时间更久,总体来说就是更稳定;
(5)参考博客:《嵌入式开发——EEPROM和FLASH的区别和优劣势》;

3、实际产品中EEPROM的使用场景

(1)使用场景:在嵌入式设备中,添加一块EEPROM,用于存放产品型号;
(2)使用的原因分析:
<1>首先可以做到一个程序兼容好几种产品,所以在程序的早期会需要知道当前的产品型号;
<2>将产品型号保存到EEPROM中,程序保存到flash中,升级的时候只会去重写flash而不会重写EEPROM,这样能保证升级失败也不会导致产品型号的丢失;
<3>EEPROM一般是在产品出厂的时候进行烧录,当然在程序正常运行后也会提高重写EEPROM的方式来进行设备的改制,读写EEPROM的方式都是研发人员或者设备生产人员才知道,不会对客户提高;

4、I2C时序分析

参考博客:《I2C通信协议详解和通信流程分析》;

5、根据I2C时序编写I2C通信代码

5.1、I2C通信开始和结束

在这里插入图片描述

/*******************************************************************************
* 函 数 名         : I2C_Start()
* 函数功能		   : 起始信号:在I2C_SCL时钟信号在高电平期间I2C_SDA信号产生一个下降沿
* 输    入         : 无
* 输    出         : 无
* 备    注         : 起始之后I2C_SDA和I2C_SCL都为0
*******************************************************************************/
void I2C_Start()
{I2C_SDA = 1;I2C_Delay10us();I2C_SCL = 1;I2C_Delay10us();//建立时间是I2C_SDA保持时间>4.7usI2C_SDA = 0;I2C_Delay10us();//保持时间是>4usI2C_SCL = 0;			I2C_Delay10us();		
}
/*******************************************************************************
* 函 数 名           : I2C_Stop()
* 函数功能	         : 终止信号:在I2C_SCL时钟信号高电平期间I2C_SDA信号产生一个上升沿
* 输    入           : 无
* 输    出         	 : 无
* 备    注           : 结束之后保持I2C_SDA和I2C_SCL都为1;表示总线空闲
*******************************************************************************/
void I2C_Stop()
{I2C_SDA = 0;I2C_Delay10us();I2C_SCL = 1;I2C_Delay10us();//建立时间大于4.7usI2C_SDA = 1;I2C_Delay10us();	}

5.2、I2C主设备读从设备函数

在这里插入图片描述

/*******************************************************************************
* 函 数 名           : I2cSendByte(uchar num)
* 函数功能 	         : 通过I2C发送一个字节。在I2C_SCL时钟信号高电平期间,
*                    * 保持发送信号I2C_SDA保持稳定
* 输    入           : num ,ack
* 输    出         	 : 0或1。发送成功返回0,发送失败返回-1
* 备    注           : 发送完一个字节I2C_SCL=0, 需要应答则应答设置为1,否则为0
******************************************************************************/
uchar I2C_SendByte(uchar dat, uchar ack)
{uchar a = 0,b = 0I2C_SCL = 0;	//保证在开始发送数据前时钟线是低电平for(a=0; a<8; a++)//要发送8位,从最高位开始{I2C_SDA = dat >> 7;	 //起始信号之后I2C_SCL=0,所以可以直接改变I2C_SDA信号dat = dat << 1;I2C_Delay10us();I2C_SCL = 1;I2C_Delay10us();//建立时间>4.7usI2C_SCL = 0;I2C_Delay10us();//时间大于4us		}I2C_SDA = 1;			// 主设备释放SDA线给从设备去操作I2C_Delay10us();I2C_SCL = 1;			// 主设备开始了第9个周期while(I2C_SDA && (ack == 1))//等待应答,也就是等待从设备把I2C_SDA拉低{b++;if(b > 200)	 //如果超过200us没有应答发送失败,或者为非应答,表示接收结束{I2C_SCL = 0;I2C_Delay10us();return -1;}}I2C_SCL = 0;I2C_Delay10us();return 0;		
}

(1)每次向数据线上发送一个bit,先发送字节的高位再发送字节的低位;
(2)发送的时序:时钟线保持低电平时,将数据发送到数据线上;拉高时钟线一段时间,这段时间是从设备从数据线上读数据;将时钟线拉低,进行下一个周期;

5.3、I2C主设备写从设备函数

/*******************************************************************************
* 函 数 名           : I2cReadByte()
* 函数功能	    	 : 使用I2c读取一个字节
* 输    入           : 无
* 输    出         	 : dat
* 备    注           : 接收完一个字节I2C_SCL=0
*******************************************************************************/uchar I2C_ReadByte()
{uchar a = 0,dat = 0;I2C_SDA = 1;	//主设备释放SDA线给从设备去操作		I2C_Delay10us();// 按道理这里应该有一个SCL = 0的I2C_SCL = 0;for(a=0; a<8; a++)//接收8个字节{I2C_SCL = 1;		// 通知从设备我要开始读了,可以放1bit数据到SDA了I2C_Delay10us();dat <<= 1;			// 读取的时候是高位在前的dat |= I2C_SDA;I2C_Delay10us();I2C_SCL = 0;		// 拉低,为下一个bit的周期做准备I2C_Delay10us();}return dat;		
}

(1)从设备已经将数据发送到数据线上;
(2)将时钟线由低变成高电平,在高电平期间读取数据线上的数据;
(3)将时钟线拉低,进行写一个读取周期;
总结:无论是主设备读/写从设备,时钟线都是主设备进行控制,所以整个I2C通信都是主设备在进行主导;

6、单片机和嵌入式设备的I2C通信区别

(1)单片机是利用GPIO模拟I2C协议进行通信。I2C时序的控制是编写单片机程序的人进行控制,不仅要考虑逻辑上的I2C协议,还需要阅读数据手册,关心时序图中高低电平的持续时间;
(2)嵌入式设备的Soc中集成了I2C控制器,由控制器来产生I2C通信时序,编写程序的人配置好I2C控制器,调用接口进行收发;如果有linux系统,则还会提高I2C驱动框架,软件开发人员基于I2C驱动框架进行编程;
总结:单片机开发需要考虑I2C通信的所有细节;而嵌入式Soc集成I2C控制器,向软件开发人员屏蔽了产生I2C通信时序的细节;

7、24c02的原理图分析

7.1、引脚介绍

引脚名称引脚作用
SCLI2C的时钟线
SDAI2C的数据线
E0、E1、E2决定从地址
WE写保护引脚,当引脚为高电平时不允许写,当引脚为低电平时允许写

7.2、从地址确定

在这里插入图片描述>(1)在发送从地址的一字节数据中,高7bit是从设备地址,最后一位表示本次主设备是要读还是写从设备;查阅24c02的数据手册可知,最低位为1表示读,最低位0表示写;
(2)7bit的从地址中,其中高4bit是固定的,最后3bit数据A0、A1、A2对应E0、E1、E2引脚的值,可以在硬件上通过接高/低电平来决定低3bit的值;
(3)查阅原理图可知,E0、E1、E2三个引脚都是接地,所以A0、A1、A2的值都是0;
总结:24c02芯片的从地址是0x1010000,读24c02芯片得命令是0xa1,写24c02芯片的命令是0xa0;

8、24c02的随机读数据操作函数

在这里插入图片描述

/*******************************************************************************
* 函 数 名         : unsigned char At24c02Read(unsigned char addr)
* 函数功能		   : 读取24c02的一个地址的一个数据
* 输    入         : 无
* 输    出         : 无
******************************************************************************/
unsigned char At24c02Read(unsigned char addr)
{unsigned char num;I2C_Start();I2C_SendByte(0xa0, 1); //发送写器件地址I2C_SendByte(addr, 1); //发送要读取的地址I2C_Start();I2C_SendByte(0xa1, 1); //发送读器件地址num=I2C_ReadByte(); //读取数据I2C_Stop();return num;	
}

9、24c02的字节写数据操作函数

在这里插入图片描述

/*******************************************************************************
* 函 数 名         : void At24c02Write(unsigned char addr,unsigned char dat)
* 函数功能		   : 往24c02的一个地址写入一个数据
* 输    入         : 无
* 输    出         : 无
******************************************************************************/
void At24c02Write(unsigned char addr,unsigned char dat)
{I2C_Start();I2C_SendByte(0xa0, 1);//发送写器件地址I2C_SendByte(addr, 1);//发送要写入内存地址I2C_SendByte(dat, 0);	//发送数据I2C_Stop();
}

推荐

给大家推荐一个学校嵌入式知识的网站,博主在大学时候学习嵌入式知识、找工作的时候都在用这个网站,网站里有C语言、Linux等等的笔试题、面试常问问题等等知识,无论是学习基础知识、面试刷题、交流工作经验都是不错的选择。大家一起进步,欢迎留言交流。
链接:学习神器跳转
在这里插入图片描述
在这里插入图片描述

相关内容

热门资讯

UNIX网络编程_socket... 这篇笔记记录什么socket的认识。 1 什么是socket socket可以看成是用户进程与内核网...
centos yum安装英伟达... 背景 最近在研究一个AI项目,需要用到英伟达显卡训练模型,centos默...
易华录拟5亿元向电科投资转让国... 易华录(300212)今日公告,公司拟以非公开协议转让方式向中电科投资控股有限公司(以下简称“电科投...
兰德链金科技有限公司发布数字黄... 在数字金融持续演进、资产信任机制面临重构的背景下,兰德链金科技有限公司(RandChain Gold...
第四章 需求弹性和供给弹性分析 需求弹性 需求弹性:一种商品的需求量对其影响因素变动的反应敏感程度;通...
夏春:大国博弈正在深刻改变全球... 夏春 系上善资本首席经济学家、中国首席经济学家论坛理事5月23日,北京大学经济学院上海校友会、复旦大...
【id:11】【20分】D. ... 题目描述 输入一个2*3的矩阵,将这个矩阵向左旋转90度后输出 比如现在有2*3矩阵...
学习Docker?一篇足以 文章目录 Docker介绍Docker优缺点容器化DockerfileDocker常用命令Docke...
赵伟:财政“前置”后该关注什么... 赵伟 贾东旭 侯倩楠(赵伟系申万宏源证券首席经济学家、中国首席经济学家论坛理事)摘要财政债务融资和支...
股价连创新高,成都银行杭州银行... 出品|达摩财经5月30日,A股三大指数下跌,银行板块逆势上涨,除了招商银行、上海银行、兴业银行,其余...
芦哲:老龄化进程下的消费变迁和... 芦哲李昌萌(芦哲系东吴证券首席经济学家、中国首席经济学家论坛成员)核心观点我国人口老龄化进程有所加速...
云桌面技术哪家强?亲身体验后才... 一. 简介 作为一家领先的云计算服务提供商,华为云提供了丰富的云计算服务,...
第一章 信息化知识 1、信息是客观事物状态和运动特征的一种普遍形式,信息的概念存在两个基本的层次ÿ...
高数重点总结 高数 公式不要去死记 配合训练题在训练中记忆 完成一下这些题目 高中函数图像回忆 与其记忆各种公式不...
手动创建数据集(csv文件),... 文章目录基础知识创建多级目录多级路径拼接打开文件并对文件进行读写创建CSV数据集的简单例子 基础知识...
特朗普宣布将把进口钢铁关税提至... 每经编辑|张锦河 据央视新闻,当地时间5月31日,欧盟委员会在一份声明中对美国宣布提高进口钢铝关税...
17万字 JUC 看这一篇就够... 今天我们继续来学习Java并发编程 Juc框架 ,把剩余部分学习完 17万字 JUC...
Python(白银时代)——继... 单继承 面向对象的三大特性 封装 根据 职责 将属性和方法封装到一个抽象类中 继承 实现代码的重...
03 dubbo源码学习_服务... 1. 服务暴露1.1 服务本地暴露1.2 服务远程暴露1.2.1 导出服务1.2.1.1 开启net...
外贸网站seo产品越多越好吗?... 外贸网站seo产品越多越好吗? 答案:是的。 没有一个搜索引擎不喜欢大量...
centos7安装mysql5... 目录1.下载mysql5.7的rpm安装包2.上传mysql安装包到centos7的系统下3.安装依...
蓝桥杯算法基础_排它平方数_课... 题目 203879 * 203879 = 41566646641 这有什么神奇呢࿱...
Tomcat自定义的端口查不到... 昨天再维护一个老项目的时候遇到一个很奇葩的问题,服务正常启动,日志正常输...
CSC访学、博士后、联培选择国... 2023年国家留学基金委(CSC)公派出国项目申报即将开始。知识人网小编...
【C++】String模拟实现... 文章目录string的基本了解string类常用接口string类对象的常见构造string类对象的...
悉尼“原始”房产64年首次挂牌... 《悉尼晨锋报》5月31日报道,在周六的拍卖会上,一个来自悉尼内西区的家庭以 689万澳元的价格购入一...
瑞幸多款饮品降价3元 公司回应 瑞幸咖啡多款产品降价引起了消费者的关注。 据大象新闻报道,5月30日,有消费者下单时发现瑞幸咖啡迈入...
福田又多了一家上市公司! 近日 知名在线保险中介机构 手回集团 正式登陆港股市场 5月30日, 手回集团有限公司(简称“手回集...
雷军:小米汽车全国销售门店达2... 【CNMO科技消息】5月31日,小米公司主要创始人、董事长雷军宣布,小米汽车全国销售门店达298家。...
SpringCloud笔记(H... 配置中心:SpringCloud Config 应用服务除了实现系统功能,...