【51】iic总线AT24C02芯片的应用

数据线(SDA)与时钟线(SCL)关系:

只有在时钟限号为低电平期间,数据线上的高电平或低电平状态才允许变化。
接下来附上51单片机模拟iic总线通讯的模拟时序图(后面的总线与信号会依照此图):
在这里插入图片描述

AT24C02的读写操作时序图:

在这里插入图片描述

具体控制程序如下(分成三个文件):

mian.c:


#include"reg52.h"
#include"i2c.h"
typedef unsigned int u16;
typedef unsigned char u8;
sbit k1=P3^1;//保存(写入)数据
sbit k2=P3^0;//读取数据
sbit k3=P3^2;//num累加
sbit k4=P3^3;//num清零
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
u8 num=0,disp[4];
u8 code smg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void delay(u16 i)
{
 while(i--);
}
void Keypros()
{
 if(k1==0)
 {
  delay(1000);//10ms
  if(k1==0)//延迟确认,老方法了
  {
   At24C02Write(1,num);//如果确定按下了k1,就写入数据与地址
  }
  while(!k1);
 }
 if(k2==0)
 {
  delay(1000);//10xms
  if(k2==0)
  {
   num=At24C02Read(1);
  }
  while(!k2);
 }
    if(k3==0)
 {
  delay(1000);//10xms
  if(k3==0)
  {
   num++;
   if(num>255) num=0;
  }
  while(!k3);
 }
 if(k4==0)
 {
  delay(1000);//10xms
  if(k4==0)
  {
   num=0;
  }
  while(!k4);
 }
}
void datapros()
{
   disp[0]=smg[num/1000];
   disp[1]=smg[num%1000/100];
   disp[2]=smg[num%1000%100/10];
   disp[3]=smg[num%1000%100%10];
}
void display()
{
 u8 i;
 for(i=0;i<4;i++)
 {
  switch(i)
  {
     case 0:LSA=0;LSB=0;LSC=0; break;
     case 1:LSA=1;LSB=0;LSC=0; break;
     case 2:LSA=0;LSB=1;LSC=0; break;
     case 3:LSA=1;LSB=1;LSC=0; break;
  }
     P0=disp[3-i];
  delay(100);
  P0=0x00; 
 }
}
void main()
{
 while(1)
 {
  Keypros();
  datapros(); 
  display();
 }
}

IIC.c

#include "i2c.h"
void Delay10us()   
{
    unsigned char a,b;
    for(b=1;b>0;b--)
        for(a=2;a>0;a--);
}
void I2cStart()/起始信号
{
 SDA=1;
 Delay10us();
 SCL=1;
 Delay10us();
 SDA=0;
 Delay10us();
 SCL=0;
 Delay10us(); 
}
void I2cStop()//终止信号
{
    SDA=0;
 Delay10us();
 SCL=1;
 Delay10us();
 SDA=1;
 Delay10us();
}
har I2cSendByte(unsigned char dat)//向IIC总线进行写操作
{
 unsigned char a=0,b;
 for(a=0;a<8;a++)//写8位的数据,从高到低
 {
  SDA=dat>>7;//dat取最高位给SDA
  dat<<=1;//dat把给过的最高位去掉
  Delay10us();
  SCL=1;
  Delay10us();
  SCL=0;
  Delay10us();//高低电压变化,发送数据
}
 SDA=1;//发送完成,释放时钟线
 Delay10us();
 SCL=1;//释放数据线
while(SDA)//判断是应答还是非应答,若产生应答,SDA=0,会跳出while循环
 {
  b++;
  if(b>200)
  {
   SCL=0;
   Delay10us();
   return 0;//应答失败即未发送数据
  }   
 }
  SCL=0;
  Delay10us();
  return 1;//发送成功
}
unsigned char I2cReadByte()//IIC总线进行读操作
{
 unsigned char a=0,dat=0;
 SDA=1;
 for(a=0;a<8;a++)
 {
  SCL=1;//SCL置1 ,限制SDA变化(可以把SCL=1理解为关上)
  Delay10us();
  dat<<=1;//位移一次理解为填一位(0->00)
  dat|=SDA; //00->01
  //根据循环如此往复8次即可将8位数据全都按顺序赋给dat
  Delay10us();
  SCL=0;//高低电平变化,读取数据
  Delay10us();
 }
 return dat;
}
void At24C02Write(unsigned char addr,unsigned char dat)//AT24C02写入数据(参照上面时序图)
{
 I2cStart();
 I2cSendByte(0xa0);//AT24C02固定的器件地址为1010 0000(+0为写入/+1为读取)
 I2cSendByte(addr);
 I2cSendByte(dat);
    I2cStop();   
}
unsigned char At24C02Read(unsigned char addr)//AT24C02读取数据(参照上面时序图)
{
 unsigned char num;
 I2cStart();
 I2cSendByte(0xa0);
 I2cSendByte(addr);
 I2cStart();
 I2cSendByte(0xa1);
    num= I2cReadByte();
    I2cStop();
 return num;
}

IIC.h

#ifndef _I2C_H
#define _I2C_H
#include<reg52.h>

sbit SCL=P2^1;
sbit SDA=P2^0;
void At24C02Write(unsigned char addr,unsigned char adt);
unsigned char At24C02Read(unsigned char addr);
#endif

新手上路,欢迎指教。
还请问一下,为什么我复制代码块的时候我原本程序里面的注释都会变成问号。这个稿件的编辑界面还会变得无法选中,有大佬知道解决的方法吗?求教。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值