EEPROM芯片(24c02)使用详解(I2C通信时序分析、操作源码分析、原理图分析)
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、引脚介绍
引脚名称 | 引脚作用 |
---|---|
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等等的笔试题、面试常问问题等等知识,无论是学习基础知识、面试刷题、交流工作经验都是不错的选择。大家一起进步,欢迎留言交流。
链接:学习神器跳转
相关文章:

EEPROM芯片(24c02)使用详解(I2C通信时序分析、操作源码分析、原理图分析)
1、前言 (1)本文主要是通过24c02芯片来讲解I2C接口的EEPROM操作方法,包含底层时序和读写的代码; (2)大部分代码是EEPROM芯片通用的,但是其中关于某些时间的要求,是和具体芯片相关的,和主控芯片和外设芯片都有关系&…...

Django4.0新特性-主要变化
Django 4.0于2021年12月正式发布,标志着Django 4.X时代的来临。参考Django 4.0 release notes | Django documentation | Django Python 兼容性 Django 4.0 将支持 Python 3.8、3.9 与 3.10。强烈推荐并且仅官方支持每个系列的最新版本。 Django 3.2.x 系列是最后…...
MySQL高级面试题整理
1. 执行流程 mysql客户端先与服务器建立连接Sql语句通过解析器形成解析树再通过预处理器形成新解析树,检查解析树是否合法通过查询优化器将其转换成执行计划,优化器找到最适合的执行计划执行器执行sql 2. MYISAM和InNoDB的区别 MYISAM:不支…...
【Java】面向对象三大基本特征
【Java】面向对象三大基本特征 1.封装 On Java 8:研发程序员开发一个工具类,该工具类仅向应用程序员公开必要的内容,并隐藏内部实现的细节。这样可以有效地避免该工具类被错误的使用和更改,从而减少程序出错的可能。彼此职责划分清晰&#x…...

蓝桥杯C++组怒刷50道真题(填空题)
🌼深夜伤感网抑云 - 南辰Music/御小兮 - 单曲 - 网易云音乐 🌼多年后再见你 - 乔洋/周林枫 - 单曲 - 网易云音乐 18~22年真题,50题才停更,课业繁忙,有空就更,2023/3/18/23:01写下 目录 👊填…...
Shell自动化管理 for ORACLE DBA
1.自动收集每天早上9点到晚上8点之间的AWR报告。 auto_awr.sh #!/bin/bash# Set variables ORACLE_HOME/u01/app/oracle/product/12.1.0/dbhome_1 ORACLE_SIDorcl AWR_DIR/home/oracle/AWR# Set date format for file naming DATE$(date %Y%m%d%H%M%S)# Check current time - …...

Unity学习日记13(画布相关)
目录 创建画布 对画布的目标图片进行射线检测 拉锚点 UI文本框使用 按钮 按钮导航 按钮触发事件 输入框 实现单选框 下拉菜单 多选框选项加图片 创建画布 渲染模式 第一个,保持画布在最前方,画布内的内容显示优先级最高。 第二个,…...

初阶C语言:冒泡排序
冒泡排序是一种简单的排序算法,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。1.冒泡排序关于冒泡排序我们在讲…...

带头双向循环链表
在前面我们学习了单链表,发现单链表还是有一些不够方便,比如我们要尾插,需要遍历一遍然后找到它的尾,这样时间复炸度就为O(N),现在我们引入双向带头链表就很方便了,我们先看看它的结构。通过观察,我们发现一…...

C#中的DataGridView中添加按钮并操作数据
背景:最近在项目中有需求需要在DataGridView中添加“删除”、“修改”按钮,用来对数据的操作以及显示。 在DataGridView中显示需要的按钮 首先在DataGridView中添加需要的列,此列是用来存放按钮的。 然后在代码中“画”按钮。 if (e.Column…...
WEB安全 PHP基础
WEB安全 PHP基础 PHP简述 PHP(全称:PHP:Hypertext Preprocessor,即"PHP:超文本预处理器")是一种通用开源脚本语言。 在一个php文件中可以包括以下内容: PHP 文件可包含文本、HTML、…...

基础篇:07-Nacos注册中心
1.Nacos安装部署 1.1 下载安装 nacos官网提供了安装部署教程,其下载链接指向github官网,选择合适版本即可。如访问受阻可直接使用以下最新稳定版压缩包:📎nacos-server-2.1.0.zip,后续我们也可能会更改为其他版本做更…...

端口镜像讲解
目录 端口类型 镜像方向 观察端口位置 端口镜像实现方式 流镜像 Vlan镜像 MAC镜像 配置端口镜像 配置本地观察端口 配置远程流镜像(基于流镜像) 端口镜像是指将经过指定端口的报文复制一份到另一个指定端口,便于业务监控和故障定位…...

图形视图框架QGraphicsScene(场景,概念)
QGraphicsScene 该类充当 QGraphicsItems 的容器。它与 QGraphicsView 一起使用,用于在 2D 表面上可视化图形项目,例如线条、矩形、文本甚至自定义项目。 QGraphicsScene具有的功能: 提供用管理大量数据项的高速接口传播事件到每一个图形项…...
ChatGPT 拓展资料: 强化学习-SARSA算法
强化学习是一种机器学习技术,它关注的是在特定环境中,如何最大化一个智能体(agent)的累积奖励(reward)。强化学习算法会根据当前状态和环境的反馈来选择下一个动作,不断地进行试错,从而优化智能体的行为。 SARSA是一种基于强化学习的算法,它可以用于解决马尔可夫决策…...

SpringJDBC异常抽象
前言spring会将所有的常见数据库的操作异常抽象转换成他自己的异常,这些异常的基类是DataAccessException。DataAccessException是RuntimeException的子类(运行时异常),是一个无须检测的异常,不要求代码去处理这类异常SQLErrorCodeSQLExcepti…...
我在字节的这两年
前言 作为脉脉和前端技术社区的活跃分子,我比较幸运的有了诸多面试机会并最终一路升级打怪如愿来到了这里。正式入职时间为2021年1月4日,也就是元旦后的第一个工作日。对于这一天,我印象深刻。踩着2020年的尾巴接到offer,属实是过了一个快乐…...
Button(按钮)与ImageButton(图像按钮)
今天给大家介绍的Android基本控件中的两个按钮控件,Button普通按钮和ImageButton图像按钮; 其实ImageButton和Button的用法基本类似,至于与图片相关的则和后面ImageView相同,所以本节只对Button进行讲解,另外Button是TextView的子类,所以TextView上很多属性也可以应用到B…...
Chrome插件开发-右键菜单开启页面编辑
开发一个执行js脚本改变页面DOM的Chrome插件,manifest_version版本为3。 Chrome插件基本知识 Chrome插件通常由以下几部分组成: manifest.json 该文件为必须项,其它文件都是可选的。该文件相当于插件的meta信息,包含manifest版…...

指针进阶(上)
内容小复习🐱: 字符指针:存放字符的数组 char arr1[10]; 整型数组:存放整型的数组 int arr2[5]; 指针数组:存放的是指针的数组 存放字符指针的数组(字符指针数组) char* arr3[5]; 存放整型指针的数组(整型指针数组) int* arr[6]; 下面进入学习了哦~&…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...

dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

WebRTC调研
WebRTC是什么,为什么,如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...