|
下面是51单片机数码管电子钟的proteus仿真原理图(工程文件可到本帖附件中下载):
单片机电子钟源程序如下:
- //#include <reg51.h>
- //# include <absacc.h>
- # include <STC12C5A60S2.h>
- # define uchar unsigned char
- # define uint unsigned int
- # define uint32 unsigned long int
- # define sint32 signed long int
- # define vtim1 50000 //定时50ms,一帧8*50=40ms,频率=40Hz
- # define vtim2 2500 //定时2.5ms,一帧8*2.5=20ms,频率=50Hz
- //# define vt DBYTE[0x21^0]
- # define vt ((unsigned char volatile data *) 0)[0x21^0]
- //sbit vt=0xe8;
- //数码管位选循环变量
- uchar wi=0;
- //共阴数码管段码表
- uchar code distable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0X40,0x00,0x31};
- //位选码表
- uchar code numi[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
- //显示缓存
- uchar V_ram[]={0x01,0x02,0x10,0x03,0x04,0x10,0x05,0x06};
- sbit p32=P3^2;
- sbit p33=P3^3;
- uchar i=0;
- uchar j=0,k=0,ss=0;
- uchar x=0;
- uchar key_num=0xff;
- void main()
- {
- vt=1;
- vt=0;
- vt=1;
- IT0=0;
- IT1=0;
- EA=1;
- ET0=1;
- ET1=1;
- EX0=1;
- EX1=1;
- PT0=1;
- TH1=(65536-vtim1)/256;
- TL1=(65536-vtim1)%256;
- TH0=(65536-vtim2)/256;
- TL0=(65536-vtim2)%256;
- TMOD=0X11;
- TR0=1;
- TR1=1;
- while(1);
-
- }
- void t1_rpt() interrupt 3 //50ms中断
- {
- TH1=(65536-vtim1)/256;
- TL1=(65536-vtim1)%256;
- /////////////////按键去抖动////////////////
- if(~(EX1||EX0))
- {
- x++;
- if(x>=5)//按键按下250ms 后,全能按键中断
- {
- IE0=0; //清中断源
- IE1=0; //清中断源
- EX1=1; //打开中断
- EX0=1; //打开中断
- }
- }
- ////////////////0.35秒闪烁周期///////////////
- if(key_num<8)
- {
- k++; //闪烁计时变量
- j++; //闪烁超时变量
- k=k&0x07; //0.4秒闪烁周期
- if(k<4)
- {
- ss=0; //0.2秒亮
- }
- else
- {
- ss=1; //0.2秒灭
- }
- if(j>=100) //超时5秒闪烁停止
- {
- key_num=0xff;
- k=0;
- j=0;
- ss=0;
- }
- }
- }
-
- void t0_rpt() interrupt 1
- { ///////////////////////////定时刷新数码管代码//////////////////////////////
- uchar dm=0,wx=0;
- TH0=(65536-vtim2)/256;
- TL0=(65536-vtim2)%256;
- dm=distable[V_ram[wi]]; //取显示段码
- if((wi==key_num)&&(ss==1))dm=distable[0x11]; // key_num:表示对应数码管闪烁;ss=1表示显示黑色
- wx=numi[wi]; //取位选码
- P1=0x00; //关显示
- P2=dm; //段码赋给P0口
- P1=wx;
- wi++;
- if(wi==8)
- {
- wi=0;
- i++;
- }
- /////////////////////////计时代码,把秒,分,时分别放入对应的显示RAM////////////////////////
- if(i==50)
- { //秒
- i=0;
- V_ram[7]++; //秒个位++
- if(V_ram[7]>=10)
- {
- V_ram[7]=0;
- V_ram[6]++; //秒十位++
- if(V_ram[6]>=6)
- {
- V_ram[6]=0;
- V_ram[4]++; //分个位++
- if(V_ram[4]>=10)
- {
- V_ram[4]=0;
- V_ram[3]++; //分十位++
- if(V_ram[3]>=6)
- {
- V_ram[3]=0;
- V_ram[1]++; //时个位++
- if((V_ram[1]>=10)&&(V_ram[0]<2))
- {
- V_ram[1]=0;
- V_ram[0]++; //时十位++
- }
- if((V_ram[1]>=4)&&(V_ram[0]>=2))
- {
- V_ram[1]=0; //时个位清零
- V_ram[0]=0; //时十位清零
- }
- }
- }
- }
- }
- }
-
- }
- void EXTR0_rpt() interrupt 0 /////////外部中断1,功能键:切换对应的数码管并使该数码管闪烁////////////////
- {
- x=0; //按键去抖动计时清零
- EX0=0; //关中断,用于去抖动
- j=0; //长期不按键,闪烁停止。闪烁超时变量清零
- if(key_num==7)
- key_num=0;
- else
- key_num++;
- if(key_num==2)key_num=3; //
- if(key_num==5)key_num=6; //
- }
- void EXTR1_rpt() interrupt 2
- {
- x=0; //按键去抖动计时清零
- EX1=0; //关中断,用于去抖动
- j=0; //长期不按键,闪烁停止。闪烁超时变量清零
- switch (key_num)
- {
- case 2:
- case 5: {
- break;
- }
- case 0: {
- if (V_ram[key_num]<2)
- {
- V_ram[key_num]=V_ram[key_num]+1; //时十位加1
- }
- else
- V_ram[key_num]=0x00;
- break;
- }
- case 1: //时个位加1
- case 4: //分个位加1
- case 7: { //秒个位加1
- if (V_ram[key_num]<9)
- V_ram[key_num]=V_ram[key_num]+1;
- else
- V_ram[key_num]=0;
- //if ((V_ram[0]==2)&&(V_ram[1]>=4))
- //{
- // V_ram[1]=3;
- //}
- break;
- }
- case 3: //分十位加1
- case 6: { //秒十位加1
- if (V_ram[key_num]<5)
- V_ram[key_num]=V_ram[key_num]+1;
- else
- V_ram[key_num]=0;
- break;
- }
- default:
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
给大家分享一些我们老师给的一些经典的单片机程序源码, 一共有十多个.都有详细的注释,然大家快速的理解每一行代码的意思。而且有proteus仿真原理图。大家可以直接验证程序的对错.

本系列所有源码打包下载地址(含proteus仿真工程文件和源程序):
http://www.51hei.com/bbs/dpj-82474-1.html
本例程下载:
电子钟.rar
(79.12 KB, 下载次数: 82)
|
|