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。
內存

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章