一、准备
原理图
通过原理图可以看到M24C02分别有时钟线SCL和数据线SDA,对应的引脚分别是PB6和PB7,并且和MCP4017T是在同一个IIC总线。
IIC协议
IIC通信、UART和SPI统称串行通信。IIC可以有一个主机,多个从机,适合短距离传输,例如片间通信,摄像头配置等。
三、CuBeMX配置
将PB5和PB6配置为output模式。
三、代码分析
在工程中添加IIC的底层代码文件。
判断硬件地址
M24C02是2K的芯片。高四位的地址是确定的,所以我们只需要判断低四位地址,A0-A2分别对应原理图中的E1-E3三个引脚,而他们都是接地的,所以只需要得出最后一位就可以了。最后一位是控制读写的,为1就代表R读,此时地址为0xa1,为0则代表W写,地址为0xa0。
内部函数
写函数
根据时序图:
- 发送start开始信号
- 发送设备地址(0xa0)
- 等待应答
- 发送内部地址(0-255)
- 等待应答
- 写入数据
- 等待应答
- 发送停止信号
void EEPROM_Write(uint8_t add, uint8_t data)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(add);
I2CWaitAck();
I2CSendByte(data);
I2CWaitAck();
I2CStop();
}
读函数
根据时序图:
- 发送start开始信号
- 发送设备地址(0xa1)
- 等待应答
- 读取数据
- 等待应答
- 发送stop停止信号
但是我们会发现,没有发送数据地址,由于读模式无法写入地址,因此我们需要先使用写模式写入要读取的数据地址,然后再进行读取数据的操作:
- 发送start开始信号
- 发送设备地址(0xa0)
- 等待应答
- 发送数据地址
- 等待应答
uint8_t EEPROM_Read(uint8_t add)
{
uint8_t val;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(add);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
val = I2CReceiveByte();
I2CWaitAck();
I2CStop();
return val;
}
测试
每次启动板子都会是val的值加一,其值存储在地址0中。
val = EEPROM_Read(0);
EEPROM_Write(0, ++val);