1 #include<reg52.h>
2 #define uint unsigned int
3 #define uchar unsigned char
4
5 sbit SCL =P2^1;
6 sbit SDA =P2^0;
7
8 sbit K1 =P3^0;
9 sbit K2 =P3^1;
10 sbit K3 =P3^0;
11 sbit K4 =P3^1;
12
13 sbit LSA =P2^2;
14 sbit LSB =P2^3;
15 sbit LSC =P2^4;
16 uchar num;
17 uchar code smgduan[] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
18
19 /*******************************************************************************
20 * 函数名 : Delay10us()
21 * 函数功能 : 延时10us
22 * 输入 : 无
23 * 输出 : 无
24 *******************************************************************************/
25 void Delay10us()//通过计算来确定延时为10uM
26 {
27 unsigned char a,b;
28 for(b=1;b>0;b--)
29 for(a=2;a>0;a--);
30
31 }
32 /*******************************************************************************
33 * 函数名 : I2cStart()
34 * 函数功能 : 起始信号:在SCL时钟信号在高电平期间SDA信号产生一个下降沿
35 * 输入 : 无
36 * 输出 : 无
37 * 备注 : 起始之后SDA和SCL都为0
38 *******************************************************************************/
39
40 void I2cStart()
41 {
42 SDA=1;
43 Delay10us();
44 SCL=1;
45 Delay10us();//建立时间是SDA保持时间>4.7us
46 SDA=0;
47 Delay10us();//保持时间是>4us
48 SCL=0;
49 Delay10us();
50 }
51 /*******************************************************************************
52 * 函数名 : I2cStop()
53 * 函数功能 : 终止信号:在SCL时钟信号高电平期间SDA信号产生一个上升沿
54 * 输入 : 无
55 * 输出 : 无
56 * 备注 : 结束之后保持SDA和SCL都为1;表示总线空闲
57 *******************************************************************************/
58
59 void I2cStop()
60 {
61 SDA=0;
62 Delay10us();
63 SCL=1;
64 Delay10us();//建立时间大于4.7us
65 SDA=1;
66 Delay10us();
67 }
68 //针对IIC的写字节
69 uchar IICsendByte(uchar dat)
70 {
71 uchar a=0,b;
72 SDA =dat;
73 for(a=0;a<8;a++)
74 {
75 SDA =dat>>7; //将最高位取出,然后其他的为都通过右移掉
76 dat =dat<<1; // 因为dat的值一直没有变化,故而,将其左移一位,最高位移掉,次高位变成最高位
77 SDA =1;
78 delay(1);
79 SCL=0;
80 delay(1);
81 } //此时8位数据已经全部传送完成 接下来进行应答
82 SDA=1; //SDA和SCL为1是为了下面应答做铺垫
83 delay(1);
84 SCL=1;
85 // delay(1);
86 while(SDA) //当应答成功的话,SDA=0;跳出循环
87 {
88 b++;
89 if(b>200)
90 SCL=0;
91 dealy(1);
92 return 0; //表示发送(通讯)失败
93 }
94 SCL =0;
95 delay(1);
96 return 1; //发送成功的时候,返回1
97 }
98 //针对IIC的读字节
99 uchar IICReadByte()
100 {
101 uchar a,dat =0;
102 SD1=1; //首先先让其拉高,让其处于空闲状态,不至于让下面的SDA的数据为低
103 delay(1);
104 for(a=0;a<8;a++)
105 {
106 SCL =1; //为了读数据,故而首先让SCL为高,就是为了让数据稳定后再读
107 dealy(1);
108 dat<<=1; // 0 00 10 110 要将其放在dat|=SDA前面,否则当把8位数据全部放到dat中后, 再移一位的话,就会使得最高位移走,数据出错 将其左移一位,等二次循环过来时,这是就会原来保存在dat中的数据就会继续左移一次
109 dat|=SDA; // 01 11 111 也就是只需要让其移动7次,不将最高位移走 让dat与SDA进行“按位或”将SDA的值赋给dat
110 delay(1);
111 SCL=0; //让SCL为低,就是为了让数据改变
112 delay(1);
113 }
114 return dat;
115 }
116 //芯片AT24C02通讯的读写
117 void AT24C02writeByte(uchar add,uchar dat)
118 {
119 IICstart();
120 IICsendByte(0xa0);//这是器件地址,8位 高四位是固定的 最后一位表示0为写、1为读、其余的三位A1、A2、A3,我们接了地
121 IICsendByte(add);
122 IICsendByte(dat);//应答与否我们都在IIC的字节函数中谢了
123 IICStop();
124 }
125 uchar AT24C02read(uchar add)//由于是要读取信号,故而需要知道读取的地址即可
126 {
127 uchar value;
128 IICstart();
129 IICsendByte(0xa0);//这是器件地址,8位 高四位是固定的 最后一位表示0为写、1为读、其余的三位A1、A2、A3,我们接了地
130 IICsendByte(add);
131 IICstart(); //由于前面要写入它的地址,之后要读里面的数据,所以读写的方向会发生变化,所以必须要重新写入起始信号和器件地址
132 IICsendByte(0xa1);
133 value =IICReadByte();//直接读取地址中的数据,并且将读回来的值保存到value中去
134 IICstop();
135 return value;
136 }
137 //独立按键的函数
138 void keypros()
139 {
140 if (K1==0)
141 {
142 delay(10);
143 if(K1==0)
144 {
145 AT24C02writeByte(1,num); //按键1实现将num的值,写入到 1 的地址中去,因为AT24C02这个芯片有255个内存
146 }
147 while(!K1);//判断按键是否释放 如果忘记写这个语句,这个函数的功能就会不停地进行
148 }
149 if (K2==0)
150 {
151 delay(10);
152 if(K2==0)
153 {
154 num =AT24C02read(1); //将存储到 1这个内存中的数据读取出来,再赋给变量num这个值
155 }
156 while(!K2);
157 }
158
159 if (K3==0)
160 {
161 delay(10);
162 if(K3==0)
163 {
164 num++; //对num的值进行加1运行
165 if(num>255) //因为num的变量为uchar,故而只能存储255个字符
166 num =0;
167 }
168 while(!K3);
169 }
170 if (K4==0)
171 {
172 delay(10);
173 if(K4==0)
174 {
175 num =0; //对num精心清零运算
176 }
177 while(!K4);
178 }
179 }
180 /*******************************************************************************
181 * 函数名 :DigDisplay()
182 * 函数功能 :数码管显示函数
183 * 输入 : 无
184 * 输出 : 无
185 *******************************************************************************/
186 void DigDisplay()
187 {
188 u8 i;
189 for(i=0;i<4;i++)
190 {
191 switch(i) //位选,选择点亮的数码管,
192 {
193 case(0):
194 LSA=0;LSB=0;LSC=0; break;//显示第0位
195 case(1):
196 LSA=1;LSB=0;LSC=0; break;//显示第1位
197 case(2):
198 LSA=0;LSB=1;LSC=0; break;//显示第2位
199 case(3):
200 LSA=1;LSB=1;LSC=0; break;//显示第3位
201 }
202 P0=disp[3-i];//发送数据
203 delay(100); //间隔一段时间扫描
204 P0=0x00;//消隐
205 }
206 }
207 /*******************************************************************************
208 * 函数名 :datapros()
209 * 函数功能 :数据处理函数
210 * 输入 : 无
211 * 输出 : 无
212 *******************************************************************************/
213 void datapros()
214 {
215 disp[0]=smgduan[num/1000];//千位
216 disp[1]=smgduan[num%1000/100];//百位
217 disp[2]=smgduan[num%1000%100/10];//个位
218 disp[3]=smgduan[num%1000%100%10];
219 }
220 void main()
221 {
222 while(1)
223 {
224 Keypros(); //按键处理函数
225 datapros(); //数据处理函数
226 DigDisplay();//数码管显示函数
227 }
228 }