📄 clock.lst
字号:
C51 COMPILER V7.04 CLOCK 09/17/2005 11:01:02 PAGE 1
C51 COMPILER V7.04, COMPILATION OF MODULE CLOCK
OBJECT MODULE PLACED IN clock.OBJ
COMPILER INVOKED BY: C:\KEIL\C51\BIN\C51.EXE clock.c BROWSE DEBUG OBJECTEXTEND
stmt level source
1 #include <AT89x51.h>
2 #include "intrins.h"
3 unsigned char hour,min,sec,year,month,day,weekday; //当前时间?日期?星期
4 unsigned int count_down; //1秒钟计时用
5 bit led_on; //数码管是否点亮的标志
6 unsigned char display[8]; //8位数码管要显示的数据
7 unsigned char attr; //八个数码管的闪烁控制字节,当为0时,对应数码管闪
8 bit flash; //LED 闪烁开关,与attr共同决定数码管是否闪烁
9 unsigned char show_status; //LED 显示状态标志
10 // 0:设置闹钟数据
11 // 1:显示当前日期及星期
12 // 2:显示当前时间
13 // 3:设置当前日期
14 // 4:设置当前时间
15 bit km; //按键已去抖动标志
16 bit kp; //按键已处理标志
17 bit sound; //蜂鸣器响标志
18 bit alarm_stop; //蜂鸣器响后用户手工按停标志
19 struct { unsigned char h; //小时
20 unsigned char m; //分钟
21 } alarm[8]; //定义结构数组,8个闹钟项
22 unsigned char alarm_en; //闹钟项启用标志
23 unsigned char alarm_wk; //闹钟项周末启用标志
24 unsigned char cur_alarm_set; //当前设置的闹钟项
25 unsigned char cur_alarm_active; //当前到点的闹钟项
26 bit new_alarm_info; //闹钟项内容已修改标志
27 sbit sound_output = P1^5; //蜂鸣器驱动端口,输出0时蜂鸣器响
28 sbit SDA = P1^6; //EEPROM数据线端口
29 sbit SCL = P1^7; //EEPROM时钟线端口
30 //以下是EEPROM操作时需要的延时函数
31 void I2cDelay()
32 {
33 1 _nop_(); _nop_(); _nop_();
34 1 _nop_(); _nop_(); _nop_();
35 1 }
36 //以下是延迟函数,参数为毫秒数
37 void DelayX1ms(unsigned char count)
38 {
39 1 unsigned char i,j;
40 1 for(i=0;i<count;i++)
41 1 for(j=0;j<240;j++) ;
42 1 }
43 //以下是I2C启动函数,24C08使用I2C方式
44 void Start()
45 {
46 1 SDA=1;
47 1 I2cDelay();
48 1 SCL=1;
49 1 I2cDelay();
50 1 SDA=0;
51 1 I2cDelay();
52 1 SCL=0;
53 1 }
54 //以下是I2C停止函数
55 void Stop()
C51 COMPILER V7.04 CLOCK 09/17/2005 11:01:02 PAGE 2
56 {
57 1 I2cDelay();
58 1 SDA=0;
59 1 I2cDelay();
60 1 SCL=1;
61 1 I2cDelay();
62 1 SDA=1;
63 1 I2cDelay();
64 1 }
65 //以下是发送1字节数据给EEPROM函数
66 bit SendByte(unsigned char value)
67 {
68 1 unsigned char i;
69 1 bit no_ack=0;
70 1 for(i=0;i<8;i++) //发送8位数据
71 1 {
72 2 I2cDelay();
73 2 if(value&0x80) SDA=1;
74 2 else SDA=0;
75 2 value=value<<1;
76 2 I2cDelay();
77 2 SCL=1;
78 2 I2cDelay();
79 2 I2cDelay();
80 2 SCL=0;
81 2 }
82 1 I2cDelay();
83 1 SDA=1; //确认脉冲周期,等待EEPROM的确认
84 1 I2cDelay();
85 1 SCL=1;
86 1 I2cDelay();
87 1 if(SDA==1) no_ack=1;
88 1 I2cDelay();
89 1 SCL=0;
90 1 return no_ack;
91 1 }
92 //以下是向EEPROM写1字节函数
93 void mywrite(unsigned char address,unsigned char value)
94 {
95 1 Start();
96 1 SendByte(0xa0); //发送从地址
97 1 SendByte(address); //发送子地址
98 1 SendByte(value); //发送数值
99 1 Stop();
100 1 DelayX1ms(10);
101 1 }
102 //以下是从EEPROM接收1字节函数
103 unsigned char ReadByte()
104 {
105 1 unsigned char i,bval;
106 1 bval=0;
107 1 for(i=0;i<8;i++) //接收8位数据
108 1 {I2cDelay();
109 2 SDA=1; //从P1输入数据时,先往P1输入"1"
110 2 I2cDelay();
111 2 SCL=1;
112 2 I2cDelay();
113 2 bval=bval<<1;
114 2 if(SDA) bval=bval|0x01;
115 2 I2cDelay();
116 2 SCL=0;}
117 1 I2cDelay();
C51 COMPILER V7.04 CLOCK 09/17/2005 11:01:02 PAGE 3
118 1 SDA=1; //确认脉冲周期,不送出确认
119 1 I2cDelay();
120 1 SCL=1;
121 1 I2cDelay();
122 1 I2cDelay();
123 1 return(bval);
124 1 }
125 //以下是从EEPROM读入1字节数据函数
126 unsigned char myread(unsigned char address)
127 {
128 1 unsigned char tmp;
129 1 Start();
130 1 SendByte(0xa0);
131 1 SendByte(address);
132 1 Start();
133 1 SendByte(0xa1);
134 1 tmp=ReadByte();
135 1 Stop();
136 1 DelayX1ms(2);
137 1 return(tmp);
138 1 }
139 //以下是定时器0中断程序,用于走时,1/8000秒一次
140 void Timer0ISR(void) interrupt 1 using 3
141 {
142 1 unsigned char tmp; unsigned int tmp_days;
143 1 count_down--;
144 1 if(count_down==1 || count_down==2001 || count_down==4001 || count_down==6001)
145 1 {flash=~flash; //数码管闪烁的开关量
146 2 if(sound && flash) sound_output=0; //驱动蜂鸣器
147 2 else sound_output=1; //关闭蜂鸣器
148 2 return;}
149 1 /*** 计算当前日期为星期几***/
150 1 if(count_down==3000)
151 1 {if(year==0) weekday=5; //2000年1月1日为星期六
152 2 else { tmp=(year-1)/4+1;
153 3 tmp=(year-tmp)+tmp*2;
154 3 weekday=(tmp+5)%7;} //计算出当前年的1月1日为星期几
155 2 tmp_days=0;
156 2 for(tmp=1;tmp<month;tmp++)
157 2 if(tmp==1 || tmp==3 || tmp==5 || tmp==7 || tmp==8 || tmp==10)
158 2 tmp_days=tmp_days+31;
159 2 else if(tmp==4 || tmp==6 || tmp==9 || tmp==11)
160 2 tmp_days=tmp_days+30;
161 2 else if(tmp==2)
162 2 {if(year%4==0) tmp_days=tmp_days+29;
163 3 else tmp_days=tmp_days+28;}
164 2 tmp_days=tmp_days+day-1;
165 2 weekday=(weekday+tmp_days%7)%7+1;
166 2 return;}
167 1 /*** 查询是否有闹钟时间项符合触发条件 ***/
168 1 if(count_down==5000)
169 1 {
170 2 if((alarm_stop || sound) && alarm[cur_alarm_active].m!=min) //触发后1分钟
171 2 {alarm_stop=0; sound=0; } //自动关蜂鸣器
172 2 if(sound==0 && alarm_stop==0) //没有已触发的闹钟项
173 2 for(tmp=0;tmp<8;tmp++) //则查询8个闹钟项内是否有符合条件的
174 2 {
175 3 if(((alarm_en>>tmp)&1)==0) continue; //该闹钟项不启用
176 3 if(((alarm_wk>>tmp)&1)==1) //该闹钟项周末有效
177 3 {if(weekday!=6 && weekday!=7) continue;}//不是星期六或星期天
178 3 else
179 3 { if(weekday==6 || weekday==7) continue; }
C51 COMPILER V7.04 CLOCK 09/17/2005 11:01:02 PAGE 4
180 3 if(alarm[tmp].h==hour && alarm[tmp].m==min) //比较当前时间
181 3 { sound=1; cur_alarm_active=tmp; break; } //与该闹钟项的时间
182 3 }
183 2 return;
184 2 }
185 1 if(count_down==0) //过了一秒钟
186 1 {
187 2 count_down=8000;
188 2 sec++;
189 2 if(sec==60)
190 2 {
191 3 sec=0;
192 3 min++;
193 3 if(min==60)
194 3 {
195 4 min=0; hour++;
196 4 if(hour==24)
197 4 {
198 5 hour=0; day++;
199 5 switch(day)
200 5 {case 29: if(month==2 && year%4) { day=1; month=3; } break;
201 6 case 30: if(month==2 && year%4==0) { day=1; month=3; } break;
202 6 case 31:if(month==4 || month==6 || month==9 || month==11)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -