zl程序教程

您现在的位置是:首页 >  工具

当前栏目

I2C知识大全系列五 —— I2C应用之单片机中的I2C

应用单片机 知识 I2C 全系列
2023-09-14 09:15:40 时间

实际上单片机中并不严格区分驱动和应用(当然也有一些代码即使在单片机程序中也分了很多层,抽象出了驱动层和应用层,甚至还有中间层),因此在这里,列举一个常见的51单片机下的i2c应用程序。

51系列单片机下的i2c程序

总线初始化:将总线拉高以释放总线

时序如下:

代码如下:

void delay(void)
{
    ;
    ;
}
void delay_1ms(uint z)
{
    uint x, y;

    for ( x = z; x > 0; x -- )
        for ( y = 110; y > 0; y -- );
}

void init_I2C ()
{
    sda = 1;
    delay ();
    scl = 1;
    delay ();
}

I2C启动:在SCL为高电平期间,SDA出现下降沿

时序如下:

代码如下:

void start() 
{
    sda = 1;
    delay ();
    scl= 1;
    delay ();
    sda = 0;
    delay ();
}

I2C停止:在SCL高电平期间,SDA上产生一上升沿

时序如下:

代码如下:

void stop() 
{
    sda = 0;
    delay ();
    scl = 1;
    delay ();
    sda = 1;
    delay ();
}

 应答信号:在SCL高电平期间,SDA被从设备拉低表示应答

 时序如下:

代码如下:

void ack()
{
    uchar i = 0;

    sda = 0;
    _nop_();
    _nop_();
    scl = 1;
    delay ();
    while ( i < 250 )
        i++; 
    scl = 0;
    delay ();
}

应答信号:在SCL高电平期间,SDA保持高表示非应答

时序如下:

 代码如下:

void nack()
{
    uchar i = 0;

    sda = 1;
    _nop_();
    _nop_();
    scl = 1;
    delay ();
    while ( i < 250 )
        i++;
    scl = 0;
    delay ();
}

 写入一个字节

void write_byte(uchar date)
{
    uchar i, temp;

    temp = date;
    for (i = 0; i < 8; i++)
    {
        temp = temp << 1;
        scl = 0;
        delay ();
        sda = CY;
        delay ();
        scl = 1;
        delay ();
    }
    scl = 0;
    delay ();
    sda = 1;
    delay ();
}

读取一个字节

uchar read_byte()
{
    uchar i, k = 0;

    scl = 0;
    delay ();
    sda = 1;
    delay ();
    for (i = 0; i < 8; i++)
    {
        scl = 1;
        delay ();
        k = (k << 1) | sda;
        delay ();
        scl = 0;
        delay ();
    }

    return k;
}

AT24C02指定单元地址写入一字节数据

void write_at24c02(uchar addr, uchar data)
{
    start();
    write_byte(AT24C02_ADDR + 0);   
    ack();
    write_byte(addr);
    ack();
    write_byte(data);
    ack();
    end();
}

AT24C02指定单元地址读取一字节数据

uchar read_at24c02(uchar addr)
{
    uchar data;

    start();
    write_byte(AT24C02_ADDR + 0);
    ack();
    write_byte(addr);
    ack();
    start();
    write_byte(AT24C02_ADDR + 1);
    ack();
    data = read_byte();
    end();

    return data;
}

向存储单元211写入数据0xae,然后在再从存储单元211中读取出来送给P1led显示

void main()
{
    write_at24c02(211, 0xae);
    delay_10ms();  //写完后,必须延时一定的时间才可以读取,否则不行
    P1 = read_at24c02(211);
    ……
}

这里只是列举了一个51单片机下的I2C应用程序。实际上单片机I2C应用程序有很多,因为单片机的种类本身就有很多,如:51系列单片机、AVR单片机、PIC单片机、STM系列、NXP LPC系列等等;而I2C的方法又包括硬件I2C和软件I2C;即使同一种单片机,不同人编写的程序也可能差异较大。因此,单片机I2C应用程序可以说千差万别、种类繁多。在此,由于不是本文重点,只介绍一种最为基本的51单片机,采用软件I2C的方式就可以了。