问题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 ();有没有哪里缺下