基于单片机的电子钟仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
蓝桥杯任务单片机源程序如下:
- #include <regx51.h>
- #include <intrins.h>
- sfr AUXR = 0x8e;
- /*数码管显示字符转换表*/
- unsigned char tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40,0x39};
- signed char num[] = {10,10,10,10,10,10,10,10}; //数码管显示缓冲区
- signed char timeclock[] = {0,0,11,0,0,11,0,0}; //闹钟时间
- unsigned char TRH0,TRL0; //T0重载值的高字节和低字节
- bit clock = 0; //闹钟时间到标志位
- bit flag = 0; //1s闪烁标志位
- bit flag200ms = 0; //200ms定时标志位
- bit timesetup = 0; //时间设置标志位
- bit clocksetup = 0; //闹钟设置标志位
- unsigned position = 0; //设置小时,分钟,秒标志位(‘1’小时,‘2’分钟,‘3’秒)
- unsigned char Temp; //温度值
- unsigned char Time[5]; //时间值
- void key(); //按键判断执行函数
- void Ds1302_Display(); //时间显示函数
- void Ds18b20_Display(); //温度显示函数
- extern void Ds1302_Init(); //DS1302初始化函数
- void Ds1302_Time(unsigned char *time); //带参数的向DS18B20写时间
- extern void Write_Ds1302_Byte(unsigned char temp); //向DS1302写入数据
- extern unsigned char Read_Ds1302 (unsigned char address); //从DS1302读取数据
- extern unsigned char DS18B20_Temp(); //读取DS18B20温度值
- /*T0初始化函数 (ms = 中断时间)*/
- void Time0_Init(unsigned char ms)
- {
- unsigned long num; //临时变量
- num = 12000000 / 12; //12分频 定时器计数频率
- num = (num * ms)/1000; //计算所需的计数值
- num = 65536 - num; //计算定时器重载值
- TRH0 = (unsigned char)(num>>8); //定时器重载值拆分为高低字节
- TRL0 = (unsigned char)num;
- TH0 = TRH0; //加载T0重载值
- TL0 = TRL0;
- AUXR &= 0x7F;
- TMOD &= 0xf0; //清零T0的控制位
- TMOD |= 0x01; //配置T0为模式1
- EA = 1; //使能总中断
- ET0 = 1; //使能T0中断
- TR0 = 1; //启动T0
- }
- void main()
- {
- unsigned char i,k=0;
- Time0_Init(1); //初始化T0,定时时间为1ms
- Ds1302_Init(); //初始化DS1302
- while(1)
- {
- key();
- for(i=0;i<8;i++)
- {
- if(num[i]==timeclock[i])
- k++ ;
- else
- k = 0;
- }
- if(k == 8)
- clock = 1;
-
- }
- }
- /*DS18B20显示函数*/
- void Ds18b20_Display()
- {
- unsigned char i;
- if(flag200ms != 0)
- {
- flag200ms = 0;
- Temp = DS18B20_Temp();
-
- for(i=0;i<5;i++)
- {
- num[i] = 10;
- }
-
- num[5] = Temp / 10;
- num[6] = Temp % 10;
- num[7] = 12;
- }
- }
- /*DS1302显示函数*/
- void Ds1302_Display()
- {
- static unsigned char i;
- static unsigned char pers = 0xaa;
-
- if(flag200ms != 0)
- {
- flag200ms = 0;
- for(i=0;i<3;i++)
- {
- Time[i] = Read_Ds1302(i); //每200ms获取时间
- }
- if(pers != Time[0]) //判断时间有没有变化
- {
- num[7] = Time[0] & 0x0f; //秒
- num[6] = Time[0] >> 4;
- num[5] = 11;
- num[4] = Time[1] & 0x0f; //分
- num[3] = Time[1] >> 4;
- num[2] = 11;
- num[1] = Time[2] & 0x0f; //时
- num[0] = Time[2] >> 4;
- pers = Time[0]; //将变化值重新写入判断值
- }
- }
- }
- /*数码管显示函数*/
- void Display()
- {
- static unsigned char we = 0;
-
- P0 = 0x00; //清除鬼影
- P2 |= 0xff;
- P2 &= ~(1<<we); //位选择
- if(clocksetup)
- P0 = tab[timeclock[we]];
- else
- P0 = tab[num[we]]; //显示数选择
-
- if(flag) //进入设置状态
- {
- switch(position) //判断是那个设置位
- {
- case 1: P2 |= 0xc0; break; //秒
- case 2: P2 |= 0x18; break; //分
- case 3: P2 |= 0x03; break; //时
- default : position = 0; timesetup = 0; clocksetup = 0; break;
- }
- }
-
- if(++we >= 8) //八个数码管
- we = 0;
- }
- /*T0中断函数*/
- void Time0_inte() interrupt 1
- {
- static unsigned char ms = 0;
- static unsigned char flag1s = 0;
- static unsigned char flag5s = 0;
- TH0 = TRH0; //加载T0重载值
- TL0 = TRL0;
- Display(); //数码管显示
- if(++ms >= 200)
- {
- flag200ms = 1;
- ms = 0;
- if(flag5s < 5 && clock) //闹钟5秒时间判断
- {
- P1_0 = ~P1_0;
- }
- else
- {
- clock = 0;
- P1_0 = 0;
- }
- if(++flag1s >= 5)
- {
- flag1s = 0;
- flag = ~flag;
- if(clock)
- flag5s++;
- else
- flag5s = 0;
- }
- }
- }
- //向DS1302写入时间
- void TimeWeite()
- {
- unsigned char ti[3];
- //将两个分开的时间合成在一起
- ti[0] = ((num[6]<<4) | num[7]);
- ti[1] = ((num[3]<<4) | num[4]);
- ti[2] = ((num[0]<<4) | num[1]);
- Ds1302_Time(ti);
- }
- void key()
- {
- if((P3_0==0||P3_1==0||P3_2==0||P3_3==0)&&clock==1) //闹钟响应,进行关闭
- {
- clock = 0;
- while(!P3_0);while(!P3_1);
- while(!P3_2);while(!P3_3);
- }
- if(timesetup!=1 && clocksetup!=1 && P3_0==1) //按下显示温度值,松开显示时间
- {
- Ds1302_Display();
- }else if(timesetup!=1 && clocksetup!=1 &&P3_0 == 0)
- {
- Ds18b20_Display();
- }
- if(clocksetup !=1 && P3_3 == 0) //进入时间设置
- {
- timesetup = 1;
- position++;
- if(position == 4) //向DS1302重新写入时间
- {
- TimeWeite();
- }
- while(!P3_3);
- }
- if(timesetup !=1 && P3_2 == 0) //进入闹钟时间设置
- {
- clocksetup = 1;
- position++;
- clock = 0;
- while(!P3_2);
- }
- if((timesetup==1||clocksetup==1) && P3_0 == 0) //进入时间设置, 时间+1
- {
- if(timesetup) //实时时钟设置
- {
- if(position == 1) //秒
- {
- if(++num[7] >= 10)
- {
- num[7] = 0;
- if(++num[6] >=6)
- num[6] = 0;
- }
- }else
- if(position == 2) //分
- {
- if(++num[4] >= 10)
- {
- num[4] = 0;
- if(++num[3] >=6)
- num[3] = 0;
- }
- }else
- if(position == 3) //时
- {
- if(num[0] == 2)
- {
- if(++num[1] >= 5)
- {
- num[1] = 0;
- num[0] = 0;
- }
- }else
- if(++num[1] >= 10)
- {
- num[1] = 0;
- if(++num[0] >=3)
- num[0] = 0;
- }
- }
- }else if(clocksetup) //闹钟时间设置
- {
- if(position == 1) //秒
- {
- if(++timeclock[7] >= 10)
- {
- timeclock[7] = 0;
- if(++timeclock[6] >=6)
- timeclock[6] = 0;
- }
- }else
- if(position == 2) //分
- {
- if(++timeclock[4] >= 10)
- {
- timeclock[4] = 0;
- if(++timeclock[3] >=6)
- timeclock[3] = 0;
- }
- }else
- if(position == 3) //时
- {
- if(timeclock[0] == 2)
- {
- if(++timeclock[1] >= 4)
- {
- timeclock[1] = 0;
- timeclock[0] = 0;
- }
- }else
- if(++timeclock[1] >= 10)
- {
- timeclock[1] = 0;
- if(++timeclock[0] >=3)
- timeclock[0] = 0;
- }
- }
- }
- while(!P3_0);
- }
- if((timesetup==1||clocksetup==1) && P3_1 == 0) //进入时间设置, 时间-1
- {
- if(timesetup) //实时时钟设置
- {
- if(position == 1) //秒
- {
- if(--num[7] < 0)
- {
- num[7] = 9;
- if(--num[6] < 0)
- num[6] = 5;
- }
- }else
- if(position == 2) //分
- {
- if(--num[4] < 0)
- {
- num[4] = 9;
- if(--num[3] < 0)
- num[3] = 5;
- }
- }else
- if(position == 3) //时
- {
- if(--num[1] < 0)
- {
- num[1] = 9;
- if(--num[0] < 0)
- {
- num[0] = 2;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
基于单片机的电子钟.zip
(84.07 KB, 下载次数: 115)
|