使用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。