Proteus仿真之SPI通信(EEPROM)

1.SPI通信简介:串行外围设备接口(Serial Peripheral Interface)是由时钟线SCK、MOSI(master output slave input)、MISO(master input slave output)、片选CS四条线组成的一种全双工通信协议。

SPI通过时钟线SCK的状态来进行不同的操作,比如当SCK从0到1(低电平到高电平)时,开始进行数据传输,即此时开始读取MOSI/MISO的状态(高低电平)。

SPI支持一主多从,从机通过片选CS进行选择,所有的从机都有自己独立的CS线,但是所有的其他线都是共享的,比如,所有的SCK线都是通过一更总线连接到MCU上。当CS位低电平0时,表示当前设备被选择。

MOSI线是主机输入数据,从机接受数据。MISO是从机输出数据,主机读取数据。因为SPI具有两根数据线,因此可以进行全双工通信,同一时刻可以进行数据发送和数据接受。

SPI的时序图如下:

 

2.EEPROM

电可擦除可编程只读存储器EEPROM(Elctrically Erasable Programmable Read-Only Memory)是一种掉电非易失性的存储器,通常是基于SPI通信协议与主机进行数据传输。

EEPROM的引脚定义入下:

 EEPROM的指令集如下:

 3.本文利用按键进行数据加减,将数据写入到EEPROM中,并且从EEPROM中读取数据,显示在数码管中。仿真电路图如下:

 代码:

#include <reg52.h>

#define EEPROM_Address_W 0x02								//从指定地址开始写
#define EEPROM_Address_R 0X03								//从指定地址开始读
#define EEPROM_Address_ENABLE 0x06					//开启写使能命令
#define EEPROM_Address_DISABLE 0x04					//关闭写使能命令
#define EEPROM_Address_REGISTER 0x05		//读取寄存器的状态(状态寄存器的值)

typedef unsigned char uchar;
typedef unsigned int  uint;

sbit KEY1 =  P1^5;					//按键
sbit KEY2 = P1^6;
sbit SCK = P3^1;						//时钟线
sbit SI = P3^2;							//主机输出,从机输入
sbit SO = P3^3;							//主机输入,从机输出
sbit CS = P3^4;							//片选线,选择使用哪一个从机

uchar num = 3;


//SPI写应该Byte函数
void SPI_WriteByte(uchar Byte)
{
	uchar i;
	for(i = 0;i < 8;i++)
	{
		//SCK从低电平到高电平(上升沿)时传输数据
		SCK = 0;
		if(Byte & 0x80)			//取出最高为,每次只能传输一个bit的数据
		{
			SI = 1;
		}
		else
		{
			SI = 0;
		}
		Byte <<= 1;
		SCK = 1;
	}
	SCK = 0;
}

//SPI读一个Byte函数
uchar SPI_ReadByte(void)
{
	uchar i,Byte;
	SCK = 0;
	for(i = 0;i < 8;i++)
	{
		SCK = 1;
		Byte <<= 1;
		if(SO)
		{
			Byte ++;
		}
		SCK = 0;
	}
	return Byte;
}

//EEPROM开启写使能函数
void EEPROM_Write_ENABLE(void)
{
	CS = 1;
	CS = 0;
	SPI_WriteByte(EEPROM_Address_ENABLE);
	CS = 1;
}

//EEPROM关闭写使能函数
void EEPROM_Write_DISABLE(void)
{
	CS = 1;
	CS = 0;
	SPI_WriteByte(EEPROM_Address_DISABLE);
	CS = 1;
}

//从EEPROM中读取数据
uchar EEPROM_Read(uchar HW_Address,uchar SW_Address)
{
	uchar date = 0;
	CS = 1;
	CS = 0;
	SPI_WriteByte(HW_Address);
	SPI_WriteByte(SW_Address);
	date = SPI_ReadByte();
	CS = 1;
	return date;
}

//往EEPROM中写数据函数
void EEPROM_Write(uchar HW_Address,uchar SW_Address,uchar date)
{
	//HW_Address:EEPROM硬件地址
	//SW_Address: EEPROM的软件地址,即写出内存的地址
	uchar status = 0x01;		
	EEPROM_Write_ENABLE();							//开启写使能
	CS = 1;
	CS = 0;
	SPI_WriteByte(HW_Address);
	SPI_WriteByte(SW_Address);
	SPI_WriteByte(date);
	CS = 1;
	
	//读取EEPROM状态寄存器的最低为,当状态寄存器的最低位为1表示还未写完
	while(1)
	{
		CS = 1;
		CS = 0;
		SPI_WriteByte(EEPROM_Address_REGISTER);
		status = SPI_ReadByte();
		if((status & 0x01) == 0)
		{
			break;
		}
		CS = 1;
	}
	EEPROM_Write_DISABLE();						//关闭写使能
}

//扫描按键
void get_key()
{
	if(KEY1 == 0)
	{
		num ++;
		if(num >= 9)										//num只能是0~9
		{
			num = 9;
			while(KEY1 == 0);
		}
	}
	else if(KEY2 == 0)
	{
		num --;
		if(num <= 0)
		{
			num = 0;
		}
		while(KEY2 == 0);
	}
}

//数码管显示,只能显示0~9
void display(uchar date)
{
//	P0 = date & 0x0f;		
		P2 = date & 0x0f;
}

//主函数
void main(void)
{
//	display(num);
	num = EEPROM_Read(EEPROM_Address_R,0x00);
	while(1)
	{
		display(num);
		EEPROM_Write(EEPROM_Address_W,0x00,num);
		get_key();
	}
}

4.运行结果:

5.总结:SPI通信时只需要四根线:SCK、MOSI、MISO、CS即可。 SPI具有通信简单、数据传输速率快的优点。但是,SPI没有应答确认机制,因此,相比较IIC通信在数据可靠性上存在不足。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值