數碼管顯示多個模式
實際使用的單片機為STC89C52,可實現掉電鬧鐘時間不丟失,開關狀態不丟失的功能
由于Proteus中沒有STC,所以用AT的51代替,因此該功能在仿真中不能實現(AT51沒有內部EEPROM),實際電路是可行的
PS:鬧鐘鈴聲為本校校歌-------《一方沃土》
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
QQ截圖20180906130759.jpg (162.46 KB, 下載次數: 73)
下載附件
帶仿真
2018-9-6 13:08 上傳
0.png (52.33 KB, 下載次數: 58)
下載附件
2018-9-13 05:00 上傳
單片機源程序如下:
- #include<reg52.h>
- #include<intrins.h>
- #include"buzzer.h"
- #include"delay.h"
- #include"stc_eeprom.h"
- #include"ds1302.h"
- #include"display.h"
- #include"keyscan.h"
- #define uchar unsigned char
- #define uint unsigned int
- char alarm_hour=0,alarm_minute=23;//鬧鐘時間設置 有符號
- uchar alarm_temp[8];
- uchar num1,alarm_en,alarm_switch=1;
- uchar tms=0,sec=0,temp_tms=0,temp_sec=0,dq_sec,dq_tms,k=3;//秒表 k為顯示的位數0-k,按下分圈計時則顯示8位
- bit miaobiao_flag=0,fenquan_flag=0;
- uchar num; //用來做定時器動態掃描的基數
- uchar mb_temp[8];//用來儲存轉換成數碼管各位顯示的數據
- /*******************************************************************/
- /**************************鬧鐘判斷函數***************************/
- /*******************************************************************/
- void alarm_judge()
- {
- if(alarm_hour==time[4]&&alarm_minute==time[5]&&alarm_en&&alarm_switch)
- {
- key0_count=4;//強制切換到鬧鐘顯示狀態,防止兩種顯示互相干擾(表現為秒顯示有殘影)
- tune=music[i]+music[i+1]*7-1;
- pai=music[i+2];
- TH1=tuneH[tune];
- TL1=tuneL[tune];
- TR1=1;
- delay_jiepai(pai);
- i+=3;
- if(i>138) //循環播放
- i=0;
- }
- else
- {
- buzzer=1;
- i=0;
- }
- }
- /*******************************************************************/
- /************************分圈計時的計算函數*************************/
- /*******************************************************************/
- void fenquanjishi()
- {
- temp_tms+=dq_tms;
- temp_sec+=dq_sec; //前n-1圈時間之和
- if(temp_tms>99) //若10毫秒數達到100則進位到秒
- {
- temp_tms-=100;
- temp_sec++;
- }
- if(tms<temp_tms) //若總時間的10毫秒數小于前n-1圈和的10毫秒數,則從秒借位
- {
- dq_tms=tms+100-temp_tms;
- dq_sec=sec-temp_sec-1;
- }
- else //第n圈單圈時間=總時間-前n-1圈時間之和
- {
- dq_tms=tms-temp_tms;
- dq_sec=sec-temp_sec;
- }
- }
- /*******************************************************************/
- /**************************主函數部分***************************/
- /*******************************************************************/
- void main()
- {
- //ds1302_init();
- alarm_hour=stc_eeprom_read(rom1);
- alarm_minute=stc_eeprom_read(rom2);//開機將存在單片機內部eeprom的鬧鐘時間和開關讀出
- alarm_switch=stc_eeprom_read(rom3);
- alarm_en=0;//鬧鐘使能默認為0,用來復位關鬧鈴
- EA=1;
- IP=0x02; //設置定時器0中斷優先,保證秒表走時的準確
- TMOD=0x11; //設置定時器工作方式
- ET1=1;
- ET0=1; //定時器0和1中斷
- while(1)
- {
- static uchar keyscan_count;//按鍵掃描計數,減少按鍵掃描頻率
- keyscan_count++;
- if(keyscan_count==10) //每隔10次進行按鍵掃描
- {
- keyscan_count=0;
- keyscan();
- }
- read_time(); //從ds1302中讀出數據
- if(time[6]==0) //走過新的一分鐘后才重新打開鬧鐘使能,用來配合復位關鬧鈴
- alarm_en=1; //(此時鬧鐘的分鐘與實際時間已不等)
- alarm_judge(); //鬧鐘判斷
- /*******************************************************************/
- /**************************時分秒顯示部分***************************/
- /*******************************************************************/
- if(key0_count==0)
- {
- display_time(time[4],time[5],time[6]);
- if(key1_count==1&&(key2_flag||key3_flag))
- {
- if(key2_flag) //判斷加還是減
- {
- time[4]++;
- key2_flag=0;
- if(time[4]>23)
- time[4]=0;
- }
- else if(key3_flag)
- {
- time[4]--;
- key3_flag=0;
- if(time[4]<0)
- time[4]=23;
- }
- ds1302_set_time(write_add[4],time[4]);
- }
- else if(key1_count==2&&(key2_flag||key3_flag))
- {
- if(key2_flag)
- {
- time[5]++;
- key2_flag=0;
- if(time[5]>59)
- time[5]=0;
- }
- else if(key3_flag)
- {
- time[5]--;
- if(time[5]<0)
- time[5]=59;
- key3_flag=0;
- }
- ds1302_set_time(write_add[5],time[5]);
- }
- else if(key1_count==3&&(key2_flag||key3_flag))
- {
- if(key2_flag)
- {
- time[6]++;
- key2_flag=0;
- if(time[6]>59)
- time[6]=0;
- }
- else if(key3_flag)
- {
- time[6]--;
- if(time[6]<0)
- time[6]=59;
- key3_flag=0;
- }
- ds1302_set_time(write_add[6],time[6]);
- }
- }
- /*******************************************************************/
- /**************************年月日顯示部分***************************/
- /*******************************************************************/
- else if(key0_count==1)
- {
- display_time(time[0],time[2],time[3]);
- static uchar Max_Day;
- switch(time[2])
- {
- case 4:
- case 6:
- case 9:
- case 11:Max_Day=30;break;
- case 2:
- if(time[0]%4==0) Max_Day=29;
- else Max_Day=28;
- break;
- default:Max_Day=31; //判斷各月的天數
- }
- if(key1_count==1&&(key2_flag||key3_flag))
- {
- if(key2_flag)
- {
- time[0]++;
- key2_flag=0;
- if(time[0]>99)
- time[0]=0;
- }
- else if(key3_flag)
- {
- time[0]--;
- if(time[0]<0)
- time[0]=99;
- key3_flag=0;
- }
- ds1302_set_time(write_add[0],time[0]);
- }
- else if(key1_count==2&&(key2_flag||key3_flag))
- {
- if(key2_flag)
- {
- time[2]++;
- if(time[2]>12)
- time[2]=1;
- key2_flag=0;
- }
- else if(key3_flag)
- {
- time[2]--;
- if(time[2]<1)
- time[2]=12;
- key3_flag=0;
- }
- ds1302_set_time(write_add[2],time[2]);
- }
- else if(key1_count==3&&(key2_flag||key3_flag))
- {
- if(key2_flag)
- {
- time[3]++;
- key2_flag=0;
- if(time[3]>Max_Day)
- time[3]=1;
- }
- else if(key3_flag)
- {
- time[3]--;
- if(time[3]<1)
- time[3]=Max_Day;
- key3_flag=0;
- }
- ds1302_set_time(write_add[3],time[3]);
- }
- }
- /*******************************************************************/
- /**************************秒表顯示部分***************************/
- /*******************************************************************/
- else if(key0_count==2) //如果模式選擇鍵按下2次,進入秒表模式
- {
- miaobiao_flag=1;//秒表模式的標志
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- TH1=(65536-5000)/256;
- TL1=(65536-5000)%256;
- TR1=1;
- do
- {
- keyscan(); //程序在此循環時不漏掉按鍵掃描
- if(key1_count)
- {
- TR0=1;
- }
- else
- {
- TR0=0;
- if(fenquan_flag) //進入分圈計后,即使按下停止鍵也能記出最后一圈的時間
- {
- fenquanjishi();
- fenquan_flag=0;
- }
- }
- if(key3_flag)
- {
- tms=0;
- sec=0;
- dq_sec=0;
- dq_tms=0;
- temp_sec=0;
- temp_tms=0;
- fenquan_flag=0;
- key3_flag=0;
- k=3; //按下清零鍵所有數據清零,只顯示數碼管0-3位正常秒表
- }
- else if(key2_flag&&TR0)//加TR0是為了在定時器未啟動時分圈計時鍵無效
- {
- key2_flag=0;
- k=7; //顯示8位數碼管,后四位為單圈時間
- fenquanjishi();
- }
- }while(key0_count==2); //防止重復設置定時器
- }
- /*******************************************************************/
- /**************************星期顯示部分***************************/
- /*******************************************************************/
- else if(key0_count==3) //如果模式選擇鍵按下3次,進入星期顯示模式
- {
- uchar b=0;
- static uchar dis_count=0;
- dis_count++;
- if(dis_count>51)
- dis_count=1;
- if(key1_count)
- b=50;
- if(dis_count>b) //若key1按下則閃動,表示進入調時模式
- {
- P2=table2[7];
- P0=table1[time[1]%16];
- delay(10);
- P2=0xff;
- delay(10);
- }
- if(key1_count&&(key2_flag||key3_flag))
- {
- if(key2_flag)
- {
- time[1]++;
- if(time[1]>7)
- time[1]=1;
- key2_flag=0;
- }
- else if(key3_flag)
- {
- time[1]--;
- if(time[1]<1)
- time[1]=7;
- key3_flag=0;
- }
- ds1302_set_time(write_add[1],time[1]);
- }
- }
- /*******************************************************************/
- /**************************鬧鐘顯示部分***************************/
- /*******************************************************************/
- else if(key0_count==4) //如果模式選擇鍵按下4次,進入鬧鐘顯示模式
- {
- uchar v1;
- if(alarm_switch)
- {
- display_time(alarm_hour,alarm_minute,0);
- }
- else
- {
- P2=0xff;
- P0=0x40;
- P2=table2[v1];
- delay(3);
- v1++;
- if(v1==8)
- v1=0;
- }
- if(key1_count==0&&(key2_flag||key3_flag))
- {
- if(key2_flag)
- {
- key2_flag=0;
- alarm_switch=1;
- stc_eeprom_erase(rom3); //擦除扇區
- stc_eeprom_write(rom3,alarm_switch); //寫入扇區
- }
- else if(key3_flag)
- {
- key3_flag=0;
- alarm_switch=0;
- stc_eeprom_erase(rom3);
- stc_eeprom_write(rom3,alarm_switch);
- }
- }
- else if(key1_count==1&&(key2_flag||key3_flag))
- {
- if(key2_flag)
- {
- alarm_hour++;
- key2_flag=0;
- if(alarm_hour>23)
- alarm_hour=0;
- }
- else if(key3_flag)
- {
- alarm_hour--;
- if(alarm_hour<0)
- alarm_hour=23;
- key3_flag=0;
- }
- stc_eeprom_erase(rom1);
- stc_eeprom_write(rom1,alarm_hour);
- }
- else if(key1_count==2&&(key2_flag||key3_flag))
- {
- if(key2_flag)
- {
- alarm_minute++;
- key2_flag=0;
- if(alarm_minute>59)
- alarm_minute=0;
- }
- else if(key3_flag)
- {
- alarm_minute--;
- if(alarm_minute<0)
- alarm_minute=59;
- key3_flag=0;
- }
- stc_eeprom_erase(rom2);
- stc_eeprom_write(rom2,alarm_minute);
- }
- alarm_temp[0]=table1[alarm_hour/10];
- alarm_temp[1]=table1[alarm_hour%10];
- alarm_temp[2]=0x40;
- alarm_temp[3]=table1[alarm_minute/10];
- alarm_temp[4]=table1[alarm_minute%10];
- alarm_temp[5]=0x40;
- alarm_temp[6]=table1[0];
- alarm_temp[7]=table1[0]; //轉化成位顯示,方便進入定時器時動態掃描
- }
- }
- }
- /*******************************************************************/
- /**************************定時器0和1中斷函數***************************/
- /*******************************************************************/
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
929861698Clock.zip
(111.03 KB, 下載次數: 37)
2018-9-6 13:06 上傳
點擊文件名下載附件
數碼管顯示多個模式 下載積分: 黑幣 -5
|