蓝桥杯----AT24C02

发布于:2025-08-06 ⋅ 阅读:(14) ⋅ 点赞:(0)

(5-1)、AT24C02掉电不丢失写入与读取

        AT24C02就是将数据写入E2PROM,保证写入数据掉电不丢失。考频低,一般不考,顶天考几个数据E2PROM,上电立马读取。AT24C02数据读取一定放在主程序最前面,否则会出现一些问题。通信方式也是I2C,因此底层代码跟AD、DA基本一样。存在下面我们来讲一下写入与读取的时序。

 

写入时序:(如图 二十二)

①初始化(通信起始信号)

②发送I2C设备地址(高七位是设备地址,最后一位是读写位,写为0,读取为1,A2、A1、A0置0,开始写操作0xa0,如图 二十一)

③从机发送反馈应答(从机发送0表明接收成功)

④写入从机设备地址(一般为8的倍数,如0、8、16、24…)

⑤从机发送反馈应答

⑥逐个写入数据、从机发送反馈应答、延时200再写(while循环)

⑦停止信号

               图 二十一 AT24C02设备地址

 

读取时序:(如图 二十三)

①初始化(通信起始信号)

②发送I2C设备地址(高七位是设备地址,最后一位是读写位,写为0,读取为1,A2、A1、A0置0,开始写操作0xa0,如图 二十一)

③从机发送反馈应答(从机发送0表明接收成功)

④写入从机设备地址(一般为8的倍数,如0、8、16、24…)

⑤从机发送反馈应答

⑥重新初始化

⑦发送开始读取信号0xa1

⑧从机发送反馈应答(从机发送0表明接收成功)

⑨开始读取数据(无需延时)、读取完成主机发送反馈1、还有数据发送0

⑩停止信号

                   图 二十二 AT24C02写入

                  图 二十三 AT24C02读取

 

(5-2)AT24C02写入与读取代码解读

    如图 二十四,我们按照写入的时序一步步分析,*String表示指针,传入数组名,就可以需要写入的 数据全部写入,Number就是数组里面有几个数据。

    首先发送开始信号,再发送从机地址并反馈(0xA0)

    再选择需要写入的寄存器地址(8的倍数),从该位置开始写,写入一次后地址会自增,数据自动放在下一位地址。

    此时开始写入数据,每次写入后需要延时200,循环Number次后,数组数据全部写完,停止。

 

                图 二十四 AT24C02写入数据代码

 

    如图 二十五,我们按照读取的时序一步步分析,*String表示指针,传入数组名,就可以将指定地址Address开始的数据全部读取,Number就是读取数据的个数。

   首先发送开始信号,再发送从机地址+读写位(读为0、写为1),并反馈(0xA0)

   再选择需要读取的寄存器地址(8的倍数),从该位置开始读取,与写入原理相同,读取一次后地址会自增,第二次读取时是第一次地址自加后的位置下的数据。

   重新初始化,发送寄存器地址+读写位置(读为0、写为1),反馈。

   此时开始读取数据,循环Number次后,数组数据全部读取完。此时注意只有当Number==0时也就是数据已经读取完了,发送反馈1,不在读取;Number!=0说明还有数据,发送反馈0,继续读取。最后停止时序。最后,请一定记得把读取的代码放在main函数最前面!

 

             图 二十五 AT24C02读取数据代码

提供参考代码,希望对读者有帮助

#include <STC15F2K60S2.H>
#include <INTRINS.H>

sbit sda = P2^1;
sbit scl = P2^0;
/*	#   I2C代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/

#define DELAY_TIME	5

//
static void I2C_Delay(unsigned char n)
{
    do
    {
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();		
    }
    while(n--);      	
}

//
void I2CStart(void)
{
    sda = 1;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 0;
	I2C_Delay(DELAY_TIME);
    scl = 0;    
}

//
void I2CStop(void)
{
    sda = 0;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 1;
	I2C_Delay(DELAY_TIME);
}

//
void I2CSendByte(unsigned char byt)
{
    unsigned char i;
	
    for(i=0; i<8; i++){
        scl = 0;
		I2C_Delay(DELAY_TIME);
        if(byt & 0x80){
            sda = 1;
        }
        else{
            sda = 0;
        }
		I2C_Delay(DELAY_TIME);
        scl = 1;
        byt <<= 1;
		I2C_Delay(DELAY_TIME);
    }
	
    scl = 0;  
}

//
unsigned char I2CReceiveByte(void)
{
	unsigned char da;
	unsigned char i;
	for(i=0;i<8;i++){   
		scl = 1;
		I2C_Delay(DELAY_TIME);
		da <<= 1;
		if(sda) 
			da |= 0x01;
		scl = 0;
		I2C_Delay(DELAY_TIME);
	}
	return da;    
}

//
unsigned char I2CWaitAck(void)
{
	unsigned char ackbit;
	
    scl = 1;
	I2C_Delay(DELAY_TIME);
    ackbit = sda; 
    scl = 0;
	I2C_Delay(DELAY_TIME);
	
	return ackbit;
}

//
void I2CSendAck(unsigned char ackbit)
{
    scl = 0;
    sda = ackbit; 
	I2C_Delay(DELAY_TIME);
    scl = 1;
	I2C_Delay(DELAY_TIME);
    scl = 0; 
	sda = 1;
	I2C_Delay(DELAY_TIME);
}

/*
   IIC通信过程
			1、AT24C02写入
			起始信号-开始写操作(0xa0)--反馈---写入从机地址--反馈---写入数据反馈--延时200--停止
			
			2、AT24C02读取
			起始信号-开始写操作(0xa0)--反馈--写入从机地址--反馈--重新开始--开始读操作(0xa1)--反馈
			--开始读取并反馈(不再接收发送1)---停止



/**
* @brief     AT24C02_Write往AT24C02中写入数据保证掉电不丢失
  * @param  *String--传入数组名
  * @param   Address寄存器地址(8的倍数,如0、8、16、24...)
  * @param   Number--需要发送的数据总共几位
*/

void AT24C02_Write(unsigned char *String,unsigned char Address,unsigned char Number)
{
	I2CStart();
	I2CSendByte(0xa0);    //写入从机地址
	I2CWaitAck();
	
	I2CSendByte(Address); //开始写入的寄存器地址
	I2CWaitAck();
	
	while(Number--)
	{
		I2CSendByte(*String++);    //写入数据
	    I2CWaitAck();
		I2C_Delay(200);    //延时
	}
	I2CStop();
	I2C_Delay(255);  I2C_Delay(255);I2C_Delay(255);I2C_Delay(255);//保证时序
}



//从地址Address开始读取Number个数据,并放入*String数组中(指针)
void AT24C02_Read(unsigned char *String,unsigned char Address,unsigned char Number)
{
	I2CStart();
	I2CSendByte(0xa0);    //写入从机地址
	I2CWaitAck();         //反馈
	
	I2CSendByte(Address);    //开始写入的寄存器地址
	I2CWaitAck();
	
	I2CStart();           //重新开始
	I2CSendByte(0xa1);    //开始读操作
	I2CWaitAck();
	
	while(Number--)    //读取Number数据
	{
		*String++ = I2CReceiveByte();
		if(Number)  //如何Number!=0表示还有数据需要读取,发送反馈0,继续读取
		I2CSendAck(0);
		else
		I2CSendAck(1);   //如何Number==0表示读取完毕,不再接收,发送反馈1
	}
	I2CStop();
}

 

 

 


网站公告

今日签到

点亮在社区的每一天
去签到