第八届省赛程序设计题--电子钟程序设计【蓝桥杯真题—03】

初始化
  1. 关闭蜂鸣器、继电器等无关外设;
  2. 设备初始化时钟为 23 时 59 分 50 秒,闹钟提醒时间 0 时 0 分 0 秒。
显示功能
  1. 时间显示格式
    在这里插入图片描述

  2. 温度显示格式
    在这里插入图片描述

按键功能
  1. 按键 S7 定义为“时钟设置”按键,通过该按键可切换选择待调整的
    时、分、秒,当前选择的显示单元以 1 秒为间隔亮灭,时、分、秒的调整需注意数据边界属性。
    在这里插入图片描述

  2. 按键 S6 定义为“闹钟设置”按键,通过该按键可进入闹钟时间设置
    功能,数码管显示当前设定的闹钟时间。
    在这里插入图片描述

  3. 按键 S5 定义为“加”按键,在“时钟设置”或“闹钟设置”状态下,
    每次按下该按键当前选择的单元(时、分或秒)增加 1 个单位。

  4. 按键 S4 定义为“减”按键,在“时钟设置”或“闹钟设置”状态下,

  5. 按键功能说明:
    按键 S4、S5 的“加”、“减”功能只在“时钟设置”或“闹钟设置”
    状态下有效;
    在 “时钟显示”状态下,按下 S4 按键,显示温度数据,松开按键,
    返回“时钟显示”界面。

闹钟提示功能
  1. 指示灯 L1 以 0.2 秒为间隔闪烁,持续 5 秒钟。
  2. 闹钟提示状态下,按下任意按键,关闭闪烁提示功能。
#include <STC15F2K60S2.H>
#include <DS1302.H>
#include <onewire.h>

void delay_ms(int n);

sbit s7=P3^0;
sbit s6=P3^1;
sbit s5=P3^2;
sbit s4=P3^3;
sbit L1=P0^0;
unsigned char table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xc6};
unsigned char Write_ds1302[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
unsigned char Read_ds1302[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
unsigned char timer[3]={0x50,0x59,0x23};  //50秒 59分 23时  19日 2月  周五 21年	0x19,0x02,0x05,0x21
unsigned char clock[3]={0x00,0x00,0x00};  //存放闹钟的时间														#include <STC15F2K60S2.H>

unsigned char flag_smg=1;  //控制数码管选中显示闪烁的标志变量,使用定时器空控制其闪烁
unsigned char flag_s7 = 0; //记录S7的当前状态,0为时钟显示,1为设置时钟
unsigned char flag_s6 = 0; //记录S6的当前状态,0为S6未按下,1为设置闹钟的时间
unsigned char count=0; //定时器定时变量
unsigned char temp=0;  //存放温度的值
unsigned char led_c = 0;							   //控制LED的计数变量变量
unsigned char led_f = 0;							   //控制LED闪烁的标志变量
unsigned char led_k = 0;							   //控制led的开关变量,0为关


//===========================定时器0初始化以及服务函数=============================
void Init_timer()
{
	TMOD=0x01;//定时器0/16位定时器
	TH0=(65536-10000)/256;
	TL0=(65536-10000)%256;
	ET0=1;
	TR0=1;
	EA=1;
}
void service_timer0() interrupt 1
{
	TH0=(65536-10000)/256;
	TL0=(65536-10000)%256;
	count++;
	if(count==100) //10ms*100=1s,控制选中的数码管进行闪烁
	{
		flag_smg=~flag_smg;
		count=0;
	}

	if(led_k==1) //表示打开LED闪烁功能
	{
		led_c++; //计算0.2S闪烁
		if(led_c%20==0)	//10ms*20=0.2s,LED闪烁间隔
		{
			led_f=~led_f; //闪速标志位取反,达到闪烁
			if(led_c>=500) //闪烁到了5s,停止闪烁
			{
				led_k=0;
			    led_c=0;
				led_f=0;
			}
		}
	}
}

//================================时钟初始化和时间读取函数==================================
void DS1302_Config()
{
     unsigned char i;
	 Write_Ds1302(0x8e,0x00);
	 for(i=0;i<3;i++)
	 {
	 	Write_Ds1302( Write_ds1302[i],timer[i] );
	 }
	 Write_Ds1302(0x8e,0x80);
}
void Read_DS1302_Timer()
{
	unsigned char j;
	for(j=0;j<3;j++)
	{
		timer[j] = Read_Ds1302 ( Read_ds1302[j] );
	}
}

//=================================温度读取函数===================================
void read_temp()
{
	unsigned char LSB;//温度的低八位
	unsigned char MSB;//温度的高八位
	Init_DS18B20();//1.DS18B20复位
	Write_DS18B20(0xcc);//2.写入字节0XCC,跳过ROM指令
	Write_DS18B20(0x44);//3.写入字节0X44,开始温度转换
    delay_ms(800);		//4.延时700~900ms

	Init_DS18B20();		//5.DS18B20复位
	Write_DS18B20(0xcc);//6.写入字节0XCC,跳过ROM指令
	Write_DS18B20(0xbe);//7.写入字节0XBE,读取温度
    
  	LSB=Read_DS18B20();  //8.读取暂存器的第0字节,即温度数据的LSB
   	MSB=Read_DS18B20();  //9.读取暂存器的第1字节,即温度数据的MSB
    Init_DS18B20();	     //10.DS18B20复位。表示读取数据结束

	temp=MSB;
	temp=(temp<<8)|LSB;
	temp>>=4;
}

//================================寄存器选择函数==================================
void selectHC(unsigned char n)
{
	switch(n)
	{
		case 4: P2=(P2&0X1f)|0x80; break;
		case 5: P2=(P2&0X1f)|0xa0; break;
		case 6: P2=(P2&0X1f)|0xc0; break;
		case 7: P2=(P2&0X1f)|0xe0; break;
		case 0: P2=(P2&0x1f)|0x00;break;
	}
}

//================================第w个数码管显示n==================================
void show(unsigned char w,unsigned char n)
{
	selectHC(6);
	P0=0X01<<w;
	selectHC(7);
	P0=table[n];
	delay_ms(5);
	P0=0xff;
	P2&=0x1f;
}
void allsmg(unsigned char dat)
{
	selectHC(6);
	P0 = 0xff;
	selectHC(7);
	P0 = dat;
	selectHC(0);	
}
//================================延时函数==================================
void delay_ms(int n)
{
	int i,j;
	for(i=n;i>0;i--)
		for(j=110;j>0;j--);
}

void delay(unsigned int t)
{
	while(t--);
}
//================================显示时钟和闹钟函数==================================
void show_timer_clock()
{
    if(flag_s6==0) //s6未按下,显示的是时钟
	{
		if(((flag_smg==1)&&(flag_s7==1))|flag_s7==0|flag_s7==2|flag_s7==3) //
		{
			show(1,timer[2]%16); //显示时
			show(0,timer[2]/16);
		}
		show(2,10);//显示——
		if(((flag_smg==1)&&(flag_s7==2))|flag_s7==0|flag_s7==1|flag_s7==3)
		{
			show(4,timer[1]%16);	//显示分
			show(3,timer[1]/16);
		}
		show(5,10);//显示——	
		if(((flag_smg==1)&&(flag_s7==3))|flag_s7==0|flag_s7==2|flag_s7==1)
		{
			show(7,timer[0]%16);	//显示秒
			show(6,timer[0]/16);
		}
		allsmg(0xff);
	}
	else if(flag_s6!=0) //显示闹钟
	{
		if(((flag_s6==1)&(flag_smg==1))|(flag_s6==0)|(flag_s6==2)|(flag_s6==3))
		{
			show(0,clock[2]/10);
			show(1,clock[2]%10);
		}
		show(2,10);
		if(((flag_s6==2)&(flag_smg==1))|(flag_s6==0)|(flag_s6==1)|(flag_s6==3))
		{
			show(3,clock[1]/10);
			show(4,clock[1]%10);
		}
		show(5,10);
		if(((flag_s6==3)&(flag_smg==1))|(flag_s6==0)|(flag_s6==2)|(flag_s6==1))
		{
			show(6,clock[0]/10);
			show(7,clock[0]%10);;
		}
		allsmg(0xff);
	}	
}

//================================LED灯显示函数==================================
void led_runing()
{
	if((clock[0]==timer[0]/16)&&(clock[1]==timer[1]/16)&&(clock[2]==timer[2]/16))
	{
		led_k=1;
	}
	if(led_f==1)
	{
		selectHC(4);
		L1=0;  //亮
		selectHC(0);
	}  	
	else if(led_f==1)
	{
		selectHC(4);
		L1=1; //熄
		selectHC(0);
	}
}

//================================BCD码的加减函数==================================
unsigned char add(unsigned char dat)
{
	dat = dat + 1;
	switch(dat)
	{
		case 10:
			dat = 16;break;			 //BCD的10
		case 26:
			dat = 32;break;			 //BCD的20
		case 42:
			dat = 48;break;			 //BCD的30
		case 58:
			dat = 64;break;			 //BCD的40
		case 74:
			dat = 80;break;			 //BCD的50
		case 90:
			dat = 96;break;			 //BCD的60
	}
	return dat;
}
unsigned char minus(unsigned char dat)
{
	dat = dat - 1;
	switch(dat)
	{
		case 79:
			dat = 73;break;	   
		case 63:
			dat = 57;break;
		case 47:
			dat = 41;break;
		case 31:
			dat = 25;break;
		case 15:
			dat = 9;break;
		case -1:
			dat = 89;break;		
	}
	return dat;
}

//================================显示温度函数==================================
void show_temp()
{
	show(5,temp/10);
	delay_ms(1);
	show(6,temp%10);
	delay_ms(1);
	show(7,11);
	delay_ms(1);
}

//================================按键扫描函数==================================
void keys()
{
	if(s7==0)
	{	
		delay(200);
		if (s7==0)
		{
			while (s7 == 0)
			{
				show_timer_clock();
				led_runing();
				Read_DS1302_Timer();	
			}
			if (led_k == 1)
			{
				led_k = 0;
				led_c = 0;
				led_f = 0;
			} 
			flag_s7++; //flag_s7默认0,0为正常显示时钟
			if (flag_s7 >= 4)
			{
				flag_s7 = 0;
			}
		}
	}

	if(s6==0)
	{	
		delay(200);
		if (s6==0)
		{
			while (s6 == 0)
			{
				show_timer_clock();
				led_runing();
				Read_DS1302_Timer();	
			}
			if (led_k == 1)
			{
				led_k = 0;
				led_c = 0;
				led_f = 0;
			} 
			flag_s6++; //flag_s7默认0,0为正常显示时钟
			if (flag_s6 >= 4)
			{
				flag_s6 = 0;
			}
		}
	}

	if(s5==0)
	{
		delay(200);
		if(s5==0)
		{
			while (s5 == 0)
			{
				show_timer_clock();
				led_runing();
				Read_DS1302_Timer();	
			}
			if (led_k == 1)
			{
				led_k = 0;
				led_c = 0;
				led_f = 0;
			} 
			if (flag_s7==1)//选择时钟 时加一
			{
				timer[2]=add(timer[2]); //BCD码加1	
				if(timer[2]>=35) //满了24小时清零
				{
					timer[2]=0;
				}
			}
			else if (flag_s7==2)//选择时钟 分加一
			{
				timer[1]=add(timer[1]);	
				if(timer[1]>=96) 
				{
					timer[1]=0;
				}
			}
			else if (flag_s7==3)//选择时钟 秒加一
			{
				timer[0]=add(timer[0]); 
				if(timer[0]>=96)
				{
					timer[0]=0;
				}
			}

			if(flag_s6==1) //选择闹钟 时加一
			{
				clock[2]=clock[2]+1; 
				if(clock[2]>=24)
				{
					clock[2]=0;
				}
			}
			else if(flag_s6==2) //选择闹钟 分加一
			{
				clock[1]=clock[1]+1; 
				if(clock[1]>=24)
				{
					clock[1]=0;
				}
			}
			else if(flag_s6==3) //选择闹钟 秒加一
			{
				clock[0]=clock[0]+1; 
				if(clock[0]>=24)
				{
					clock[0]=0;
				}
			}
			DS1302_Config();
		}
	}

	if(s4==0)
	{
		delay(200);
		if(s4==0)
		{
			while (s4 == 0)
			{
				if ((flag_s6 == 0) & (flag_s7 == 0))
				{
					read_temp();
					show_temp();	
				}
				else 
				{
					show_timer_clock();
					led_runing();	
				}
				DS1302_Config();
			}
			if (led_k == 1)
			{
				led_k = 0;
				led_c = 0;
				led_f = 0;
			} 
			if (flag_s7==1)//选择时钟 时减一
			{
				timer[2]=minus(timer[2]); 	
				if(timer[2]==89) 
				{
					timer[2]=35;
				}
			}
			else if (flag_s7==2)//选择时钟 分减一
			{
				timer[1]=minus(timer[1]);	
			}
			else if (flag_s7==3)//选择时钟 秒减一
			{
				timer[0]=add(timer[0]); 
			}

			if(flag_s6==1) //选择闹钟 时减一
			{
				clock[2]=clock[2]-1; 
				if(clock[2]==-1)
				{
					clock[2]=23;
				}
			}
			else if(flag_s6==2) //选择闹钟 分减一
			{
				clock[1]=clock[1]-1; 
				if(clock[1]==-1)
				{
					clock[1]=59;
				}
			}
			else if(flag_s6==3) //选择闹钟 秒减一
			{
				clock[0]=clock[0]-1; 
				if(clock[0]==-1)
				{
					clock[0]=59;
				}
			}
			DS1302_Config();
		}
	} 
}

void main()
{
	selectHC(4); P0=0xff; P2&=0X1F;
	selectHC(5); P0=0x00; P2&=0X1F;
    DS1302_Config();
	Init_timer();
	while(1)
	{
	    Read_DS1302_Timer();
		show_timer_clock();
		keys();
		led_runing();
	}
}
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谏书稀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值