2020-03-30/i²c总线和EEPROOM

本篇分两部分:1.i²c总线和EEPROOM相关 2.DSB1820温度传感器的使用
第一部分:
1.i²c总线与UART比较
i²c总显示是一种通信协议,与串口通信不同,串口通信一般用于板件通信, UART的发送接受时间受到单片机晶振你的严格控制。i²c总线多用于板上读取写入信息,常见于读取传感器采集的信息之类;
适配与i²c总线的器件有很多,这里用EEPROM来举例说明
2.i²c总线简介
I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL;

i²c总线的数据传输:
早SCL高电平时要求数据稳定,在低电平时可以发生变化


i²c总线的数据传输要求

i²c总线的起始信号和中止


i²c总线的起始信号

起始信号和终止信号一般由单片机主机发出,若主机上挂在了i²c总线协议的器件,则能轻易识别出该信号


时序图

对应时间
 //i2c起始信号
SCL=1;
SDA=1;
delay1ms(); //起始信号建立时间
SDA=0;
delay1ms();//起始信号保持时间
SCL=0;//拉低为下一次准备
//i2c终止信号
SCL=1;
SDA=0;
delay1ms();//停止信号建立时间
SDA=1;
delay1ms();//新的发送开始前总线的空闲时间

字节的传送与应答
每一个字节必须保证时8位,数据传送时先发送最高位
第9位位应答位,若为应答为,则SDA被置为,若无应答,则SDA为高电平
单片机进行写操作时,首先发送该器件的7位地址码和写方向位“0”(共8位,即一个字节),发送完后释放SDA线并在SCL线上产生第9个时钟信号。被选中的存储器器件在确认是自己的地址后,在SDA线上产生一个应答信号作为相应,单片机收到应答后就可以传送数据了。


字节的传送

读操做
单片机先发送该器件的7位地址码和写方向位“0”(“伪写”),发送完后释放SDA线并在SCL线上产生第9个时钟信号。被选中的存储器器件在确认是自己的地址后,在SDA线上产生一个应答信号作为回应。
然后,再发一个字节的要读出器件的存储区的首地址,收到应答后,单片机要重复一次起始信号并发出器件地址和读方向位(“1”),收到器件应答后就可以读出数据字节,每读出一个字节,单片机都要回复应答信号。当最后一个字节数据读完后,单片机应返回以“非应答”(高电平),并发出终止信号以结束读出操作。


读操作
//写一个字节的数据
int I,a;
for(i=0;i<8;i++)
{
  SDA=dat>>7;//先发送最高位 1100 0011
  dat<<1;//次高位为做高位
  SCL=1;//拉高,发送数据
  delay1ms();//时钟高电平周期
}
while(SDA)
{
       a++;
       if(a>500)
        {
                a=0;
                SCL=0;
                 return -1;
        }
  }
SCL=0;
delay1ms();//为下次做准备
//读一个字节的数据
int i;
char dat,num=0;
SCL=0;
delay1ms();
for(i=7;i>=0;i--)
{
    SCL=1;
    delay1ms();
    dat=SDA;
    dat>>i;//dat 中的最高位移到最后一位
    num|=dat;
    SCL=0;
    delay1ms();
//缺少应答
}

实现用数码管显示AT24C02的所存功能:
任务:当使用独立按键K1,单片机向ATC02写入数据; 使用独立按键K2, 单片机读取AT24C02的数据;3.使用独立按键K3,数码管显示数据加1;4使用独立按键K4,数码管清零
程序

//main 函数
#include 
#include "EEPROM.H"
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;//74h138段选
sbit K1=  P3^1;
sbit K2=  P3^0;
sbit K3= P3^2;
sbit K4= P3^3;

char ch[]={};//显示字符
char keyfun(char dat);
void shumaguan();
int main()
{
    char dat;
    while(1)
          {
            dat=keyfun();//返回dat
            shumaguan(dat);//调用数码管函数
          }
          return 0;
}
char keyfun(char dat)
{
     if(K1==0)
     {
       delay5ms();
       if(K1==0)
       {
            ATwrite(dat);
            
       }
     if(K2==0)
     {
         read(0x00,dat);
     }
     if(K3==0)
     {
          dat++;
     }
     if(K4=0)
     {
          dat=0;
     }
    return dat;
}
void shumaguan()
{
    int i,j,k,a=0;
    P0=0x00;//消隐
    i= dat/100;//百位
    j= dat%100/10;//   十位
    k= dat%100%10;//个位
    while()
    {
        switch(a++)
        {
                case[0]:LSA=0;LSB=0;LSC=0;P0=ch[i],delay1ms();break;
                case[1]:LSA=1;LSB=0;LSC=0;P0=ch[j];delay1ms();break;
                case[2]:LSA=0;LSB=1;LSC=0;P0=ch[k]; delay1ms(); break;
                default: a=0;break;
        }
    }
 }
\\AT24C02程序
void delay1ms()//延时程序
{       
}

void  IICStart()
{
       SCL=1;
      SDA=1;
      delay1ms(); //起始信号建立时间
      SDA=0;
      delay1ms();//起始信号保持时间
      SCL=0;//拉低为下一次准备
}

void IICStop()
{
       SCL=1;
      SDA=0;
      delay1ms();//停止信号建立时间
      SDA=1;
      delay1ms();//新的发送开始前总线的空闲时间   
}

void IICSendbyte(dat)
{
    int i;
    for(i=0;i<8;i++)
    {
        SDA=dat>>7;//先发送最高位 1100 0011
        dat<<1;//次高位为做高位
        SCL=1;//拉高,发送数据
        delay1ms();//时钟高电平周期
        SCL=0;//拉低为下次准备
        delay1ms();//时钟低电平周期
    }
        while(SDA)
        {
           a++;
           if(a>500)
          {
               a=0;
               SCL=0;
               return -1;
          }
      }
      SCL=0;
      a=0;
    }
}

void IICReadbyte()
{
  int i;
  char dat,num=0;
  SCL=0;
  delay1ms();
  for(i=7;i>=0;i--)
  {
      SCL=1;
      delay1ms();
      dat=SDA;
      dat>>i;//dat 中的最高位移到最后一位
      num|=dat;
     SCL=0;
     delay1ms()
   }
  while(SDA)
  {
      a++;
      if(a>500)
      {
            a=0;
            SCL=0;
            return -1;
      }
  }
SCL=0;
a=0;
return 0;      
}
void AT24C02Write()
{
    IICStart();
    IICSendbyte(0x00);//器件地址和写
    IICSendbyte(dat);
    IICStop();
}

char AT24C02Read(char addr,char dat)
{
     IICStart();
     IICSendbyte(0x00);//器件地址和写
     IICSendbyte(addr);//读取AT24C02首地址
     IICStart(); 
     IICSendbyte(0x01);
     dat=IICReadbyte();
     IICStop();
 }

//增加IIC.h
void delay1ms();
void AT24C02Write();
char AT24C02Read(char addr,char dat);

你可能感兴趣的:(2020-03-30/i²c总线和EEPROOM)