蓝桥杯嵌入式-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写入数据全部为255的解决方案 在蓝桥杯嵌入式比赛中,遇到EEPROM写入的数据全为255的情况通常是由于以下几个原因引起的: #### 1. **未初始化EEPROM** 如果EEPROM从未被写入过任何有效数据,默认情况下其内部存储单元可能处于高阻态或者默认255(即0xFF)。这是因为大多数EEPROM芯片出厂时所有的位都被设置为逻辑“1”。因此,在首次使用之前需要对其进行初始化[^2]。 #### 初始化方法 可以通过向指定地址范围内逐一写入初始来完成初始化。例如: ```c void eeprom_init() { uint8_t i; for (i = 0; i <= 0xFF; i++) { // 遍历整个地址范围 write_eeprom(i, 0); // 将所有地址位置置零 } } ``` #### 2. **硬件连接问题** 确保IIC总线上的SCL和SDA信号正常工作。如果存在电气干扰或线路接触良等问题,可能会导致通信失败,从而使得读取到的数据始终为255。检查电路连接并确认拉电阻是否合适也很重要[^3]。 #### 3. **软件层面错误** - **延迟足**:某些型号的EEPROM需要一定时间才能完成一次完整的写周期。如果没有足够的延时处理,则可能导致后续操作覆盖掉尚未保存好的旧数据。 解决办法是在每次调用`write_eeprom()`之后加入适当长度的时间间隔。 ```c #define WRITE_DELAY_MS 10 void delay_ms(uint16_t ms); void safe_write_eeprom(uint8_t addr, uint8_t data){ write_eeprom(addr,data); delay_ms(WRITE_DELAY_MS); } ``` - **函数实现当**:仔细核对你所编写的用于访问外部存储器的功能模块是否有误。比如参数传递顺序颠倒、指针指向错误等都会引发异常行为[^4]。 #### 示例代码片段 以下是基于上述分析的一个简单例子展示如何正确地对AT24C02型EEPROM执行基本的操作流程: ```c #include <stdio.h> #include "stm32fxxx_hal.h" // 定义全局变量 #define DEVICE_ADDR 0xA0 >> 1 // AT24C02设备地址右移一位得到实际使用的7bit形式 void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c); uint8_t read_eeprom(uint16_t mem_addr); void write_eeprom(uint16_t mem_addr,uint8_t byte_to_write); int main(void){ uint8_t value; /* MCU Initialization Code */ // 初始化EEPROM eeprom_init(); // 测试写入特定地址 write_eeprom(0xEE,32); write_eeprom(0xEF,64); // 重新启动后验证内容一致性 value=read_eeprom(0xEE); if(value!=32 || read_eeprom(0xEF)!=64 ){ printf("First time run detected!\n"); // 执行必要的初始化动作... eeprom_init(); }else{ printf("Data verified successfully.\n"); } while(1){} } /* IIC驱动部分省略 */ ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值