RISC单片机EEPROM实战/IIC通讯

EEPROM

采用的是BL24C02P芯片,该芯片具体请看我之前写的文章,有对该芯片进行介绍

这种EEPROM都差不多,可以举一反三

http://t.csdnimg.cn/NcEIp

IIC简介

EEPROM(Electrically Erasable Programmable Read-Only Memory)是一种电子可擦可编程只读存储器。它结合了EPROM(Erasable Programmable Read-Only Memory,可擦可编程只读存储器)的可擦除特性和EEPROM的电气编程能力,使得数据可以在不需要从电路板中移除芯片的情况下进行擦除和重新编程。

EEPROM的主要特点包括:

  1. 电可擦除:与EPROM需要紫外线照射来擦除数据不同,EEPROM的数据可以通过电信号来擦除,这使得EEPROM在应用中更加方便和灵活。

  2. 可编程:EEPROM允许用户通过编程来存储和修改数据,这使得它非常适合于需要存储配置信息、校准数据或程序代码的场合。

  3. 耐用性:虽然EEPROM的写入次数有限(通常可以擦写数十万次到数百万次不等,具体取决于具体型号和制造工艺),但它比传统的ROM(只读存储器)要耐用得多,因为它可以多次擦写。

  4. 非易失性:与RAM(随机存取存储器)不同,EEPROM在断电后不会丢失存储的数据,这使得它非常适合用于需要长期保存数据的场合。

  5. 容量:EEPROM的容量相对较小,通常从几KB到几MB不等,这使得它在需要小量存储空间的场合非常有用。

  6. 封装形式:EEPROM通常以DIP(双列直插式封装)、SOP(小外形封装)或TSOP(薄小外形封装)等形式存在,易于集成到各种电子设备中。

EEPROM广泛应用于各种需要存储少量但重要数据的电子设备中,如计算机、通信设备、汽车电子设备、医疗设备以及消费电子产品等。在这些应用中,EEPROM通常用于存储配置设置、校准参数、序列号、固件更新或任何其他需要在设备使用过程中保持不变或可更新的数据。

IIC优势

IIC(Inter-Integrated Circuit),也称为I2C,是一种由飞利浦公司(现在的恩智浦半导体)开发的用于短距离数字通信的串行、同步、半双工通信接口协议。IIC总线具有多方面的优势,以下是其主要的优势点:

1. 简单性和易用性

  • 物理链路简单:IIC总线只需要SDA(串行数据)和SCL(串行时钟)两条信号线,相比于其他通信协议(如PCI/LocalBus需要几十根信号线,SPI总线至少需要4根信号线)要简单得多。这使得硬件实现方便,扩展性也非常好。
  • 协议简单:IIC总线的通信协议相对简单,易于理解和实现,减少了开发难度。

2. 节省硬件资源

  • 节省引脚:由于只需要两根信号线,IIC总线能够大大节省硬件引脚,这对于引脚数量受限的集成电路特别有利。
  • 小型化设计:采用IIC总线的器件封装更容易实现小型化,对PCB空间的要求较小,降低了设备的整体成本。

3. 多设备连接

  • 多主多从架构:IIC总线支持多主设备和多从设备的连接,这意味着一个主设备可以与多个从设备进行通信,而且多个主设备之间也能够协调地进行通信。这种灵活性在复杂的系统中非常有用。
  • 设备识别:每个挂在IIC总线的设备都有唯一的地址来标识,确保了不同设备之间访问的准确性。

4. 可靠性和稳定性

  • 差分信号传输:IIC总线使用差分信号传输,对电气噪声和干扰的抵抗能力较强,提高了通信的稳定性和可靠性。
  • 故障诊断和调试简单:由于IIC总线信号线少、协议简单,因此故障诊断和调试相对容易。

5. 低功耗

  • 低功耗设计:IIC总线通信协议相对简单,其实现通常需要较少的功耗,这对于依赖电池供电的设备尤为重要。

6. 多速率支持

  • 多种速率模式:IIC总线协议支持不同的传输速率,包括标准模式(最高100kbit/s)、快速模式(最高400Kbit/s)、快速模式增强模式(最高1Mbit/s)和高速模式(最高3.4Mbit/s),满足不同带宽要求的应用场景。

7. 广泛的应用领域

  • 广泛应用:IIC总线在现代电子领域得到广泛应用,特别是在物联网(IoT)、嵌入式系统、消费电子、工业自动化、汽车电子、医疗设备等领域。其通用性使得它能够满足不同应用的通信需求。

IIC物理接线

查了资料,3.3v电源最小接1k电阻

5v电源最小接1.5k电阻

IIC时序图

IIC起始/结束信号

SCL 线为高电平期间,SDA 线由高电平向低电平的变化表示起始信号;SCL 线为高电平期间,SDA 线由低电平向高电平的变化表示终止信号。如下图:

IIC数据有效性

IIC应答非应答

每当发送器件传输完一个字节的数据后,后面必须紧跟一个校验位,这个校 验位是接收端通过控制 SDA(数据线)来实现的,以提醒发送端数据我这边已经 接收完成,数据传送可以继续进行。这个校验位其实就是数据或地址传输过程中 的响应。响应包括“应答(ACK)”和“非应答(NACK)”两种信号。

非应答就是上图拉低的ack信号,选择不拉低

EEPROM写入等待时间

EEPROM写入读出规范

EEPROM地址

写入时最后一位地址为1时为读取,电平为0时为读出

写入

字节写入

写入操作需要一个 8 位数据字地址,紧跟在设备地址字和确认之后。收到此地址后,BL24C02P将再次以“0”响应,然后输入第一个 8 位数据字。在收到 8 位数据字后,BL24C02P将输出“0”,并且寻址设备(例如微控制器)必须以停止条件终止写入序列。然后,BL24C02P进入内部定时写入周期,在此写入周期内,所有输入都被禁用,并且在写入完成之前,BL24C02P不会响应

本文中用的是这种写入方式,更多的操作可以看我之前的文章

http://t.csdnimg.cn/NcEIp

读出

任意地址读出

也叫做随机读取

随机读取需要在数据字地址中加载一个“虚拟”字节写入序列。一旦器件地址字和数据字地址被输入并被BL24C02P确认,微控制器就必须生成另一个启动条件。微控制器现在通过发送具有读/写选择位高电平的设备地址来启动当前地址读取。BL24C02P确认设备地址并串行输出数据字。微控制器不会以“0”响应,但会生成以下停止条件

本文中用的是这种读出方式,更多的操作可以看我之前的文章

http://t.csdnimg.cn/NcEIp

IIC写EEPROM实战

了解了上面这些基础就可以进行实战了

首先我们要把,起始信号,终止信号,应答,非应答的信号用代码表示出来

引脚配置

根据不同的芯片有不同的配置方法,这边我就不写出来了

主要配置两个端口

scl时钟线:一直配置成输出就好了,输出配置成开漏输出

sda信号线:先配置成开漏输出模式,需要输入时再把引脚配置成输入模式

起始信号

void IIC_Start(void)
{     	
    
    EE_SDA=1;// SDA=1   
    EE_SCL=1;// CLK=1
    delay_1us(20);             // start hold 保持时间,必须大于4.7us
    EE_SDA=0;                 // SDA=0
    delay_1us(20);               // start hold 保持时间,必须大于4.7us
    EE_SCL=0;               // CLK=0
    delay_1us(20);                // start hold 保持时间,必须大于4.7us
}

终止信号

void IIC_Stop(void)
{
    
    EE_SCL=0;                 // CLK=0
    delay_1us(20);  
    EE_SDA=0;                 // SDA=0
    delay_1us(20); 
    EE_SCL=1;                 // CLK=1
    delay_1us(20); 
    EE_SDA=1;                 // SDA=1
}

应答

void IIC_ACK(void)
{
     EE_SCL=0;                 // SCK=0
     EE_SDA=0;                  // SDA=0
     delay_1us(20); 
     EE_SCL=1;                  // SCK=1
     delay_1us(20); 
     EE_SCL=0;                 // SCK=0
}

非应答

void IIC_NACK(void)
{
     EE_SCL=0;                 // SCK=0
     EE_SDA=1;                  // SDA=1
     delay_1us(20); 
     EE_SCL=1;                  // SCK=1
     delay_1us(20); 
     EE_SCL=0;                 // SCK=0
}

接收应答代码

判断EEPROM有无传回ack回应

unsigned char IIC_Wait_Ack()
{
   	unsigned char ack = 0;
   	EE_SDA = 1;
   	EE_SCL = 0;    	    
   	delay_1us(20); 
   	EE_SCL = 1;
   	delay_1us(20); 
   	if(EE_SDA == 0) //检测数据线SDA是否被拉低
   	   	ack = 1;
   	else 
   	   	ack = 0;
   	EE_SCL = 0;
   	return ack;
}

发送字节代码

void IIC_WriteB(char data)
{
    char i;             
    DDR1&= 0x7f; //代表把SDA引脚配置成输出
    for (i=0; i<8; i++)              // send One byte
    {
        EE_SCL=0; // SCK=0
        delay_1us(20);                 
        if (data & 0x80)      //获取最高位
        {
            EE_SDA=1;            // DA=1 
        }                               
        else                            
        {
             EE_SDA=0;              // DA=0 
        } 
        EE_SCL=1; 
        delay_1us(20);                   
        data <<= 1;
    }
    EE_SCL=0;
 
}

接收一个字节代码

char IIC_ReadB()
{
    char i; 
    char Byt;
   	Byt=0;                           //
    DDR1|= 0x80;                   //设为输入,可以更据不同芯片进行代码替换
    for (i=0;i<8;i++)                    //
    {
        Byt <<= 1;              // Clock high time
         EE_SCL=0;                  // sclk=0
       delay_1us(20);
        EE_SCL=1;                 // sclk=1
       delay_1us(20);  
        if (EE_SDA)               // 接收到1
        {
           Byt |= (0x01);        // 数据末位置1 (+1)
        }                               //
    }                                   //
        EE_SCL=0;                 // sclk=0
        DDR1&= 0x7f;            //重新设置为输出
   	   	return Byt;                   
        //IIC_NACK();        //发送nACK,没用到
        //IIC_ACK();         //发送ACK  没用到
      
}

单字节写入EEPROM

void EEPROM_Write(unsigned char addr, unsigned char dat)
{
   	IIC_Start();
   	IIC_WriteB(0xA0); //发送I2C设备地址
    IIC_Wait_Ack();      //等待从机响应
   	IIC_WriteB(addr); //发送要写入的内存地址
   	IIC_Wait_Ack();
   	IIC_WriteB(dat);  //写入数据
   	IIC_Wait_Ack();
   	IIC_Stop();
   	delayms(10);     //写周期
}

单字节读EEPROM

char EEPROM_Read(unsigned char addr)
{
   	char dat = 0, i = 0;
   	IIC_Start();
   	IIC_WriteB(0xA0); //发送I2C设备地址
   	IIC_Wait_Ack();      //等待从机响应
   	IIC_WriteB(addr); //发送要写入的内存地址
   	IIC_Wait_Ack();
      
   	IIC_Start();
   	IIC_WriteB(0xA1); //发送I2C设备地址(读数据)
   	IIC_Wait_Ack();       //等待从机响应
   	dat = IIC_ReadB(); //读取数据
   	IIC_Wait_Ack();
   	IIC_Stop();
   	return dat;
}

主程序调用

验证代码的可行

只需看最后两行即可不用看其他的代码

仿真验证

可以看到T1DATA变成了给的0x55。

现在换个赋值,可以看到赋值为0x44时,T1DATA的值也变成了0x44。

  • 16
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值