zoukankan      html  css  js  c++  java
  • [51单片机] EEPROM AT24c02 [存储读取一个字节]

      1 /*-----------------------------------------------
      2 名称:IIC协议 EEPROM24c02 存数读取数据
      3 内容:此程序用于检测EEPROM性能,测试方法如下:写入24c02一个数据,然后在内存中改变这些数据,
      4 掉电后主内存将失去这些信息,然后从24c02中调入这些数据。看是否与写入的相同。这里用8个LED演示
      5 函数是采用软件延时的方法产生SCL脉冲,固对高晶振频率要作 一定的修改....(本例是1us机器
      6 周期,即晶振频率要小于12MHZ)
      7 ------------------------------------------------*/              
      8 #include <reg52.h>          //头文件的包含
      9 #include <intrins.h>
     10 
     11 #define  _Nop()  _nop_()        //定义空指令
     12 // 常,变量定义区                                           
     13 sbit SDA=P2^1;            //模拟I2C数据传送位
     14 sbit SCL=P2^0;            //模拟I2C时钟控制位
     15 
     16 bit ack;                  //应答标志位
     17 
     18 void DelayUs2x(unsigned char t);//函数声明 
     19 void DelayMs(unsigned char t);
     20 /*------------------------------------------------
     21 uS延时函数,含有输入参数 unsigned char t,无返回值
     22 unsigned char 是定义无符号字符变量,其值的范围是
     23 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
     24 长度如下 T=tx2+5 uS 
     25 ------------------------------------------------*/
     26 void DelayUs2x(unsigned char t)
     27 {   
     28     while(--t);
     29 }
     30 /*------------------------------------------------
     31 mS延时函数,含有输入参数 unsigned char t,无返回值
     32 unsigned char 是定义无符号字符变量,其值的范围是
     33 0~255 这里使用晶振12M,精确延时请使用汇编
     34 ------------------------------------------------*/
     35 void DelayMs(unsigned char t)
     36 {
     37     
     38     while(t--)
     39     {
     40         //大致延时1mS
     41         DelayUs2x(245);
     42         DelayUs2x(245);
     43     }
     44 }
     45 
     46 /*------------------------------------------------
     47 启动总线
     48 ------------------------------------------------*/
     49 void Start_I2c()
     50 {
     51     SDA=1;   //发送起始条件的数据信号
     52     _Nop();
     53     SCL=1;
     54     _Nop();    //起始条件建立时间大于4.7us,延时
     55     _Nop();
     56     _Nop();
     57     _Nop();
     58     _Nop();    
     59     SDA=0;     //发送起始信号
     60     _Nop();    //起始条件锁定时间大于4μ
     61     _Nop();
     62     _Nop();
     63     _Nop();
     64     _Nop();       
     65     SCL=0;    //钳住I2C总线,准备发送或接收数据
     66     _Nop();
     67     _Nop();
     68 }
     69 /*------------------------------------------------
     70 结束总线
     71 ------------------------------------------------*/
     72 void Stop_I2c()
     73 {
     74     SDA=0;    //发送结束条件的数据信号
     75     _Nop();   //发送结束条件的时钟信号
     76     SCL=1;    //结束条件建立时间大于4μ
     77     _Nop();
     78     _Nop();
     79     _Nop();
     80     _Nop();
     81     _Nop();
     82     SDA=1;    //发送I2C总线结束信号
     83     _Nop();
     84     _Nop();
     85     _Nop();
     86     _Nop();
     87 }
     88 
     89 
     90 
     91 
     92 /*----------------------------------------------------------------
     93 字节数据传送函数               
     94 函数原型: void  SendByte(unsigned char c);
     95 功能:  将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
     96 此状态位进行操作.(不应答或非应答都使ack=0 假)     
     97 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
     98 ------------------------------------------------------------------*/
     99 void  SendByte(unsigned char c)
    100 {
    101     unsigned char BitCnt;
    102     
    103     for(BitCnt=0;BitCnt<8;BitCnt++)  //要传送的数据长度为8位
    104     {
    105         if((c<<BitCnt)&0x80)SDA=1;   //判断发送位
    106         else  SDA=0;                
    107         _Nop();
    108         SCL=1;               //置时钟线为高,通知被控器开始接收数据位
    109         _Nop(); 
    110         _Nop();             //保证时钟高电平周期大于4μ
    111         _Nop();
    112         _Nop();
    113         _Nop();         
    114         SCL=0; 
    115     }
    116     
    117     _Nop();
    118     _Nop();
    119     SDA=1;               //8位发送完后释放数据线,准备接收应答位
    120     _Nop();
    121     _Nop();   
    122     SCL=1;
    123     _Nop();
    124     _Nop();
    125     _Nop();
    126     if(SDA==1)ack=0;     
    127     else ack=1;        //判断是否接收到应答信号
    128     SCL=0;
    129     _Nop();
    130     _Nop();
    131 }
    132 /*----------------------------------------------------------------
    133 字节数据传送函数               
    134 函数原型: unsigned char  RcvByte();
    135 功能:  用来接收从器件传来的数据,并判断总线错误(不发应答信号),
    136 发完后请用应答函数。  
    137 ------------------------------------------------------------------*/    
    138 unsigned char  RcvByte()
    139 {
    140     unsigned char retc;
    141     unsigned char BitCnt;
    142     
    143     retc=0; 
    144     SDA=1;             //置数据线为输入方式
    145     for(BitCnt=0;BitCnt<8;BitCnt++)
    146     {
    147         _Nop();           
    148         SCL=0;       //置时钟线为低,准备接收数据位
    149         _Nop();
    150         _Nop();      //时钟低电平周期大于4.7us
    151         _Nop();
    152         _Nop();
    153         _Nop();
    154         SCL=1;       //置时钟线为高使数据线上数据有效
    155         _Nop();
    156         _Nop();
    157         retc=retc<<1;
    158         if(SDA==1)retc=retc+1; //读数据位,接收的数据位放入retc中
    159         _Nop();
    160         _Nop(); 
    161     }
    162     SCL=0;    
    163     _Nop();
    164     _Nop();
    165     return(retc);
    166 }
    167 
    168 
    169 
    170 /*----------------------------------------------------------------
    171 应答子函数
    172 原型:  void Ack_I2c(void);
    173 ----------------------------------------------------------------*/
    174 void Ack_I2c(void)
    175 {
    176     
    177     SDA=0;     
    178     _Nop();
    179     _Nop();
    180     _Nop();      
    181     SCL=1;
    182     _Nop();
    183     _Nop();              //时钟低电平周期大于4μ
    184     _Nop();
    185     _Nop();
    186     _Nop();  
    187     SCL=0;               //清时钟线,钳住I2C总线以便继续接收
    188     _Nop();
    189     _Nop();    
    190 }
    191 /*----------------------------------------------------------------
    192 非应答子函数
    193 原型:  void NoAck_I2c(void);
    194 ----------------------------------------------------------------*/
    195 void NoAck_I2c(void)
    196 {
    197     
    198     SDA=1;
    199     _Nop();
    200     _Nop();
    201     _Nop();      
    202     SCL=1;
    203     _Nop();
    204     _Nop();              //时钟低电平周期大于4μ
    205     _Nop();
    206     _Nop();
    207     _Nop();  
    208     SCL=0;                //清时钟线,钳住I2C总线以便继续接收
    209     _Nop();
    210     _Nop();    
    211 }
    212 /*----------------------------------------------------------------
    213 向无子地址器件发送字节数据函数               
    214 函数原型: bit  ISendByte(unsigned char sla,ucahr c);  
    215 功能:     从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.
    216 如果返回1表示操作成功,否则操作有误。
    217 注意:    使用前必须已结束总线。
    218 ----------------------------------------------------------------*/
    219 /*bit ISendByte(unsigned char sla,unsigned char c)
    220 {
    221 Start_I2c();               //启动总线
    222 SendByte(sla);             //发送器件地址
    223 if(ack==0)return(0);
    224 SendByte(c);               //发送数据
    225 if(ack==0)return(0);
    226 Stop_I2c();                 //结束总线
    227 return(1);
    228 }
    229 */
    230 
    231 /*----------------------------------------------------------------
    232 向有子地址器件发送多字节数据函数               
    233 函数原型: bit  ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);  
    234 功能:     从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
    235 地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
    236 如果返回1表示操作成功,否则操作有误。
    237 注意:    使用前必须已结束总线。
    238 ----------------------------------------------------------------*/
    239 bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
    240 {
    241     unsigned char i;
    242     
    243     Start_I2c();               //启动总线
    244     SendByte(sla);             //发送器件地址
    245     if(ack==0)return(0);
    246     SendByte(suba);            //发送器件子地址
    247     if(ack==0)return(0);
    248     
    249     for(i=0;i<no;i++)
    250     {   
    251         SendByte(*s);            //发送数据
    252         if(ack==0)return(0);
    253         s++;
    254     } 
    255     Stop_I2c();                  //结束总线
    256     return(1);
    257 }
    258 
    259 /*----------------------------------------------------------------
    260 向无子地址器件读字节数据函数               
    261 函数原型: bit  IRcvByte(unsigned char sla,ucahr *c);  
    262 功能:     从启动总线到发送地址,读数据,结束总线的全过程,从器件地
    263 址sla,返回值在c.
    264 如果返回1表示操作成功,否则操作有误。
    265 注意:    使用前必须已结束总线。
    266 ----------------------------------------------------------------*/
    267 /*bit IRcvByte(unsigned char sla,unsigned char *c)
    268 {
    269 Start_I2c();                //启动总线
    270 SendByte(sla+1);            //发送器件地址
    271 if(ack==0)return(0);
    272 *c=RcvByte();               //读取数据
    273 NoAck_I2c();              //发送非就答位
    274 Stop_I2c();               //结束总线
    275 return(1);
    276 }
    277 
    278 */
    279 /*----------------------------------------------------------------
    280 向有子地址器件读取多字节数据函数               
    281 函数原型: bit  ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);  
    282 功能:     从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
    283 地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
    284 如果返回1表示操作成功,否则操作有误。
    285 注意:    使用前必须已结束总线。
    286 ----------------------------------------------------------------*/
    287 bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
    288 {
    289     unsigned char i;
    290     
    291     Start_I2c();               //启动总线
    292     SendByte(sla);             //发送器件地址
    293     if(ack==0)return(0);
    294     SendByte(suba);            //发送器件子地址
    295     if(ack==0)return(0);
    296     
    297     Start_I2c();
    298     SendByte(sla+1);
    299     if(ack==0)return(0);
    300     
    301     for(i=0;i<no-1;i++)
    302     {   
    303         *s=RcvByte();              //发送数据
    304         Ack_I2c();                //发送就答位 
    305         s++;
    306     } 
    307     *s=RcvByte();
    308     NoAck_I2c();                 //发送非应位
    309     Stop_I2c();                    //结束总线
    310     return(1);
    311 }
    312 /*------------------------------------------------
    313 主函数
    314 ------------------------------------------------*/
    315 void main()
    316 {
    317     unsigned char doflye;       // 定义临时变量
    318     unsigned char i;
    319     
    320     IRcvStr(0xae,4,&doflye,1);  //调用存储数据
    321 
    322     while(1)
    323     {  
    324         P1=doflye;             //数值用二进制显示,直接用8个LED表示
    325         for(i=0;i<5;i++)   
    326             DelayMs(200);
    327         doflye++;              //1s钟变量自加1,改变值后存储到24c02
    328         //下次开机时将显示当前数值
    329         ISendStr(0xae,4,&doflye,1); //写入24c02
    330     }
    331 }


    除了上面的p2.0和p2.1要连外还要把p1的8个脚和灯相连

  • 相关阅读:
    持续集成 自动化构建、测试、部署您的Coding代码
    MySQL主从 常见的错误及解决方案
    老王带你走过 Kafka 入门教程
    Spring Cloud Eureka 常用配置及说明
    关于智慧大数据中心平台建设思路
    工作经验是积累总结出来的
    程序员晋级CTO之路的8大准则
    Spring Cloud Feign 使用方法与性能优化
    Elasticsearch(ES)API 增删查改常用操作
    ELK 日志采集 实战教程
  • 原文地址:https://www.cnblogs.com/zjutlitao/p/3704038.html
Copyright © 2011-2022 走看看