【单片机】14-I2C通信之EEPROM

1.EEPROM概念

1.EEPROM

1.1 一些概念

(1)一些概念:ROM【只读存储器---硬盘】,RAM【随机访问存储器--内存】,PROM【可编程的ROM】,EPROM【可擦除ROM】,EEPROM【电可擦除ROM】

1.2 为什么需要EEPROM

单片机内部的ROM只能在程序下载时进行擦除和改写,但是程序运行本身是不能改写的。

单片机内部的RAM中的数据程序运行时可以改,但是掉电就丢失了。

有时候我们需要有一些数据存在系统中,要求掉电不丢失,而且程序还要能改。所以内部ROM和RAM都不行。【这时候系统需要一块EEPROM】

1.3 EEPROM和flash的区别与联系

单片机解密中Flash和EEPROM的区别-电子工程世界

1.4 EEPROM存在系统中的2种形式

1:内置在单片机内部

2:外部扩展

2.EEPROM如何编程

1.I2C接口底层时序

底层:CPU和I2C的接口

2.器件定义的寄存器读写时序

上层:器件时序

2.AT24C02原理图和数据手册

1.接线确定

查看SCL和SDA无其他接线影响

SCL对应P2.1 SDA对应P2.0

2.数据手册理论

立创商城_一站式电子元器件采购自营商城_现货元器件交易网-嘉立创电子商城

24c02中文官方资料手册pdf - 百度文库

1.芯片的基本信息

类似于一个主持人叫A说话,其他人就不可以说话,但是其他人可以听到主持人和A说话,但是不可以回应。 --广播式

主设备:51单片机---发送器

从设备:24Cxxx---接收器

2.I2C从地址确定

每一个I2C都有从地址

3.I2C底层时序

起始信号:

发送字节:一般第一个是从设备的地址【因为我们在通话之前,要先发送要进行通话的地址,设备都与自己的地址是否相同,如果相同则响应;如果不同,则丢弃】

读取字节:

停止信号:

3.I2C总结

(1)主CPU和其附属芯片之间最常用的接口,尤其是各种传感器,因此在物联网时代非常重要

(2)三根线:SCL,SDA,GND,串行,电平式

(3)总线式结构:可以一对多,总线上可以挂上百个器件【一个主设备,多个从设备】,用【从地址】来区分--主设备不需要地址

(4)主从式,由主设备来发起通信及总线仲裁,从设备被动响应

(5)通信速率一般(kbps级别),不合适语音,视频等信息类型

4.I2C总线协议定义

起始信号

终止信号

应答信号

从设备回复主设备,判断从设备是否得到数据。

可以设置是否要进行”应答信号“【可有可无】

3.I2C低层时序图和程序

1.起始信号和结束信号

SCL和SDA交互进行判断

(1)起始信号:SCL保持高时,SDA有一个从高到低(下降沿)
(2)结束信号:SCL保持高时,SDA有一个从低到高(上升沿)

起始信号

/*******************************************************************************
* 函 数 名       : iic_start
* 函数功能		 : 产生IIC起始信号
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void iic_start(void)
{IIC_SDA=1;//如果把该条语句放在SCL后面,第二次读写会出现问题delay_10us(1);IIC_SCL=1;delay_10us(1);IIC_SDA=0;	//当SCL为高电平时,SDA由高变为低,表示起始信号delay_10us(1);IIC_SCL=0;//钳住I2C总线,准备发送或接收数据delay_10us(1);
}

终止信号

/*******************************************************************************
* 函 数 名         : iic_stop
* 函数功能		   : 产生IIC停止信号   
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void iic_stop(void)
{	IIC_SDA=0;//如果把该条语句放在SCL后面,第二次读写会出现问题delay_10us(1);IIC_SCL=1;delay_10us(1);IIC_SDA=1;	//当SCL为高电平时,SDA由低变为高,表示结束信号delay_10us(1);			
}

2.I2C发送一个字节

传输”0“或应答位(A)

传输”1“或应答位(/A)

/*******************************************************************************
* 函 数 名         : iic_write_byte
* 函数功能		   : IIC发送一个字节 
* 输    入         : dat:发送一个字节
* 输    出         : 无
*******************************************************************************/
void iic_write_byte(u8 dat)
{                        u8 i=0; //为了保证时序正确,这里要加上    //当SDA将数据放好才可以将SCL置为高电平IIC_SCL=0; for(i=0;i<8;i++)	//循环8次将一个字节传出,先传高再传低位{              if((dat&0x80)>0) IIC_SDA=1;elseIIC_SDA=0;dat<<=1; //将次高位移动到最高位	  delay_10us(1);  IIC_SCL=1; //产生一个上升沿delay_10us(1); IIC_SCL=0; //产生一个下降沿	delay_10us(1);}	 
}

 

(1)I2C发送和接收字节时,都是从高位开始的

3.应答位处理

在接收完8位bit后,在第9个时间周期

应答处理:SDA变低【AT2402拉低】。

如果我们去检测,如果此时SDA为低电平,则表示已经被拉低,则表示已经响应到;如果SDA为高电平,则表示未能响应到。

 产生ACK应答  

/*******************************************************************************
* 函 数 名         : iic_ack
* 函数功能		   : 产生ACK应答  
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void iic_ack(void)
{IIC_SCL=0;IIC_SDA=0;	//SDA为低电平delay_10us(1);IIC_SCL=1;   //将SCL拉高delay_10us(1);IIC_SCL=0;  //在将SCL拉低
}

 产生NACK非应答 

/*******************************************************************************
* 函 数 名         : iic_nack
* 函数功能		   : 产生NACK非应答  
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void iic_nack(void)
{IIC_SCL=0;IIC_SDA=1;	//SDA为高电平delay_10us(1);IIC_SCL=1;delay_10us(1);IIC_SCL=0;	
}

等待应答信号到来 

/*******************************************************************************
* 函 数 名         : iic_wait_ack
* 函数功能		   : 等待应答信号到来   
* 输    入         : 无
* 输    出         : 1,接收应答失败0,接收应答成功
*******************************************************************************/
u8 iic_wait_ack(void)
{u8 time_temp=0;IIC_SCL=1;delay_10us(1);while(IIC_SDA)	//等待SDA为低电平{time_temp++;if(time_temp>100)//超时则强制结束IIC通信{	iic_stop();return 1;	}			}IIC_SCL=0;return 0;	
}

4.I2C接收一个字节

释放总线

在51单片机中,SDA=1就是释放总线【相当于主持人把话筒给嘉宾】;在其他更高级的单片机(比如STM32)这里的处理还会不一样。【因为拉高,则可以拉低(接地);但是拉低了,但是无法拉高】

为什么SDA=1就是释放总线??是因为当51单片机把引脚拉高时,从设备可以选择再把引脚拉高或者拉低;但是当51单片机把这个引脚拉低(接地)后,从设备也没有办法把这个引脚拉高了。

unsigned char IIC_ReadByte()
{unsigned char a=0,dat=0;//释放总线IIC_SDA=1;  //起始和发送一个字节之后IIC_SCL都是0IIC_delay();//按道理来说这里应该有一个SCL=0的for(a=0;a<8;a++){IIC_SCL=1;//通知从设备我要开始读了,可以放bit数据到SDA了IIC_delay();dat<<=1; //读取的时候高位再前dat|=IIC_SDA;IIC_delay();IIC_SCL=0;// 拉低为下一个bit周期做准备ICC_delay();}return dat;
}

4.EEPROM读写测试

1.  器件寻址

(1)从器件的地址是由器件自身定义的,不同的从器件的地址的定义方式是不同的,要查具体的芯片数据手册来确定

(2)同一个I2C网络中只有一个主设备,但是从设备可以有多个。这多个从设备的地址不能相同。【硬件工程师必须保证这一点。因为从地址是不能通过软件设定的】

(3)A0,A1,A2----2的三次方=8【表示最多只能接8个EEPROM】

从CPU的角度来分析24C02的地址定义【如果不是从CPU角度看则得出结果不一样】

        从设备地址是:读地址:0xa1

                                 写地址:0xa0

2.24C02写高层时序

写操作时序

start-send_byte(从地址)--send_byte(字节地址)---send_byte(写入数据)

 字节写

/*******************************************************************************
* 函 数 名         : at24c02_write_one_byte
* 函数功能		   : 在AT24CXX指定地址写入一个数据
* 输    入         : addr:写入数据的目的地址 dat:要写入的数据
* 输    出         : 无
*******************************************************************************/
void at24c02_write_one_byte(u8 addr,u8 dat)
{				   	  	    																 iic_start();  iic_write_byte(0XA0);	//发送写命令,发送写器件地址	    	  iic_wait_ack();	//表示要接收应答 iic_write_byte(addr);	//发送写地址   iic_wait_ack(); //表示要接收应答 	 										  		   iic_write_byte(dat);	//发送字节    							   iic_wait_ack();  		    	   iic_stop();				//产生一个停止条件delay_ms(10);	 
}

页写

/*******************************************************************************
* 函 数 名         : at24c02_write_one_byte
* 函数功能		   : 在AT24CXX指定地址写入一个数据
* 输    入         : addr:写入数据的目的地址 dat:要写入的数据
* 输    出         : 无
*******************************************************************************/
void at24c02_write_one_byte(u8 addr,u8 dat[],u8 i)
{				   	u8 j;  	    																 iic_start();  iic_write_byte(0XA0);	//发送写命令,发送写器件地址	    	  iic_wait_ack();	//表示要接收应答 iic_write_byte(addr);	//发送写地址   iic_wait_ack(); //表示要接收应答 	 										  		   for(j=0;j<i;i++){iic_write_byte(dat[i]);	//发送字节    							   iic_wait_ack();}  		    	   iic_stop();				//产生一个停止条件delay_ms(10);	 
}

3. 24C02读高层时序

/*******************************************************************************
* 函 数 名         : at24c02_read_one_byte
* 函数功能		   : 在AT24CXX指定地址读出一个数据
* 输    入         : addr:开始读数的地址 
* 输    出         : 读到的数据
*******************************************************************************/
u8 at24c02_read_one_byte(u8 addr)
{				  u8 temp=0;		  	    																 iic_start();  iic_write_byte(0XA0);	//发送写命令	   iic_wait_ack(); iic_write_byte(addr); 	//发送写地址  iic_wait_ack();	    iic_start();  	 	   iic_write_byte(0XA1); 	//进入接收模式         			   iic_wait_ack();	 temp=iic_read_byte(0);	//读取字节		   iic_stop();				//产生一个停止条件    return temp;			//返回读取的数据
}

4.复合格式

1.先发送在接收

2.字节写+随机读

4.加入串口输出代码

/*******************************************************************************
* 实验名			  : EEPROM实验
* 使用的IO	    : 
* 实验效果      : 按K1保存显示的数据,按K2读取上次保存的数据,按K3显示数据加一,
*按K4显示数据清零。
*	注意					:由于P3.2口跟红外线共用,所以做按键实验时为了不让红外线影响实验效果,最好把红外线先
*取下来。
*
*********************************************************************************/
#include <reg51.h>
#include "at24c02.h"
#include "uart.h"void delay20ms(void)   //误差 -0.000000000005us
{unsigned char a,b,c;for(c=1;c>0;c--)for(b=222;b>0;b--)for(a=40;a>0;a--);
}/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/void main()
{unsigned char i;unsigned char addr;	unsigned char src_data[] = "()ab#cde!fg1234567";	unsigned char buf[8] = "ABCDEFGH";uart_init();
/*for (i=0; i<128; i++){uart_send_byte(i);}while (1);
*/// 先随便找一堆数据,譬如"abcdefg1234567-_-*&%@/\"// 把这些写入EEPROM的特定地址中// 然后读EEROM的这些地址,读出后通过串口打印出来看是不是我们写入的uart_send_byte('%');addr = 0;for (i=0; i<8; i++){At24c02Write(addr, src_data[i]);delay20ms();addr++;}//先打印出buf//如果这里没有给buf初始化,则打印会出现问题for (i=0; i<8; i++){uart_send_byte(buf[i]);}//分割for (i=0; i<20; i++){uart_send_byte('-');}// 读出测试addr = 0;for (i=0; i<8; i++){buf[i] = At24c02Read(addr);delay20ms();addr++;}//将数据打印出来for (i=0; i<8; i++){uart_send_byte(buf[i]);}while (1);// 进一步测试// 先写入一些特定内容,然后关机断电;然后改代码为读出并打印显示看内容}		

问题分析

(1)通过调试发现程序跑飞了,经检测发现uart中没有关中断

(2)读出内容不对,怀疑是EEPROM经不起快速的连续读写,所以在读和写之间加入20ms的delay,测试后发现读写正确了

(3)定义了局部变量没有初始化,程序中直接去通过串口输出,结果导致程序

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/147883.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

接口测试入门实践

简单接口搭建(表单/REST) 五步教会你写接口 首先要安装flask包: pip install flask 从flask中导入Flask类和request对象: from flask import Flask, request从当前模块实例化出一个Flask实例:appFlask(__name__)编写一个函数来处理请求 从请求对象中获取数据:arequest.values.…

LeetCode【121. 买卖股票的最佳时机】

你才不是什么小人物&#xff0c;你在我这里&#xff0c;是所有的天气和心情。 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一…

【Leetcode】滑动窗口合集

这里写目录标题 209.长度最小的子数组题目思路代码 3. 无重复字符的最长子串&#xff08;medium&#xff09;题目思路 11. 最大连续 1 的个数 III题目思路 1658. 将 x 减到 0 的最⼩操作数题目思路代码 904. 水果成篮题目思路代码 438.找到字符串中所有字母的异位词题目思路代码…

二十八、高级IO与多路转接之select

文章目录 一、五种IO模型&#xff08;一&#xff09;阻塞IO:&#xff08;二&#xff09;非阻塞IO:&#xff08;三&#xff09;信号驱动IO:&#xff08;四&#xff09;IO多路转接:&#xff08;五&#xff09;异步IO: 二、高级IO重要概念&#xff08;一&#xff09;同步通信 vs 异…

【STL】用哈希表(桶)封装出unordered_set和unordered_map

⭐博客主页&#xff1a;️CS semi主页 ⭐欢迎关注&#xff1a;点赞收藏留言 ⭐系列专栏&#xff1a;C进阶 ⭐代码仓库&#xff1a;C进阶 家人们更新不易&#xff0c;你们的点赞和关注对我而言十分重要&#xff0c;友友们麻烦多多点赞&#xff0b;关注&#xff0c;你们的支持是我…

pytorch_神经网络构建1

文章目录 pytorch简介神经网络基础分类问题分析:逻辑回归模型逻辑回归实现多层神经网络多层网络搭建保存模型 pytorch简介 为什么神经网络要自定义数据类型torch.tensor? tensor可以放在gpu上训练,支持自动求导,方便快速训练,同时支持numpy的运算,是加强版,numpy不支持这些 为…

python二次开发CATIA:导出Excel格式BOM

BOM是英文Bill of Material的缩写&#xff0c;中文翻译为“物料清单”&#xff0c;也称为产品结构表或产品结构树。它是计算机可以识别的产品结构数据文件&#xff0c;也是ERP的主导文件。BOM使系统识别产品结构&#xff0c;也是联系与沟通企业各项业务的纽带。ERP系统中的BOM的…

多线程经典代码案例及手动实现

目录 一.线程和多线程 二. 多线程的经典的代码案例 1.单例模式 2.阻塞队列 (1)概念介绍 (2)生产者消费者模型 (3)手动实现阻塞队列 (4)代码解释及问题分析 3.定时器 (1)概念介绍 (2)思路分析 (3)手动实现定时器 (4)代码解释及问题分析 问题一:优先级 问题二 :忙等…

基于SSM的电动车上牌管理系统(有报告)。Javaee项目。

演示视频&#xff1a; 基于SSM的电动车上牌管理系统&#xff08;有报告&#xff09;。Javaee项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring SpringM…

Java基本数据类型和变量

目录 一、基本数据类型 1.1 整型 1.1.1 byte 1.1.2 short 1.1.3 int 1.1.4 long 1.2 浮点型 1.2.1 float 1.2.2 double 1.3 字符型 1.4 布尔型 二、变量 2.1 变量的概念 2.2 语法格式 2.3 整型变量 2.3.1 整型变量 2.3.2 长整型变量 2.3.3 短整型变量 2.3.…

MySQL之DQL

DQL是数据查询语言 SELECT语句 语法&#xff1a; SELECT {*,列名&#xff0c;函数等} FROM 表名;SELECT *&#xff1a;表示匹配所有列 FROM :提供数据源 例如:查询student表的所有记录 SELECT * FROM student;例如&#xff1a;查询学生姓名和地址&#xff1a; SELECT Stud…

学信息系统项目管理师第4版系列16_资源管理过程

1. 组建项目团队&#xff0c;建设项目团队和管理项目团队属于执行过程组 1.1. 【高22上选21】 1.1.1. 【高21上选25】 1.2. 3版 2. 【高19上案三】 2.1. 【高18上案三】 2.2. 【高23上案一】 3. 规划资源管理 3.1. 定义如何估算、获取、管理和利用团队以及实物资源的过…

mstsc无法保存RDP凭据, 100%生效

问题 即使如下两项都打勾&#xff0c;其还是无法保存凭据&#xff0c;特别是连接Ubuntu (freerdp server)&#xff1a; 解决方法 网上多种复杂方法&#xff0c;不生效&#xff0c;其思路是修改后台配置&#xff0c;以使mstsc跟平常一样自动记住凭据。最后&#xff0c;如下的…

斯坦福数据挖掘教程·第三版》读书笔记(英文版)Chapter 10 Mining Social-Network Graphs

来源&#xff1a;《斯坦福数据挖掘教程第三版》对应的公开英文书和PPT。 Chapter 10 Mining Social-Network Graphs The essential characteristics of a social network are: There is a collection of entities that participate in the network. Typically, these entiti…

Python学习笔记之分支结构与循环结构

Python学习笔记之分支结构与循环结构 一、分支结构 使用关键字if、elif、else 练习1&#xff1a;使用分支结构实现分段函数求值 """分段函数求值""" x float(input("x "))if x > 1:y 3 * x - 5 elif x < -1:y 5 * x 3…

2023/10/4 -- ARM

今日任务&#xff1a;QT实现TCP服务器客户端搭建的代码&#xff0c;现象 ser&#xff1a; #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);server new QTcpSe…

免费、丰富、便捷的资源论坛——Yiove论坛,包括但不限于阿里云盘、夸克云盘、迅雷云盘等等

引言 目前资源的数量达到了60000&#xff0c;六万多的资源意味着在这里几乎可以找到任何你想要的资源。 当然&#xff0c;资源并不是论坛的全部&#xff0c;其中还包括了技术交流、福利分享、最新资讯等等。 传送门&#xff1a;YiOVE论坛 - 一个有资源有交流&#xff0c;有一…

PCL 计算点云中值

目录 一、算法原理2、主要函数二、代码实现三、结果展示四、参考链接本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、算法原理 计算点云坐标的中值点,首先对点云坐标进行排序,然后计算中值。如果点云点的个数为奇数…

计组—— I/O系统

&#x1f4d5;&#xff1a;参考王道课件 目录 一、I/O系统的基本概念 1.什么是“I/O”&#xff1f; ​编辑2.主机如何和I/O设备进行交互&#xff1f; 3.I/O控制方式 &#xff08;1&#xff09;程序查询方式 &#xff08;2&#xff09;程序中断方式 &#xff08;3&#x…

号卡推广管理系统源码/手机流量卡推广网站源码/PHP源码+带后台版本+分销系统

源码简介&#xff1a; 号卡推广管理系统源码/手机流量卡推广网站源码&#xff0c;基于PHP源码&#xff0c;而且它是带后台版本&#xff0c;分销系统。运用全新UI流量卡官网系统源码有后台带文章。 这个流量卡销售网站源码&#xff0c;PHP流量卡分销系统&#xff0c;它可以支持…