[51单片机] EEPROM 24c02 + 数码管 + 中断 [统计开机次数]

  1. 云栖社区>
  2. 博客>
  3. 正文

[51单片机] EEPROM 24c02 + 数码管 + 中断 [统计开机次数]

史迪奇2号 2017-10-31 20:08:00 浏览596
展开阅读全文


>_<:24c02的SCL连P2.0;SDA连P2.1;WP接GND;P0接8位数码管的8针;P2.2连段码;P2.3连位码;

>_<:delay.c

复制代码
 1 #include "delay.h"
 2 /*------------------------------------------------
 3 uS延时函数,含有输入参数 unsigned char t,无返回值
 4 unsigned char 是定义无符号字符变量,其值的范围是
 5 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 6 长度如下 T=tx2+5 uS 
 7 ------------------------------------------------*/
 8 void DelayUs2x(unsigned char t)
 9 {   
10     while(--t);
11 }
12 /*------------------------------------------------
13 mS延时函数,含有输入参数 unsigned char t,无返回值
14 unsigned char 是定义无符号字符变量,其值的范围是
15 0~255 这里使用晶振12M,精确延时请使用汇编
16 ------------------------------------------------*/
17 void DelayMs(unsigned char t)
18 {
19     while(t--)
20     {
21         //大致延时1mS
22         DelayUs2x(245);
23         DelayUs2x(245);
24     }
25 }
复制代码

>_<:delay.h

复制代码
 1 #ifndef __DELAY_H__
 2 #define __DELAY_H__
 3 /*------------------------------------------------
 4  uS延时函数,含有输入参数 unsigned char t,无返回值
 5  unsigned char 是定义无符号字符变量,其值的范围是
 6  0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 7  长度如下 T=tx2+5 uS 
 8 ------------------------------------------------*/
 9 void DelayUs2x(unsigned char t);
10 /*------------------------------------------------
11  mS延时函数,含有输入参数 unsigned char t,无返回值
12  unsigned char 是定义无符号字符变量,其值的范围是
13  0~255 这里使用晶振12M,精确延时请使用汇编
14 ------------------------------------------------*/
15 void DelayMs(unsigned char t);
16 
17 #endif
复制代码

>_<:display.c

复制代码
 1 #include"display.h"
 2 #include"delay.h"
 3 
 4 #define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0 替换
 5 //sbit LATCH1=P2^0;//定义锁存使能端口 段锁存
 6 //sbit LATCH2=P2^3;//                 位锁存
 7 
 8 unsigned char code dofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0~9
 9 unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码
10 unsigned char TempData[8]; //存储显示值的全局变量
11 /*------------------------------------------------
12 显示函数,用于动态扫描数码管
13 输入参数 FirstBit 表示需要显示的第一位,如赋值2表示从第三个数码管开始显示
14 如输入0表示从第一个显示。
15 Num表示需要显示的位数,如需要显示99两位数值则该值输入2
16 ------------------------------------------------*/
17 void Display(unsigned char FirstBit,unsigned char Num)
18 {
19     static unsigned char i=0;
20 
21     DataPort=0;   //清空数据,防止有交替重影
22     LATCH1=1;     //段锁存
23     LATCH1=0;
24 
25     DataPort=dofly_WeiMa[i+FirstBit]; //取位码 
26     LATCH2=1;     //位锁存
27     LATCH2=0;
28 
29     DataPort=TempData[i]; //取显示数据,段码
30     LATCH1=1;     //段锁存
31     LATCH1=0;
32 
33     i++;
34     if(i==Num)
35        i=0;   
36 }
37 /*------------------------------------------------
38 定时器初始化子程序
39 ------------------------------------------------*/
40 void Init_Timer0(void)
41 {
42     TMOD |= 0x01;      //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响             
43     //TH0=0x00;          //给定初值
44     //TL0=0x00;
45     EA=1;            //总中断打开
46     ET0=1;           //定时器中断打开
47     TR0=1;           //定时器开关打开
48 }
49 /*------------------------------------------------
50 定时器中断子程序
51 ------------------------------------------------*/
52 void Timer0_isr(void) interrupt 1 
53 {
54     TH0=(65536-2000)/256;          //重新赋值 2ms
55     TL0=(65536-2000)%256;
56     Display(0,8);
57 }
复制代码

>_<:display.h

复制代码
 1 #include<reg52.h>
 2 
 3 #ifndef __DISPLAY_H__
 4 #define __DISPLAY_H__
 5 
 6 #define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0 替换
 7 sbit LATCH1=P2^2;//定义锁存使能端口 段锁存
 8 sbit LATCH2=P2^3;//                 位锁存
 9 
10 extern unsigned char TempData[8]; //存储显示值的全局变量
11 extern unsigned char code dofly_DuanMa[10];
12 /*------------------------------------------------
13 显示函数,用于动态扫描数码管
14 输入参数 FirstBit 表示需要显示的第一位,如赋值2表示从第三个数码管开始显示
15 如输入0表示从第一个显示。
16 Num表示需要显示的位数,如需要显示99两位数值则该值输入2
17 ------------------------------------------------*/
18 void Display(unsigned char FirstBit,unsigned char Num);
19 /*------------------------------------------------
20 定时器初始化子程序
21 ------------------------------------------------*/
22 void Init_Timer0(void);
23 
24 #endif
复制代码

>_<:i2c.c

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

>_<:i2c.h

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

>_<:main()

复制代码
 1 /*-----------------------------------------------
 2 名称:IIC协议 24c02存储开机次数
 3 内容:每次开机,开机数值加1并存储到24c02
 4 ------------------------------------------------*/  
 5 #include <reg52.h>                
 6 #include "i2c.h"
 7 #include "delay.h"
 8 #include "display.h"
 9 
10 main()
11 {
12     unsigned char num=0;
13     Init_Timer0();
14     IRcvStr(0xae,50,&num,1);   //从24c02读出数据                             
15     num++;                 
16     ISendStr(0xae,50,&num,1);  //写入24c02 
17     DelayMs(10);
18     TempData[0]=dofly_DuanMa[num/100];    
19     TempData[1]=dofly_DuanMa[(num%100)/10];
20     TempData[2]=dofly_DuanMa[(num%100)%10];
21     
22     while(1)
23     {
24     }
25 }
复制代码


网友评论

登录后评论
0/500
评论
史迪奇2号
+ 关注