一个简单的四位数码管的时钟,可以调节、暂停、清零时间,断电保存并且在设定的时间内有流水灯亮起。(附有程序和接线图)
如果有哪里做得不好的还请大家多指教。
单片机源程序如下:
- /*********************************************************************
- 简易时钟: 1. 四位数码管显示(分秒计时)。
- 2. 每到30~40秒时有流水灯亮起。
- 3. 可断电保存
- 4. 按键1——暂停
- 按键2——清零
- 按键3——加10秒
- 按键4——减10秒
- 按键5——加10分
- 按键6——减10分
- *********************************************************************/
- #include<reg51.h>
- #include"i2c.h"
- #include <intrins.h>
- #define uint unsigned int
- #define uchar unsigned char
- unsigned char m=0;
- uchar z=0;
- sbit key1=P1^0; //定义各按键对应的IO口
- sbit key2=P1^1 ;
- sbit key3=P1^2;
- sbit key4=P1^3;
- sbit key5=P1^4;
- sbit key6=P1^5;
- typedef unsigned char u8;
- typedef unsigned int u16;
- u8 i;
- uchar display2[]={ 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd }; //用于流水灯
- uint counter=0;
- u8 smgduan[16]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,
- 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71,};// 段选
- u8 smgduan1[16]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,}; //百位的段选
- u8 smgwei[8]={0x00,0x04,0x08,0x0c,0x10,0x14,0x18,0x1c}; //位选
- u8 a[4];//保存时钟的数据
- u8 sec,min;
- void delay(u16 i) //延迟函数
- {
- while(i--);
- }
- /*******************************************************************************
- * 函 数 名 : void At24c02Write(unsigned char addr,unsigned char dat)
- * 函数功能 : 往24c02的一个地址写入一个数据
- *******************************************************************************/
- void At24c02Write(unsigned char addr,unsigned char dat) //把dat的值存放到addr地址上
- {
- I2C_Start();
- I2C_SendByte(0xa0, 1);//发送写器件地址
- I2C_SendByte(addr, 1);//发送要写入内存地址
- I2C_SendByte(dat, 0); //发送数据
- I2C_Stop();
-
- }
- /*******************************************************************************
- * 函 数 名 : unsigned char At24c02Read(unsigned char addr)
- * 函数功能 : 读取24c02的一个地址的一个数据
- *******************************************************************************/
- unsigned char At24c02Read(unsigned char addr)
- {
- unsigned char sec;
- I2C_Start();
- I2C_SendByte(0xa0, 1); //发送写器件地址
- I2C_SendByte(addr, 1); //发送要读取的地址
- I2C_Start();
- I2C_SendByte(0xa1, 1); //发送读器件地址
- sec=I2C_ReadByte(); //读取数据
- I2C_Stop();
- return sec;
- }
- /***********************************
- 显示函数
- ************************************/
- void display()
- {
- a[0]=smgduan[sec%10];
- a[1]=smgduan[sec/10];
- a[2]=smgduan1[min%10];
- a[3]=smgduan[min/10];
- for(i=0;i<4;i++)
- {
- P0=a[i];
- P2=smgwei[4-i];
- delay(300); //不同的延时时间对数码管显示亮度会产生很大的影响,时间越短影响越大
- }
- }
- initial() //定时器0初始化
- { TMOD=0x01; //选择定时器工作模式
- TH0=55536/256; //设置定时初值
- TL0=55536%256;
- EA=1;
- ET0=1;
- TR0=1; }
- void time1init()
- { //定时器1初始化
- TMOD=0x01;
- TL1 = 0xCB;
- TH1 = 0xF3;
- EA=1; //总中断
- ET1=1; //中断允许开关
- TR1=1; //定时器开关
- }
- /***********************
- 按键扫描函数
- ************************/
- void keyscan()
- {
- delay(200);
- if(key2==0) //清零
- {
- delay(200);
- min=0;
- sec=0;
- while (!key2);}
- if(key1==0) //暂停
- {
- delay(200);
- while (!key1);
- TR1=~TR1; //停止或启动定时器1
- }
- if(key3==0) //增加10s,若此时秒大于50则在增加后进min进一,sec照量改变
- {
- delay(200);
- if(sec<=49)
- sec +=10;
- else
- {min+=1;
- sec-=50;}
- while(!key3);
- }
- if(key5==0) //增加10m
- {
- delay(200);
- min+=10;
- while(!key5);}
- if(min>=60) //min满60后全部归零
- {delay(200);
- min=0;
- sec=0;
- while(!key5);}
- delay(200);
- if(key6==0) //减少10m,若此时时间少于10m,则时间归零
- {
- delay(200);
- if(min>=10)
- {
- min-=10;
- while(!key6);}
- else
- {delay(200);
- min=0 ;
- sec=0;
- while(!key6);}
- }
- if(key4==0) //减少10秒
- {
- delay(200);
- if(sec>=10)
- {delay(200);
- sec-=10;
- while(!key4);
- }
- else if(min>=1&&sec<=10)
- {delay(200);
- min-=1;
- sec+=50;
- while(!key4);
- }
- else if(min==0&&sec<=10) //时间少于10s的在按下key4后归零
- {delay(200);
- min=0;
- sec=0;
- while(!key4);
- }
- }
- }
- /**********************
- 主函数
- ***********************/
- void main()
- {
- if(m==0) //断电后读数
- { sec=At24c02Read(1);
- min=At24c02Read(2);
- }
- time1init(); //调用各种子函数
- while(1)
- { At24c02Write(1,sec);
- keyscan();
- display();
- initial();
- }
- }
-
- void T0_int () interrupt 1 //定时器0控制流水灯
- { TR0=0;
- ET0=0;
- TH0=55536/256; //设置初值
- TL0=55536%256;
- if(sec>=30&&sec<=40) //在30s~40s时流水灯亮起
- {
- if(z<14)
- { counter++;
- if(counter==30) //定时控制LED灯的改变
- { z++;
- counter=0;
- }
- P3=display2[z]; }
- if(z==14)
- { P3=0xff;
- z=0; }
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
时钟.zip
(526.98 KB, 下载次数: 28)
|