可调时钟的闹钟模式(接上篇)

写在前面:

        上篇文末提到可以优化的地方包括加入闹钟,了解无源蜂鸣器的工作原理后,就着手扩展闹钟设置功能了,同时按键按下加入蜂鸣器的提示音。由于上篇的篇幅过长了,所以决定单独写一篇这个闹钟模块。

一、实现思路 

  1. 保持原有功能情况下加入第三个模式
  2. 当前模式下执行功能,设置时分秒,同样是选中位闪烁,增大减小,越界判断等可以直接照搬前面的
  3. 设置的时分秒存在一个数组,当当前时间的时分秒都与之对应相等调用蜂鸣器
  4. 按下任意独立按键可以终止闹钟

二、蜂鸣器

1、工作原理

普中的板子上的是无源蜂鸣器,BZ连接在了步进电机OUT5,ULN2003D逻辑框图如下

 对于蜂鸣器驱动需要输入振荡脉冲,ULN2003D作用为继电器驱动,在这里我们只需要考虑输入取反输出即可,因此蜂鸣器连接对应51寄存器地址为P2_5(图和板子不一样)

sbit Buzzer = P2^5;  //类型声明蜂鸣器地址

 2、蜂鸣器响任意时间函数

循环体内使Buzzer每隔250us取反,一个周期为0.5ms,即2000HZ,循环执行次数决定持续时间,期间接收按键键码,只要键码不为0,即有任意独立按键按下,跳出循环,声音停止

#include <REGX52.H>
#include"Delay.h"
#include"Key.h"

sbit Buzzer = P2^5;  //类型声明蜂鸣器地址
unsigned int i;   //计数

/**
  * @brief 蜂鸣器以2000HZ的时间响x250us
  * @param  xms 蜂鸣器响的时间
  * @retval 无
  */
void Buzzer_Time(unsigned int x250us)
{
	unsigned KeyNumber;
	for(i=0;i<x250us;i++)
	{
		KeyNumber = Key();
		Buzzer = !Buzzer;    //振荡输入
		Delay10us(25);		 //高低电平维持时间为250us,一个周期就是0.5ms
		if(KeyNumber)break;
	}			

}

 封装好之后可以用于按键提示音和闹钟

三、代码设计和修改

1、预备工作

 定义Clock_Sel为闹钟设置模式下的时间位索引,定义数组存放设置闹钟的时分秒

//存放设置的脑钟时间
char Clock[] = {0,0,0};
//定义键码、设置时间位索引、设置时间闪烁标志、模式(显示时间/设置时间),闹钟设置时间位索引
unsigned char KeyNum, TimeSet_Sel, TimeSetFlag, Mode, Clock_Sel;  

2、增加模式

按下1键让Mode在0、1、2之间循环,为了保持原有设置时间功能(从设置时间模式切换到模式0时写入修改后的时间),将模式2作为设置时间模式,模式1为新增的设置闹钟时间。每次切换到闹钟模式时,闹钟时间位索引清0,固定从时开始设置,并且将LCD清空第一行显示“Clock:”

if(KeyNum == 1)
		{
			Buzzer_Time(100);    //蜂鸣器按键提示音
			if(Mode == 0)
			{
				Mode = 1;			//切换至设置闹钟模式
				LCD_Init();
				Delay(100);
				Clock_Sel = 0;    //每次切换到设置闹钟索引清0
			}
			else if(Mode == 1 )
			{
				Mode = 2;			//切换至设置时间模式
				TimeSet_Sel = 0;    //每次切换到设置时间模式索引清0,固定从“年”开始闪烁
			}
			else if(Mode == 2)
			{
				Mode = 0;		//切换回显示时间模式
				DS1302_SetTime();  //将已修改的时间数据写入芯片				
			}
		}
		switch(Mode)     //显示当前工作模式
		{
			case 0: LCD_ShowString(2,12,"Show ");break;
			case 1: LCD_ShowString(2,12,"Clock ");break;
			case 2: LCD_ShowString(2,12,"Set  ");break;
		}

当Mode == 1时,执行设置闹钟模式代码 

3、设置闹钟函数SetClock()

思路可以说是完全照搬了上一篇的设置时间函数,都是按2键索引++,3键当前时间位++,4键当前时间位--,越界判断和校正从之前的函数里截取了时分秒的部分,闪烁设置也是一样的,按键提示音在整个程序所有地方都加上了,没什么好说的直接贴代码

void SetClock(void)
{
	LCD_ShowString(1,1,"Clock:");
	LCD_ShowNum(1,13,Clock_Sel,2);
	if(KeyNum == 2)         //2号按键选择设置的时间位
	{
		Buzzer_Time(100);    //蜂鸣器按键提示音
		Clock_Sel++;
		Clock_Sel %= 3;	//索引在0~1
	}
	if(KeyNum == 3)         //3号按键使当前时间位+1
	{
		Buzzer_Time(100);    //蜂鸣器按键提示音		
		Clock[Clock_Sel]++;
		if(Clock[0]>23)Clock[0] = 0;   //小时越界判断	
		if(Clock[1]>59)Clock[1] = 0;   //分越界判断
		if(Clock[2]>59)Clock[2] = 0;   //秒越界判断
	}
	if(KeyNum == 4)			//4号键使当前时间位-1
	{
		Buzzer_Time(100);    //蜂鸣器按键提示音
		Clock[Clock_Sel]--;
		if(Clock[0]<0)Clock[0] = 23;   //小时越界判断	
		if(Clock[1]<0)Clock[1] = 59;   //分越界判断
		if(Clock[2]<0)Clock[2] = 59;   //秒越界判断		
	}	
	LCD_ShowChar(2,3,':');				
	LCD_ShowChar(2,6,':');
	if(Clock_Sel == 0 &&  TimeSetFlag ==1)
		LCD_ShowString(2,1,"  ");
	else
		LCD_ShowNum(2,1,Clock[0],2);	//显示时	

	if(Clock_Sel == 1 &&  TimeSetFlag ==1)
		LCD_ShowString(2,4,"  ");
	else
		LCD_ShowNum(2,4,Clock[1],2);	//显示分
	if(Clock_Sel == 2 &&  TimeSetFlag ==1)
		LCD_ShowString(2,7,"  ");
	else
		LCD_ShowNum(2,7,Clock[2],2);	//显示秒
}

4、闹钟响的条件

为了防止闹钟响个不停,所以设置闹钟的时间位要设计到秒才行,或者默认为0,并且只在模式0,也就是正常显示实时时间的模式下才会响,就不会出现,在设置闹钟的时候数字1位1位的加,“路过”闹钟时间结果响个几秒的尴尬

		if(Mode == 0)    //模式0,显示时间
		{
			DS1302_ReadTime();
			TranserShowStr_Day(DS1302_Time[6]);  //将数字转化为对应字符串显示
			ShowTime();                 //显示年月日时分秒
			if(DS1302_Time[3] == Clock[0]&&DS1302_Time[4] == Clock[1]&&DS1302_Time[5] == Clock[2])  //到时间蜂鸣器响5s
				Buzzer_Time(24000);	
		}

5、遇到的问题

其实遇到的问题挺多的,但很多已经没什么印象了说明不怎么重要

1、关于进入闹钟模式清空屏幕,因为残留的显示数据不会消失,所以必须手动先清空,一开始我把LCD初始化函数写在了Clock_Set函数里,结果闪个不停,并且,时间位闪烁完全看不出来,后来意识到在while循环里只要Mode还等于1,就会不停的清空屏幕,因此闪个不停。但是其实一开始我并没有把模式切换写的那么详细,更喜欢之前的风格,Mode++,然后对3取余反复循环,这样写还要在写一步由模式0切换到1的判断,很麻烦,于是换了

2、由于很多代码都是用的前面的,,中间出了不少差错,还是不够细心..

四、效果演示

基于51单片机的可调时钟的闹钟设置和效果演示

最后,整个电子时钟的设计就结束了,完整的文件资源已上传

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值