51单片机——I2C总线EEPROM

我们可以把数据保存在EEPROM中,这样断电数据也不会丢失。

常用的串行总线协议:

目前常用的微机与外设之间进行数据传输的串行总线主要有I2C总线、SPI总线和SCI总线。

I2C总线:以同步串行2线方式进行通信(一条时钟线,一条数据线)。

SPI总线:则以同步串行3线方式进行通信(一条时钟线,一条数据输入线,一条数据输出线)。

SCI总线:是以异步方式进行通信(一条数据输入线,一条数据输出线)。

1-wire  即单线总线,又叫单总线。

例子:

1-wire ——数字温度传感器DS18B20

IIC——oled屏幕


I2C串行总线的组成及工作原理

I2C总线是PHLIPS公司推出的一种串行总线,它只有两根双向信号线。一根是数据线SDA(serial data I/O),另一根是时钟线SCL(serial clock)。

如下图所示,IIC总线上可以挂多个器件,而每个器件都有唯一的地址,这样可以标识通信目标。数据的通信的方式采用主从方式,主机负责主动联系从机,而从机则被动回应数据。

        在多主机系统中,可能同时有几个主机企图启动总线传送数据。为了避免混乱,I2C总线要通过总线仲裁来决定由哪一台主机控制总线。

        但是我们现在学习的单片机一般都是单主机情况。

     I2C总线通过上拉电阻接正电源。当总线空闲时,两根线均为高电平。连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系。


函数

要掌握IIC的通信协议,需要掌握以下几个函数的写法:
1.起始信号 i2c_Start()
2.终止信号 i2c_Stop()
3.写数据 i2c_SendByte()
4.读数据 i2c_ReadByte()
5.发送应答信号 i2c_Ack()
6.发送非应答信号 i2c_Nack()
7.等待应答 i2c_WaitAck()
8.检测I2C总线设备 i2c_CheckDevice


I2C总线传输协议

I2C的起始和终止信号

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

起始和终止信号都是由主机发出的,在起始信号产生后,总线就处于被占用的状态;在终止信号产生后,总线就处于空闲状态。

连接到I2C总线上的器件,若具有I2C总线的硬件接口,则很容易检测到起始和终止信号。

        接受期间收到一个完整的数据字节后,有可能需要完成一些其他工作,例如处理内部中断服务等,可能无法立刻接收下一个字节,这时接收器件可以将SCL线拉成低电平,从而使主机处于等待状态。直到接受器件准备好接收下一个字节时,再释放SCL线使之为高电平,从而使数据传送可以继续进行。

数据位的有效性规定

        SCL为高电平期间,数据线上的数据必须保持稳定,只有SCL信号为低电平期间,SDA状态才允许变化。

I2C字节的传送与应答

    每一个字节必须保证是8位长度。数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)。

应答位的作用

        主机在发送数据时,每次发送一字节数据,都需要读取从机应答位当从机空闲可以接收该字节数据时,从机会发出应答(一帧数据的第9位为“0”当从机正忙于其他工作的处理来不及接收主机发送的数据时,从机会发出非应答(一帧数据的第9位为“1”主机则应发出终止信号以结束数据的继续传送,主机通过从机发出的应答位来判断从机是否成功接收数据。    

        当主机接收数据时,它收到最后一个数据字节后,必须向从机发出一个结束传送的信号。这个信号是由对从机的“非应答”来实现的。然后,从机释放SDA线,以允许主机产生终止信号。


注意:阴影部分是主机的数据,白色部分是从机的数据

I2C写数据流程

        在起始信号后必须传送一个从机的地址(7位)我们开发板上的AT24C02地址为0xa0,第8位是数据的传送方向位(R/T),用“0”表示主机发送数据(T)——写,“1”表示主机接收数据(R)——读

I2C读数据流程

        在读数据时也要先发送器件地址,读写方向为写,因为我们下一帧需要发送从AT24C02内那个单元开始读,之后需在发一次器件地址这个时候读写方向就为读了,接着我们就可以从总线上读取数据。


 

 

 

 从机地址例子(AT24C02的1k),这里不同内存版本的芯片不同可编程位数量。

A0 - A2是可编程位,可以通过控制引脚电平来控制内容

 


软件模拟I2C通信时序

 I2C总线的数据传送有严格的时序要求。I2C总线的起始信号、终止信号、发送“0”及发送“1”的模拟时序 :

代码思路:

/*
*********************************************************************************************************
*   函 数 名: i2c_Start
*   功能说明: CPU发起I2C总线开启信号
*   形    参:  无
*   返 回 值: 无
*********************************************************************************************************
*/
void i2c_Start(void)
{
    /* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */
    SDA = 1;
    SCL = 1;
    i2c_Delay();
    SDA = 0;
    i2c_Delay();
    SCL = 0;
    i2c_Delay();
}


/*
*********************************************************************************************************
*   函 数 名: i2c_Stop
*   功能说明: CPU发起I2C总线停止信号
*   形    参:  无
*   返 回 值: 无
*********************************************************************************************************
*/
void i2c_Stop(void)
{
    /* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */
    SDA = 0;
    SCL = 1;
    i2c_Delay();
    SDA = 1;
    i2c_Delay();
}

/*
*********************************************************************************************************
*   函 数 名: i2c_WaitAck
*   功能说明: CPU产生一个时钟,并读取器件的ACK应答信号
*   形    参:  无
*   返 回 值: 返回0表示正确应答,1表示无器件响应
*********************************************************************************************************
*/
unsigned char i2c_WaitAck(void)
{
     unsigned char re; //应答信号等于0则应答正确,等于1则没有应答
     SDA = 1;          //释放总线,能让对方拉低
     i2c_Delay();
     SCL = 1;          //此时刻开始,数据保持应答状态稳定
     i2c_Delay();
     if(SDA == 1)
     {
        re = 1;        //没有应答
     }
     else
     {
        re = 0;        //应答正确                                                                                                                                                                            
     }
     SCL = 0;
     i2c_Delay();

     return re;
}

/*
*********************************************************************************************************
*   函 数 名: i2c_SendByte
*   功能说明: CPU向I2C总线设备发送8bit数据
*   形    参:  _ucByte : 等待发送的字节
*   返 回 值: 无
*********************************************************************************************************
*/
void i2c_SendByte(unsigned char _ucByte)
{
     unsigned char i;     //其实信号开始后SCL是被拉低的
     for(i = 0; i < 8; i++)
     {
        if(_ucByte & 0x80)
            SDA = 1;
        else
            SDA = 0;
        SCL = 1; 
        i2c_Delay();
        SCL = 0;      //SCL等于0的时候写数据
        if(i == 7)    //最后一次时释放总线
        {
            SDA = 1;
        }
        _ucByte<<=1;  //左移一位
        i2c_Delay();
     }
}


/*
*********************************************************************************************************
*   函 数 名: i2c_ReadByte
*   功能说明: CPU从I2C总线设备读取8bit数据
*   形    参:  无
*   返 回 值: 读到的数据
*********************************************************************************************************
*/
unsigned char i2c_ReadByte(void)
{
     unsigned char i;
     unsigned char value = 0;
     for(i = 0; i < 8; i++)
     {
        value<<=1;
        SCL = 1;  //稳定状态的时候读数据
        if(SDA == 1)
            value++;
        SCL = 0;  //允许数据变化
        i2c_Delay();
     }

     return value;
}


/*
*********************************************************************************************************
*   函 数 名: i2c_Ack
*   功能说明: CPU产生一个ACK信号
*   形    参:  无
*   返 回 值: 无
*********************************************************************************************************
*/
void i2c_Ack(void)
{
    SDA = 0;//响应
    i2c_Delay();
    SCL = 1;
    i2c_Delay();
    SCL = 0;
    i2c_Delay();   //在SCL为高电平期间SDA都为0即产生一个应答信号
    SDA = 1;       //释放总线
    i2c_Delay();
}

/*
*********************************************************************************************************
*   函 数 名: i2c_NAck
*   功能说明: CPU产生1个NACK信号
*   形    参:  无
*   返 回 值: 无
*********************************************************************************************************
*/
void i2c_NAck(void)
{
     SDA = 1;
     i2c_Delay();
     SCL = 1;
     i2c_Delay();
     SCL = 0;
     i2c_Delay();   //在SCL为高电平期间SDA都为1即产生一个非应答信号
}


/*
*********************************************************************************************************
*   函 数 名: i2c_Delay
*   功能说明: I2C总线位延迟,最快400KHz
*   形    参:  无
*   返 回 值: 无
*********************************************************************************************************
*/
static void i2c_Delay(void)
{
    unsigned char i;

    /* 
        IIC 延时时间根据具体情况自行决定for循环延迟时间的大小

        实际应用选择小于400KHz左右的速率即可
    */
    for (i = 0; i < 10; i++);
}

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
gd32f103是一种单片机芯片,它具有多个外设用于实现各种通信功能,其中之一是I2C(Inter-Integrated Circuit)总线I2C总线是一种串行通信协议,用于在多个设备之间传输数据。在gd32f103芯片中,具有多个I2C接口,其中I2C1是其中一个,可以用于与外部设备进行通信,例如EEPROM。 EEPROM(Electrically Erasable Programmable Read-Only Memory)是一种电可擦可编程只读存储器,可以在通电的情况下读写数据。通过I2C1接口,gd32f103可以与EEPROM进行数据的读写操作。 首先,我们需要配置gd32f103的GPIO引脚,将I2C1与EEPROM连接起来。然后,通过初始化I2C1控制器,设置为主模式,并定义通信速率。接下来,发送起始信号,告知EEPROM开始通信。 在读取数据时,我们需要向EEPROM发送一个读取请求,并接收EEPROM返回的数据。在写入数据时,我们需要向EEPROM发送一个写入请求,并传输要写入的数据。 完成数据读写后,我们需要发送一个停止信号,以结束与EEPROM的通信。 在进行I2C1对EEPROM的读写操作时,我们需要注意一些问题。首先,要确保I2C1和EEPROM之间的通信电平适配器的设置正确。其次,要根据EEPROM的规格书仔细了解寄存器和通信协议的细节。最后,要对I2C1进行错误处理,例如处理超时或通信失败的情况,以确保数据的可靠性。 总之,通过gd32f103的I2C1接口,我们可以方便地实现与EEPROM的数据读写操作,为系统提供更多的存储和数据传输方式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值