蓝桥杯嵌入式-EEPROM 为毛读到的老是255

问题1:隔一年再考蓝桥杯嵌入式,发现这个EEPROM读取到的总是255!!!

而我用单步debug,逐行执行时在屏幕上打印出来值确实对的,只要一run就出错

发现:eeprom_write函数不能放在循环里!!!!!!所以一般把它都放在 按键触发 的代码里,实现 :只要点一下按键就保存一下。

但是eeprom_read函数可以放在循环里!!!!  但是又有问题,我循环里读取,如果连续读取两个不同位置的数,那第二个读取会出毛病  ,你要是在第一个和第二个中间加上HAL_Delay(10);这又会影响使用,因为循环里不推荐用HAL_Delay()

解决方案:

将eeprom_read()和eeprom_write都放在  按键触发的代码里,并且不论是读还是写中间都加上HAL_Delay(10);   

最终代码:

		if(key[1].single_flag==1)
		{
			LCD_Clear(Black);
			
			eeprom_write(1,x);//x写进位置1里
			HAL_Delay(10);
			
			sprintf(text,"i2cread_x=%d",eeprom_read(1));				
			LCD_DisplayStringLine(Line5, (unsigned char *)text);
			HAL_Delay(10);
			//////////////////////////////////////////////////////////////
			eeprom_write(2,y);//y写进位置2里
			HAL_Delay(10);
			
			sprintf(text,"i2cread_y=%d",eeprom_read(2));
			LCD_DisplayStringLine(Line6, (unsigned char *)text);
			
			key[1].single_flag=0;
		}

连续读/写时候 一定要主动加时延!!!

addr,data,以及返回值不论是定义成uint8_t还是unsigned char还是char在自己用的时候一般不会有啥区别,也没报错,我的意思是定义8位变量就ok了,定义变量上无需纠结

I2C写的代码: 

uchar eeprom_read(uchar addr)  //读的函数 这里的uchar是我在main.h里定义的 #define uchar unsigned char           
{
	
	I2CStart ();//总线开启
	I2CSendByte(0xa0); //联系芯片,1010 0000      Read: 1    Write:0  
	I2CWaitAck ();//写完之后要等待应答!!!         
	
	I2CSendByte (addr);//发送要读取的地址
	I2CWaitAck ();//写完就可以休息
	I2CStop ();
	//这里的stop和start都得写,我自己测了不写就出问题
	
	I2CStart();
	I2CSendByte(0xa1); //切换到读的模式                                                                       
	I2CWaitAck();//等待一下
	
	uchar data=I2CReceiveByte ();
	I2CWaitAck(); //这里写I2CWaitAck()!!!!不要写I2CSendACK(),我自己实测如果用I2CSendACK()在连续 读取两个不同位置的数时 第二个数可能会读取失败!!!!	        
    I2CStop();
	return data;
}

问题2:读取两个数,第一个数读取,显示全正常  ,,但是读取到的第二个数没反应

其中关注我代码倒数第三行: 这里写I2CWaitAck()!!!!不要写I2CSendACK(),我自己实测如果用I2CSendACK()在连续 写两个不同位置的数时 第二个数可能会写失败!!!!

I2C读取的代码:

void eeprom_write(uchar addr,uchar data)///写入信息
{
	I2CStart ();//总线开启
	I2CSendByte(0xa0); //联系芯片,1010 0000   Read: 1   Write:0   所以是     写
	I2CWaitAck ();//写完之后要等待应答
	
	I2CSendByte (addr);//发送要读取的地址
	I2CWaitAck ();//写完就可以休息
	
	I2CSendByte (data);//把需要的数据发送给芯片
	I2CWaitAck ();
	I2CStop ();
}

其他255可能:

1.PB6,PB7引脚是不是GPIO OUTPUT

2.I2CWaitAck ();有没有哪里缺下

### EEPROM读取的数据类型和内容 在Arduino环境中,EEPROM可以用于持久化存储各种数据类型。对于基本数据类型的读写相对简单,而对于复杂数据类型如结构体,则需要特别处理。 #### 基本数据类型 EEPROM可以直接支持多种基本数据类型的读写操作,包括但不限于: - `byte` 或者 `uint8_t` - `int` 或者 `int16_t` - `long` 或者 `int32_t` - `float` 这些基本数据类型的读写可以通过内置函数完成,例如使用`EEPROM.read()` 和 `EEPROM.write()` 函数[^1]。 ```cpp // 写入单个字节到地址0处 EEPROM.write(0, value); // 从地址0处读取单个字节 byte readValue = EEPROM.read(0); ``` #### 结构体数据类型 当涉及到更复杂的结构体时,直接存取会变得困难。为了保存整个结构体的内容至EEPROM并从中恢复它,通常采用序列化的方法。这意味着要将结构体转换成一系列连续的字节数组形式以便于存储,并能够在稍后将其反序列化回原始状态。 定义如下所示的一个结构体作为例子: ```cpp typedef struct { int a; float b; } MyStruct; ``` 针对上述自定义结构体的操作方式如下: ##### 存储结构体实例 通过指针访问成员变量的方式逐字段复制到指定位置;也可以利用库函数简化此过程,比如`memcpy`配合特定偏移量实现批量拷贝[^3]: ```cpp MyStruct dataToSave; void saveData(int address) { EEPROM.put(address, dataToSave); // 使用put方法自动处理大小端问题 } ``` ##### 加载已存储的结构体实例 同样地,在加载过程中也需要按照相同顺序解析各个部分直至重建完整的对象表示: ```cpp MyStruct loadedData; void loadData(int address){ EEPROM.get(address, loadedData); // get方法负责解包之前打包好的数据 } ``` 需要注意的是,如果目标硬件平台不是Arduino Uno而是其他型号(如ESP系列),则应查阅相应文档确认是否存在差异化的API调用接口。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值