数码管显示多个模式
实际使用的单片机为STC89C52,可实现掉电闹钟时间不丢失,开关状态不丢失的功能
由于Proteus中没有STC,所以用AT的51代替,因此该功能在仿真中不能实现(AT51没有内部EEPROM),实际电路是可行的
PS:闹钟铃声为本校校歌-------《一方沃土》
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #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)
|