十三、51单片机之EEPROM(I2C)

这篇具有很好参考价值的文章主要介绍了十三、51单片机之EEPROM(I2C)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、EEPROM简介

(1)存储设备类型:ROM、RAM、PROM(可编程ROM)、EPROM(可擦除ROM)、EEPROM(电可擦除ROM)。

(2)为什么需要EEPROM?

某些数据内容我们需要掉电不丢失且在程序运行中可以修改这些数据内容,这就需要用到EEPROM。

(3)EEPROM和flash(闪存)的区别。

EEPROM是按功能分类的一种存储设备类型;flash是存储设备生产的一种工艺。EEPROM就可能采用了flash工艺,常见的U盘也是采用flash工艺。

(4)这里的EEPROM芯片具体型号是AT24C02,采用I2C时序进行读写。

2、AT24C02数据手册

十三、51单片机之EEPROM(I2C)

(1)引脚介绍

A0、A1、A2 I2C总线上器件地址
GND 电源地
VCC 电源正极
WP 写保护引脚
SCL 串行时钟输入
SDA 串行地址和数据输入/输出

(2)AT24C02中02表示容量。

3、原理图

EEPROM芯片使用AT24C02。

十三、51单片机之EEPROM(I2C)

(1)E0、E1、E2标识I2C总线的从地址。

(2)VDD表示电源正,VSS接电源地。

(3)WE(Write Enable)写保护引脚。(上划线代表低电平使能,低电平状态才能写)

(4)SDA(Serial Data)串行数据)引脚接单片机引脚P2^0。

(5)SCL(Serial Clock 串行时钟)引脚接单片机引脚P2^1。

4、I2C总结

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

(2)三根线:GND、SCL、SDA,串行通信(只有一根数据传输线),电平式通信(相对于差分信号)。

(3)总线式结构,可以一对多,总线上可以挂上百个器件,用从地址来区分。

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

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

5、EEPROM编程思路

主要包含下面两部分:

(1)I2C接口底层时序。起始信号、停止信号、发送字节、读取字节。

(2)EEPROM的寄存器读写时序。

6、I2C从设备的地址

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

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

(3)分析原理图和AT24C02的数据手册,得出: 从设备地址是:读地址:0xA1,写地址:0xA0.

十三、51单片机之EEPROM(I2C)

7、示例程序

十三、51单片机之EEPROM(I2C)

(1)app.c文件

#include <reg52.h>
#include "drv_uart.h"
#include "at24c02.h"
#include "intrins.h"


/*函数声明*/
void Delay20ms();		  //@12.000MHz
void Delay500ms();		//@12.000MHz


void main(void)
{
	unsigned char  ReadData[10] = "aaaaaaaaaa";  //保存从EP读取的数据
	unsigned char WriteData[10] = "zjd6661234";  //保存写入EP的数据
	unsigned char AddrBase = 0x05;               //EP内存操作基地址
	unsigned char i = 0;                         //用于for循环
	
	UartInit();		                        //串口初始化
	/*注释写操作,检测断电是否丢失*/
	for(i=0; i<10; i++)
	{
		AT24C02_WriteByte(AddrBase+i,WriteData[i]);
		Delay20ms();
	}
	
	for(i=0; i<10; i++)
	{
		ReadData[i] = AT24C02_ReadByte(AddrBase+i);
		Delay20ms();
	}
	
	for(i=0; i<10; i++)
	{
		UartSendByte(ReadData[i]);
	}
	while(1)
	{
		UartSendString("hello world.\r\n");
		Delay500ms();
	}
}


void Delay20ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 39;
	j = 230;
	do
	{
		while (--j);
	} while (--i);
}


void Delay500ms()		//@12.000MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 205;
	k = 187;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}







(2)drv_i2c.c

#include "drv_i2c.h"
#include <intrins.h>
#include <reg52.h>

sbit SCL = P2^1;      
sbit SDA = P2^0; 

/*函数声明*/
void Delay10us();		//@12.000MHz


/*
 *功能:I2C总线起始信号   
 *参数:无
 *返回值:无
 *注:
 (1)起始信号:在SCL时钟信号在高电平期间SDA信号产生一个下降沿
 (2)起始之后SDA和SCL都为0
 */
void I2C_Start()
{
	SCL = 1;
	SDA = 1;   
	Delay10us();
	SDA = 0;      /*SDA下降延*/
	Delay10us();
	SCL = 0;      /*为后续读写做好准备*/
	Delay10us();
}


/*
 *功能:I2C总线停止信号
 *参数:无
 *返回值:无
 *注:
 (1)终止信号:在SCL时钟信号高电平期间I2C_SDA信号产生一个上升沿
 (2)结束之后保持SDA和SCL都为1,表示总线空闲
 */
void I2C_Stop()
{
	SCL = 1;
	SDA = 0;
	Delay10us();
	SDA = 1;
	Delay10us();
}


/*
 *功能:I2C发送一个字节
 *参数:
	Data: 待发送数据
	ack: 1表示等待应答信号,0表示不等待应答信号
 *返回值:发送成功返回1,发送失败返回0。
 *注:
 (1)发送完一个字节I2C_SCL=0, 需要应答则应答设置为1,否则为0。
 (2)SCL低电平时,MCU把数据准备好,SCL高电平,从设备把数据读走。
 */
uchar I2C_SendByte(uchar Data, uchar ack)
{
	uchar i = 0;   				/*用于for循环*/
	uchar TimeCount = 0;	/*等待应答信号计数*/ 				
	SCL = 0;      				/*预防I2C起始信号最后没有把SCL拉低*/
	for(i=0; i<8; i++)    /*发送8bit,从高位到低位*/
	{
		SDA = Data >> 7;	 //起始信号之后I2C_SCL=0,所以可以直接改变I2C_SDA信号
		Data = Data << 1;
		Delay10us();
		SCL = 1;
		Delay10us();
		SCL = 0;
		Delay10us();	
	}

	SDA = 1;			/*主设备释放SDA线给从设备去操作*/
	Delay10us();       /*延时5uS*/
	SCL = 1;			/*SCL第9个周期*/
	
	while(SDA && (ack == 1)) /*等待应答,也就是等待从设备把SDA拉低*/
	{
		TimeCount++;
		if(TimeCount > 400)	       /*如果超过2000us没有应答发送失败,或者为非应答,表示接收结束*/
		{
			SCL = 0;
			Delay10us();	
			return 0;
		}
	}
	SCL = 0;      /*为发送下一字节做准备*/
	Delay10us();
 	return 1;		
}


/*
 *功能:I2C读取一个字节
 *参数:无
 *返回值:读取的一字节数据
 */
uchar I2C_ReadByte()
{
	uchar i = 0;       /*用于for循环*/
	uchar Data = 0;    /*保存读取的数据*/
	
	SCL = 0;			/*预防起始信号或发送字节后SCL不是0*/
	SDA = 1;			/*起始和发送一个字节之后I2C_SCL都是0*/
	Delay10us();
	
	for(i=0; i<8; i++)   /*接收8个bit*/
	{
		SCL = 1;     /*通知从设备MCU要开始读了,可以放1bit数据到SDA*/
		Delay10us();
		Data <<= 1;  /*读取高位在前*/
		Data |= SDA;
		Delay10us();
		SCL = 0;     /*为下bit传输做准备*/
		Delay10us();
	}
	return Data;		
}


void Delay10us()		//@12.000MHz
{
	unsigned char i;

	_nop_();
	i = 2;
	while (--i);
}


(3)drv_i2c.h

#ifndef __DRV_I2C_H__
#define __DRV_I2C_H__

#define uchar unsigned char
#define uint unsigned int


/*函数声明*/
void I2C_Start();                           /*I2C总线起始信号*/
void I2C_Stop();                            /*I2C总线停止信号*/
uchar I2C_SendByte(uchar Data, uchar ack);  /*I2C发送一个字节*/
uchar I2C_ReadByte();                       /*I2C读取一个字节*/

#endif

(4)drv_uart.c

#include "drv_uart.h"
#include <reg52.h>


/*
 *功能:串口初始化函数,8数据位,1停止位,无校验位,波特率4800
 *参数:无
 *返回值:无
 */
void UartInit(void)
{
	SCON = 0x50;  //串口工作在模式1,8位数据位,允许串行接收
	PCON = 0x80;  //波特率加倍
	TMOD = 0x20;  //设置T1为模式2 
	TH1 = 243;    //波特率4800	,TH1 = 晶振频率/12/32/波特率
	TL1 = 243;    //8位自动重装,意识是TH1用完了之后下一个周期TL1会自动重装到TH1去。
	TR1 = 1;      //开启定时器1
	//ES = 1;       //打开串口中断
	//EA = 1;       //打开总中断
}


/*
 *功能:通过串口发送一个字节数据
 *参数:需要发送的内容
 *返回值:无
 */
void UartSendByte(unsigned char Dat)
{
	SBUF = Dat;      //准备好需要发送的一个字节
	while(TI == 0);  //确认串口发送没有再忙,while循环需要加超时判断
	TI = 0;					 //软件复位TI标志位
}


/*
 *功能:通过串口发送字符串
 *参数:待发送的字符串
 *返回值:无
 */
void UartSendString(unsigned char *str)
{
	while(*str != '\0')    //等待字符串发完*/
	{
		UartSendByte(*str);  //发送一个字符
		str++;               //指针指向下一个字符
	}
}


/*
 *功能:串口中断接收函数
 *参数:无
 *返回值:无
 *注意:中断函数通过中断编号识别,中断编号可通过查数据手册得到
 */
void Uart_Isr() interrupt 4 
{
	unsigned char ReceiveBit;
	if(RI == 1)
	{
		ReceiveBit = SBUF;		//读取SBUF,读取串口接收到的一个字节
		RI = 0;
	}
	UartSendByte(ReceiveBit);		  //接收到的内容原封不动发回去
}

(5)drv_uart.h

#ifndef __DRV_UART_H__
#define __DRV_UART_H__


/*函数声明*/
void UartInit(void);                       /*串口初始化函数*/
void UartSendByte(unsigned char Dat);      /*通过串口发送一个字节数据*/
void UartSendString(unsigned char *str);   /*通过串口发送字符串*/

#endif

(6)at24c02.c

#include "at24c02.h"


/*
 *功能:AT24C02写入一个字节
 *参数:
  Addr:AT24C02存储数据的地址
  Data:写入的数据
 *返回值:无
 */
void AT24C02_WriteByte(uchar Addr, uchar Data)
{
	I2C_Start();
	I2C_SendByte(0xA0, 1);  // 发送AT24C02写地址
	I2C_SendByte(Addr, 1);  // 发送要写入数据的内存地址
	I2C_SendByte(Data, 1);  // 发送要写入的数据
	I2C_Stop();
}


/*
 *功能:AT24C02读取一个字节
 *参数:
  Addr:读取内容存放的内存地址
 *返回值:读取到的内容
 */
uchar AT24C02_ReadByte(uchar Addr)
{
	uchar Data = 0;
	
	I2C_Start();
	I2C_SendByte(0xA0, 1);  // 发送AT24C02写地址
	I2C_SendByte(Addr, 1);  // 发送读取内容存放地址
	
	I2C_Start();
	I2C_SendByte(0xA1, 1);  // 发送AT24C02读地址
	Data = I2C_ReadByte();  // 读取数据
	I2C_Stop();
	
	return Data;
}

(7)at24c02.h文章来源地址https://www.toymoban.com/news/detail-426570.html

#ifndef __AT24C02_H__
#define __AT24C02_H__


#include "drv_i2c.h"


/*AT24C02写入一个字节*/
void AT24C02_WriteByte(uchar Addr, uchar Data);
/*AT24C02读取一个字节*/
uchar AT24C02_ReadByte(uchar Addr);

#endif

到了这里,关于十三、51单片机之EEPROM(I2C)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【GD32】从0开始学GD32单片机(8)—— I2C外设详解+主机从机发送和接收例程

    I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。 I2C总线是一个真正的多主机总线,如果两个或多个主机同时初始化数据传输,可以通过冲突检测和仲裁防止数据破坏,每个连接到总线上的器件都有

    2024年02月02日
    浏览(89)
  • 【单片机】UART、I2C、SPI、TTL、RS232、RS422、RS485、CAN、USB、SD卡、1-WIRE、Ethernet等常见通信方式

    在单片机开发中,UART、I2C、RS485等普遍在用,这里做一个简单的介绍 UART口指的是一种物理接口形式(硬件)。 UART是异步(指不使用时钟同步,依靠帧长进行判断),全双工(收发可以同时进行)串口总线。它比同步串口复杂很多。有两根线,一根TXD用于发送,一根RXD用于接收

    2024年02月11日
    浏览(42)
  • I2C学习——读写eeprom

    I2C 通讯协议(Inter-Integrated Circuit)是由Philips公司开发的一种简单、双向二线制同步串行总线,只需要两根线即可在连接于总线上的器件之间传送信息。 特点如下: 1.在一个I2C通讯总线中,可挂载多个设备,这些设备既可做主机也可做从机。(一般总线上挂载的设备所在的地址

    2023年04月08日
    浏览(41)
  • 【STM32CubeMX+HAL库】I2C详解+读写EEPROM

    在之前的标准库中,STM32的硬件IIC非常复杂,更重要的是它并不稳定,所以都不推荐使用。但是在我们的HAL库中,对硬件IIC做了全新的优化,使得之前软件IIC几百行代码,在HAL库中,只需要寥寥几行就可以完成 那么这篇文章将带你去感受下它的优异之处。 通过本篇博客您将

    2024年02月03日
    浏览(57)
  • 【51单片机】EEPROM-IIC实验(按键控制数码管)

    目录   🎁I2C总线 ​编辑 🎁代码 🏳️‍🌈main.c 🏳️‍🌈i2.c 🎆代码分析   I2C总线是Philips公司在八十年代初推出的一种串行、半双工的总线,主要用于近距离、低速的芯片之间的通信;I2C总线有两根双向的信号线,一根 数据线SDA 用于收发数据,一根 时钟线SCL 用于通信

    2024年02月11日
    浏览(52)
  • 第五章 stm32 cubemx 软件I2C实验以及EEPROM的使用理论及实验过程

    本章将讲解stm32通讯协议中的IIC协议,利用cubeMX完成软件和硬件IIC的实现,并结合实验数据,给人更为深刻的体验。 我们结合IIC的具体协议和逻辑分析仪得到的具体实验数据理解IIC协议。 I2C通讯协议是由Phiilps公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要

    2024年01月21日
    浏览(53)
  • EEPROM芯片(24c02)使用详解(I2C通信时序分析、操作源码分析、原理图分析)

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

    2024年02月09日
    浏览(64)
  • STM32存储左右互搏 I2C总线FATS读写EEPROM ZD24C1MA

    在较低容量存储领域,EEPROM是常用的存储介质,可以通过直接或者文件操作方式进行读写。不同容量的EEPROM的地址对应位数不同,在发送字节的格式上有所区别。EEPROM是非快速访问存储,因为EEPROM按页进行组织,在连续操作模式,当跨页时访问地址不是跳到下一页到开始,而

    2024年02月12日
    浏览(68)
  • 51单片机的基础知识——单片机简介

    仅用于学习交流!!! 仅用于学习交流!!! 仅用于学习交流!!! 单片机,即单片微型计算器,简称为单片机。用专业术语来讲单片机就是在一块硅片上集成了微处理器、存储器以及各种输入/输出(I/O,I指的是input,O指的是output)口的芯片。通俗点讲,单片机是一块集

    2024年02月03日
    浏览(61)
  • 51单片机(十三)DS18B20温度传感器

    ❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋

    2024年02月11日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包