• [51单片机] EEPROM 24c02 [读取存储多字节]


    先将数据存进去,然后再读出来显示在数码管上。

    除了代码里定义的连线外还要把p0连接到8位数码管的8针上。

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