题目要求:
首先将下面两个函数加到程序中(记住),比赛时应该需要自己写:在文章末尾会有一点说明。
//EEPROM_Read
void EEPROM_Read(uint8_t add,uint8_t * array,uint8_t n){
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(add);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
while(n--)
{
*array++=I2CReceiveByte();
if(n)
{
I2CSendAck();
}
else
{
I2CSendNotAck();
}
}
I2CStop();
}
void EEPROM_Write(uint8_t add,uint8_t * array,uint8_t n){
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(add);
I2CWaitAck();
while(n--)
{
I2CSendByte(*array++);
I2CWaitAck();
}
I2CStop();
}
接下来就是稍微麻烦的地方了,就是判断是否为第一次上电,其实以后比赛记住这种模式就可以:稍微解释一下:我们可以随便读取EEPROM里的任意单元地址(不要和我们需要保存的数据地址相同)里的数据。对该数据进行判断,是否等于一个0x27(等于别的也可以),如果不等于0x27,则读取到的是EEPROM原本存储的值,说明是第一次上电,将0xf8写进该单元,此时该单元的值等于0x27。如果等于0x27,则说明不是第一次上电。其实这种方法也有一点点误差1/256%,也可以忽略不计了吧。产生误差的原因是第一次上电eeprom读取的数据有可能和原来相应位置存储的数据相同,这就为会产生错误了。
void System_Init(){
u8 temp;
EEPROM_Read(0x07, &temp, 1);
if(temp!=0x27){//不等于0x27是第一次上电
temp = 0x27;
EEPROM_Write(0x07,&temp,1);
HAL_Delay(10);
EEPROM_Write(0x00,&X_Count,1);
HAL_Delay(10);
EEPROM_Write(0x01,&Y_Count,1);
HAL_Delay(10);
EEPROM_Write(0x02,&X_Price,1);
HAL_Delay(10);
EEPROM_Write(0x03,&Y_Price,1);
HAL_Delay(10);
}
else{//不是第一次上电
EEPROM_Read(0x00,&X_Count,1);
HAL_Delay(10);
EEPROM_Read(0x01,&Y_Count,1);
HAL_Delay(10);
EEPROM_Read(0x02,&X_Price,1);
HAL_Delay(10);
EEPROM_Read(0x03,&Y_Price,1);
HAL_Delay(10);
}
}
题目中要求每次修改库存数量和价格时都要更新eeprom存储的值,那我们就在按键相应部分加上一条更新语句就可以啦!如下图所示>>>
EEPROM单字节读取方式
写函数
void EEPROM_Write(uint8_t add,uint8_t date)
{
I2CStart();//起始
I2CSendByte(0xa0);//控制字,写
I2CWaitAck();
I2CSendByte(add);//片内单元地址
I2CWaitAck();
I2CSendByte(date);//写入的字节
I2CWaitAck();
I2CStop(); //停止
}
读函数:
uint8_t EEPROM_Read(uint8_t add)
{
uint8_t temp;
I2CStart();//起始
I2CSendByte(0xa0);//控制字,告诉EEPROM进行写字节操作
I2CWaitAck();
I2CSendByte(add);//片内单元地址
I2CWaitAck();
I2CStop();//停止
I2CStart();//起始
I2CSendByte(0xa1);//控制字,告诉EEPROM进行读字节操作
I2CWaitAck();
temp=I2CReceiveByte();//读取字节
I2CSendNotAck();
I2CStop(); //停止
return temp;
}
AT24C02(EEPROM)片内地址从0x00到0xff共256个地址单元,每个地址单元可以存放一个字节。需要注意的是,连续多个字节写入EEPROM要进行10ms的延时,这是因为EEPROM处理数据的速度远小于单片机的速度,为了防止数据丢失,所以需要延时。
上述代码中的add即为EEPROM的片内地址,上述代码中的date即为写入EEPROM的数据。
以上代码就是单字节的读写函数,每次只能读写一个字节。这些代码比赛是需要我们自行编写的。
读写举例:
uint8_t date=26;
EEPROM_Write(0x00,date);//写入EEPROM的0x00单元,数据大小为26的uint8_t类型数据。
date=19;
date=EEPROM_Read(0x00);//读取EEPROM的0x00单元数据,当前date大小为26
EEPROM多字节读取方式
多字节读写函数
优点:
EEPROM不但可以单字节读写,还可以按页一次性多个字节读写,每页8个字节,所以最多可以连续读写8个字节,非常的方便。我们只需要向EEPROM传递EEPROM每页的首地址,就可以连续读写多个字节。
除此之外,多字节读写方式对于多字节的基本数据类型的读写也非常简单。有效的解决了前面的问题。例如8个字节的double,4个字节的float,2个字节的uint16_t,很多同学都会进行相应的换算,这样着实麻烦。
我们知道在相同的平台上,相同的数据类型,在内存中所占的字节大小是固定的,而且单个数据变量的字节在内存上的排布是连续的,所以,我们可以直接将该变量的所有字节写入EEPROM中,读取的时候,也是将相应的字节都读取出来,不用任何类型换算。
当然理解这部分内容需要对于指针和地址,要有一点点的了解。不懂也没关系,会用就可以。
写函数
void EEPROM_Write(uint8_t add,uint8_t * array,uint8_t n)
{
I2CStart();
I2CSendByte(0xa0);//写操作
I2CWaitAck();
I2CSendByte(add);//片内单元地址
I2CWaitAck();
while(n--)//进行n次循环,写入n个数据,每次写入进行一次等待。
{
I2CSendByte(*array++);
I2CWaitAck();
}
I2CStop();
}
读函数:
void EEPROM_Read(uint8_t add,uint8_t * array,uint8_t n)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(add);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
while(n--)
{
*array++=I2CReceiveByte();//读取
if(n)//如果还有数据要读取
{
I2CSendAck();
}
else//如果没有数据要读取
{
I2CSendNotAck();
}
}
I2CStop();
}
延时问题
无论是单字节的读写方式,还是多字节的读写方式,向EEPROM写入数据的时候都要进行相应的延时,建议延时10ms,这个问题前面有讲到。主要是因为EEPROM的速度跟不上stm32的速度。
更加详细的eeprom讲解请参考:(72条消息) 蓝桥杯嵌入式(G431RBT6): EEPROM进阶学习_电子鹦鹉的博客-CSDN博客