基于單片機的電子鐘仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
0.jpg (131.25 KB, 下載次數: 32)
下載附件
2017-12-14 12:25 上傳
0.jpg (26.44 KB, 下載次數: 41)
下載附件
2017-12-14 12:25 上傳
藍橋杯任務單片機源程序如下:
- #include <regx51.h>
- #include <intrins.h>
- sfr AUXR = 0x8e;
- /*數碼管顯示字符轉換表*/
- unsigned char tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40,0x39};
- signed char num[] = {10,10,10,10,10,10,10,10}; //數碼管顯示緩沖區
- signed char timeclock[] = {0,0,11,0,0,11,0,0}; //鬧鐘時間
- unsigned char TRH0,TRL0; //T0重載值的高字節和低字節
- bit clock = 0; //鬧鐘時間到標志位
- bit flag = 0; //1s閃爍標志位
- bit flag200ms = 0; //200ms定時標志位
- bit timesetup = 0; //時間設置標志位
- bit clocksetup = 0; //鬧鐘設置標志位
- unsigned position = 0; //設置小時,分鐘,秒標志位(‘1’小時,‘2’分鐘,‘3’秒)
- unsigned char Temp; //溫度值
- unsigned char Time[5]; //時間值
- void key(); //按鍵判斷執行函數
- void Ds1302_Display(); //時間顯示函數
- void Ds18b20_Display(); //溫度顯示函數
- extern void Ds1302_Init(); //DS1302初始化函數
- void Ds1302_Time(unsigned char *time); //帶參數的向DS18B20寫時間
- extern void Write_Ds1302_Byte(unsigned char temp); //向DS1302寫入數據
- extern unsigned char Read_Ds1302 (unsigned char address); //從DS1302讀取數據
- extern unsigned char DS18B20_Temp(); //讀取DS18B20溫度值
- /*T0初始化函數 (ms = 中斷時間)*/
- void Time0_Init(unsigned char ms)
- {
- unsigned long num; //臨時變量
- num = 12000000 / 12; //12分頻 定時器計數頻率
- num = (num * ms)/1000; //計算所需的計數值
- num = 65536 - num; //計算定時器重載值
- TRH0 = (unsigned char)(num>>8); //定時器重載值拆分為高低字節
- TRL0 = (unsigned char)num;
- TH0 = TRH0; //加載T0重載值
- TL0 = TRL0;
- AUXR &= 0x7F;
- TMOD &= 0xf0; //清零T0的控制位
- TMOD |= 0x01; //配置T0為模式1
- EA = 1; //使能總中斷
- ET0 = 1; //使能T0中斷
- TR0 = 1; //啟動T0
- }
- void main()
- {
- unsigned char i,k=0;
- Time0_Init(1); //初始化T0,定時時間為1ms
- Ds1302_Init(); //初始化DS1302
- while(1)
- {
- key();
- for(i=0;i<8;i++)
- {
- if(num[i]==timeclock[i])
- k++ ;
- else
- k = 0;
- }
- if(k == 8)
- clock = 1;
-
- }
- }
- /*DS18B20顯示函數*/
- void Ds18b20_Display()
- {
- unsigned char i;
- if(flag200ms != 0)
- {
- flag200ms = 0;
- Temp = DS18B20_Temp();
-
- for(i=0;i<5;i++)
- {
- num[i] = 10;
- }
-
- num[5] = Temp / 10;
- num[6] = Temp % 10;
- num[7] = 12;
- }
- }
- /*DS1302顯示函數*/
- void Ds1302_Display()
- {
- static unsigned char i;
- static unsigned char pers = 0xaa;
-
- if(flag200ms != 0)
- {
- flag200ms = 0;
- for(i=0;i<3;i++)
- {
- Time[i] = Read_Ds1302(i); //每200ms獲取時間
- }
- if(pers != Time[0]) //判斷時間有沒有變化
- {
- num[7] = Time[0] & 0x0f; //秒
- num[6] = Time[0] >> 4;
- num[5] = 11;
- num[4] = Time[1] & 0x0f; //分
- num[3] = Time[1] >> 4;
- num[2] = 11;
- num[1] = Time[2] & 0x0f; //時
- num[0] = Time[2] >> 4;
- pers = Time[0]; //將變化值重新寫入判斷值
- }
- }
- }
- /*數碼管顯示函數*/
- void Display()
- {
- static unsigned char we = 0;
-
- P0 = 0x00; //清除鬼影
- P2 |= 0xff;
- P2 &= ~(1<<we); //位選擇
- if(clocksetup)
- P0 = tab[timeclock[we]];
- else
- P0 = tab[num[we]]; //顯示數選擇
-
- if(flag) //進入設置狀態
- {
- switch(position) //判斷是那個設置位
- {
- case 1: P2 |= 0xc0; break; //秒
- case 2: P2 |= 0x18; break; //分
- case 3: P2 |= 0x03; break; //時
- default : position = 0; timesetup = 0; clocksetup = 0; break;
- }
- }
-
- if(++we >= 8) //八個數碼管
- we = 0;
- }
- /*T0中斷函數*/
- void Time0_inte() interrupt 1
- {
- static unsigned char ms = 0;
- static unsigned char flag1s = 0;
- static unsigned char flag5s = 0;
- TH0 = TRH0; //加載T0重載值
- TL0 = TRL0;
- Display(); //數碼管顯示
- if(++ms >= 200)
- {
- flag200ms = 1;
- ms = 0;
- if(flag5s < 5 && clock) //鬧鐘5秒時間判斷
- {
- P1_0 = ~P1_0;
- }
- else
- {
- clock = 0;
- P1_0 = 0;
- }
- if(++flag1s >= 5)
- {
- flag1s = 0;
- flag = ~flag;
- if(clock)
- flag5s++;
- else
- flag5s = 0;
- }
- }
- }
- //向DS1302寫入時間
- void TimeWeite()
- {
- unsigned char ti[3];
- //將兩個分開的時間合成在一起
- ti[0] = ((num[6]<<4) | num[7]);
- ti[1] = ((num[3]<<4) | num[4]);
- ti[2] = ((num[0]<<4) | num[1]);
- Ds1302_Time(ti);
- }
- void key()
- {
- if((P3_0==0||P3_1==0||P3_2==0||P3_3==0)&&clock==1) //鬧鐘響應,進行關閉
- {
- clock = 0;
- while(!P3_0);while(!P3_1);
- while(!P3_2);while(!P3_3);
- }
- if(timesetup!=1 && clocksetup!=1 && P3_0==1) //按下顯示溫度值,松開顯示時間
- {
- Ds1302_Display();
- }else if(timesetup!=1 && clocksetup!=1 &&P3_0 == 0)
- {
- Ds18b20_Display();
- }
- if(clocksetup !=1 && P3_3 == 0) //進入時間設置
- {
- timesetup = 1;
- position++;
- if(position == 4) //向DS1302重新寫入時間
- {
- TimeWeite();
- }
- while(!P3_3);
- }
- if(timesetup !=1 && P3_2 == 0) //進入鬧鐘時間設置
- {
- clocksetup = 1;
- position++;
- clock = 0;
- while(!P3_2);
- }
- if((timesetup==1||clocksetup==1) && P3_0 == 0) //進入時間設置, 時間+1
- {
- if(timesetup) //實時時鐘設置
- {
- if(position == 1) //秒
- {
- if(++num[7] >= 10)
- {
- num[7] = 0;
- if(++num[6] >=6)
- num[6] = 0;
- }
- }else
- if(position == 2) //分
- {
- if(++num[4] >= 10)
- {
- num[4] = 0;
- if(++num[3] >=6)
- num[3] = 0;
- }
- }else
- if(position == 3) //時
- {
- if(num[0] == 2)
- {
- if(++num[1] >= 5)
- {
- num[1] = 0;
- num[0] = 0;
- }
- }else
- if(++num[1] >= 10)
- {
- num[1] = 0;
- if(++num[0] >=3)
- num[0] = 0;
- }
- }
- }else if(clocksetup) //鬧鐘時間設置
- {
- if(position == 1) //秒
- {
- if(++timeclock[7] >= 10)
- {
- timeclock[7] = 0;
- if(++timeclock[6] >=6)
- timeclock[6] = 0;
- }
- }else
- if(position == 2) //分
- {
- if(++timeclock[4] >= 10)
- {
- timeclock[4] = 0;
- if(++timeclock[3] >=6)
- timeclock[3] = 0;
- }
- }else
- if(position == 3) //時
- {
- if(timeclock[0] == 2)
- {
- if(++timeclock[1] >= 4)
- {
- timeclock[1] = 0;
- timeclock[0] = 0;
- }
- }else
- if(++timeclock[1] >= 10)
- {
- timeclock[1] = 0;
- if(++timeclock[0] >=3)
- timeclock[0] = 0;
- }
- }
- }
- while(!P3_0);
- }
- if((timesetup==1||clocksetup==1) && P3_1 == 0) //進入時間設置, 時間-1
- {
- if(timesetup) //實時時鐘設置
- {
- if(position == 1) //秒
- {
- if(--num[7] < 0)
- {
- num[7] = 9;
- if(--num[6] < 0)
- num[6] = 5;
- }
- }else
- if(position == 2) //分
- {
- if(--num[4] < 0)
- {
- num[4] = 9;
- if(--num[3] < 0)
- num[3] = 5;
- }
- }else
- if(position == 3) //時
- {
- if(--num[1] < 0)
- {
- num[1] = 9;
- if(--num[0] < 0)
- {
- num[0] = 2;
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
基于單片機的電子鐘.zip
(84.07 KB, 下載次數: 115)
2017-12-14 10:29 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|