美文网首页
2020-03-30/i²c总线和EEPROOM

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

作者: LH大牛 | 来源:发表于2020-04-06 13:16 被阅读0次

    本篇分两部分: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 <reg51.h>
    #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

          本文链接:https://www.haomeiwen.com/subject/ipjvuhtx.html