首页 > 代码库 > [51单片机] EEPROM 24c02 [I2C代码封装-保存实现流水灯]

[51单片机] EEPROM 24c02 [I2C代码封装-保存实现流水灯]

 

这里把EEPROM 24c02封装起来,今后可以直接调用,其连线方式为:SDA-P2.1;SCL-P2.0;WP-VCC

>_<:i2c.c

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

>_<:i2c.h

 1 /*-----------------------------------------------
 2   名称:IIC协议 头文件
 3 ------------------------------------------------*/  
 4 #ifndef __I2C_H__
 5 #define __I2C_H__           
 6 #include <reg52.h>          //头文件的包含
 7 #include <intrins.h>
 8 #define  _Nop()  _nop_()        //定义空指令
 9 /*-----------------------------------------------
10  uS延时函数,含有输入参数 unsigned char t,无返回值
11  unsigned char 是定义无符号字符变量,其值的范围是
12  0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
13  长度如下 T=tx2+5 uS 
14 ------------------------------------------------*/
15 void DelayUs2x(unsigned char t);
16 /*------------------------------------------------
17  mS延时函数,含有输入参数 unsigned char t,无返回值
18  unsigned char 是定义无符号字符变量,其值的范围是
19  0~255 这里使用晶振12M,精确延时请使用汇编
20 ------------------------------------------------*/
21 void DelayMs(unsigned char t);
22 /*------------------------------------------------
23                     启动总线
24 ------------------------------------------------*/
25 void Start_I2c();
26 /*------------------------------------------------
27                     结束总线
28 ------------------------------------------------*/
29 void Stop_I2c();
30 /*----------------------------------------------------------------
31                  字节数据传送函数               
32 函数原型: void  SendByte(unsigned char c);
33 功能:  将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
34      此状态位进行操作.(不应答或非应答都使ack=0 假)     
35      发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
36 ------------------------------------------------------------------*/
37 void  SendByte(unsigned char c);
38 /*----------------------------------------------------------------
39                  字节数据传送函数               
40 函数原型: unsigned char  RcvByte();
41 功能:  用来接收从器件传来的数据,并判断总线错误(不发应答信号),
42      发完后请用应答函数。  
43 ------------------------------------------------------------------*/    
44 unsigned char  RcvByte();
45 /*----------------------------------------------------------------
46                      应答子函数
47 原型:  void Ack_I2c(void);
48 ----------------------------------------------------------------*/
49 void Ack_I2c(void);
50 /*----------------------------------------------------------------
51                      非应答子函数
52 原型:  void NoAck_I2c(void);
53 ----------------------------------------------------------------*/
54 void NoAck_I2c(void);
55 /*----------------------------------------------------------------
56                     向无子地址器件发送字节数据函数               
57 函数原型: bit  ISendByte(unsigned char sla,ucahr c);  
58 功能:     从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.
59            如果返回1表示操作成功,否则操作有误。
60 注意:    使用前必须已结束总线。
61 ----------------------------------------------------------------*/
62 bit ISendByte(unsigned char sla,unsigned char c);
63 
64 /*----------------------------------------------------------------
65                     向有子地址器件发送多字节数据函数               
66 函数原型: bit  ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);  
67 功能:     从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
68           地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
69            如果返回1表示操作成功,否则操作有误。
70 注意:    使用前必须已结束总线。
71 ----------------------------------------------------------------*/
72 bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no);
73 /*----------------------------------------------------------------
74                     向无子地址器件读字节数据函数               
75 函数原型: bit  IRcvByte(unsigned char sla,ucahr *c);  
76 功能:     从启动总线到发送地址,读数据,结束总线的全过程,从器件地
77           址sla,返回值在c.
78            如果返回1表示操作成功,否则操作有误。
79 注意:    使用前必须已结束总线。
80 ----------------------------------------------------------------*/
81 bit IRcvByte(unsigned char sla,unsigned char *c);
82 /*----------------------------------------------------------------
83                     向有子地址器件读取多字节数据函数               
84 函数原型: bit  ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);  
85 功能:     从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
86           地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
87            如果返回1表示操作成功,否则操作有误。
88 注意:    使用前必须已结束总线。
89 ----------------------------------------------------------------*/
90 bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no);
91 #endif

>_<:下面是main函数中如何调用封装好的函数来实现流水灯的效果的:
>_<:流水灯8个的连线这里用的是P1

 1 /*-----------------------------------------------
 2 名称:IIC协议 24c02存储花样灯程序
 3 内容:将表格内容写入24c02,然后批量删除这些数据,
 4 并从24c02中读取数据并显示
 5 ------------------------------------------------*/  
 6 #include <reg52.h>                
 7 #include "i2c.h"
 8 /*------------------------------------------------
 9 花样灯表格
10 ------------------------------------------------*/
11 unsigned char      dat[]={0x7f,0xbf,0xdf,0xef,
12 0xf7,0xfb,0xfd,0xfe,
13 0xff,0xff,0x00,0x00,
14 0x55,0x55,0xaa,0xaa
15 };//ram允许情况可以无限添加
16 /*------------------------------------------------
17   主函数
18 ------------------------------------------------*/
19 main()
20 {
21     //bit flag;
22     unsigned char i;
23     ISendStr(0xae,80,dat,16);            //写入24c02
24     DelayMs(1);                          //写入后必须延时等待24c02内部
25     //烧录数据处理完毕方可继续其他操作
26     for(i=0;i<16;i++)                    //清除数据
27         dat[i]=0;
28     IRcvStr(0xae,80,dat,16);             //从24c02读出数据 
29     while(1)
30     {
31         for(i=0;i<16;i++)              //查表
32         {
33             DelayMs(200);
34             P1=dat[i];
35         }
36     }
37 }