首页 > 技术文章 > 蓝桥杯单片机练习_第八届电子时钟

nsss 2019-03-15 15:31 原文

一、题目要求

二、程序源码

  1 #include "stc15.h"
  2 #include "ds1302.h"
  3 #include "onewire.h"
  4 
  5 #define uchar unsigned char
  6 #define uint unsigned int    
  7 #define KEYCOM P3
  8 #define KEY_S4 0x08 
  9 #define    KEY_S5 0x04 
 10 #define    KEY_S6 0x02 
 11 #define    KEY_S7 0x01 
 12 
 13 
 14 uchar code smg_dis[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40,0x39};
 15 uchar code Time_Init [3] ={23,59,50};//时钟初始化 时 分 秒 
 16 
 17 uchar code Time_Max [3] = {23,59,59};//时间阈值
 18 uchar Time_rd_Buf[3];//时间读取缓存
 19 uchar Clock_buf[3]={0,0,0};//闹钟时间
 20 uchar Time_set_Buf[3];//时间设置缓存
 21 uchar Smg_Buf[8];//数码管显示缓存
 22 
 23 uchar Trg;//按键当前值
 24 uchar Cont;//按键前次值 
 25 
 26 bit KeyFlag = 0;
 27 bit ClockFlag = 0;//闹钟
 28 bit TimeFlag = 0;//时间获取
 29 
 30 bit ClockSet  = 0;//设置闹钟
 31 bit TimeSet  = 0;//设置时间
 32 
 33 bit BlinkFlag=0;
 34 bit TempShow =0;//温度显示
 35 
 36 
 37 void KeyRead (void);
 38 void Timer0Init(void);
 39 void SMG_Show (uchar *arr);
 40 void SMG_Show1 (uchar *arr);
 41 uchar Resize (uchar sum , uchar max);//按键调整时间
 42 void Ds1302_Init (unsigned char *arr);
 43 void Ds1302_Get (unsigned char *arr);
 44 unsigned char Read_Temp (void);
 45 
 46 int main (void)
 47 {
 48     uchar Temp_Val=0;//温度值
 49     char T_Len=-1;// 设置的位数切换
 50     P0=0x00;P2=0xa0;P2=0x00;
 51     P0=0xff;P2=0x80;P2=0x00;
 52     Ds1302_Init(Time_Init);//设置初始化时间
 53     Temp_Val=Read_Temp();//读取一次消除 第一次的85
 54     Timer0Init();
 55     while(1)
 56     {
 57         if(KeyFlag)
 58         {
 59             KeyFlag=0;
 60             KeyRead();
 61                 if((Trg & KEY_S7) && !ClockSet && !ClockFlag)//非闹钟设置或闹钟
 62                 {
 63                     if(!TimeSet)//只有第一次按下时才写入
 64                     {
 65                         Time_set_Buf[0]=Time_rd_Buf[0]/16*10+Time_rd_Buf[0]%16;//16进制转换10进制  写入函数的入参是十进制
 66                         Time_set_Buf[1]=Time_rd_Buf[1]/16*10+Time_rd_Buf[1]%16;//将读取的时间写到设置的缓存中,调整的也是缓存中的值
 67                         Time_set_Buf[2]=Time_rd_Buf[2]/16*10+Time_rd_Buf[2]%16;//整个设置过程中不再读取时间
 68                     }
 69                     TimeSet=1;
 70                     ++T_Len;
 71                         if( T_Len > 2) //初值为 -1 按下立即自加一次 =0    取值 0 1 2  对应 Time_set_Buf 和 Time_Max 和 Clock_buf 数组的下标
 72                         {
 73                             T_Len=-1;
 74                             TimeSet=0;//退出设置模式
 75                             Ds1302_Init(Time_set_Buf);//时分秒全部设置后 写入时间
 76                         }
 77                 }
 78                 if(Trg & KEY_S6  && !TimeSet && !ClockFlag)//闹钟设置
 79                 {
 80                     ClockSet=1;
 81                     ++T_Len;
 82                         if( T_Len > 2) //与时间设置同理
 83                         {
 84                             T_Len=-1;
 85                             ClockSet=0;
 86                         }
 87                 }
 88                 
 89                 if(Trg & KEY_S4 && !TimeSet && !ClockSet && !ClockFlag || Cont & KEY_S4 )//按下显示温度
 90                 {
 91                     TempShow=1;
 92                     Temp_Val=Read_Temp();
 93                     Smg_Buf[0]=10;
 94                     Smg_Buf[1]=10;
 95                     Smg_Buf[2]=10;
 96                     Smg_Buf[3]=10;
 97                     Smg_Buf[4]=10;
 98                     Smg_Buf[5]=Temp_Val/10;
 99                     Smg_Buf[6]=Temp_Val%10;
100                     Smg_Buf[7]=12;
101                 }
102                 else
103                     TempShow=0;
104             
105                 if(TimeSet)//时间设置
106                 {
107                     SMG_Show1(Time_set_Buf);
108                     if(BlinkFlag && T_Len>=0)//闪烁 每隔1s标志位会变化一次 标志位为1的时候,将不显示该位
109                     {
110                         Smg_Buf[T_Len*3+1]=10;
111                         Smg_Buf[T_Len*3 ]=10;
112                     }
113                     Time_set_Buf[T_Len]=Resize(Time_set_Buf[T_Len],Time_Max[T_Len]);//调整
114                 }
115 
116                 if(ClockSet)//闹钟设置   与时间设置同理
117                 {
118                     SMG_Show1(Clock_buf);
119                     if(BlinkFlag && T_Len>=0)
120                     {
121                         Smg_Buf[T_Len*3+1]=10;
122                         Smg_Buf[T_Len*3 ]=10;
123                     }
124                     Clock_buf[T_Len]=Resize(Clock_buf[T_Len],Time_Max[T_Len]);
125                 }
126 
127                 if(ClockFlag && (Trg & KEY_S4 || Trg & KEY_S5 || Trg & KEY_S6 || Trg & KEY_S7))//关闹钟
128                 {
129                     ClockFlag=0;
130                     P0=~0x00;P2=0x80;P2=0x00;
131                 }
132                 
133         }
134         if(TimeFlag && !TimeSet && !ClockSet )//100ms 获取时间并在非设置状态下显示
135         {
136             TimeFlag=0;
137             Ds1302_Get(Time_rd_Buf);
138             if(!TempShow)
139                 SMG_Show(Time_rd_Buf);//显示温度的时候不更新显示缓存
140             if(Time_rd_Buf[0]==Clock_buf[0] && Time_rd_Buf[1]==Clock_buf[1] && Time_rd_Buf[2]==Clock_buf[2] )//闹钟
141             {
142                 ClockFlag=1;
143             }
144         }
145     }
146 }
147 
148 
149 void Timer0Init(void)        //1ms@11.0592MHz
150 {
151     AUXR |= 0x80;        
152     TMOD &= 0xF0;        
153     TL0 = 0xCD;        
154     TH0 = 0xD4;        
155     TF0 = 0;    
156     TR0 = 1;        
157     ET0 = 1;
158     EA  = 1;
159 }
160 
161 void TIME0 (void) interrupt 1
162 {
163     static uchar SmgCount = 0;
164     static uchar KeyCount = 0;
165     static uchar TimeCount = 0;
166     static uint BlinkCount = 0;
167     static uchar SmgLen = 0;
168     static uchar ClockCount = 0;
169     static uchar ClockNum=0;
170     if( ++KeyCount > 10)
171     {
172         KeyCount = 0;
173         KeyFlag = 1;
174     }
175     
176     if(TimeSet || ClockSet)//设置的时候闪烁
177     {
178         if( ++BlinkCount >1000) 
179         {
180             BlinkCount=0;
181             BlinkFlag=~BlinkFlag;//不可手动置零
182         }
183     }
184     else//不在设置下全部清零
185     {
186         BlinkCount=0;
187         BlinkFlag=0;
188     }
189     
190     if( ++SmgCount > 1)//数码管动态
191     {
192         SmgCount = 0;
193         P0=~smg_dis[Smg_Buf[SmgLen]];P2=0xe0;P2=0X00;
194         P0=1<<SmgLen;P2=0xc0;P2=0X00;
195         if(++SmgLen > 7) SmgLen=0;
196     }
197     
198     if( ++TimeCount > 100)//时间获取间隔
199     {
200         TimeCount=0;
201         TimeFlag=1;
202     }
203     
204     if(ClockFlag)//闹钟
205     {
206         ClockCount++;
207         if(ClockCount >=200)//0.2s 
208         {
209             ClockCount=0;
210             ClockNum++;
211             if(ClockNum>=25) //次数
212             {
213                 ClockNum=0;
214                 ClockFlag=0;
215                 ClockCount=0;
216             }
217             if( ClockNum%2 )//亮或灭
218             {
219                 P0=~0x01;P2=0x80;P2=0x00;
220             }
221             else
222             {
223                 P0=~0x00;P2=0x80;P2=0x00;
224             }
225         }
226     }
227         else//不在闹钟状态下全部清零
228         {
229                 ClockNum=0;
230                 ClockCount=0;
231         }
232 }
233 
234 void KeyRead (void)
235 {
236       unsigned char ReadData = KEYCOM^0xff;        
237     Trg = ReadData & (ReadData ^ Cont);     
238     Cont = ReadData; 
239 }
240 
241 void SMG_Show (uchar *arr)
242 {
243         Smg_Buf[0]=arr[0]/16;
244         Smg_Buf[1]=arr[0]%16;
245         Smg_Buf[2]=11;
246         Smg_Buf[3]=arr[1]/16;
247         Smg_Buf[4]=arr[1]%16;
248         Smg_Buf[5]=11;
249         Smg_Buf[6]=arr[2]/16;
250         Smg_Buf[7]=arr[2]%16;
251 }
252 
253 void SMG_Show1 (uchar *arr)//10进制 设置的时候显示
254 {
255         Smg_Buf[0]=arr[0]/10;
256         Smg_Buf[1]=arr[0]%10;
257         Smg_Buf[2]=11;
258         Smg_Buf[3]=arr[1]/10;
259         Smg_Buf[4]=arr[1]%10;
260         Smg_Buf[5]=11;
261         Smg_Buf[6]=arr[2]/10;
262         Smg_Buf[7]=arr[2]%10;
263 }
264 
265 
266 uchar Resize (uchar sum , uchar max)//按键调整 
267 {
268     char temp;
269     temp = sum;
270     if(Trg & KEY_S5)// +
271     {
272         if( ++temp > max ) temp=max;
273     }
274     if(Trg & KEY_S4)// -
275     {
276         if( --temp < 0)   temp=0;
277     }
278     return temp;
279 }
280 
281 void Ds1302_Init (unsigned char *arr)
282 {
283     Write_Ds1302(0x8e,0);
284     Write_Ds1302(0x80,(arr[2]/10)*16+arr[2]%10);//小时
285     Write_Ds1302(0x82,(arr[1]/10)*16+arr[1]%10);//
286     Write_Ds1302(0x84,(arr[0]/10)*16+arr[0]%10);//
287     Write_Ds1302(0x8e,0x80);
288 }
289 
290 void Ds1302_Get (unsigned char *arr)//时间获取
291 {
292     arr[2]=Read_Ds1302(0x81);
293     arr[1]=Read_Ds1302(0x83);
294     arr[0]=Read_Ds1302(0x85);
295 }
296 
297 unsigned char Read_Temp (void)//温度
298 {
299     unsigned char Low,High,Temp;
300     init_ds18b20();
301     Delay_OneWire(1);
302     Write_DS18B20(0xcc);
303     Write_DS18B20(0x44);
304     init_ds18b20();
305     Delay_OneWire(1);
306     Write_DS18B20(0xcc);
307     Write_DS18B20(0xbe);
308     Low=Read_DS18B20();
309     High=Read_DS18B20();
310     Low=Low>>4;
311     High=High<<4;
312     Temp=High|Low;
313     return Temp;
314 }

 

推荐阅读