EEPROM芯片(24c02)使用详解(I2C通信时序分析、操作源码分析、原理图分析)

2023-11-02

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.7us
	I2C_SDA = 0;
	I2C_Delay10us();//保持时间是>4us
	I2C_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.7us
	I2C_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 = 0

	I2C_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.7us
		I2C_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、引脚介绍

引脚名称 引脚作用
SCL I2C的时钟线
SDA I2C的数据线
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等等的笔试题、面试常问问题等等知识,无论是学习基础知识、面试刷题、交流工作经验都是不错的选择。大家一起进步,欢迎留言交流。
链接:学习神器跳转
在这里插入图片描述
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

EEPROM芯片(24c02)使用详解(I2C通信时序分析、操作源码分析、原理图分析) 的相关文章

随机推荐

  • 点云高度归一化处理(附 python 代码)

    gt 由于不同地物之间存在着高程的差异 为了去除地形起伏对点云数据高程值的影响 所以需要根据提取出的地面点进行点云归一化处理 这一步是很多算法的基础 可以提高后续点云分类或分割的准确度等 如下图所示 gt 归一化的过程其实相对简单 遍历每一
  • 贪心算法力扣刷题练习(含思路与题解)

    贪心算法 保证每次操作都是局部最优 使得最终结果也是全局最优的 需要找到贪心的策略 使得每次的最优能保证全局最优 通常需要排序 根据排序需求 自定义比较函数 sort a begin a end vector
  • protobuf c++编程笔记

    文章目录 字段内容的定义 修饰符 字段类型 引用方式 不同字段的方法 1 optional修饰的基本类型 2 optional修饰的对象类型 3 repeated修饰的基本类型 4 repeated修饰的对象类型 序列化 反序列化 字段内容
  • Vue + 高德地图 + 三维模型

    一 创建高德的kek和密钥 根据需求选择服务平台 我选择的是web端 JS API 二 在vue中引入高德地图 在public文件下找到index html文件引入你的key值 参考 https lbs amap com demo jsap
  • Could not resolve com.android.tools.build:gradle:4.0.0.

    打开别人发过来的项目的时候gradle一直下载不下来 然后报错 尝试了很多办法 最后在用户变量种添加 Android SDK ROOT 自己的Android SDK路径 gradle 下载成功 可能遇到的具体错误问题不一样仅供参考
  • CentOS8基础篇15:防火墙命令配置

    一 防火墙服务 1 启动 关闭 重启防火墙服务 systemctl start firewalld service systemctl stop firewalld service systemctl restart firewalld s
  • ES 查询不稳定现象及解决方案

    问题描述 对于相同的查询语句 ES 查询返回不同的检索内容 示例 1 filter match content 宝骏510 order score size 10 在上面的示例中可以看到推荐句子的第二句和第三句的顺序发生了变化 产生原因 官
  • spring事务的隔离级别。如何避免脏读或者幻读

    事务隔离级别为四个等级 默认是数据库的隔离级别 需要去数据库查询一下隔离级别 1 查看当前会话隔离级别 select tx isolation 2 查看系统当前隔离级别 select global tx isolation 隔离级别 Iso
  • unity MeshCollider组件

    在应用MeshCollider组件中的一个属性 Convex 这个功能很好用 但是他也是有一个坑在里面 他的好处 当你点击之后他会自动根据模型自动生成一个碰撞器 这个是不规则的碰撞器 他的坏处 没有点击 Convex 时候 比如当你有一个物
  • Commond:命令模式

    命令模式即将请求封装为对象Commond 执行者可以执行多个操作 即执行者才是操作真正的实现者 设其为操作0 9 每个操作都封装了一个对应的Commond类 当该Commond被调用时 Commond会令执行者执行其对应的操作 用户需要执行
  • 文化:测试团队建设--读书会

    如何做管理 曾经很迷茫 一路跌跌撞撞 慢慢的发现了 想要做好管理 团队文化和团队建设也是管理的重要环节 其实在一个大的测试团队里 有很多测试同学相互之间是没有交集的 如何让大家熟悉团结起来 团队建设是其中一个方法 下面和大家分享 团队建设
  • Linux进程通信——消息队列

    Linux进程通信 消息队列 消息队列概述 消息队列发送端 消息队列接收端 补充key值作用 消息队列互相发送接收 消息队列概述 消息队列是存在Linux内核中 以链表形式来存消息 一个消息队列由一个标识符 即队列ID 来标识 用户进程可以
  • JS技巧---Set数组去重

    在 ES6 中 引入了一个新的数据结构类型 Set 而 Set 与 Array 的结构是很类似的 且 Set 和 Array 可以相互进行转换 数组去重 也算是一个比较常见的前端面试题了 方法有很多种 这里不多赘述 下面我们看看用 Set
  • 互联网黑话

    互联网岗位的口头禅 1 各个岗位的口头禅 产品岗 没排上期 下个版本 设计岗 别戳屏幕 研发岗 实现不了 测试岗 醒醒 有bug 数据岗 你们要这个干啥 运维岗 磁盘满了 网络抖动 程序员终极大法 删库跑路 法务岗 这个有风险 公关岗 建议
  • 深入云存储系统Swift核心组件:Ring实现原理剖析

    深入云存储系统Swift核心组件 Ring实现原理剖析 简介 OpenStack是一个美国国家航空航天局和Rackspace合作研发的开源云计算项目 并成为Apache下的一个重要开源项目 目前已经发展到了180家公司参与其中 OpenSt
  • 探索MVVM -- 体会DataBinding的魅力

    前言 本文用到的demo是以 ONE 一个 的API为基础 模仿其功能实践一下MVVM的用法 以感受MVVM架构为主要目的 并未完全模仿其功能 代码结构借鉴了Google的sample 虽然谷歌今年出了一个架构组件指南 来指导开发者构建Ap
  • pdf加密在线破解

    http www unlock pdf com
  • wsl+ zsh + oh-my-zsh配置

    wsl zsh oh my zsh配置 经常在windows平台办公 配置一些开发环境时在Linux中会比较简单 参照了在Linux服务器中的配置 同步在WSL中 测试平台 WIN10 X64专业版 V1903 只支持WSl V1 WSL
  • Unity编辑器扩展之Excel表转CS文件(C#类)

    前言 这里我们需要理解动态生成CS文件的一些基础 https blog csdn net qq 37254346 article details 103216761 怎样读取Excel表这里就不说了 Excel表转CS文件 这是我们需要转的
  • EEPROM芯片(24c02)使用详解(I2C通信时序分析、操作源码分析、原理图分析)

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