仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include <AT89X52.h> //调用51单片机的头文件
- #define uint unsigned int
- #define uchar unsigned char
- sbit LS164_DATA = P3^0; //74LS164数据线
- sbit LS164_CLK = P3^1; //74LS164时钟线
- sbit LS164_MR = P3^3; //74LS164使能
- sbit HOUR_A = P1^0;
- sbit HOUR_S = P1^1;
- sbit MINUTE_A = P1^2;
- sbit MINUTE_S = P1^3;
- sbit SECOND_A = P1^4;
- sbit SECOND_S = P1^5;
- sbit CLOCK_ON = P1^6;
- sbit CLOCK_OFF = P1^7;
- //---------------------------------------
- //数码管字形表,供显示时查询
- unsigned char code LED[11]=
- { //定义表格一定要使用code,这样会做到程序存储区中
- 0x3F, //"0"的字形表,0B00111111
- 0x06, //"1"的字形表,0B00000110
- 0x5B, //"2"的字形表,0B01011011
- 0x4F, //"3"的字形表,0B01001111
- 0x66, //"4"的字形表,0B01100110
- 0x6D, //"5"的字形表,0B01101101
- 0x7D, //"6"的字形表,0B01111101
- 0x07, //"7"的字形表,0B00000111
- 0x7F, //"8"的字形表,0B01111111
- 0x6F, //"9"的字形表,0B01101111
- 0x40, //"-", 0B01000000
- };
- uint miao=0; //秒
- uint fen=15; //分
- uint shi=12; //时
- uint n=0; //计数
- uint i=0;
- uint state=0;
- uint date[6]={0,0,0,0,0,0}; //定义一个有6个地址的数组,分别存时分秒的个位和十位
- //---------------------------------------
- //8位数码管相关I/O设置
- //P2.0-P2.2为3-8译码器U16的3个输入,P2=0x00 0x01 0x02 0x03最大为 0x07
- //可以不用定义三个位,直接写P2=0X即可
- //---------------------------------------
- //x为段选数据,y为位选0x00 0x01 0x02 0x03最大为 0x07
- void tube_display(uint x,uint y)
- {
- P2=y;
- // P0=LED[x];
- LS164_MR=1;
- state=LED[x];
- for(i=0;i<8;i++) //循环写8位扩展引脚状态
- {
- LS164_CLK = 0;
- if(state & 0x80)
- {
- LS164_DATA = 1;
- }
- else
- {
- LS164_DATA = 0;
- }
- LS164_CLK = 1;
- state = state<<1;
- }
- }
- //延时函数
- void delay(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=50;y>0;y--);
- }
- //定时器初始化
- void time_init(void) //定时器初始化函数
- {
- TMOD=0x02; //选择方式2
- TH0=156; //重装初值为156 100us
- TL0=156; //运行值为156
- EA=1; //开总中断
- ET0=1; //开定时器0中断
- TR0=1; //开定时器0
- }
- //外部中断初始化
- void INT0_init(void) //定时器初始化函数
- {
- IT0=1; //INT0负跳变沿触发
- EX0=1; //外部中断0使能
- EA=1; //总中断使能
- }
- void display(void)
- {
- tube_display(10,0x02);
- delay(1);
- tube_display(10,0x05);
- delay(1);
-
- tube_display(date[0],0x07);
- delay(1);
-
- tube_display(date[1],0x06);
- delay(1);
-
- tube_display(date[2],0x04);
- delay(1);
-
- tube_display(date[3],0x03);
- delay(1);
-
- tube_display(date[4],0x01);
- delay(1);
-
- tube_display(date[5],0x00);
- delay(1);
- }
- /*************************** main code ******************************/
- void main(void) //主函数,单片机开机后就是从这个函数开始运行
- {
- time_init();
- INT0_init();
- while(1) //死循环,单片机初始化后,将一直运行这个死循环
- {
- display();
- }
- }
- /********************************************************************/
- /*定时器中断*/
- void timer() interrupt 1 //定时器0中断
- {
- n++;
- if(n==10000) //当n=10000时,表示1s到了
- {
- n=0;
- miao++;
- if(miao==60)
- {
- miao=0;
- fen++;
- if(fen==60)
- {
- fen=0;
- shi++;
- if(shi==24)
- {
- shi=0;
- }
- }
- }
- date[0]=miao%10;
- date[1]=miao/10;
- date[2]=fen%10;
- date[3]=fen/10;
- date[4]=shi%10;
- date[5]=shi/10;
- }
- }
- /*按键中断*/
- void INT0_ISR(void) interrupt 0
- {
- EX0=0;
- delay(1);
- if(HOUR_A==0)
- {
- shi++;
- while(HOUR_A==0);
- }
- else if(HOUR_S==0)
- {
- shi--;
- while(HOUR_S==0);
- }
- else if(MINUTE_A==0)
- {
- fen++;
- while(MINUTE_A==0);
- }
- else if(MINUTE_S==0)
- {
- fen--;
- while(MINUTE_S==0);
- }
- else if(SECOND_A==0)
- {
- miao++;
- while(SECOND_A==0);
- }
- else if(SECOND_S==0)
- {
- miao--;
- while(SECOND_S==0);
- }
- else if(CLOCK_ON==0)
- {
- TR0=1;
- while(CLOCK_ON==0);
- }
- else if(CLOCK_OFF==0)
- {
- TR0=0;
- while(CLOCK_OFF==0);
- }
- date[0]=miao%10;
- date[1]=miao/10;
- date[2]=fen%10;
- date[3]=fen/10;
- date[4]=shi%10;
- date[5]=shi/10;
- IE0=0;
- EX0=1;
- }
复制代码
Proteus8.8仿真工程文件51hei附件下载:
8Wei_Time.zip
(152.58 KB, 下载次数: 71)
|