配置
- 电路原理图
这块开发板使用的是 AT24C02,所以设备地址我们看 1K/2K 这一行
由电路原理图可知,E1/E2/E3 都接地,所以对应的 A0/A1/A2 默认都为0,最后一位表示主机的读写(1:表示读 0:表示写)
最后总结为
写:发送 0xA0
读:发送 0xA1
- cubeMX
将PB6、PB7 设置为GPIO_Input
3. 导入资料包的文件
将资料包中的 i2c - hal.c和i2c - hal.h导入
官方提供的i2c - hal.c文件的头文件有误,要将 #include “i2c.h” ----> #include “i2c - hal.h”
注意修改i2c - hal.c中的I2CWaitAck()函数后部分的语句
SDA_Output_Mode();
SCL_Output(0);
delay1(DELAY_TIME);
return SUCCESS;
//修改为(交换顺序,原顺序在高主频是会错误产生停止条件)
//由于SCL为高电平,SDA下拉是停止信号,这里的SDA转态不稳定,所以SDA_Output_Mode()最好放到后面
SCL_Output(0);
delay1(DELAY_TIME);
SDA_Output_Mode();
return SUCCESS;
程序编写
EERROM的读写方法
- 一个字节
//读取
uint8_t eeprom_read(uint8_t addr)
{
uint8_t date;
I2CStart();
I2CSendByte(0xA0); //器件地址,发送写指令
I2CWaitAck();
I2CSendByte(addr); //内存地址
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0xA1); //发送读指令
I2CWaitAck();
date=I2CReceiveByte();
I2CSendNotAck();
I2CStop();
return date;
}
//写入
void eeprom_write(uint8_t addr, uint8_t data)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(data);
I2CWaitAck();
I2CStop();
}
- 写入和读取一个16bit的数据
//写入
uint16_t val = 89;
uint8_t val_h = val >> 8; //取高8位
uint8_t val_l = val & 0xff; //取低8位
eeprom_write(0x01, val_h);
HAL_Delay(10); //这里要加10ms延时,寄存器的写比EEPROM的读块很多
eeprom_write(0x02, val_l);
//读取
uint16_t eepeom_temp = (eeprom_read(0x01)<<8)+eeprom_read(0x02);
- 字符串
//读取一个字符串
void iic_str_read(unsigned char *buf,uint8_t addr,uint8_t num)
{
I2CStart();
I2CSendByte(0xA0); // 器件地址(写)
I2CWaitAck();
I2CSendByte(addr); // 写数据地址
I2CWaitAck();
I2CStart();
I2CSendByte(0xA1); // 读数据
while(num--)
{
*(buf++) = I2CReceiveByte();
if(num) // 没有接收完
I2CSendAck();
else
I2CSendNotAck();
}
I2CStop();
}
//写入一个字符串
void iic_str_write(unsigned char *buf,uint8_t addr,uint8_t num)
{
I2CStart();
I2CSendByte(0xA0); // 器件地址
I2CWaitAck();
I2CSendByte(addr); // 写数据地址
I2CWaitAck();
while(num--)
{
I2CSendByte(*(buf++));
I2CWaitAck();
}
I2CStop();
delay1(500);
}
- 使用共用体进行数据读写
为了读写float这种类型的数据,可以使用共用体
union eeprom_float
{
float value;
uint8_t data[4];
}float_write, float_read;
将要保存的数据赋值给共用体的value
float_write.value = 1.5;
确定data的空间时,可以使用sizeof()计算类型的空间大小。
//写入
for(int i=0; i<sizeof(float);i++)
{
eeprom_write(0x10 + i, float_write.data[i]);
HAL_Delay(10);
}
//读取
for(int i=0; i<sizeof(float); i++)
{
float_read.data[i] = eeprom_read(0x10 + i);
}
想要拿出读取到数据,只需要读取共用体的value。
sprintf((char *)buf, "%f", float_read.value);
LCD_DisplayStringLine(Line2, buf);