EEPROM读写

1> 实验目的2> AT24C02-灵魂4问?2.1> 长啥样?2.1.1> 实物图2.1.2> 引脚图

2.2> 能干哈?2.3> 咋干的?2.3.1> 内部框图2.3.2> AT24C02设备地址2.3.3> AT24C02存储单元地址

2.4> 咋用他?2.4.1> 硬件设计2.4.2> 程序设计

3> I2C 通信协议3.1> 写1个字节3.2> 读1个字节3.3> 起停信号3.4> 主机写:数据信号3.5> 主机读:数据信号3.6> 应答信号

4> AT24C02时序参数(1000KHz)5> 程序设计5.1> 实现功能5.2> 编程思路5.3> I2C时序-底层驱动5.4> EEPROM 读写程序

6> 实验波形-逻辑分析仪6.1> 写时序6.2> 应答信号细节6.3> 读1字节时序6.4> AT24C02输出数据6.5> 读写时间间隔

7> 视频链接

1> 实验目的

实现51单片机对EEPROM - AT24C02,1字节的读写操作; 通过串口打印到串口终端;

小技巧: 理解I2C,他待会拉高,待会拉低,挺烦人, 可以换个角度思考下,为什么他这样设计;

2> AT24C02-灵魂4问?

2.1> 长啥样?

2.1.1> 实物图

2.1.2> 引脚图

2.2> 能干哈?

AT24C02是EEPROM存储器,可以形象的看作是个【本本】, 用于记录数据

或者想象成一个存储格子

型号含义:

AT24C02:

8Byte X 32 X 8bit = 2048bit; 每个字节的地址为 0x00~0xFF;

2.3> 咋干的?

2.3.1> 内部框图

2.3.2> AT24C02设备地址

高4位固定位“1010”, A2~A0由外部电路配置,拉高为1,拉低为0; 从机只有一个器件时, 通常都拉低,所以为【1010 000X】;

2.3.3> AT24C02存储单元地址

AT24C02 存储单元地址范围:0x00 ~ 0xFF;共256字节;

2.4> 咋用他?

2.4.1> 硬件设计

2.4.2> 程序设计

单片机 通过I2C通信来读写,AT24C02

3> I2C 通信协议

IIC总线(Inter-Integrated Circuit)

传输方式:串行; 传输方向:半双工; 同步方式:同步;

速度: 标准模式:100Kbit/s; 快速模式:400Kbit/s; 高速模式:3.4Mbit/s;

3.1> 写1个字节

流程图:

时序图:

3.2> 读1个字节

流程图:

注意:读写控制为,写为“0”,读为1;

随机读1字节,时序图:

3.3> 起停信号

起始信号:SCL高电平期间,SDA产生下降沿,表示开始传输数据;

停止信号:SCL高电平期间,SDA产生上升沿,表示结束传输数据;

3.4> 主机写:数据信号

在每个SCL的上升沿,【主机】51单片机将SDA数据写入【从机】AT24C02; 所以在SCL的上升沿到来前,需要将数据在SDA上放好; 第8个SCL下降沿,【主机】51单片机要释放SDA,为AT24C02拉低SDA做准备;

3.5> 主机读:数据信号

【从机】AT24C02,在每个SCL的下降沿,向SDA写数据; 那么【主机】51单片机就可以在上SCL的上升沿和高电平期间读数据;

3.6> 应答信号

主机:SCL高电平期间,向SDA写0应答,写1非应答; 从机:SCL高电平期间,向SDA写0应答,写1非应答;

这样设计很合理, 把总线拉低,代表有响应,就是应答信号, 总线拉高,总线空闲,正好就是非应答,不回应了;

4> AT24C02时序参数(1000KHz)

写周期最大为5ms

5> 程序设计

5.1> 实现功能

实现对AT24C02,1字节的读写操作模块; 通过串口打印到串口终端;

5.2> 编程思路

参考其他人代码,总结;

1》 实现,启动,停止,读写数据,应答,单个操作代码,然后拼装整个时序; 2》 IIC时序时一层代码,对AT24C02的读写是上一层;

5.3> I2C时序-底层驱动

/**

* @brief : I2C start condition

*/

void I2C_Start(void)

{

I2C_SDA = 1; // 初始化

I2C_SCL = 1;

I2C_SDA = 0; // SCL高电平期间,SDA拉低,产生下降沿;

I2C_SCL = 0;

}

/**

* @brief : I2C Stop condition

*/

void I2C_Stop(void)

{

I2C_SDA = 0;

I2C_SCL = 1;

I2C_SDA = 1; // SCL高电平期间,SDA产生上升沿;

}

/**

* @brief :Master wait Acknowledge of Slave

*/

void I2C_Wait_Ack(void)

{

I2C_SCL = 1;

// 判断AT24C02是否拉低,暂时忽略

I2C_SCL = 0;

}

/**

* @brief :Master send No Acknowledge to Slave

*/

void I2C_Write_NAck(void)

{

I2C_SDA = 1;

I2C_SCL = 1;

I2C_SCL = 0;

}

/**

* @brief : Master write byte

* @dat : 8-bit data

*/

void I2C_Write_Byte(uchar8_t dat)

{

uchar8_t i = 0;

for (i = 0; i < 8; i++) {

I2C_SDA = dat >> 7; // 先发高位bit7

dat = dat << 1;

I2C_SCL = 1;

I2C_SCL = 0;

}

I2C_SDA = 1; // 51单片机释放总线

}

/**

* @brief : Master Read byte

* @retval : 8-bit data from AT24C02

*/

uchar8_t I2C_Read_Byte(void)

{

uchar8_t i = 0;

uchar8_t dat = 0;

for (i = 0; i < 8; i++) {

I2C_SCL = 1;

dat = dat << 1;

dat |= I2C_SDA; // 先接收高位

I2C_SCL = 0;

}

return dat;

}

5.4> EEPROM 读写程序

/**

* @brief : Master wrie byte

* @device_addr : device address Byte

* @word_addr : Word address Byte

* @dat : 8-bit Data word

*/

void EEPROM_Write_Byte(uchar8_t device_addr, uchar8_t word_addr, uchar8_t dat)

{

I2C_Start();

I2C_Write_Byte(device_addr);

I2C_Wait_Ack();

I2C_Write_Byte(word_addr);

I2C_Wait_Ack();

I2C_Write_Byte(dat);

I2C_Wait_Ack();

I2C_Stop();

}

/**

* @brief : Master random read byte

* @device_addr : device address Byte

* @word_addr : Word address Byte

* @retval : 8-bit Data word from AT24C02

*/

uchar8_t EEPROM_Read_Byte(uchar8_t device_addr, uchar8_t word_addr)

{

uchar8_t dat = 0;

/* 第1阶段:伪写 */

I2C_Start();

I2C_Write_Byte(device_addr);

I2C_Wait_Ack();

I2C_Write_Byte(word_addr);

I2C_Wait_Ack();

/* 第2阶段:读数据 */

I2C_Start();

I2C_Write_Byte(device_addr | 0x01); // read

I2C_Wait_Ack();

dat = I2C_Read_Byte();

I2C_Write_NAck();

I2C_Stop();

return dat;

}

6> 实验波形-逻辑分析仪

6.1> 写时序

0x0F是为方便观察应答信号,写的值;

6.2> 应答信号细节

不用逻辑分析仪抓下波形,还就真不知道!有意思

6.3> 读1字节时序

6.4> AT24C02输出数据

6.5> 读写时间间隔

7> 视频链接

 B站视频

好文链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: