使用C51擴展24C04,在24C04中寫入數據"Qing Ye Mu Rong!",再從24C04中讀取"Qing Ye Mu Rong!"並保存在C51內存之中。LED燈亮表示寫入成功,根據存取狀態返回值判斷。
AT24C04簡介
- 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。