仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
單片機源程序如下:
- /*基于51單片機設(shè)計定時器鬧鐘 小老弟~*/
- #include "reg51.h" //定義頭文件
- #define uchar unsigned char
- #define uint unsigned int
- #define LED P0 //定義數(shù)碼管段選(數(shù)據(jù))管腳
- sbit LSA=P2^0; //定義24譯碼器管腳,進行位選
- sbit LSB=P2^1;
- sbit k1=P2^2; //定義按鍵管腳
- sbit k2=P2^3;
- sbit k3=P2^4;
- sbit k4=P2^5;
- sbit beep=P2^6; //蜂鳴器管腳
- uchar s,sec,h; //定義計數(shù)變量對應分別為秒、分、時
- char pre_s=0,pre_sec=0,pre_h=8; //定義報警時間變量,對應分別為秒、分、時
- bit state,h_sec; //狀態(tài)變量,state=1為進入鬧鈴時間設(shè)置,h_sec為時分選擇設(shè)置
- uchar disp[4]; //數(shù)碼管顯示數(shù)組
- uchar pre_time[4]; //設(shè)定鬧鈴時間顯示數(shù)組
- uchar code smgduan[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //段碼表
- void delay_ms(uint t) //延時函數(shù)
- {
- uchar i;
- for(;t>0;t--)
- {
- for(i=0;i<125;i++);
- }
- }
- void T0Init() //定時器T0初始化
- {
- TMOD=0x01;
- TH0=(65536-1000)/256;
- TL0=(65536-1000)%256;
- EA=1;
- ET0=1;
- TR0=1;
- }
- void time_pro() //計數(shù)時間處理函數(shù)
- {
- disp[0]=smgduan[sec%10]; //分的個位
- disp[1]=smgduan[sec/10]; //分的十位
- disp[2]=smgduan[h%10]; //時的個位
- disp[3]=smgduan[h/10]; //時的十位
- }
- void pretime_pro()
- {
- pre_time[0]=smgduan[pre_sec%10]; //定時分的個位
- pre_time[1]=smgduan[pre_sec/10]; //定時分的十位
- pre_time[2]=smgduan[pre_h%10]; //定時時的個位
- pre_time[3]=smgduan[pre_h/10]; //定時時的十位
- }
- void digdisp() //計數(shù)時間顯示
- {
- uchar i;
- for(i=0;i<4;i++)
- {
- switch(i)
- {
- case(0):
- LSA=0;LSB=0;break; //位選
- case(1):
- LSA=1;LSB=0;break;
- case(2):
- LSA=0;LSB=1;break;
- case(3):
- LSA=1;LSB=1;break;
- }
- LED=disp[i]; //對應位的顯示
- delay_ms(1);
- LED=0xff; //消隱
- }
- }
- void digdisp_pre() //定時時間顯示
- {
- uchar i;
- for(i=0;i<4;i++)
- {
- switch(i)
- {
- case(0):
- LSA=0;LSB=0;break; //位選
- case(1):
- LSA=1;LSB=0;break;
- case(2):
- LSA=0;LSB=1;break;
- case(3):
- LSA=1;LSB=1;break;
- }
- LED=pre_time[i]; //對應位的顯示
- delay_ms(1);
- LED=0xff; //消隱
- }
- }
- void key_pro() //按鍵處理函數(shù)
- {
- if(k1==0)
- {
- delay_ms(1); //消抖
- if(k1==0)
- {
- state=~state; //改變狀態(tài)state,state=1進入定時時間設(shè)置
- while(!k1); //松手檢測
- }
- }
- if((k2==0)&&(state==1))
- {
- delay_ms(1); //消抖
- if((k2==0)&&(state==1))
- {
- h_sec=~h_sec; //改變狀態(tài)h_sec,h_sec=1設(shè)置分,h_sec=0設(shè)置時
- while(!k2); //松手檢測
- }
- }
- if((k3==0)&&(state==1)) //加一
- {
- delay_ms(1); //消抖
- if((k3==0)&&(state==1))
- {
- if(h_sec==0)
- {
- pre_h++; //定時時加一
- if(pre_h==24)
- {
- pre_h=0;
- }
- }
- else
- {
- pre_sec++; //定時分加一
- if(pre_sec==60)
- {
- pre_sec=0;
- }
- }
- while(!k3); //松手檢測
- }
- }
- if((k4==0)&&(state==1)) //減一
- {
- delay_ms(1);
- if((k4==0)&&(state==1))
- {
- if(h_sec==0)
- {
- pre_h--; //定時時減一
- if(pre_h<0)
- {
- pre_h=23;
- }
- }
- else
- {
- pre_sec--; //定時分減一
- if(pre_sec<0)
- {
- pre_sec=59;
- }
- }
- while(!k4); //松手檢測
- }
- }
- }
- void sound() //蜂鳴器報警函數(shù)
- {
- uchar i;
- for(i=0;i<10;i++)
- {
- beep=~beep;
- delay_ms(1);
- }
- }
- void main()
- { //T0初始化
- T0Init();
- while(1)
- {
- key_pro(); //按鍵檢測
- if(state==0) //如果state為0,數(shù)碼管顯示計數(shù)時間
- {
- time_pro();
- digdisp();
- if((pre_sec==sec)&&(pre_h==h)&&(s-pre_s<10)) //計數(shù)時間到定時時間發(fā)出報警聲,持續(xù)10s
- {
- sound();
- }
- }
- else //如果state=0,進入定時時間設(shè)置,數(shù)碼管顯示當前設(shè)置時間
- {
- pretime_pro();
- digdisp_pre();
- }
- }
- }
- void time0() interrupt 1 //定時器T0中斷處理函數(shù)
- {
- static int n; //定義局部靜態(tài)變量
- TH0=(65536-1000)/256; //賦初值
- TL0=(65536-1000)%256;
- n++; //進入一次中斷n+1
- if(n==1000) //當n=1000時,滿足1s
- {
- n=0;
- s++; //秒加1
- if(s==60)
- {
- s=0;
- sec++; //秒滿60,分加1
- if(sec==60)
- {
- sec=0; //分滿60,時加1
- h++;
- if(h==24)
- {
- h=0;
- }
- }
- }
- }
- }
復制代碼
所有資料51hei提供下載:
定時器鬧鐘(帶仿真).zip
(67.7 KB, 下載次數(shù): 110)
2020-12-3 12:32 上傳
點擊文件名下載附件
完整代碼,帶仿真
|