Proteus8仿真:51单片机25AA020A(SPI接口EEPROM)的使用

Microchip的25AA020A是一个2Kbit串行电可擦除可编程只读存储器(EEPROM)。内存可以通过一个简单的串行外围接口(SPI)兼容的串行总线来访问。所需的总线信号是时钟输入(SCK)加上独立的数据(SI)和数据输出(SO)线。通过芯片选择(CS)输入来控制对设备的访问。

实验内容

实验内容

使用25AA020A完成对计数器的计数值的保存。

实验原理图
在这里插入图片描述
实验器件

元器件 名称
51单片机 AT89C51
按键 BUTTON
数码管 7SEG-BCD-BLUE
EEPROM 25AA020A

25AA020A引脚功能

在这里插入图片描述

引脚 功能
SCK SPI时钟
SI SPI的MOSI(主机输出从机输入)
SO SPI的MISO(主机输入从机输出)
SCK SPI时钟
CS SPI的片选信号
WP 读写保护位
HOLD 暂停传输信号,拉高保证连续传输

SPI信号模拟

8位写

在这里插入图片描述

/**********************************************************************************************************************************
作用:SPI一个Byte写入函数
Byte:要写入的Byte
从高位往低位,上升沿传输

**********************************************************************************************************************************/
void SPI_WriteByte(uint_8 Byte)
{
    
    
	uint_8 i=0;
	for(i=0;i<8;i++)
	{
    
    
		SCK=0;
		if(Byte&0x80)SI=1;
		else SI=0;
		Byte <<=1;
		SCK=1;
	}
	SCK=0;
}

8位读

在这里插入图片描述

/**********************************************************************************************************************************
作用:SPI一个Byte读取函数
返回:读取的一个Byte
从高位往低位,下降沿传输
**********************************************************************************************************************************/

uint_8 SPI_ReadByte(void)
{
    
    
	uint_8 i;
	uint_8 Byte;
	SCK=0;
	for(i=0;i<8;i++)
	{
    
    
		SCK=1;
		Byte <<=1;
		if(SO)Byte++;
		SCK=0;
	}
	return Byte;
}

EEPROM读写函数

EEPROM写使能

在这里插入图片描述

/**********************************************************************************************************************************
作用:EEPROM写使能

**********************************************************************************************************************************/

void EEPROM_WriteData_ENABLE(void)
{
    
    
	CS=1;
	CS=0;
	SPI_WriteByte(EEPROM_Address_ENABLE);
	CS=1;
}

在这里插入图片描述

/**********************************************************************************************************************************
作用:EEPROM写不使能
**********************************************************************************************************************************/
void EEPROM_WriteData_DISENABLE(void)
{
    
    
	CS=1;
	CS=0;
	SPI_WriteByte(EEPROM_Address_DISABLE);
	CS=1;
}

EEPROM写一个Byte

在这里插入图片描述
在任何尝试将数据写入25AA020A之前,写启用锁必须通过发WREN来设置使用说明。这是通过设置CS较低来实现的然后把正确的指令输入到25AA020A.在所有的八位指令之后传输时,CS必须驱动到高才能设置写入启用锁存器。如果在没有CS驱动的高的情况下,在WREN指令后立即启动写操作,数据自写入后将不会被写入数组启用锁存器没有正确设置。

/**********************************************************************************************************************************
作用:EEPROM写入一个Byte函数
HW_Address:EEPROM硬件地址
SW_Address:EEPROM软件地址即写出内存的地址
Data:写入的数据

**********************************************************************************************************************************/

void EEPROM_WriteData(uint_8 HW_Address,uint_8 SW_Address,uint_8 Data)
{
    
    
	uint_8 status=0x01;
	//打开EEPROM写使能
	EEPROM_WriteData_ENABLE();
	CS=1;
	CS=0;
	SPI_WriteByte(HW_Address);
	SPI_WriteByte(SW_Address);
	SPI_WriteByte(Data);
	CS=1;
	//读取EEPROM寄存器
	//从寄存器最低位判断写是否完成
	while((status&0x01)==0x01)
	{
    
    
		CS=1;
		CS=0;
		SPI_WriteByte(EEPROM_Address_Read_REGISTER);
		status=SPI_ReadByte();	
		CS=1;		
	}
	//关闭EEPROM写使能
	EEPROM_WriteData_DISENABLE();
}

实验程序例程

main.c

#include "REG51.h"

sbit KEY1=P1^0;
sbit KEY2=P1^1;
sbit SCK=P3^0;
sbit SI=P3^1;
sbit SO=P3^2;
sbit CS=P3^3;

#define EEPROM_Address_W 0X02
#define EEPROM_Address_R 0X03
#define EEPROM_Address_ENABLE 0X06
#define EEPROM_Address_DISABLE 0X04
#define EEPROM_Address_Read_REGISTER 0x05

typedef unsigned char uint_8;
typedef unsigned int uint_16;

void SPI_WriteByte(uint_8 Byte);
uint_8 SPI_ReadByte(void);

void EEPROM_WriteData(uint_8 HW_Address,uint_8 SW_Address,uint_8 Data);
uint_8 EEPROM_ReadData(uint_8 HW_Address,uint_8 SW_Address);
void EEPROM_WriteData_ENABLE(void);


void get_key(void);
void SMG_output(uint_8 Data);
char num=5;

void main(void)
{
    
    
	num=EEPROM_ReadData(EEPROM_Address_R,0x00);
	while(1)
	{
    
    
		SMG_output(num);
		EEPROM_WriteData(EEPROM_Address_W,0x00,num);
		get_key();	
	}
}

/**********************************************************************************************************************************
作用:EEPROM写使能

**********************************************************************************************************************************/

void EEPROM_WriteData_ENABLE(void)
{
    
    
	CS=1;
	CS=0;
	SPI_WriteByte(EEPROM_Address_ENABLE);
	CS=1;
}

/**********************************************************************************************************************************
作用:EEPROM写不使能
**********************************************************************************************************************************/
void EEPROM_WriteData_DISENABLE(void)
{
    
    
	CS=1;
	CS=0;
	SPI_WriteByte(EEPROM_Address_DISABLE);
	CS=1;
}

/**********************************************************************************************************************************
作用:SPI一个Byte写入函数
Byte:要写入的Byte
从高位往低位,上升沿传输

**********************************************************************************************************************************/

uint_8 EEPROM_ReadData(uint_8 HW_Address,uint_8 SW_Address)
{
    
    
	uint_8 Data=0;
	CS=1;
	CS=0;
	SPI_WriteByte(HW_Address);
	SPI_WriteByte(SW_Address);
	Data=SPI_ReadByte();
	CS=1;
	return Data;
}

/**********************************************************************************************************************************
作用:EEPROM写入一个Byte函数
HW_Address:EEPROM硬件地址
SW_Address:EEPROM软件地址即写出内存的地址
Data:写入的数据

**********************************************************************************************************************************/

void EEPROM_WriteData(uint_8 HW_Address,uint_8 SW_Address,uint_8 Data)
{
    
    
	uint_8 status=0x01;
	//打开EEPROM写使能
	EEPROM_WriteData_ENABLE();
	CS=1;
	CS=0;
	SPI_WriteByte(HW_Address);
	SPI_WriteByte(SW_Address);
	SPI_WriteByte(Data);
	CS=1;
	//读取EEPROM寄存器
	//从寄存器最低位判断写是否完成
	while((status&0x01)==0x01)
	{
    
    
		CS=1;
		CS=0;
		SPI_WriteByte(EEPROM_Address_Read_REGISTER);
		status=SPI_ReadByte();	
		CS=1;		
	}
	//关闭EEPROM写使能
	EEPROM_WriteData_DISENABLE();
}

/**********************************************************************************************************************************
作用:SPI一个Byte读取函数
返回:读取的一个Byte
从高位往低位,下降沿传输
**********************************************************************************************************************************/

uint_8 SPI_ReadByte(void)
{
    
    
	uint_8 i;
	uint_8 Byte;
	SCK=0;
	for(i=0;i<8;i++)
	{
    
    
		SCK=1;
		Byte <<=1;
		if(SO)Byte++;
		SCK=0;
	}
	return Byte;
}

/**********************************************************************************************************************************
作用:SPI一个Byte写入函数
Byte:要写入的Byte
从高位往低位,上升沿传输

**********************************************************************************************************************************/
void SPI_WriteByte(uint_8 Byte)
{
    
    
	uint_8 i=0;
	for(i=0;i<8;i++)
	{
    
    
		SCK=0;
		if(Byte&0x80)SI=1;
		else SI=0;
		Byte <<=1;
		SCK=1;
	}
	SCK=0;
}
/**********************************************************************************************************************************
作用:按键扫描

**********************************************************************************************************************************/

void get_key(void)
{
    
    
	if(KEY1==0)
	{
    
    
		num++;
		if(num>=9)num=9;
		while(KEY1==0);
	}
	else if(KEY2==0)
	{
    
    
		num--;
		if(num<=0)num=0;
		while(KEY2==0);		
	}
}
/**********************************************************************************************************************************
作用:数码管显示

**********************************************************************************************************************************/

void SMG_output(uint_8 Data)
{
    
    
	P2=Data&0x0F;
}


工程文件

工程文件

猜你喜欢

转载自blog.csdn.net/darlingqx/article/details/128513478