[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个脚和灯相连

 

posted @ 2014-05-02 14:37  beautifulzzzz  阅读(2467)  评论(0编辑  收藏  举报