8051学习笔记——IIC与EEPROM实验

main.c

  1 #include <reg51.h>
  2 #include "iic.h"
  3 #define  AT24C02 0xa0  //AT24C02 地址
  4 
  5 sbit    LS138A=P2^2;      //译码器端
  6 sbit    LS138B=P2^3;
  7 sbit    LS138C=P2^4; 
  8 
  9 sbit    K1 = P1^0;     //保存
 10 sbit    K2 = P1^1;     //读取
 11 sbit    K3 = P1^2;     //+数据
 12 sbit    K4 = P1^3;   //-数据
 13 
 14 void delay(unsigned int i);
 15 
 16 //此表为 LED 的字模, 共阴数码管 0-9 
 17 unsigned char code Disp_Tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; 
 18 
 19 unsigned char Count1;
 20 unsigned long D[17], LedOut[5],LedNumVal;
 21 unsigned int idata USEC;   //表示这个变量类型是unsigned int,地址在idata区,也就是内部RAM地址的128~255内
 22 
 23 void  system_ini() 
 24 {    
 25     TMOD|= 0x11;    //mode 1
 26     TH1 = 0xfe;     //0.5ms
 27     TL1 = 0x0c;
 28     TR1 = 1; 
 29     IE = 0x8A;
 30 }
 31 
 32 void main()
 33 {
 34     unsigned char i;
 35     unsigned char pDat[8];
 36 
 37        system_ini();
 38        while(1)
 39        {
 40          //========================IIC 读取
 41         if(K2 == 0)       //第二个按钮读取数据
 42         { 
 43               IRcvStr(AT24C02,0,&pDat[0], 8); 
 44               for (i=0; i<4; i++)
 45               {
 46                 D[14+i]=pDat[i*2+0]+pDat[i*2+1]*0x100;
 47                 Count1 = D[14];
 48                }         
 49          }
 50 
 51        //========================IIC 保存
 52            if(K1 == 0)    //第一个按钮保存数据
 53            { 
 54             D[14]= Count1;
 55              for (i=0; i<4; i++)
 56              {
 57                    pDat[i*2+0]=D[14+i];
 58                    pDat[i*2+1]=D[14+i]>>8;
 59              }
 60              ISendStr(AT24C02, 0 , &pDat[0], 8); 
 61               D[14] = 0;
 62            }
 63 
 64       /********以下将2402中保存的数据送到LED数码管显示*************/
 65         LedNumVal=Count1;
 66           LedOut[0]=Disp_Tab[LedNumVal%10000/1000];
 67           LedOut[1]=Disp_Tab[LedNumVal%1000/100];
 68           LedOut[2]=Disp_Tab[LedNumVal%100/10]|0x80;
 69           LedOut[3]=Disp_Tab[LedNumVal%10]; 
 70         
 71         for(i=0; i<4; i++) 
 72           {        
 73             P0 =  LedOut[i];
 74            
 75             switch(i)                      
 76              {        
 77                 case 0:LS138A=0; LS138B=0; LS138C=0; break;         
 78                 case 1:LS138A=1; LS138B=0; LS138C=0; break;                 
 79                 case 2:LS138A=0; LS138B=1; LS138C=0; break; 
 80                 case 3:LS138A=1; LS138B=1; LS138C=0; break; 
 81                 case 4:LS138A=0; LS138B=0; LS138C=1; break;
 82              }
 83             delay(100);
 84           }
 85    }
 86 }
 87 
 88 void delay(unsigned int i)
 89 {
 90     char j;
 91     for(i; i > 0; i--)
 92         for(j = 200; j > 0; j--);
 93 }
 94 
 95 void T1zd(void) interrupt 3   //3 为定时器1的中断号  1 定时器0的中断号 0 外部中断1 2 外部中断2  4 串口中断
 96 {
 97     TH1 = 0xfe; //12M    
 98     TL1 = 0x0c;
 99        if(USEC++==200)
100        {    
101         USEC = 0;
102         if(!K3) Count1++;     //改变数据
103         if(!K4)    Count1--;
104     }  
105 }

iic.h

  1 #include <reg51.h>
  2 #include <intrins.h>
  3 #define _NOP() _nop_()
  4 sbit    SCL = P2^1;
  5 sbit    SDA = P2^0;
  6 bit ack;
  7 
  8 void Start_IIC()
  9 {
 10     SDA = 1;
 11     _NOP();
 12     SCL = 1;
 13     _NOP();_NOP();_NOP();_NOP();_NOP();
 14     SDA = 0;
 15     _NOP();_NOP();_NOP();_NOP();_NOP();
 16     SCL = 0;
 17     _NOP();_NOP();
 18 }
 19 
 20 void Stop_IIC()
 21 {
 22     SDA = 0;
 23     _NOP();
 24     SCL = 1;
 25     _NOP();_NOP();_NOP();_NOP();_NOP();
 26     SDA = 1;
 27     _NOP();_NOP();_NOP();_NOP();_NOP();
 28 }
 29 
 30 void Send_Byte(unsigned char byte)
 31 {
 32     int i;
 33     for(i = 0;i < 8;i++)
 34     {
 35         if((byte << i) & 0x80)    SDA = 1;
 36         else    SDA = 0;
 37         SCL = 1;
 38         _NOP();_NOP();_NOP();_NOP();_NOP();
 39         SCL = 0;
 40     }
 41 
 42     SCL = 1;      //准备接受应答位
 43     _NOP();_NOP();
 44 
 45     if(SDA == 1)    ack = 0;
 46     else    ack = 1;
 47 
 48     SCL = 0;
 49     _NOP();_NOP();
 50 }
 51 
 52 unsigned char Rcv_Byte()
 53 {
 54     unsigned char byte;
 55     int i;
 56     byte = 0;
 57 
 58     for(i = 0;i < 8;i++)
 59     {
 60         SCL = 0;
 61         _NOP();_NOP();_NOP();_NOP();_NOP();
 62         SCL = 1;
 63         _NOP();_NOP();_NOP();_NOP();_NOP();
 64         byte <<= 1;
 65         if(SDA == 1)    byte++;
 66     }
 67     SCL = 0;
 68     _NOP();_NOP();
 69     return byte;
 70 }
 71 
 72 void Ack_IIC(bit a)
 73 {
 74   
 75   if(a==0)    SDA=0;              /*在此发出应答或非应答信号 */
 76   else    SDA=1;
 77   _NOP();_NOP();_NOP();     
 78   SCL=1;
 79   _NOP();_NOP();_NOP();_NOP();_NOP();
 80   SCL=0;                     /*清时钟线,钳住I2C总线以便继续接收*/
 81   _NOP();_NOP();  
 82 }
 83 
 84 //AT2402的功能函数
 85 /*******************************************************************
 86                     向有子地址器件发送多字节数据函数               
 87 函数原型: bit  ISendStr(UCHAR sla,UCHAR suba,ucahr *s,UCHAR no);  
 88 功能:     从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
 89           地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
 90           如果返回1表示操作成功,否则操作有误。
 91 注意:    使用前必须已结束总线。
 92 ********************************************************************/
 93 bit ISendStr(unsigned char  sla,unsigned char  suba,unsigned char  *s,unsigned char  no)
 94 {
 95    unsigned char i;
 96 
 97    Start_IIC();               /*启动总线*/
 98    Send_Byte(sla);             /*发送器件地址*/
 99    if(ack==0)    return(0);
100    Send_Byte(suba);            /*发送器件字地址,存储单元的地址*/
101    if(ack==0)    return(0);
102 
103    for(i=0;i<no;i++)
104    {   
105      Send_Byte(*s);            /*发送数据*/
106      if(ack==0)return(0);
107      s++;
108    } 
109    Stop_IIC();                /*结束总线*/ 
110 
111    return(1);
112 }
113 
114 /*******************************************************************
115                     向有子地址器件读取多字节数据函数               
116 函数原型: bit  RecndStr(UCHAR sla,UCHAR suba,ucahr *s,UCHAR no);  
117 功能:     从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
118           地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
119            如果返回1表示操作成功,否则操作有误。
120 注意:    使用前必须已结束总线。
121 ********************************************************************/
122 bit IRcvStr(unsigned char  sla,unsigned char suba,unsigned char  *s,unsigned char  no)
123 {
124     unsigned char i;
125 
126     Start_IIC();                  /*启动总线*/
127     Send_Byte(sla);                /*发送器件地址*/
128     if(ack==0)    return(0);
129     Send_Byte(suba);               /*发送器件子地址*/
130     if(ack==0)    return(0);
131 
132     Start_IIC();                 /*重新启动总线*/
133     Send_Byte(sla+1);
134     if(ack==0)    return(0);
135     for(i=0;i<no-1;i++)
136     {   
137         *s=Rcv_Byte();               /*发送数据*/
138           Ack_IIC(0);                  /*发送就答位*/  
139          s++;
140        } 
141        *s=Rcv_Byte();
142        Ack_IIC(1);                   /*发送非应答位*/
143        Stop_IIC();                   /*结束总线*/ 
144        return 1;
145 }
原文地址:https://www.cnblogs.com/boyiliushui/p/4781360.html