I2C通讯EEPROM

文章讨论了在使用I2C协议与EEPROM交互时遇到的数据错误问题,特别是关于写入时的时序细节,包括停止信号、起始信号、地址发送和ACK信号的解释。作者发现EEPROM在特定时序下的锯齿波是正常现象,并非导致数据错误的原因。此外,文章还提到了EEPROM在掉电保护后可能出现的数据丢失问题,强调了先写后读的重要性。
摘要由CSDN通过智能技术生成

1。对I2C写数据的时候,首先发一个停止信号,确保接下来发送新的数据保存至EEPROM。

2。发送起始信号

3。发送EEPROM设备地址

根据对应的EEPROM,规格书,以及线路图,发送地址。

根据线路图A0,A1,A2接地,表示 都是0,最后一位是写操作,则为1。

最终地址 是0XA0 |1

 4。发送EEPROM数据地址,8位8位的发。

5。开始发送数据

6.完成之后,发送停止信号 .

如上图,在发送 0XA1的时候,在第九个时序,的下降沿,从机EEPROM会生成一个高电平。

如以此图更清晰,正好是第九个时序的下降沿,会出现这样一个锯齿形的高电平。

因为我的代码在写数据进EEPROM的时候,存在数据出错的问题。

一开始我以为这个锯齿形脉冲,就是从机返回的非应答信号。ACK信号。

所以我以为是我的应答函数出现了问题。

但是怎么改,这个锯齿波一直是在第九个时序的下降出现,然后,我翻阅规格书。

我用的AT24C32D-SSHM-T的EEPROM.,发现它的写时序 中也存在这样一个锯齿波。如下图

这么第一个锯齿波,规格书上也没有详细的说明。接着,我又翻阅其它EEPROM的。

以下是 AT24C02的规格书写时序 :

发现也有这样一个小尖波,如此,我就认为这不是偶尔的事情。随后,我查询资料,发现这样一片文章。在这里插入图片描述

在ACK位有时候会出现一个小脉冲,不过这个脉冲出现在时钟的低电平,不会对IIC时序判决有影响。

为什么会出现这个脉冲呢?
ACK位一般标志着主机和从机对总线控制权的转换:
1、主机为发送端发送地址位,从机为接收端接收地址位;
2、主机发送写信号,需要往从机写数据;
3、从机接收到信号,响应,在这一个bit位,主机释放总线变为接收端,从机变为发送端获取总线控制权。之后再将控制权交还给主机,用于后面的写操作,这个交换的过程存在时间差,主机拉SDA晚了,就有可能出现上面这种情况(理论上讲,前一次交换也可能出现这种现象;如果是读操作,一般就观察不到这种现象了)。

经此,我才确定,我的写时序应该没有什么问题。

第二个有关EEPROM的问题。

我的程序 都已经调试完成,但换上新板子之后,数码管显示 36,(这应该是EEPROM存储单元的随机数)。因为我的程序 是在程序 启动的时候,进入读EEPROM,但因为掉电保护的问题,0-3的单元,调电时间一久,就出现保存不住的情况,所以,我将其换成了226-228,但是这三个单元从来没有进行写操作,出现的现象就是板子上电启动,数码管只显示一个3,这表面上就好像程序 没有运行一样。

随后我将其改回0-3,则恢复正常。

从而得出,如果EEPROM没有写之前 就去读,有可能出现未知的问题。还是先做一次写再说。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
I2C通讯协议是一种串行通讯协议,用于在微控制器和外部设备之间传输数据。在51单片机和STC90C52RC单片机中,可以使用硬件I2C模块来实现I2C通讯。下面是一个简单的I2C通讯协议代码示例: ```c #include <reg52.h> // 定义I2C总线的速率 #define I2C_SPEED 100000UL // 定义EEPROM的地址 #define EEPROM_ADDR 0xA0 // 定义EEPROM的写入命令 #define EEPROM_WRITE_CMD 0xA0 // 定义EEPROM的读取命令 #define EEPROM_READ_CMD 0xA1 // 初始化I2C总线 void i2c_init() { // 设置I2C总线的速率 TH1 = 256 - (FOSC / (I2C_SPEED * 12 * 2)); TL1 = TH1; // 启动定时器1 TR1 = 1; // 设置I2C总线的工作模式 SCON = 0x50; // 设置I2C总线的地址 ADDR = 0xA0; // 使能I2C总线中断 ES = 1; // 使能全局中断 EA = 1; } // 向EEPROM写入一个字节数据 void eeprom_write_byte(unsigned char addr, unsigned char data) { // 发送起始信号 i2c_start(); // 发送EEPROM的地址和写入命令 i2c_send_byte(EEPROM_ADDR | EEPROM_WRITE_CMD); // 发送EEPROM的地址 i2c_send_byte(addr); // 发送数据 i2c_send_byte(data); // 发送停止信号 i2c_stop(); } // 从EEPROM读取一个字节数据 unsigned char eeprom_read_byte(unsigned char addr) { unsigned char data; // 发送起始信号 i2c_start(); // 发送EEPROM的地址和写入命令 i2c_send_byte(EEPROM_ADDR | EEPROM_WRITE_CMD); // 发送EEPROM的地址 i2c_send_byte(addr); // 发送起始信号 i2c_start(); // 发送EEPROM的地址和读取命令 i2c_send_byte(EEPROM_ADDR | EEPROM_READ_CMD); // 读取数据 data = i2c_recv_byte(); // 发送停止信号 i2c_stop(); return data; } // I2C总线中断服务函数 void i2c_isr() interrupt 8 { // TODO: 处理I2C总线中断事件 } int main() { // 初始化I2C总线 i2c_init(); // 向EEPROM写入数据 eeprom_write_byte(0x00, 0x55); // 从EEPROM读取数据 unsigned char data = eeprom_read_byte(0x00); return 0; } ``` 在上面的代码中,我们定义了一些常量,如I2C总线的速率、EEPROM的地址、写入命令和读取命令等。然后,我们编写了一些函数,如i2c_init()用于初始化I2C总线,eeprom_write_byte()用于向EEPROM写入一个字节数据,eeprom_read_byte()用于从EEPROM读取一个字节数据等。最后,在主函数中调用这些函数来实现I2C通讯

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值