普中51单片机:AT24C02芯片EPROM数据存储(十二)

在这里插入图片描述

引言

AT24C02是一款由Atmel(现为Microchip Technology公司的一部分)生产的2Kb(256字节)I²C接口EEPROM存储器芯片。它常用于需要非易失性存储的小型嵌入式系统中,比如存储配置信息或校准数据。可用于保存单片机运行时想要永久保存的数据信息。存储介质是E2PROM。

什么是EEPROM?

EEPROM(Electrically Erasable Programmable Read-Only Memory,电可擦除可编程只读存储器)是一种非易失性存储器,可以通过电信号擦除和重新编程。

EEPROM的特性

数据在断电后依然保存,这使得EEPROM非常适合存储需要长期保存的配置信息、校准数据和其他重要信息。EEPROM可以通过电信号进行擦除和写入,无需物理移除芯片。EEPROM支持字节级别的读写操作,这意味着可以对单个字节进行修改,而无需擦除整个块。EEPROM的读写速度相对较慢,特别是与RAM相比,但足以满足大多数非实时数据存储需求。

芯片概述

AT24C02是EEPROM的一种具体实现,它采用了IIC接口进行数据传输。具体而言,AT24C02是EEPROM大家族中的一个成员,具备了EEPROM的基本特性,同时结合了I²C总线接口,方便与微控制器进行通信。它具有以下特点:

  • 存储容量:最大容量2Kb(256字节)
  • 接口类型:IIC通信协议(Inter-Integrated Circuit)
  • 工作电压:1.8V至5.5V
  • 工作温度范围:-40°C至+85°C
  • 封装类型:常见封装包括8引脚的PDIP、SOIC、TSSOP等

注意:有关IIC通信协议,可查看此博客内容讲解:IIC总线原理特性解析及通信要点

芯片及引脚说明

AT24C02通常采用8引脚的封装形式,如PDIP、SOIC、TSSOP等。每个引脚都有其特定的功能,具体引脚配置如下:
在这里插入图片描述
各引脚功能详解

  • 地址引脚0(A0, 引脚1):用于设置I²C设备地址的一部分。通过连接到Vcc或GND,可以设置不同的设备地址。A0引脚的电平值决定了地址的最低位(A0位)。
  • 地址引脚1(A1, 引脚2):用于设置I²C设备地址的一部分。通过连接到Vcc或GND,可以设置不同的设备地址。A1引脚的电平值决定了地址的次低位(A1位)。
  • 地址引脚2(A2, 引脚3):用于设置I²C设备地址的一部分。通过连接到Vcc或GND,可以设置不同的设备地址。A2引脚的电平值决定了地址的次高位(A2位)。
  • GND(引脚4):电源地连接,提供芯片的基准电压,是整个电路的参考点。
  • SDA(引脚5):串行数据线,用于IIC总线上的双向数据传输。通过这条线,主设备和从设备之间可以进行数据交换。
  • SCL(引脚6):串行时钟线,提供IIC总线上的时钟信号,用于同步数据传输。主设备生成时钟信号,控制通信的节奏。
  • WP(引脚7):写保护引脚,控制EEPROM的写保护状态。当WP引脚接高电平时,EEPROM进入写保护模式,禁止写操作;当WP引脚接低电平时,允许写操作。
  • 0 Vcc(引脚8):电源引脚,连接到电源正极,提供工作电压给芯片,工作电压范围为1.8V至5.5V。

在这里插入图片描述
高四位是固定的,为1010,低四位是可编程的,最后一位用于设置数据传输方向。在前面提到的IIC总线原理特性解析及通信要点有详细讲解。

电路图

下图是普中A7开发板EEPROM模块电路图,采用STC89C51RC/RD+系列,SCL连接P2_1引脚,SDA连接P2_0引脚。(从图中可以看出,这两条线上带有上拉电阻),操作方式可以采用IIC时序,IIC总线原理特性解析及通信要点有详细讲解。这里不过多说明。
在这里插入图片描述

起始停止信号

根据IIC总线通信时序,进行编写代码,下图则是对应时序图:
在这里插入图片描述

//起始信号
void iic_start()
{
	IIC_SCL = 1;
	IIC_SDA = 1;
	DelayXms(1);
	IIC_SDA = 0;
	DelayXms(1);
	IIC_SCL = 0;//开始占用总线
}

//停止信号
void iic_stop()
{
	IIC_SCL = 1;
	IIC_SDA = 0;
	DelayXms(1);
	IIC_SDA = 1;
}

应答与非应答

时钟线SCL为低电平期间,SDA数据允许发生更改。SDA低电平表示应答信号,高电平表示非应答信号。下方为对应时序图:
在这里插入图片描述

//应答信号
void iic_ack()
{
	IIC_SCL = 0;
	IIC_SDA = 0;
	DelayXms(1);
	IIC_SCL = 1;
	DelayXms(1);
	IIC_SCL = 0;
}

//非应答信号
void iic_nack()
{
	IIC_SCL = 0;
	IIC_SDA = 1;
	DelayXms(1);
	IIC_SCL = 1;
	DelayXms(1);
	IIC_SCL = 0;
}

代码演示

系统运行时,数码管右3位显示0,按K1键将数据写入到EEPROM内保存,按K2键读取EEPROM内保存的数据,按K3键显示数据加1,按K4键显示数据清零。

#include <REGX52.H>
#include <INTRINS.H>
#define EEPROM_ADDRESS 0

sbit KEY1 = P3^0;
sbit KEY2 = P3^1;
sbit KEY3 = P3^2;
sbit KEY4 = P3^3;

sbit IIC_SCL = P0^0;
sbit IIC_SDA = P0^1;


sbit LED1 = P2^0;
sbit LED2 = P2^1;

//共阴极数码管显示 0~F 的段码数据
unsigned char gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

void DelayXms(unsigned int xms)	//@12.000MHz
{
	unsigned char data i, j;
	
	while(xms)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

unsigned char Scan_keys()
{
	if(KEY1 == 0 || KEY2 == 0 || KEY3 == 0 || KEY4 == 0)
	{
		DelayXms(100);//消抖处理
		if(KEY1 == 0)
			return 1;
		else if(KEY2 == 0)
			return 2;
		else if(KEY3 == 0)
			return 3;
		else if(KEY4 == 0)
			return 4;
	}
	return 0;
}

void Init_Port_Smg(unsigned char Location,unsigned char dat[])
{
	unsigned char i = 0;
	unsigned char local = Location - 1;
	for(i = Location;i < 8;i++)
	{
		switch(i+1)
		{
			case 1:
				P2_2 = 0;P2_3 = 0;P2_4 = 0;
				break;
			case 2:
				P2_2 = 1;P2_3 = 0;P2_4 = 0;
				break;
			case 3:
				P2_2 = 0;P2_3 = 1;P2_4 = 0;
				break;
			case 4:
				P2_2 = 1;P2_3 = 1;P2_4 = 0;
				break;
			case 5:
				P2_2 = 0;P2_3 = 0;P2_4 = 1;
				break;
			case 6:
				P2_2 = 1;P2_3 = 0;P2_4 = 1;
				break;
			case 7:
				P2_2 = 0;P2_3 = 1;P2_4 = 1;
				break;
			case 8:
				P2_2 = 1;P2_3 = 1;P2_4 = 1;
				break;
		}
		P1 = gsmg_code[dat[i-Location]];
		DelayXms(1);
		P1 = 0x00;//消影	
	}	

}

//起始信号
void iic_start()
{
	IIC_SCL = 1;
	IIC_SDA = 1;
	_nop_();
	IIC_SDA = 0;
	_nop_();
	IIC_SCL = 0;//开始占用总线
}

//停止信号
void iic_stop()
{
	IIC_SCL = 1;
	IIC_SDA = 0;
	_nop_();
	IIC_SDA = 1;
}

//应答信号
void iic_ack()
{
	IIC_SCL = 0;
	IIC_SDA = 0;
	_nop_();
	IIC_SCL = 1;
	_nop_();
	IIC_SCL = 0;
}

//非应答信号
void iic_nack()
{
	IIC_SCL = 0;
	IIC_SDA = 1;
	_nop_();
	IIC_SCL = 1;
	_nop_();
	IIC_SCL = 0;
}

unsigned char iic_wait_ack()
{
	unsigned char time = 0;
	IIC_SCL = 1;
	_nop_();
	while(IIC_SDA)
	{
		time++;
		if(time>100)
		{
			iic_stop();
			return 1;
		}
	}
	IIC_SCL = 0;
	return 0;
}

void iic_write_byte(unsigned char dat)
{
	unsigned char i = 0;
	IIC_SCL = 0;//数据可以发生变化
	for(i = 0;i< 8;i++)
	{
		if((dat&0X80)>0)//先发送高位
		{
			IIC_SDA = 1;
		}
		else
		{
			IIC_SDA = 0;
		}
		dat<<=1;
		IIC_SCL = 1;//数据发送
		_nop_();
		IIC_SCL = 0;
		_nop_();
	}
}

unsigned char iic_read_byte(unsigned char ack)
{
	unsigned char i = 0;
	unsigned char res = 0;
	for(i = 0;i < 8;i++)
	{
		IIC_SCL = 0;
		_nop_();
		IIC_SCL = 1;//数据发送
		_nop_();
		res<<=1;
		if(IIC_SDA)
		{
			res++;	
		}
	}
	if(!ack)//nack
		iic_nack();
	else
		iic_ack();
	return res;
}


void at24c02_write_byte(unsigned char dat,unsigned char addr)
{
	iic_start();//发送起始信号 A0写 A1读
	iic_write_byte(0xa0);
	iic_wait_ack();//等待从机的ack
	iic_write_byte(addr);//发送要写的设备地址
	iic_wait_ack();//等待从机的ack
	iic_write_byte(dat);//发送数据
	iic_wait_ack();//等待从机的ack
	iic_stop();//停止
	_nop_();
}

unsigned char at24c02_read_byte(unsigned char addr)
{
	unsigned char temp = 0;
	iic_start();//发送起始信号 A0写 A1读
	iic_write_byte(0xa0);
	iic_wait_ack();//等待从机的ack
	iic_write_byte(addr);//发送要写的设备地址
	iic_wait_ack();//等待从机的ack
	iic_start();//发送起始信号 A0写 A1读
	iic_write_byte(0xa1);//发送数据
	iic_wait_ack();//等待从机的ack
	temp = iic_read_byte(0);
	iic_stop();//停止
	return temp;
}

void main()
{
	unsigned char keynum = 0;
	unsigned char i = 0;
	unsigned char sava_value = 0;
	unsigned char save_buf[3];
	while(1)
	{

		keynum = Scan_keys();
		if(keynum == 1)
		{
			at24c02_write_byte(sava_value,EEPROM_ADDRESS);	
		}
		else if(keynum == 2)
		{
			sava_value = at24c02_read_byte(EEPROM_ADDRESS);
		}
		else if(keynum == 3)
		{
			sava_value++;
			if(sava_value >= 255)//最大值
			{
				sava_value = 255;
			}
		}
		else if(keynum == 4)
		{
			sava_value = 0;
		}
		save_buf[0] = sava_value/100;//百位
		save_buf[1] = sava_value%100/10;//十位
		save_buf[2] = sava_value%100%10;//个位

		Init_Port_Smg(5,save_buf);
	}
}
  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨辰JC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值