您的位置 首页 电路

51单片机 I2C AT24C02

I2C协议在项目开发中使用很常见,很多存储芯片使用I2C接口。由于51单片机没有I2C接口,这里使用IO口模拟I2C通讯协议,来完成I2C芯片驱动

I2C协议在项目开发中运用很常见,许多存储芯片运用I2C接口。由于51单片机没有I2C接口,这儿运用IO口模仿I2C通讯协议,来完结I2C芯片驱动。运用的I2C芯片为AT24C02

原理图如下:

代码如下:

//程序功用:计时器每一秒向AT24C02坚持数据,一起数码管显现,重启之后读取出数据接着计时,100S循环
//程序问题:无法写入
#include
#define uint unsigned int
#define uchar unsigned char
//变量界说
uint timer_flag; //用于判别定时器T0方法一是否计满1s
uchar shiwei,gewei; //数码管显现的十位与个位
uint number;
uchar time_date; //当时时刻数据
//操控端口声明
sbit duanxuan=P2^6; //数码管段选端
sbit weixuan=P2^7; //数码管位选端
sbit AT24C02_SDA=P2^0; //AT24C02串行数据输入输出端口
sbit AT24C02_SCLK=P2^1; //时钟信号端口
//数码管显现数字段码界说
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
//相关函数声明
void delay_minute(); //延时us级函数声明
void delay_xs(uint); //延时s级函数声明
void timer_init(); //定时器T0方法一初始化函数声明
void AT24C02_init(); //I^2C通讯总线初始化函数声明
void star(); //I^2C通讯发动函数声明
void stop(); //I^2C通讯中止函数声明
void response(); //应对函数声明
void write_in_byte(uchar); //写入一个字节函数声明
uchar read_out_byte(); //读出一个字节函数声明,函数放回到读出的值
//留意写入一个字节与写入数据的差异,前者是后者的一个子进程,读取同
void saveing(uchar,uchar); //向AT24C02保存数据函数声明
uchar load(uchar); //从AT24C02载入掉电之前的数据,函数放回到读出的值
void quwei(uchar); //显现数字取出各位与十位
void display(uchar); //数码管显现函数声明
//主函数
void main()
{
AT24C02_init(); //AT24C02初始化
time_date=load(3); //开机首要载入AT24C02中的数据,这儿读取的是第三位址的数据
if(time_date>100) //避免上一次保存的数据是100,这儿计时是100循环的
{
time_date=1;
}
timer_init(); //计时器T0方法一初始化
while(1)
{
display(time_date); //显现时刻
if(timer_flag==1) //假如计满一秒,就保存时刻数据
{
timer_flag=0;
saveing(3,time_date); //保存时刻数据
}
}
}
//延时us级函数主体
void delay_minute()
{;;}
//延时s级函数主体
void delay_xs(uint s)
{
uint i,j;
for(i=s;i>0;i–)
{
for(j=110;j>0;j–)
{
}
}
}
//定时器T0方法一初始化函数主体
void timer_init()
{
//方法挑选
TMOD=0x01;
//预装初值
TH0=(65536-46080)/256;
TL0=(65536-46080)%6;
//开中止
EA=1;
ET0=1;
//发动定时器
TR0=1;
}
//I^2C通讯总线初始化函数主体
void AT24C02_init() //两线均写1 AT24C02数据有用规矩,sclk为高电平且sda数据安稳,当sda产生有用数据改变时,sclk有必要要是0
{
AT24C02_SDA=1;
delay_minute();
AT24C02_SCLK=1;
delay_minute();
}
//I^2C通讯发动函数主体
void star() //发动规矩:SCLK-1,SDA下降沿
{
AT24C02_SDA=1; //必定要SDA首要为1,再是SCLK为1,不然会呈现一个中止信号
delay_minute();
AT24C02_SCLK=1;
delay_minute();
AT24C02_SDA=0;
delay_minute();
}
//I^2C通讯中止函数主体
void stop() //中止规矩:SCLK-1,SDA上升沿
{
AT24C02_SDA=0; //必定要SDA首要为0,再是SCLK为1,不然会呈现一个发动信号
delay_minute();
AT24C02_SCLK=1;
delay_minute();
AT24C02_SDA=1;
delay_minute();
}
//应对函数主体
void response() //应对规矩:SCLK-1,等候从机把SDA拉低
{
uint i;
AT24C02_SCLK=1;
delay_minute();
while(AT24C02_SDA==1&&i<255)//等候从机把SDA拉低,且超越必定时刻没有应对,默许现已应对
{
i++;
}
AT24C02_SCLK=0; //应对之后,SCLK-0.避免数据误操作,由于SCLK-1,数据便是有用地
delay_minute();
}
//写入一个字节函数主体
void write_in_byte(uchar date)
{
uint i,buffer; //i用于循环发送每一位,buffer缓冲数据
buffer=date;
for(i=0;i<8;i++)
{
buffer=buffer<<1; //buffer左旋,高位就放入CY
AT24C02_SCLK=0; //有用发送规矩:sclk-0改变数据,sclk-1数据安稳后有用
delay_minute();
AT24C02_SDA=CY;
delay_minute();
AT24C02_SCLK=1;
delay_minute();
}
AT24C02_SCLK=0; //不发送,必定是SCLK-0,SDA-1
delay_minute();
AT24C02_SDA=1;
delay_minute();
}
//读出一个字节函数主体
uchar read_out_byte() //读出规矩:发动-操控字片选+写(为了写入要读取的地址)-应对-写入存储地址-应对-读取数据-应对-中止
{
uchar i,buffer_writting;
//————————————————–
//不能少的
AT24C02_SCLK=0; //便利SDA数据产生有用改变
delay_minute();
AT24C02_SDA=1;
delay_minute();
//————————————————–
for(i=0;i<8;i++)
{
AT24C02_SCLK=1;
delay_minute();
buffer_writting=(buffer_writting<<1)|AT24C02_SDA;//buffer_writting左旋之后与AT24C02_SDA的数据线与
delay_minute();
AT24C02_SCLK=0;
delay_minute();

}
return buffer_writting;
}
//向AT24C02保存数据函数主体
void saveing(uchar address,uchar time_date0) //写入字节规矩:发动-操控字片选+写-应对-写入存储地址-应对-写入数据-应对-中止
{
star(); //发动信号
write_in_byte(0xa0);
response();
write_in_byte(address);
response();
write_in_byte(time_date0);
response();
stop();
}
//从AT24C02载入掉电之前的数据函数主体
uchar load(uchar address) //读出规矩:发动-操控字片选+写(为了写入要读取的地址)-应对-写入存储地址-应对-读取数据-应对-中止
{
uchar time_date_former;
star();
write_in_byte(0xa0);
response();
write_in_byte(address);
response();
time_date_former=read_out_byte();
stop();
return time_date_former;
}
//显现数字取出各位与十位函数主体
void quwei(uchar quwei_date)
{
shiwei=quwei_date/10;
gewei=quwei_date;
}
//数码管显现函数函数主体
void display(uchar display_date)
{
quwei(display_date);
//显现第一个数码管
duanxuan=1;
P0=table[shiwei];
duanxuan=0;
P0=0xff;
weixuan=1;
P0=0xfe;
weixuan=0;
delay_xs(2);
//显现第二的数码管
duanxuan=1;
P0=table[gewei];
duanxuan=0;
P0=0xff;
weixuan=1;
P0=0xfd;
weixuan=0;
delay_xs(2);
}
//T0定时器方法一中止服务程序
void T0_timer_no1() interrupt 1
{
//预装初值
TH0=(65536-46080)/256;
TL0=(65536-46080)%6;
number++;
if(number==20) //20次计满便是1s
{
number=0;
time_date++; //时刻累加
timer_flag=1; //计满一次就保存数据
if(time_date==100) //100s循环计时
{
time_date=0;
}
}
}
以上,完毕。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/fangan/dianlu/259194.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部