藍橋杯單片機練習_第八屆電子時鍾


一、題目要求

二、程序源碼

  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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM