AT89C51使用I2C总线扩展AT24C02


  使用C51扩展24C04,在24C04中写入数据"Qing Ye Mu Rong!",再从24C04中读取"Qing Ye Mu Rong!"并保存在C51内存之中。LED灯亮表示写入成功,根据存取状态返回值判断。

AT24C04简介

24C04

  • 24C02是一个2K位串行CMOS 的EEPROM,内部含有256个8位字节。
  • 引脚简介:
		VCC和VSS是芯片的电源和地,电压的工作范围为:+1.8V~+6.0V。
		A0、A1、A2是IC的地址选择脚。
		WP是写保护使能脚。当WP引脚接高电平的时,24C02只能进行读取操作,不能进行写操作。只有当WP引脚悬空或接低电平时,24C02才能进行写操作。
		SCL/SCK是I2C通讯时钟引脚。
		SDA是I2C通讯数据引脚

电路原理图

青烨慕容

C代码

#include <reg52.h>
//#include <intrins.h>
#include <stdio.h>
#define uchar unsigned char
#define uint unsigned int

#define HIGH 1
#define LOW 0
#define FALSE 0
#define TRUE ~FALSE
#define BLOCK_SIZE 16  //读写块大小
//uchar EAROMImage[16] = "Hello everybody!"  ;//定义写入数据
uchar EAROMImage[16] = "Qing Ye Mu Rong!"  ;//定义写入数据
uchar transfer[16];
uchar *point;
uchar WRITE, READ;
sbit SCL = P1^6;
sbit SDA = P1^7;
sbit P07 = P0^7;

void delay(void)
{
    ;
}
//延时
void DelayMS(uint x)
{
    uchar t;
    while(x--)
    {
        for(t = 120; t > 0; t--);
    }
}
void wait_5ms(void)
{
	uint i;
	for(i=0;i<1000;i++)
	;
}
//I2C总线起始函数
void I2c_Start(void)
{
    SCL = HIGH;
    delay();
    SDA = LOW;
    delay();
    SCL = LOW;
    delay();

}
//I2C停止
void I2c_Stop(void)
{
    SDA = LOW;
    delay();
    SCL = HIGH;
    delay();
    SDA = HIGH;
    delay();
    SCL = LOW;
    delay();
}
//I2C初始化
void I2C_Init(void)
{
    SCL = LOW;
    I2c_Stop();
}
//I2C总线时钟函数
bit I2c_Clock(void)
{
    bit sample;
    SCL = HIGH;
    delay();
    sample = SDA;
    SCL = LOW;
    delay();
    return (sample);
}
//数据发送函数   发送8位数据 请求应答信号ACK 收到ACK则返回1.否则0
bit I2c_Send(uchar I2c_Data)
{
    uchar i;
    for(i = 0; i < 8; i++)
    {
        SDA = (bit)(I2c_Data & 0x80); //取出最高位并送出SDA
        I2c_Data = I2c_Data << 1;//左移一位
        I2c_Clock();
    }
    SDA = HIGH ;
    return (~I2c_Clock());
}
//接受数据
uchar I2c_Receive(void)
{
    uchar I2c_Data = 0;
    uchar i;
    SDA = HIGH;  //必须先使SDA为高电平
    for (i = 0; i < 8; i++)
    {
        I2c_Data*=2;
        if(I2c_Clock())
        {
            I2c_Data++;

        }
    }
    return (I2c_Data);

}

//应答信号 向I2C总线发送一个应答信号ACK
void I2c_Ack(void)
{
    SDA = LOW;
    I2c_Clock();
    SDA = HIGH;
}
//地址写入  向24C02 写入器件和指定的字节地址
bit Ep_Address(uchar Address)
{
    I2c_Start();
    if(I2c_Send(WRITE))
        return(I2c_Send(Address));
    else
        return (FALSE) ;
}
//数据读取 从24C02 指定地址BLOCK_SIZE 读取并且转存在8051内RAM
// 采用序列方式连续读取数据地址 如果不接受指定地址则返回0
bit Ep_Read_Block(uchar start)
{
    uchar i;
    if(Ep_Address(start))
    {
        I2c_Start();
        if(I2c_Send(READ))
        {
            for(i = 0; i < BLOCK_SIZE; i++)
            {
                transfer[i] = (I2C_Receive());
                if(i != BLOCK_SIZE)
                {
                    I2c_Ack();

                }
                else
                {
                    I2c_Clock();
                    I2c_Stop();
                }
            }
            return (TRUE);
        }
        else
        {
            I2c_Stop();
            return (FALSE);
        }

    }
    else
    {
        I2c_Stop();
			}
        return (FALSE);
}
//写入数据函数  将数据写入24C02指定的地址开始的BLOCK_SIZE字节
//每次写入都要指定片内地址
bit Ep_Write_Block(uchar start)  //start为写入首地址
{
    uchar i;
    for(i = 0; i < BLOCK_SIZE; i++)
    {
        if(Ep_Address(i + start) && I2c_Send(EAROMImage[i])) //i+star 为I2c中当前地址
        {
            I2c_Stop();
            wait_5ms();//延时5ms
        }
        else
            return(FALSE);
    }
    return (TRUE);
}
//主函数
void main()
{
    bit g, gg;
    uchar add = 0x50; //定义24C02片内地址
    WRITE = 0xA0;    //定义24C02写入地址
    READ = 0xA1;    //定义24C02读取地址
    I2C_Init();
    g = Ep_Write_Block(add);  //向24C02写入数据
    gg = Ep_Read_Block(add) ;  //从24C02读取数据
	  P07 = 0;
    while(1)
		{
			if(gg!=0&&g!=0)
			{
				P07 = 0;
				DelayMS(500);
			}
			else
			{
				P07 = 1;
				DelayMS(500);
			}
			P07 = 1;
			DelayMS(500);
		}
}



仿真效果

  在Proteus仿真界面查看数据是否写入,可以看到数据已经成功的写入了24C02。
内存

猜你喜欢

转载自blog.csdn.net/weixin_45488643/article/details/106726013