蓝桥杯单片机设计与开发⑧ ---E2PROM读写多个字节和页写入

E2PROM 多字节操作

我们知道,写数据的时候,E2PROM是先写到缓冲区,然后再“搬运到”到掉电非易失区。所以这个过程需要一定的时间,AT24C02这个过程是不超过5ms!如果在这个时候去让它应答是没有响应的!
所以,当我们在写多个字节时,写入一个字节之后,再写入下一个字节之前,必须等待E2PROM再次相应才可以。

main.c

#include "sys.h"

void main()
{														
	unsigned char dat1[8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
	unsigned char dat2[8] = {0};
	int len = 0;
	ALL_Init();
	//将dat1数据写到E2PROM
	E2Write(dat1,30,sizeof(dat1));
	//将E2PROM所存的数据读到dat2中
	E2Read(dat2,30,sizeof(dat2));
	while(1)
	{
		//将dat2里面的值作为参数 实现流水灯
		Led_illume(dat2[len]);
		Operate_Delay(1000);
		len++;
		if(len == 8)
		{
			len = 0;
		}
	}
	
}

at24c02.c

#include "iic.h"

/*******************************************************************************
* 函数名	:E2Read
* 输入值	:unsigned char *buf, unsigned char addr, unsigned char len
* 返回值	:none
* 作者		:	guyao
* 时间		:2021/2/22
* 功能描述:连续读取多个数据
* 备注		:buf为数据接收指针,addr为E2PROM中要读取的数据起始地址,len为读取长度
*******************************************************************************/
void E2Read(unsigned char *buf, unsigned char addr, unsigned char len)
{
		do{		//用寻址操作查询当前是否可以进行读操作
				IIC_Start();
				IIC_SendByte(SlaveAddrW);//发送器件地址
				if(IIC_WaitAck())//应答则跳出循环,非应答则进行下一次查询
				{
						break;
				}
				IIC_Stop();
			}while(1);
	
		IIC_SendByte(addr);    		//写入起始地址
		IIC_WaitAck();
		IIC_Stop();
	
		IIC_Start();
		IIC_SendByte(SlaveAddrR);	//寻址器件,后续为读操作
		IIC_WaitAck();
		while(len > 1)				//连续读取len-1个字节
		{
			*buf++ = IIC_RecByte();	//最后字节之前为读取操作并且应答
			IIC_Ack(1); 					
			len--;
		}
		*buf = IIC_RecByte();		//最后一个字节为读取操作并且非应答
		IIC_Ack(0);							
		IIC_Stop();

}
/*******************************************************************************
* 函数名	:E2Write
* 输入值	:unsigned char *buf, unsigned char addr, unsigned char len
* 返回值	:none
* 作者		:guyao
* 时间		:2021/2/22
* 功能描述:连续写入多个数据
* 备注		:buf为源数据指针,addr为E2PROM中要写入的数据起始地址,len为写入长度
*******************************************************************************/
void E2Write(unsigned char *buf, unsigned char addr, unsigned char len)
{
		while(len--)
		{
				do{		//用寻址操作查询当前是否可以进行读操作
						IIC_Start();
						IIC_SendByte(SlaveAddrW);//发送器件地址
						if(IIC_WaitAck())//应答则跳出循环,非应答则进行下一次查询
						{
								break;
						}
						IIC_Stop();
					}while(1);
						
				IIC_SendByte(addr++);  //写入起始地址
				IIC_WaitAck();  	   //等待从机应答
				IIC_SendByte(*buf++); //写入一个字节数据	
				IIC_WaitAck();  	  //等待从机应答		
				IIC_Stop();			  //结束写操作,以等待写入完成
		}
}

led.c

#include "sys.h"

void Led_illume(uchar dat)
{
		P2 = (P2 & 0X1F)| 0X80;//打开Y4C
		P0 = dat;
}

sys.c

#include "sys.h"

/**
*@brief     外设初始化  
*@param[in] none
*@return    none
**/
void ALL_Init()
{
	P2 = (P2&0x1f)|0xa0;	//打开Y5C
	P0 = 0x00;				//关闭蜂鸣器&继电器
	P2 = (P2&0x1f)|0xe0;	//打开Y7C
	P0 = 0xff;				//关闭数码管
	P2 = (P2&0x1f)|0x80;	//打开Y4C
	P0 = 0xff;				//关闭LED
	P2 = P2&0x1f;			//关闭所用使能
}
/**
*@brief     延时函数
*@param[in] 延时多少ms(0~65535)
*@return    none
**/
void Operate_Delay(u16 ms)
{
	u16 i;
	for(ms;ms>0;ms--)
		for(i=921;i>0;i--);
}
#ifndef __SYS_H__
#define __SYS_H__


//头文件包含
#include <STC15F2K60S2.H>
#include <intrins.h>

//管脚声明

//变量类型声明
typedef unsigned int uint;
typedef unsigned int u16;
typedef unsigned char uchar;
typedef unsigned char u8;


//外部变量声明

//函数声明
void ALL_Init();
void Operate_Delay(unsigned int ms);
//at24c02.c
void E2Read(unsigned char *buf, unsigned char addr, unsigned char len);
void E2Write(unsigned char *buf, unsigned char addr, unsigned char len);
//led.c
void Led_illume(uchar dat);
#endif

E2PROM 页写入

多字节写入我们也能感受到一次写一个字节的慢,然后等待ACK后才能写入下一个字节。效率太低!所以就诞生了分页写的模式。
这一次我们专门成立了一个eeprom的模块。

24C02,一共是 256 个字节,8 个字节一页,那么就一共有 32 页。

分配好页之后,如果我们在同一个页内连续写入几个字节后,最后再发送停止位的时序。EEPROM 检测到这个停止位后,就会一次性把这一页的数据写到非易失区域,就不需要像上节课那样写一个字节检测一次了,并且页写入的时间也不会超过 5ms。

如果我们写入的数据跨页了,那么写完了一页之后,我们要发送一个停止位,然后等待并且检测 EEPROM 的空闲模式,一直等到把上一页数据完全写到非易失区域后,再进行下一页的写入,这样就可以在很大程度上提高数据的写入效率。

/*******************************************************************************
* 函数名	:E2Write_page
* 输入值	:unsigned char *buf, unsigned char addr, unsigned char len
* 返回值	:none
* 作者	:guyao
* 时间	:2021/2/22
* 功能描述:连续写入一页数据
* 备注	:buf为源数据指针,addr为E2PROM中要写入的数据起始地址,len为写入长度
*******************************************************************************/
void E2Write_page(unsigned char *buf, unsigned char addr, unsigned char len)
{
		while(len)
		{
				
				do{							//用寻址操作查询当前是否可以进行读操作
						IIC_Start();
						IIC_SendByte(SlaveAddrW);//发送器件地址
						if(IIC_WaitAck())//应答则跳出循环,非应答则进行下一次查询
						{
								break;
						}
						IIC_Stop();
					}while(1);
				
				IIC_SendByte(addr);//写入起始地址
				IIC_WaitAck();
				
				while(len > 0)
				{
						IIC_SendByte(*buf++);//写入一个字节数据
						IIC_WaitAck();
						len--;							 //代写入长度递减
						addr++;							 //E2PROM地址递增
						if((addr & 0x07) == 0)//检查地址是否达到页边界,24c02每页8节
								break;
				}
				IIC_Stop();
		}
}
  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值