欢迎光临~啄木鸟电子科技

软件设计

STC 时钟设计


/*********************************************************
红外遥控;(用 遥控 来设置 时间)
// 按键 长按 短按 控制; 

// 标准化 音频 模块 ;
// LCD1602 背光灯 控制,(按下按键,开启 计时器,20 秒后,如无按键操作,指示灯 灭; 

// 单片机内部 EEPROM 不使能
*********************************************************/

#include <reg52.h>
#include <intrins.h>

#define uchar unsigned char			// 以后unsigned char就可以用uchar代替
#define uint  unsigned int			// 以后unsigned int 就可以用uint 代替

sfr ISP_DATA  = 0xe2;				// 数据寄存器
sfr ISP_ADDRH = 0xe3;				// 地址寄存器高八位
sfr ISP_ADDRL = 0xe4;				// 地址寄存器低八位
sfr ISP_CMD   = 0xe5;				// 命令寄存器
sfr ISP_TRIG  = 0xe6;				// 命令触发寄存器
sfr ISP_CONTR = 0xe7;				// 命令寄存器

sbit LcdRs_P  = P2^7;       		// 1602液晶的RS管脚       
sbit LcdRw_P  = P2^6;       		// 1602液晶的RW管脚 
sbit LcdEn_P  = P2^5;       		// 1602液晶的EN管脚

sbit RST_P    = P1^3;				// 时钟芯片DS1302的RST管脚
sbit SDA_P    = P1^2;				// 时钟芯片DS1302的SDA管脚
sbit SCK_P    = P1^1;				// 时钟芯片DS1302的SCK管脚

sbit K1   = P3^2;				// 设置时间按键
sbit K2   = P3^3;				// 设置闹钟按键
sbit K3   = P3^4;				// 秒表功能按键
sbit K4   = P3^5;				// 子功能按键1
sbit K5   = P3^6;				// 子功能按键2

sbit Buzzer_P 			= P2^0;				// 蜂鸣器
sbit DQ       			= P1^0;				// DS18B20传感器的引脚定义

sbit LED 	  			= P2^2;       		// LED 工作指示 灯; 
sbit LCD1602_LED 	  	= P2^1;       		// LCD1602 背光灯; 

// 时间数组,默认2017年9月1日,星期五,18:30:40
uchar TimeBuff[7]={17,9,1,6,18,30,40};		
// TimeBuff[0] 代表年份,范围00-99
// TimeBuff[1] 代表月份,范围1-12
// TimeBuff[2] 代表日期,范围1-31
// TimeBuff[3] 代表星期,范围1-7,1是星期天,2是星期一... ...
// TimeBuff[4] 代表小时,范围00-23
// TimeBuff[5] 代表分钟,范围00-59
// TimeBuff[6] 代表秒钟,范围00-59

// 将 10 组数据 对称 放入数组中; 
uchar Clock_Hour[10];					// 闹钟的小时
uchar Clock_Minute[10];				// 闹钟的分钟
uchar Clock_Swt[10];					// 闹钟的开关

uchar Buzzer_Flag=0;				// 蜂鸣器工作标志

uchar Stop_Watch_Count=0;			// 用于秒表计数,10毫秒加1
uint  Stop_Watch_Second=0;			// 用于秒表计数,1秒加1

///////////////////////////////////////////////////////////////////////
uchar count_x = 0;  // 定时器 定时 计数;每 1s 自加 1; 

///////////////////////////////////////////////////////////////////////

// 数组定义;

uchar code char_1[] ={0x7E,0xFF,0x06,0x0F,0x00,0x01,0x01,0xEF}; // 指定文件夹 01 文件名 
uchar code char_2[] ={0x7E,0xFF,0x06,0x0F,0x00,0x01,0x02,0xEF}; // TF 指定播放第 2首 
uchar code char_3[] ={0x7E,0xFF,0x06,0x0F,0x00,0x01,0x03,0xEF}; // TF 指定播放第 3首
uchar code char_4[] ={0x7E,0xFF,0x06,0x0F,0x00,0x01,0x04,0xEF}; // TF 指定播放第 4首

uchar code char_5[] ={0x7E,0xFF,0x06,0x0F,0x00,0x01,0x05,0xEF}; // 指定文件夹 01 文件名
uchar code char_6[] ={0x7E,0xFF,0x06,0x0F,0x00,0x01,0x06,0xEF}; // 
uchar code char_7[] ={0x7E,0xFF,0x06,0x0F,0x00,0x01,0x07,0xEF}; // 
uchar code char_8[] ={0x7E,0xFF,0x06,0x0F,0x00,0x01,0x08,0xEF}; //
uchar code char_9[] ={0x7E,0xFF,0x06,0x0F,0x00,0x01,0x09,0xEF}; // 

uchar code char_10[] ={0x7E,0xFF,0x06,0x16,0x00,0x00,0x00,0xEF}; // 停止;
uchar code char_11[] ={0x7E,0xFF,0x06,0x04,0x00,0x00,0x00,0xEF}; // 音量 +;
uchar code char_12[] ={0x7E,0xFF,0x06,0x05,0x00,0x00,0x00,0xEF}; // 音量 -;
 
/*
uchar code char_1[] ={0x7E,0xFF,0x06,0x03,0x00,0x00,0x01,0xEF}; // TF 指定播放第 1首
uchar code char_2[] ={0x7E,0xFF,0x06,0x03,0x00,0x00,0x02,0xEF}; // TF 指定播放第 2首 
uchar code char_3[] ={0x7E,0xFF,0x06,0x03,0x00,0x00,0x03,0xEF}; // TF 指定播放第 3首
uchar code char_4[] ={0x7E,0xFF,0x06,0x03,0x00,0x00,0x04,0xEF}; // TF 指定播放第 4首
*/

// 函数 声明; 

void KeyScanf1();

void Led_Flash(uchar x);  // 工作指示 灯; 

void Music_Play(uchar track_x);
void Music_Stop();
void Music_Volume_Down();
void Music_Volume_Up();

void Lcd1602_Led_Timer_On();
void Lcd1602_Led_On_Off();


/*********************************************************/
// 单片机内部EEPROM不使能
/*********************************************************/
void ISP_Disable()
{
	ISP_CONTR = 0;
	ISP_ADDRH = 0;
	ISP_ADDRL = 0;
}

/*********************************************************/
// 从单片机内部EEPROM读一个字节,从0x2000地址开始
/*********************************************************/
unsigned char EEPROM_Read(unsigned int add)
{
	ISP_DATA  = 0x00;
	ISP_CONTR = 0x83;
	ISP_CMD   = 0x01;
	ISP_ADDRH = (unsigned char)(add>>8);
	ISP_ADDRL = (unsigned char)(add&0xff);
	// 对STC89C51系列来说,每次要写入0x46,再写入0xB9,ISP/IAP才会生效
	ISP_TRIG  = 0x46;	   
	ISP_TRIG  = 0xB9;
	_nop_();
	ISP_Disable();
	return (ISP_DATA);
}

/*********************************************************/
// 往单片机内部EEPROM写一个字节,从0x2000地址开始
/*********************************************************/
void EEPROM_Write(unsigned int add,unsigned char ch)
{
	ISP_CONTR = 0x83;
	ISP_CMD   = 0x02;
	
	ISP_ADDRH = (unsigned char)(add>>8);
	ISP_ADDRL = (unsigned char)(add&0xff);
	
	ISP_DATA  = ch;
	
	ISP_TRIG  = 0x46;
	ISP_TRIG  = 0xB9;
	_nop_();
	ISP_Disable();
}


/*********************************************************/
// 擦除单片机内部EEPROM的一个扇区
// 写8个扇区中随便一个的地址,便擦除该扇区,写入前要先擦除
/*********************************************************/
void Sector_Erase(unsigned int add)	  
{
	ISP_CONTR = 0x83;
	ISP_CMD   = 0x03;
	ISP_ADDRH = (unsigned char)(add>>8);
	ISP_ADDRL = (unsigned char)(add&0xff);
	ISP_TRIG  = 0x46;
	ISP_TRIG  = 0xB9;
	_nop_();
	ISP_Disable();
}

/*********************************************************/
// 毫秒级的延时函数,time是要延时的毫秒数
/*********************************************************/
void DelayMs(uint time)
{
	uint i,j;
	for(i=0;i<time;i++)
		for(j=0;j<112;j++);
}

/**********************************************************************
* 函数: Delay_Nms(u16 x)
* 功能: 延时Nms;
* 输入: int x; 
* 输出: 无
***********************************************************************/
void Delay_Nms(uint x)
{
  uint a,b;
  while(x--)
  {
    for(a=0;a<18;a++)
    {
      for(b=0; b<176; b++);  // 175->998us;  176->1.00425ms; 
    }    
  }
}
/*********************************************************/
// 延时15微秒
/*********************************************************/
void Delay15us(void)
{
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
}

/*********************************************************/
// 复位DS18B20(初始化)
/*********************************************************/
void DS18B20_ReSet(void)
{
	uchar i;
	DQ=0;				// 总线 拉低; (单片机 主动 给出的信号 ;) 
	i=240;				// 保持 480us;  
	while(--i);
	DQ=1;				// 总线 释放,拉高,上升沿; 
	i=30;
	while(--i);			// 保持 60us; 
	while(~DQ);			// 等待 传感器 释放总线,把IO 拉高;( 温感 给出的信号 ;) 
	i=4;
	while(--i);			// 保持 8-10us; 
}


/*********************************************************/
// 向DS18B20写入一个字节
/*********************************************************/
void DS18B20_WriteByte(uchar dat)
{
	uchar j;
	uchar btmp;
	
	for(j=0;j<8;j++)
	{
		btmp=0x01;				// 0000 0001 ;  
		btmp=btmp<<j;
		btmp=btmp&dat;			// 用 1 & 0/1 相与; 
		
		if(btmp>0)		// 写1
		{
			DQ=0;
			Delay15us();
			DQ=1;
			Delay15us();
			Delay15us();
			Delay15us();
			Delay15us();
		}
		else			// 写0
		{
			DQ=0;
			Delay15us();
			Delay15us();
			Delay15us();
			Delay15us();
			DQ=1;
			Delay15us();
		}
	}
}

/*********************************************************/
// 读取温度值
/*********************************************************/
int DS18B20_ReadTemp(void)
{
	uchar j;
	int b,temp=0;	

	DS18B20_ReSet();					// 产生复位脉
	DS18B20_WriteByte(0xcc);			// 忽略ROM指令(只接 1 个传感器,无需序列号) 
	DS18B20_WriteByte(0x44);			// 启动温度转换指令

	DS18B20_ReSet();					// 产生 复位脉
	DS18B20_WriteByte(0xcc);			// 忽略 ROM 指令
	DS18B20_WriteByte(0xbe);			// 读取 温度指令(读 暂存器 指令) 

	for(j=0;j<16;j++)					// 读取 温度数量 (16次循环) 
	{						
		DQ=0;							// 拉低 总线; 
		_nop_();						// 保持最少 1us;  
		_nop_();
		DQ=1;							// 释放 总线; 
		Delay15us();					// 等待 15us;  
		b=DQ;							// 采集 总线 电压 保存 到 变量 b;  
		Delay15us();
		Delay15us();					// 等待 45 us;  
		Delay15us();
		
		b=b<<j;							// 注意:b 是一个 单 1 bit 的 值(0,或1) 
		temp=temp|b;
	}
	
	temp=temp*0.0625*10;				// 合成温度值并放大10倍	  0.0625 是精度;				
	return (temp);						// 返回检测到的温度值
}

/*********************************************************/
// 1602液晶写命令函数,cmd就是要写入的命令
/*********************************************************/
void Lcd1602_Write_Cmd(uchar cmd)
{ 
	LcdRs_P = 0;
	LcdRw_P = 0;
	LcdEn_P = 0;
	P0=cmd;
	DelayMs(2);
	LcdEn_P = 1;    
	DelayMs(2);
	LcdEn_P = 0;	
}


/*********************************************************/
// 1602液晶写数据函数,dat就是要写入的数据
/*********************************************************/
void Lcd1602_Write_Data(uchar dat)
{
	LcdRs_P = 1; 
	LcdRw_P = 0;
	LcdEn_P = 0;
	P0=dat;
	DelayMs(2);
	LcdEn_P = 1;    
	DelayMs(2);
	LcdEn_P = 0;
}


/*********************************************************/
// 1602液晶初始化函数
/*********************************************************/
void Init_LCD1602()
{
	Lcd1602_Write_Cmd(0x38);        // 16*2显示,5*7点阵,8位数据口
	Lcd1602_Write_Cmd(0x0C);        // 开显示,不显示光标
	Lcd1602_Write_Cmd(0x06);        // 地址加1,当写入数据后光标右移
	Lcd1602_Write_Cmd(0x01);        // 清屏
}


/*********************************************************/
// 液晶光标定位函数
/*********************************************************/
void Lcd1602_Goto_XY(uchar line,uchar column)
{
	// 第一行
	if(line==0)        
		Lcd1602_Write_Cmd(0x80+column); 
	// 第二行
	if(line==1)        
		Lcd1602_Write_Cmd(0x80+0x40+column); 
}


/*********************************************************/
// 液晶输出字符串函数
/*********************************************************/
void Lcd1602_Print_Str(uchar *str)
{
	while(*str!='\0')
			Lcd1602_Write_Data(*str++);
}


/*********************************************************/
// 液晶显示内容的初始化
/*********************************************************/
void Lcd1602_Show_Init()
{
	Lcd1602_Goto_XY(0,0);
	Lcd1602_Print_Str("20  -  -        ");
	Lcd1602_Goto_XY(1,0);
	Lcd1602_Print_Str("  :  :         C");
	Lcd1602_Goto_XY(1,14);									// 温度单位摄氏度上面的圆圈符号
	Lcd1602_Write_Data(0xdf);	
}



/*********************************************************/
// 液晶输出数字
/*********************************************************/
void Lcd1602_Print_Num(uchar num)
{
	Lcd1602_Write_Data(num/10+48);		// 十位
	Lcd1602_Write_Data(num%10+48); 		// 个位
}


/*********************************************************/
// 液晶显示星期
/*********************************************************/
void Lcd1602_Print_Week(uchar week)
{
	switch(week)
	{
		case 1: Lcd1602_Print_Str(" SUN");	break;
		case 2: Lcd1602_Print_Str(" MON");	break;
		case 3: Lcd1602_Print_Str("TUES");	break;
		case 4: Lcd1602_Print_Str(" WED");	break;
		case 5: Lcd1602_Print_Str("THUR");	break;
		case 6: Lcd1602_Print_Str(" FRI");	break;
		case 7: Lcd1602_Print_Str(" SAT");	break;
		default:						break;
	}
}


/*********************************************************/
// 刷新时间显示
/*********************************************************/
void Led1602_Flash_Time()
{
	Lcd1602_Goto_XY(0,2);										// 年份
	Lcd1602_Print_Num(TimeBuff[0]);
	Lcd1602_Goto_XY(0,5);										// 月份
	Lcd1602_Print_Num(TimeBuff[1]);
	Lcd1602_Goto_XY(0,8);										// 日期
	Lcd1602_Print_Num(TimeBuff[2]);
	Lcd1602_Goto_XY(1,0);										// 小时
	Lcd1602_Print_Num(TimeBuff[4]);
	Lcd1602_Goto_XY(1,3);										// 分钟
	Lcd1602_Print_Num(TimeBuff[5]);
	Lcd1602_Goto_XY(1,6);										// 秒钟
	Lcd1602_Print_Num(TimeBuff[6]);
	Lcd1602_Goto_XY(0,12);									// 星期	
	Lcd1602_Print_Week(TimeBuff[3]);
}



/*********************************************************/
// 温度值的显示
/*********************************************************/
void Lcd1602_Print_Temp(int temp)
{
	if(temp<0)								// 是否 < 0; 													
	{
		Lcd1602_Write_Data('-');					// 显示负号	
		temp=0-temp;						// 负数转为正数	
	}
	else if(temp>999) 						// 显示百位
	{
		Lcd1602_Write_Data(temp/1000+0x30);		// 提取 百位 1; 
	}
	else
	{
		Lcd1602_Write_Data(' ');					// 不显示(如不是 负数,如不是 > 100,就显示 空格) 
	}
	Lcd1602_Write_Data(temp%1000/100+0x30);		// 显示十位
	Lcd1602_Write_Data(temp%100/10+0x30);			// 显示个位
	Lcd1602_Write_Data('.');						// 显示小数点
	Lcd1602_Write_Data(temp%10+0x30);				// 显示小数后一位小数
}

/*********************************************************/
// 初始化DS1302
/*********************************************************/
void Init_DS1302(void)
{
	RST_P=0;			// RST脚置低
	SCK_P=0;			// SCK脚置低
	SDA_P=0;			// SDA脚置低				
}  

/*********************************************************/
// 从DS1302读出一字节数据
/*********************************************************/
uchar DS1302_Read_Byte(uchar addr) 
{
	uchar i;
	uchar temp;
	
	RST_P=1;								
	
	/* 写入目标地址:addr*/
	for(i=0;i<8;i++) 
	{     
		if(addr&0x01) 
			SDA_P=1;
		else 
			SDA_P=0;
		
		SCK_P=1;
		_nop_();
		SCK_P=0;
		_nop_();
		
		addr=addr>> 1;
	}
	
	/* 读出该地址的数据 */
	for(i=0;i<8;i++) 
	{
		temp=temp>>1;
		
		if(SDA_P) 
			temp|= 0x80;
		else 
			temp&=0x7F;
		
		SCK_P=1;
		_nop_();
		SCK_P=0;
		_nop_();
	}
	
	RST_P=0;
	
	return temp;
}

/*********************************************************/
// 向DS1302写入一字节数据
/*********************************************************/
void DS1302_Write_Byte(uchar addr, uchar dat)
{
	uchar i;
	
	RST_P = 1;
	
	/* 写入目标地址:addr*/
	for(i=0;i<8;i++) 
	{ 
		if(addr&0x01) 
			SDA_P=1;
		else 
			SDA_P=0;

		SCK_P=1;
		_nop_();
		SCK_P=0;
		_nop_();
		
		addr=addr>>1;
	}
	
	/* 写入数据:dat*/
	for(i=0;i<8;i++) 
	{
		if(dat&0x01) 
			SDA_P=1;
		else 
			SDA_P=0;
	
		SCK_P=1;
		_nop_();
		SCK_P=0;
		_nop_();
		
		dat=dat>>1;
	}
	
	RST_P=0;					
}

/*********************************************************/
// 向DS1302写入时间数据
/*********************************************************/
void DS1302_Write_Time() 
{
  	uchar i;
	uchar temp1;
	uchar temp2;
	
	for(i=0;i<7;i++)			// 十进制转BCD码
	{
		temp1=(TimeBuff[i]/10)<<4;
		temp2=TimeBuff[i]%10;
		TimeBuff[i]=temp1+temp2;
	}
	
	DS1302_Write_Byte(0x8E,0x00);								// 关闭写保护 
	DS1302_Write_Byte(0x80,0x80);								// 暂停时钟 
	DS1302_Write_Byte(0x8C,TimeBuff[0]);				// 年 
	DS1302_Write_Byte(0x88,TimeBuff[1]);				// 月 
	DS1302_Write_Byte(0x86,TimeBuff[2]);				// 日 
	DS1302_Write_Byte(0x8A,TimeBuff[3]);				// 星期
	DS1302_Write_Byte(0x84,TimeBuff[4]);				// 时 
	DS1302_Write_Byte(0x82,TimeBuff[5]);				// 分
	DS1302_Write_Byte(0x80,TimeBuff[6]);				// 秒
	DS1302_Write_Byte(0x80,TimeBuff[6]&0x7F);		// 运行时钟
	DS1302_Write_Byte(0x8E,0x80);								// 打开写保护  
}

/*********************************************************/
// 从DS1302读出时间数据
/*********************************************************/
void DS1302_Read_Time()  
{ 
	uchar i;

	TimeBuff[0]=DS1302_Read_Byte(0x8D);						// 年 
	TimeBuff[1]=DS1302_Read_Byte(0x89);						// 月 
	TimeBuff[2]=DS1302_Read_Byte(0x87);						// 日 
	TimeBuff[3]=DS1302_Read_Byte(0x8B);						// 星期
	TimeBuff[4]=DS1302_Read_Byte(0x85);						// 时 
	TimeBuff[5]=DS1302_Read_Byte(0x83);						// 分 
	TimeBuff[6]=(DS1302_Read_Byte(0x81))&0x7F;		// 秒 

	for(i=0;i<7;i++)		// BCD转十进制
	{           
		TimeBuff[i]=(TimeBuff[i]/16)*10+TimeBuff[i]%16;
	}
}

/**********************************************************************
* 函数: Key_Time_Set() 
* 功能: 按键 长按 短按 处理;
* 输入: 无
* 输出: 无

void Key_Time_Set() 
{
	//uchar count_x; 								// 定义 临时 变量;	
    if( !K1 )  								// 按键 按下; 
    {
        Delay_Nms(30);							// 防抖; 
        if(!K1)								// 确定 按键 真实 按下; 
	    {
		    count_x = 0; 						// 记数清 0; 
		    do{
		        count_x ++;   					// 记录 长按 短按;
		        Delay_Nms(100);
		        if( count_x >= 20) break;  		// 记到 20就封顶;
		     } while(!K1);  				// 设计到 1000ms ,就松手,就退出 计数;
		
		    if(count_x <= 30) 	// 短按;
		    {
		       ;	 			// 忽略;
		    }
		    else  				// 长按;
		    {
		       	;
			}
	    }
    }
}

***********************************************************************/

/*********************************************************/
// 按键扫描(设置时间)
/*********************************************************/
void Key_Time_Set()
{
	if(K1==0)
	{
		Lcd1602_Write_Cmd(0x0f);						// 启动光标闪烁
		Lcd1602_Goto_XY(0,3);							// 定位光标到年份闪烁
		DelayMs(10);							// 延时等待,消除按键按下的抖动
		while(!K1);							// 等待按键释放
		DelayMs(10);							// 延时等待,消除按键松开的抖动
		
		/* 调整年份 */
		while(1)
		{
			if(K4 == 0)									// 如果减按键被下去
			{
				if(TimeBuff[0]>0)						// 判断年份是否大于0		
					TimeBuff[0]--;						// 是的话就减去1
				Lcd1602_Goto_XY(0,2);							// 光标定位到年份的位置
				Lcd1602_Print_Num(TimeBuff[0]);		// 刷新显示改变后的年份
				Lcd1602_Goto_XY(0,3);							// 定位光标到年份闪烁
				DelayMs(300);								// 延时0.3秒左右
			}
			
			if(K5==0)									// 如果加按键被下去
			{
				if(TimeBuff[0]<99)					// 判断年份是否小于99
					TimeBuff[0]++;						// 是的话就加上1
				Lcd1602_Goto_XY(0,2);							// 光标定位到年份的位置
				Lcd1602_Print_Num(TimeBuff[0]);		// 刷新显示改变后的年份
				Lcd1602_Goto_XY(0,3);							// 定位光标到年份闪烁
				DelayMs(300);								// 延时0.3秒左右
			}
			
			if(K1==0)
			{
				break;
			}
		}
		
		Lcd1602_Goto_XY(0,6);					// 定位光标到月份闪烁
		DelayMs(10);						// 延时等待,消除按键按下的抖动
		while(!K1);					// 等待按键释放
		DelayMs(10);						// 延时等待,消除按键松开的抖动
			
		/* 调整月份 */
		while(1)
		{
			if(K4 == 0)									// 如果减按键被下去
			{
				if(TimeBuff[1]>1)						// 判断月份是否大于1		
					TimeBuff[1]--;						// 是的话就减去1
					
				Lcd1602_Goto_XY(0,5);					// 光标定位到月份的位置
				Lcd1602_Print_Num(TimeBuff[1]);			// 刷新显示改变后的月份
				Lcd1602_Goto_XY(0,6);					// 定位光标到月份闪烁
				DelayMs(300);							// 延时0.3秒左右
			}
			
			if(K5 == 0)									// 如果加按键被下去
			{
				if(TimeBuff[1]<12)						// 判断月份是否小于12
					TimeBuff[1]++;						// 是的话就加上1
					
				Lcd1602_Goto_XY(0,5);					// 光标定位到月份的位置
				Lcd1602_Print_Num(TimeBuff[1]);			// 刷新显示改变后的月份
				
				Lcd1602_Goto_XY(0,6);					// 定位光标到月份闪烁
				DelayMs(300);							// 延时0.3秒左右
			}
			
			if(K1 == 0)
			{
				break;
			}
		}
		
		Lcd1602_Goto_XY(0,9);							// 定位光标到 日期 闪烁
		DelayMs(10);									// 延时等待,消除按键按下的抖动
		while(!K1);										// 等待按键释放
		DelayMs(10);									// 延时等待,消除按键松开的抖动
		
		/* 调整 日期 */
		while(1)
		{
			if(K4==0)									// 如果减按键被下去
			{
				if(TimeBuff[2]>1)						// 判断日期是否大于1		
					TimeBuff[2]--;						// 是的话就减去1
					
				Lcd1602_Goto_XY(0,8);					// 光标定位到日期的位置
				Lcd1602_Print_Num(TimeBuff[2]);			// 刷新显示改变后的日期
				Lcd1602_Goto_XY(0,9);					// 定位光标到日期闪烁
				DelayMs(300);							// 延时0.3秒左右
			}
			
			if(K5==0)									// 如果加按键被下去
			{
				if(TimeBuff[2]<31)						// 判断日期是否小于31
					TimeBuff[2]++;						// 是的话就加上1
					
				Lcd1602_Goto_XY(0,8);					// 光标定位到日期的位置
				Lcd1602_Print_Num(TimeBuff[2]);			// 刷新显示改变后的日期
				Lcd1602_Goto_XY(0,9);					// 定位光标到日期闪烁
				DelayMs(300);							// 延时0.3秒左右
			}
			
			if(K1==0)
			{
				break;
			}
		}
		
		Lcd1602_Goto_XY(0,15);							// 定位光标到星期闪烁
		DelayMs(10);									// 延时等待,消除按键按下的抖动
		while(!K1);										// 等待按键释放
		DelayMs(10);									// 延时等待,消除按键松开的抖动
		
		/* 调整 星期 */
		while(1)
		{
			if(K4==0)									// 如果减按键被下去
			{
				if(TimeBuff[3]>1)						// 判断星期是否大于1		
					TimeBuff[3]--;						// 是的话就减去1
					
				Lcd1602_Goto_XY(0,12);					// 光标定位到星期的位置
				Lcd1602_Print_Week(TimeBuff[3]);		// 刷新显示改变后的星期
				Lcd1602_Goto_XY(0,15);					// 定位光标到星期闪烁
				DelayMs(300);							// 延时0.3秒左右
			}
			
			if(K5==0)									// 如果加按键被下去
			{
				if(TimeBuff[3]<7)						// 判断星期是否小于7
					TimeBuff[3]++;						// 是的话就加上1
					
				Lcd1602_Goto_XY(0,12);					// 光标定位到星期的位置
				Lcd1602_Print_Week(TimeBuff[3]);		// 刷新显示改变后的星期
				Lcd1602_Goto_XY(0,15);					// 定位光标到星期闪烁
				DelayMs(300);							// 延时0.3秒左右
			}
			
			if(K1==0)
			{
				break;
			}
		}
		
		Lcd1602_Goto_XY(1,1);							// 定位光标到小时闪烁
		DelayMs(10);									// 延时等待,消除按键按下的抖动
		while(!K1);										// 等待按键释放
		DelayMs(10);									// 延时等待,消除按键松开的抖动
		
		/* 调整 小时 */
		while(1)
		{
			if(K4==0)									// 如果减按键被下去
			{
				if(TimeBuff[4]>0)						// 判断小时是否大于0
					TimeBuff[4]--;						// 是的话就减去1
				Lcd1602_Goto_XY(1,0);					// 光标定位到小时的位置
				Lcd1602_Print_Num(TimeBuff[4]);			// 刷新显示改变后的小时
				Lcd1602_Goto_XY(1,1);					// 定位光标到小时闪烁
				DelayMs(300);							// 延时0.3秒左右
			}
			
			if(K5==0)									// 如果加按键被下去
			{
				if(TimeBuff[4]<23)						// 判断小时是否小于23
					TimeBuff[4]++;						// 是的话就加上1
				Lcd1602_Goto_XY(1,0);					// 光标定位到小时的位置
				Lcd1602_Print_Num(TimeBuff[4]);			// 刷新显示改变后的小时
				Lcd1602_Goto_XY(1,1);					// 定位光标到小时闪烁
				DelayMs(300);							// 延时0.3秒左右
			}
			
			if(K1==0)
			{
				break;
			}
		}
		
		Lcd1602_Goto_XY(1,4);					// 定位光标到分钟闪烁
		DelayMs(10);						// 延时等待,消除按键按下的抖动
		while(!K1);					// 等待按键释放
		DelayMs(10);						// 延时等待,消除按键松开的抖动
		
		/* 调整 分钟 */
		while(1)
		{
			if(K4==0)									// 如果减按键被下去
			{
				if(TimeBuff[5]>0)						// 判断分钟是否大于0
					TimeBuff[5]--;						// 是的话就减去1
				Lcd1602_Goto_XY(1,3);							// 光标定位到分钟的位置
				Lcd1602_Print_Num(TimeBuff[5]);		// 刷新显示改变后的分钟
				Lcd1602_Goto_XY(1,4);							// 定位光标到分钟闪烁
				DelayMs(300);								// 延时0.3秒左右
			}
			
			if(K5==0)									// 如果加按键被下去
			{
				if(TimeBuff[5]<59)					// 判断分钟是否小于59
					TimeBuff[5]++;						// 是的话就加上1
				Lcd1602_Goto_XY(1,3);							// 光标定位到分钟的位置
				Lcd1602_Print_Num(TimeBuff[5]);		// 刷新显示改变后的分钟
				Lcd1602_Goto_XY(1,4);							// 定位光标到分钟闪烁
				DelayMs(300);								// 延时0.3秒左右
			}
			
			if(K1==0)
			{
				break;
			}
		}
		
		Lcd1602_Goto_XY(1,7);					// 定位光标到秒钟闪烁
		DelayMs(10);						// 延时等待,消除按键按下的抖动
		while(!K1);					// 等待按键释放
		DelayMs(10);						// 延时等待,消除按键松开的抖动
		
		/* 调整秒钟 */
		while(1)
		{
			if(K4==0)									// 如果减按键被下去
			{
				if(TimeBuff[6]>0)						// 判断秒钟是否大于0
					TimeBuff[6]--;						// 是的话就减去1
				Lcd1602_Goto_XY(1,6);							// 光标定位到秒钟的位置
				Lcd1602_Print_Num(TimeBuff[6]);		// 刷新显示改变后的秒钟
				Lcd1602_Goto_XY(1,7);							// 定位光标到秒钟闪烁
				DelayMs(300);								// 延时0.3秒左右
			}
			
			if(K5==0)									// 如果加按键被下去
			{
				if(TimeBuff[6]<59)					// 判断秒钟是否小于59
					TimeBuff[6]++;						// 是的话就加上1
				Lcd1602_Goto_XY(1,6);							// 光标定位到秒钟的位置
				Lcd1602_Print_Num(TimeBuff[6]);		// 刷新显示改变后的秒钟
				Lcd1602_Goto_XY(1,7);							// 定位光标到秒钟闪烁
				DelayMs(300);								// 延时0.3秒左右
			}
			
			if(K1==0)
			{
				break;
			}
		}
		
		/* 退出前的设置 */
		Lcd1602_Write_Cmd(0x0C);			// 关闭光标闪烁
		DS1302_Write_Time();		// 把新设置的时间值存入DS1302芯片
		DelayMs(10);						// 延时等待,消除按键按下的抖动
		while(!K1);					// 等待按键释放
		DelayMs(10);						// 延时等待,消除按键松开的抖动
	}
}

/*********************************************************
按键扫描(设置闹钟)
仅一组 定时;

void KeyScanf2()
{
	if(K2==0)
	{
		Lcd1602_Goto_XY(0,0);							// 液晶显示为闹钟设置的界面
		Lcd1602_Print_Str("ALARM CLOCK SET");
		
		Lcd1602_Goto_XY(1,0);				
		Lcd1602_Print_Str("     :          ");
		
		Lcd1602_Goto_XY(1,3);							// 显示闹钟的小时
		Lcd1602_Print_Num(Clock_Hour);
		
		Lcd1602_Goto_XY(1,6);							// 显示闹钟的分钟
		Lcd1602_Print_Num(Clock_Minute);
		
		Lcd1602_Goto_XY(1,10);						// 显示闹钟状态
		if(Clock_Swt==0)
		{
			Lcd1602_Print_Str("OFF");
		}
		else
		{
			Lcd1602_Print_Str(" ON");
		}
		
		Lcd1602_Goto_XY(1,4);							// 光标定位 (时 位) 
		Lcd1602_Write_Cmd(0x0f);						// 光标闪烁
		DelayMs(10);							// 延时等待,消除按键按下的抖动
		
		while(!K2);				   			// 等待按键释放
		DelayMs(10);							// 延时等待,消除按键松开的抖动		
		
		// 调整闹钟小时 
		while(1)								
		{
			if(K4==0)						// 如果减按键被下去
			{
				if(Clock_Hour>0)				// 判断闹钟小时是否大于0
					Clock_Hour--;				// 是的话就减去1
				Lcd1602_Goto_XY(1,3);					// 光标定位到闹钟小时的位置
				Lcd1602_Print_Num(Clock_Hour);		// 刷新显示改变后的闹钟小时
				Lcd1602_Goto_XY(1,4);					// 定位光标到闹钟小时闪烁
				DelayMs(300);					// 延时0.3秒左右
			}
			
			if(K5==0)						// 如果加按键被下去
			{
				if(Clock_Hour<23)				// 判断闹钟小时是否小于23
					Clock_Hour++;				// 是的话就加上1
				Lcd1602_Goto_XY(1,3);					// 光标定位到闹钟小时的位置
				Lcd1602_Print_Num(Clock_Hour);		// 刷新显示改变后的闹钟小时
				Lcd1602_Goto_XY(1,4);					// 定位光标到闹钟小时闪烁
				DelayMs(300);					// 延时0.3秒左右
			}
			
			if(K2==0)
			{
				break;
			}
		}
		
		Lcd1602_Goto_XY(1,7);					   		// 定位光标到闹钟分钟的闪烁
		DelayMs(10);							// 延时等待,消除按键按下的抖动
		while(!K2);							// 等待按键释放
		DelayMs(10);							// 延时等待,消除按键松开的抖动
		
		// 调整分钟 
		while(1)
		{
			if(K4==0)						// 如果减按键被下去
			{
				if(Clock_Minute>0)				// 判断闹钟分钟是否大于0
					Clock_Minute--;				// 是的话就减去1
				Lcd1602_Goto_XY(1,6);					// 光标定位到闹钟分钟的位置
				Lcd1602_Print_Num(Clock_Minute);		// 刷新显示改变后的闹钟分钟
				Lcd1602_Goto_XY(1,7);					// 定位光标到闹钟分钟闪烁
				DelayMs(300);					// 延时0.3秒左右
			}
			
			if(K5==0)									// 如果加按键被下去
			{
				if(Clock_Minute<59)					// 判断闹钟分钟是否小于59
					Clock_Minute++;						// 是的话就加上1
				Lcd1602_Goto_XY(1,6);							// 光标定位到闹钟分钟的位置
				Lcd1602_Print_Num(Clock_Minute);	// 刷新显示改变后的闹钟分钟
				Lcd1602_Goto_XY(1,7);							// 定位光标到闹钟分钟闪烁
				DelayMs(300);								// 延时0.3秒左右
			}
			
			if(K2==0)
			{
				break;
			}
		}
		
		Lcd1602_Goto_XY(1,12);				// 定位光标到闹钟开关的位置闪烁
		DelayMs(10);						// 延时等待,消除按键按下的抖动
		while(!K2);					// 等待按键释放
		DelayMs(10);						// 延时等待,消除按键松开的抖动
		
		// 闹钟开关
		while(1)
		{
			if(K4==0)								// 如果减按键被下去
			{
				if(Clock_Swt==1)						// 判断闹钟是否开启
					Clock_Swt=0;						// 关闭闹钟
				Lcd1602_Goto_XY(1,10);						// 光标定位到秒钟开关的位置
				Lcd1602_Print_Str("OFF");				    	// 液晶显示“OFF”
				Lcd1602_Goto_XY(1,12);						// 定位光标到闹钟开关的位置闪烁
				DelayMs(300);				    		// 延时0.3秒左右
			}
			
			if(K5==0)								// 如果加按键被下去
			{
				if(Clock_Swt==0)						// 判断闹钟是否关闭
					Clock_Swt=1;						// 启动闹钟
				Lcd1602_Goto_XY(1,10);						// 光标定位到秒钟开关的位置
				Lcd1602_Print_Str(" ON");						// 液晶显示“ ON”
				Lcd1602_Goto_XY(1,12);						// 定位光标到闹钟开关的位置闪烁
				DelayMs(300);							// 延时0.3秒左右
			}
			
			if(K2==0)
			{
				break;
			}
		}
		
		// 退出前的设置 
		Lcd1602_Write_Cmd(0x0C);							// 关闭光标闪烁
		Lcd1602_Show_Init();								// 液晶显示内容恢复为检测界面的
		DelayMs(10);								// 延时等待,消除按键按下的抖动
		while(!K2);								// 等待按键释放
		DelayMs(10);								// 延时等待,消除按键松开的抖动
		
		Sector_Erase(0x2000);						// 擦除 扇区 2000; 
		EEPROM_Write(0x2000,Clock_Hour);			// 往0x2000这个地址写入闹钟的小时 
		EEPROM_Write(0x2001,Clock_Minute);			// 往0x2001这个地址写入闹钟的分钟
		EEPROM_Write(0x2002,Clock_Swt);				// 往0x2002这个地址写入闹钟的开关
	}
}

*********************************************************/

/*********************************************************
// 按键扫描(设置 多组 闹钟)
1;组:uchar Group[9]={1,2,3,4,5,6,7,8,9}; Group_1; 
2. 时;uchar Hour_h[9] 			Hour_1 - Hour_9;  
3. 分:uchar Minute_m[9] 		Minute_1 - Minute_9; 
4. 开|关: uchar Swt_s[9] 		Swt_1 - Swt_9; 

设置 4 个 数组;存入 4 种数据,一一对应; 

*********************************************************/
void Key_Clock_Set()
{
	uchar i;

	if(K2==0)
	{
		// 第 1 行; 
		Lcd1602_Goto_XY(0,0);							// 液晶显示为闹钟设置的界面
		Lcd1602_Print_Str("ALARM CLOCK SET ");
		//Lcd1602_Print_Str("0123456789ABCDEF");		
		
		// 第 2 行; 
		Lcd1602_Goto_XY(1,0);				
		Lcd1602_Print_Str("     :          ");	// 第 5 位 有分隔符; 
		//Lcd1602_Print_Str("0123456789ABCDEF");  // 16个 字符长度;(把原有数据清除) 
		
		// 默认 进入 设置状态时,显示 第 1 组数据 (时:分 开|关 状态);		 
		Lcd1602_Goto_XY(1,3);							// 显示闹钟的小时
		Lcd1602_Print_Num(Clock_Hour[1]);
		
		Lcd1602_Goto_XY(1,6);							// 显示闹钟的分钟
		Lcd1602_Print_Num(Clock_Minute[1]);
		
		Lcd1602_Goto_XY(1,10);						// 显示闹钟状态
		if(Clock_Swt[1]==0)
		{
			Lcd1602_Print_Str("OFF");
		}
		else
		{
			Lcd1602_Print_Str(" ON");
		}
		
		// 进入后,光标停顿 的 位置;		
		Lcd1602_Goto_XY(1,4);							// 光标定位 (时钟 个位) 
		Lcd1602_Write_Cmd(0x0f);						// 光标闪烁
		DelayMs(10);							// 延时等待,消除按键按下的抖动		
		
		while(!K2);				   			// 等待按键释放
		DelayMs(10);							// 延时等待,消除按键松开的抖动

		for(i=1;i<=9;i++)
		{
			// 组; 
			Lcd1602_Goto_XY(1,0);							// 显示闹钟的 分组编号; 
			Lcd1602_Print_Num(i);										
			
			// 时; 
			Lcd1602_Goto_XY(1,3);						// 光标定位到闹钟小时的位置
			Lcd1602_Print_Num(Clock_Hour[i]);			// 刷新显示改变后的闹钟小时
			
			// 分; 
			Lcd1602_Goto_XY(1,6);						// 定位光标到闹钟分钟闪烁
			Lcd1602_Print_Num(Clock_Minute[i]);		// 刷新显示改变后的闹钟分钟
			
			// 开 = 1 | 关 = 0 
			Lcd1602_Goto_XY(1,10);					// 光标定位到秒钟开关的位置
			if(Clock_Swt[i]==0)
			{
				Lcd1602_Print_Str("OFF");				 			
			}
			if(Clock_Swt[i]==1)
			{
				Lcd1602_Print_Str(" ON");					// 液晶显示“ ON”			
			}
			
			// 光标 定位; 
			Lcd1602_Goto_XY(1,4);							// 光标定位 (时钟 个位) 
			Lcd1602_Write_Cmd(0x0f);						// 光标闪烁
			DelayMs(10);							// 延时等待,消除按键按下的抖动
			while(!K3);							// 等待按键释放
			DelayMs(10);							// 延时等待,消除按键松开的抖动
		
					
			/* 调整闹钟小时 */
			while(1)
			{
				if(K4==0)						// 如果减按键被下去
				{
					if(Clock_Hour[i]>0)				// 判断闹钟小时是否大于0
						Clock_Hour[i]--;			// 是的话就减去1
						
					Lcd1602_Goto_XY(1,3);					// 光标定位到闹钟小时的位置
					Lcd1602_Print_Num(Clock_Hour[i]);		// 刷新显示改变后的闹钟小时
					Lcd1602_Goto_XY(1,4);					// 定位光标到闹钟小时闪烁
					DelayMs(300);					// 延时0.3秒左右
				}
				
				if(K5==0)						// 如果加按键被下去
				{
					if(Clock_Hour[i]<23)				// 判断闹钟小时是否小于23
						Clock_Hour[i]++;				// 是的话就加上1
					Lcd1602_Goto_XY(1,3);					// 光标定位到闹钟小时的位置
					Lcd1602_Print_Num(Clock_Hour[i]);		// 刷新显示改变后的闹钟小时
					Lcd1602_Goto_XY(1,4);					// 定位光标到闹钟小时闪烁
					DelayMs(300);					// 延时0.3秒左右
				}
				
				if(K2==0)  						//  退出 时 设置; 
				{
					while(!K2);	
					break;							// 等待这个按键 再次按 下 确认退出; 
				}
			}
			
			Lcd1602_Goto_XY(1,7);					   		// 定位光标到闹钟分钟的闪烁
			DelayMs(10);							// 延时等待,消除按键按下的抖动
			while(!K2);							// 等待按键释放
			DelayMs(10);							// 延时等待,消除按键松开的抖动
			
			/* 调整 分钟 */
			while(1)
			{
				if(K4==0)						// 如果减按键被下去
				{
					if(Clock_Minute[i]>0)				// 判断闹钟分钟是否大于0
						Clock_Minute[i]--;				// 是的话就减去1
					Lcd1602_Goto_XY(1,6);					// 光标定位到闹钟分钟的位置
					Lcd1602_Print_Num(Clock_Minute[i]);		// 刷新显示改变后的闹钟分钟
					Lcd1602_Goto_XY(1,7);					// 定位光标到闹钟分钟闪烁
					DelayMs(300);					// 延时0.3秒左右
				}
				
				if(K5==0)									// 如果加按键被下去
				{
					if(Clock_Minute[i]<59)					// 判断闹钟分钟是否小于59
						Clock_Minute[i]++;						// 是的话就加上1
					Lcd1602_Goto_XY(1,6);							// 光标定位到闹钟分钟的位置
					Lcd1602_Print_Num(Clock_Minute[i]);	// 刷新显示改变后的闹钟分钟
					Lcd1602_Goto_XY(1,7);							// 定位光标到闹钟分钟闪烁
					DelayMs(300);								// 延时0.3秒左右
				}
				
				if(K2==0)
				{
					while(!K2);	
					break;
				}
			}
			
			Lcd1602_Goto_XY(1,12);				// 定位光标到闹钟开关的位置闪烁
			DelayMs(10);						// 延时等待,消除按键按下的抖动
			while(!K2);					// 等待按键释放
			DelayMs(10);						// 延时等待,消除按键松开的抖动
			
			/* 闹钟 开关 */
			while(1)
			{
				if(K4==0)								// 如果减按键被下去
				{
					Clock_Swt[i]=0;						// 关闭闹钟
						
					Lcd1602_Goto_XY(1,10);						// 光标定位到秒钟开关的位置
					Lcd1602_Print_Str("OFF");				    	// 液晶显示“OFF”
					Lcd1602_Goto_XY(1,12);						// 定位光标到闹钟开关的位置闪烁
					DelayMs(300);				    		// 延时0.3秒左右
					while(!K4); 					// 等待 按键 释放; 
				}
				
				if(K5==0)								// 如果加按键被下去
				{
					Clock_Swt[i]=1;						// 启动闹钟
						
					Lcd1602_Goto_XY(1,10);						// 光标定位到秒钟开关的位置
					Lcd1602_Print_Str(" ON");						// 液晶显示“ ON”
					Lcd1602_Goto_XY(1,12);						// 定位光标到闹钟开关的位置闪烁
					DelayMs(300);							// 延时0.3秒左右
					while(!K5); 					// 等待 按键 释放; 
				}
				
				if(K2==0)
				{
					while(!K2);	
					break;
				}
			}
		}
			
			/* 闹钟 开关 ************************************************************************
			while(1)
			{
				if(K4==0)								// 如果减按键被下去
				{
					if(Clock_Swt[i]==1)						// 判断闹钟是否开启
						Clock_Swt[i]=0;						// 关闭闹钟
						
					Lcd1602_Goto_XY(1,10);						// 光标定位到秒钟开关的位置
					Lcd1602_Print_Str("OFF");				    	// 液晶显示“OFF”
					Lcd1602_Goto_XY(1,12);						// 定位光标到闹钟开关的位置闪烁
					DelayMs(300);				    		// 延时0.3秒左右
				}
				
				if(K5==0)								// 如果加按键被下去
				{
					if(Clock_Swt[i]==0)						// 判断闹钟是否关闭
						Clock_Swt[i]=1;						// 启动闹钟
						
					Lcd1602_Goto_XY(1,10);						// 光标定位到秒钟开关的位置
					Lcd1602_Print_Str(" ON");						// 液晶显示“ ON”
					Lcd1602_Goto_XY(1,12);						// 定位光标到闹钟开关的位置闪烁
					DelayMs(300);							// 延时0.3秒左右
				}
				
				if(K2==0)
				{
					while(!K2);	
					break;
				}
				
			}
			*****************************************************************************/	
			
		/* 退出前的设置 */
		Lcd1602_Write_Cmd(0x0C);								// 关闭光标闪烁
		Lcd1602_Show_Init();									// 液晶显示内容恢复为检测界面的
		DelayMs(10);									// 延时等待,消除按键按下的抖动
		while(!K2);									// 等待按键释放
		DelayMs(10);									// 延时等待,消除按键松开的抖动
			
														// STC_EEPROM 需要全部擦除后,再重写数据,才有效; 
		Sector_Erase(0x2000);							// 擦除 扇区 2000; 
		Sector_Erase(0x2200);							// 擦除 扇区 2200; 
		Sector_Erase(0x2400);							// 擦除 扇区 2400;
		 
		for(i=1;i<=9;i++)
		{
			EEPROM_Write(0x2000+i,Clock_Hour[i]);		// 往 第 1 扇区 首地址:写入闹钟的小时 
			DelayMs(30);								 
			EEPROM_Write(0x2200+i,Clock_Minute[i]);		// 往 第 2 扇区 首地址:写入闹钟的分钟
			DelayMs(30);
			EEPROM_Write(0x2400+i,Clock_Swt[i]);		// 往 第 3 扇区 首地址:写入闹钟的开关	
			DelayMs(30);		
		}
	}
		
}


/*********************************************************/
// 定时 查询; 
/*********************************************************/
void Key_Look_Set()
{
	uchar i=1 ;  // 翻页 编号; 
	
	if(K3==0)
	{			
		Lcd1602_Goto_XY(0,0);							// 液晶显示为 定时查询 界面
		Lcd1602_Print_Str("      CLOCK     ");
		//Lcd1602_Print_Str("0123456789ABCDEF");
		Lcd1602_Goto_XY(1,0);				
		Lcd1602_Print_Str("     :          ");		// 第 5 位 有分隔符;
		
		// 进入界面时,显示第 1 组 数据; 
		Lcd1602_Goto_XY(1,0);				
		Lcd1602_Print_Num(1);       				// 分组 编号;
							
		Lcd1602_Goto_XY(1,3);						// 光标定位到闹钟小时的位置
		Lcd1602_Print_Num(Clock_Hour[1]);			// 刷新显示改变后的闹钟小时			
				
		Lcd1602_Goto_XY(1,6);						// 光标定位到闹钟分钟的位置
		Lcd1602_Print_Num(Clock_Minute[1]);		// 刷新显示改变后的闹钟分钟
				
		Lcd1602_Goto_XY(1,10);					// 光标定位到秒钟开关的位置
		if(Clock_Swt[1]==0)
		{
			Lcd1602_Print_Str("OFF");				 			
		}
		if(Clock_Swt[1]==1)
		{
			Lcd1602_Print_Str(" ON");					// 液晶显示“ ON”			
		}				
		Lcd1602_Write_Cmd(0x0C);					// 关闭光标闪烁 
		
		DelayMs(10);							// 延时等待,消除按键按下的抖动
		while(!K3);							// 等待按键释放
		DelayMs(10);							// 延时等待,消除按键松开的抖动
		
		while(1)
		{
			if(K4==0)								// 如果减按键被下去
			{
				i--;
				if(i == 0) 
				{
					i = 1;
				}  
				
				Lcd1602_Goto_XY(1,0);				
				Lcd1602_Print_Num(i);       				// 编号;
							
				Lcd1602_Goto_XY(1,3);						// 光标定位到闹钟小时的位置
				Lcd1602_Print_Num(Clock_Hour[i]);			// 刷新显示改变后的闹钟小时			
				
				Lcd1602_Goto_XY(1,6);						// 光标定位到闹钟分钟的位置
				Lcd1602_Print_Num(Clock_Minute[i]);		// 刷新显示改变后的闹钟分钟
				
				
				// 开|关 位;				
				Lcd1602_Goto_XY(1,10);					// 显示闹钟状态
				if(Clock_Swt[i]==0)
				{
					Lcd1602_Print_Str("OFF");
				}
				else
				{
					Lcd1602_Print_Str(" ON");
				}				
				Lcd1602_Write_Cmd(0x0C);					// 关闭光标闪烁 
				
				while(!K4);  					// 等待按键 释放;
				DelayMs(10);						// 延时等待,消除按键松开的抖动 
					
			}
				
			if(K5==0)							// 如果加按键被下去			
			{
				i++;
				if(i>=10)
				{
					i = 9;
				}
				Lcd1602_Goto_XY(1,0);				
				Lcd1602_Print_Num(i);       			// 编号;
							
				Lcd1602_Goto_XY(1,3);						// 光标定位到闹钟小时的位置
				Lcd1602_Print_Num(Clock_Hour[i]);			// 刷新显示改变后的闹钟小时			
				
				Lcd1602_Goto_XY(1,6);						// 光标定位到闹钟分钟的位置
				Lcd1602_Print_Num(Clock_Minute[i]);		// 刷新显示改变后的闹钟分钟
				
				// 开|关 位;				
				Lcd1602_Goto_XY(1,10);					// 显示闹钟状态
				if(Clock_Swt[i]==0)
				{
					Lcd1602_Print_Str("OFF");
				}
				else
				{
					Lcd1602_Print_Str(" ON");
				}				
				Lcd1602_Write_Cmd(0x0C);					// 关闭光标闪烁 
				
				while(!K5);  					// 等待按键 释放;
				DelayMs(10);						// 延时等待,消除按键松开的抖动				 
			}
			
			if(K3==0)
			{
				while(!K3);	  // 查询按键再次 按下时,退出 查询,回到 时间界面;
				DelayMs(10);							// 延时等待,消除按键松开的抖动 
				break;
			}
		}
		
		Lcd1602_Show_Init();								// 液晶显示时钟界面
		DelayMs(10);								// 延时等待,消除按键按下的抖动
	
	}
}

/*********************************************************
// 进入/退出 秒表

void KeyScanf3()
{
	if(K3==0)
	{
		Lcd1602_Goto_XY(0,0);										// 液晶显示为秒表的界面
		Lcd1602_Print_Str("   Stop-Watch   ");
		Lcd1602_Goto_XY(1,0);				
		Lcd1602_Print_Str("  00:00:00 00   ");
		
		DelayMs(10);											// 延时等待,消除按键按下的抖动
		while(!K3);										// 等待按键释放
		DelayMs(10);											// 延时等待,消除按键松开的抖动
		
		// 调整闹钟小时 
		while(K3)
		{
			// 秒表的开始和暂停切换
			if(K4==0)							
			{
				if(TR1==0)										// 关变开
				{
					TR1=1;
				}
				else													// 开变关
				{
					TR1=0;
				}
				DelayMs(10);									// 延时等待,消除按键按下的抖动
				while(!K4);								// 等待按键释放
				DelayMs(10);									// 延时等待,消除按键松开的抖动
			}
			
			// 秒表清零
			if(K5==0)								
			{
				Stop_Watch_Count=0;								// 计数变量1清零
				Stop_Watch_Second=0;							// 计数变量2清零
				Lcd1602_Goto_XY(1,0);										// 显示清零
				Lcd1602_Print_Str("  00:00:00 00   ");
				DelayMs(10);											// 延时等待,消除按键按下的抖动
				while(!K5);										// 等待按键释放
				DelayMs(10);											// 延时等待,消除按键松开的抖动
			}
			
			//秒表计时的显示
			if(TR1==1)
			{
				Lcd1602_Goto_XY(1,2);	
				Lcd1602_Print_Num(Stop_Watch_Second/3600);			// 小时
				Lcd1602_Goto_XY(1,5);
				Lcd1602_Print_Num(Stop_Watch_Second%3600/60);		// 分钟
				Lcd1602_Goto_XY(1,8);
				Lcd1602_Print_Num(Stop_Watch_Second%60);				// 秒钟
				Lcd1602_Goto_XY(1,11);													
				Lcd1602_Print_Num(Stop_Watch_Count);						// 毫秒
			}
			
		}
		// 退出秒表,回到时钟模式
		TR1=0;														// 停止定时器		
		Stop_Watch_Count=0;								// 计数变量1清零
		Stop_Watch_Second=0;							// 计数变量2清零
		Lcd1602_Show_Init();										// 液晶显示时钟界面
		DelayMs(10);											// 延时等待,消除按键按下的抖动
		while(!K3);										// 等待按键释放
		DelayMs(10);											// 延时等待,消除按键松开的抖动
	}
}
*********************************************************/


/*********************************************************/
// 闹钟判断
/*********************************************************/
void Clock_Judge()
{	
	uchar i; 	
	
	for(i=0; i<=10;i++)
	{
		if(Clock_Swt[i] == 1) 													// 对应 组 是开时,有效; 
		{
			if((Clock_Hour[i]==TimeBuff[4])&&(Clock_Minute[i]==TimeBuff[5]))   // 当前小时和分钟,和闹钟的小时和分钟是否一致
			{
				if(TimeBuff[6]==0)												// 秒数是否等于0
				{
					//if(MP3_BUSY) // 如果 处于 空闲时,可以播放操作; 
					{
						Music_Play(i); 
						//Music_Folder_Track(0x01,i);							// 播放对应的 指定文件夹 文件名 播放; 触发播放 1 遍; 
						DelayMs(2000);						
					}					
				}
			}			
		}
	}	
	
	//if(!Music_Busy) // 如果在播放过程中, 
	 /*
	{
		if(TimeBuff[6]==59)			// 如果当前秒数为59秒
		{
			//Music_Stop();			// 停止 播放;
			 
		}		
	}
	*/		
}


/**********************************************************************
* 名称 : Init_Uart()
* 功能 : 设置串口通讯环境;
* 输入 : 无
* 输出 : 无
* 说明 :  
***********************************************************************/
void Init_Uart()
{
	SCON= 0x40;  //串口方式1;  0100,0000:不允许接收
	//SM0=0;
	//SM1=1;
	//REN=0;
	
	PCON = 0x00;   	// SMOD:0 波特率不倍频;	
	TMOD = 0x20;  	// 0010 0000 定时器1;定时方式 2
		
	TH1  = 0xFD;   	// 11.0592M 9600 波特率
	TL1  = 0xFD;
	
	TR1  = 1;      	//启动定时器
} 

//定时器 初始化函数
void Init_Timer_0() 
{
	count_x = 0;				// 用于 中断后 计数,判断;	
	// TMOD = 0x01; 			//T0 工作方式 1;16位 计数器;
	TMOD = 0x21;   // 0010 0001  (T1:用于串口时钟,T0:用于 定时器 时钟) 
	
	TH0=(65536-50000)/256;  // 初值高 8 位 走 1000 次,每次 1us :晶振 12MHz;  
	TL0=(65536-50000)%256;	// 初值低 8 位 走 1000 次,每次 1us :晶振 12MHz;  
		
	TR0  = 1; // 开启 T0 定时器;
	ET0  = 1; // 允许 T0 定时器中断; 
	EA   = 1; // 开启 总中断 允许;
}


/**********************************************************************
* 函数: Music_Folder_Track(u8 folder_x, u8 track_y) 
* 功能: 指定文件夹 文件名 播放;
* 输入: 无
* 输出: 无

void Music_Folder_Track(u8 folder_x, u8 track_y) 
{
  Table[0]= 0x7E;
  Table[1]= 0xFF;
  Table[2]= 0x06;	
  Table[3]= 0x0F; // 命令码;	
	
  Table[4]= 0x00;
  Table[5]= folder_x;
  Table[6]= track_y;
  Table[7]= 0xEF;  
  
  UART1_SendString(Table,8);
}
***********************************************************************/

/********************************************************************
* 名称 : Music_Play(uchar track_x))
* 功能 : 播放对应曲目;
* 输入 : 无
* 输出 : 无
********************************************************************/
void Music_Play(uchar track_x)
{	
	uchar x,temp; 	
	//Init_Uart();  // 设置串口通讯环境;
	
	if (track_x == 1)
	{
		x = 0;
		while(x <= 7)
		{
			temp = char_1[x];  // 播放第 1 曲;
			SBUF = temp;
			while(TI==0);
			TI=0;
			x++; 		
		}		
	}
	
	if (track_x == 2)
	{
		x = 0;
		while(x <= 7)
		{
			temp = char_2[x];  // 播放第 2 曲;
			SBUF = temp;
			while(TI==0);
			TI=0;
			x++; 		
		}		
	}
	
	if (track_x == 3)
	{
		x = 0;
		while(x <= 7)
		{
			temp = char_3[x];  // 播放第 3 曲;
			SBUF = temp;
			while(TI==0);
			TI=0;
			x++; 		
		}		
	}
	
	if (track_x == 4)
	{
		x = 0;
		while(x <= 7)
		{
			temp = char_4[x];  // 播放第 4 曲;
			SBUF = temp;
			while(TI==0);
			TI=0;
			x++; 		
		}		
	}
	
	if (track_x == 5)
	{
		x = 0;
		while(x <= 7)
		{
			temp = char_5[x];  // 播放第 5 曲;
			SBUF = temp;
			while(TI==0);
			TI=0;
			x++; 		
		}		
	}
	
	if (track_x == 6)
	{
		x = 0;
		while(x <= 7)
		{
			temp = char_6[x];  // 播放第 6 曲;
			SBUF = temp;
			while(TI==0);
			TI=0;
			x++; 		
		}		
	}
	
	if (track_x == 7)
	{
		x = 0;
		while(x <= 7)
		{
			temp = char_7[x];  // 播放第 7 曲;
			SBUF = temp;
			while(TI==0);
			TI=0;
			x++; 		
		}		
	}
	
	if (track_x == 8)
	{
		x = 0;
		while(x <= 7)
		{
			temp = char_8[x];  // 播放第 8 曲;
			SBUF = temp;
			while(TI==0);
			TI=0;
			x++; 		
		}		
	}
	
	if (track_x == 9)
	{
		x = 0;
		while(x <= 7)
		{
			temp = char_9[x];  // 播放第 9 曲;
			SBUF = temp;
			while(TI==0);
			TI=0;
			x++; 		
		}		
	}
	
}

/********************************************************************
* 名称 : Music_Stop()
* 功能 : 停止; 
* 输入 : 无
* 输出 : 无
********************************************************************/
void Music_Stop()
{
	uchar x,temp;	

	x = 0;
	while(x <= 7)
	{
		temp = char_10[x];  // 播放第 1 曲;
		SBUF = temp;
		while(TI==0);
		TI=0;
		x++; 		
	}	
}

/********************************************************************
* 名称 : Music_Volume_Up()
* 功能 : 音量 + 
* 输入 : 无
* 输出 : 无
********************************************************************/
void Music_Volume_Up()
{
	uchar x,temp;
	x = 0;
	while(x <= 7)
	{
		temp = char_11[x];  // 播放第 1 曲;
		SBUF = temp;
		while(TI==0);
		TI=0;
		x++; 		
	}	
}

/********************************************************************
* 名称 : Music_Volume_Down()
* 功能 : 音量 -
* 输入 : 无
* 输出 : 无
********************************************************************/
void Music_Volume_Down()
{
	uchar x,temp;	
	x = 0;
	while(x <= 7)
	{
		temp = char_12[x];  // 播放第 1 曲;
		SBUF = temp;
		while(TI==0);
		TI=0;
		x++; 		
	}	
}

/********************************************************************
* 名称 : Key_Volume()
* 功能 : 音量 调节; 
* 输入 : 无
* 输出 : 无

单独按 + - 按键时,调节音量;
可以考虑用 长按 短按 下处理 是否停止 播放; 
********************************************************************/
void Key_Volume()
{
	if(K4==0)
	{
		Delay_Nms(30);
		if(!K4)
		{
			Music_Volume_Down();
			Delay_Nms(200);
			Led_Flash(1);			// 指示灯 闪 一下;			
		}
		while(!K4);  				// 等待 按键 释放; 
	}
	
	if(K5==0)
	{
		Delay_Nms(30);
		if(!K5)
		{
			Music_Volume_Up();
			Delay_Nms(200);	
			Led_Flash(1);			// 指示灯 闪 一下;			
		}
		while(!K5);  				// 等待 按键 释放; 
	}	
} 
 
 void Key45_Long_Short() 
{
    uchar count_x;                   // 定义 临时 变量,用于统计按键的 计时长度; 
    if( !K4 )                               // 按键 按下; 
    {
        DelayMs(10);               // 防抖; 
        if(!K4)                           // 确定 按键 真实 按下; 
        {
            count_x = 0;           // 记数清 0; 
            do{     
                count_x ++;        // 记录 长按 短按;
                DelayMs(10);
                if( count_x >= 50) break;    // 记到 20就封顶;
            } while(!K4);          // 设计到 1000ms ,就松手,就退出 计数;
            
	      	// 长按 短按 的 时间分界点:(0----20---30)
	      	if(count_x <= 20)  					//短按对应 程序体1;
	      	{
	      		Led_Flash(1);
				LCD1602_LED = ~LCD1602_LED;   	// P2^1 输出 高|低电平 控制 LCD1602 背光灯;0 = 亮;1 = 灭;      
	       	}
	      	else      							// 长按;(在长按的 过程中,调节音量; 
	      	{
	      		do{
	      			Music_Volume_Down();
					DelayMs(80);
					Led_Flash(1);					// 指示灯 闪 一下;      //长按对应 程序体2;      			
				}while(!K4);	          	
	        }
     	}
   	}	
 
	if( !K5 )                               // 按键 按下; 
	{
        DelayMs(10);               			// 防抖; 
        if(!K5)                           	// 确定 按键 真实 按下; 
        {
            count_x = 0;           			// 记数清 0; 
            do{     
                count_x ++;        			// 记录 长按 短按;
                DelayMs(10);
                if( count_x >= 50) break;   // 记到 20就封顶;
            } while(!K5);          			// 设计到 1000ms ,就松手,就退出 计数;
               
	      	// 长按 短按 的 时间分界点:(0----20---30)
	      	if(count_x <= 20)  					//短按对应 程序体1;
	      	{
	      		Led_Flash(1);
				LCD1602_LED = ~LCD1602_LED;   	// P2^1 输出 高|低电平 控制 LCD1602 背光灯;0 = 亮;1 = 灭;      
	       	}
	      	else      							// 长按;
	      	{
	      		do{
	      			Music_Volume_Up();
					DelayMs(80);
					Led_Flash(1);				// 指示灯 闪 一下;      //长按对应 程序体2
				}while(!K5);          	
	        }
     	}
   	}   
}

/***********************************************************************/
 
 
 
 
void Led_Flash(uchar x)
{
	uchar i;
	for(i=0; i<=x; i++)
	{
		LED = 0; 
		DelayMs(3);
		LED = 1;
		DelayMs(3);
	}
	LED = 1; 						// 指示 灯 灭;  	
}


/*********************************************************/
// 主函数
/*********************************************************/
void main()
{
	// 定时变量; 
	int temp;							// 保存温度值
	uchar i; 

	// 功能模块  初始化; 
	Init_LCD1602();						// 执行液晶初始化	
	Init_DS1302();						// 时钟芯片的初始化
	Lcd1602_Show_Init();				// 液晶显示内容的初始化	
	Init_Uart();  						// 设置串口通讯环境;
	//Init_Timer_0();						// 定时器 初始化; TMOD = 0x21;  (2:串口工作模式2;1是定时器工作模式 1)  (T1:用于串口时钟,T0:用于 定时器 时钟) 
	//TimerInit();						// 定时器初始化	
	
	if(DS1302_Read_Byte(0x81)>=128)		// 判断时钟芯片是否正在运行
	{
		DS1302_Write_Time();			// 如果没有,则初始化一个时间
	}	
	
	for(i=1; i<=9; i++)
	{
		Clock_Hour[i] = EEPROM_Read(0x2000+i);		// 读取0x2000这个地址的内容,赋值给闹钟的小时变量
		if(Clock_Hour[i]>23)						// 如果读取到的闹钟小时数值不正常,则重新赋值
		{
			Clock_Hour[i]=12;
		}
		
		Clock_Minute[i] = EEPROM_Read(0x2200+i);	// 读取0x2001这个地址的内容,赋值给闹钟的分钟变量
		if(Clock_Minute[i]>59)					// 如果读取到的闹钟分钟数值不正常,则重新赋值
		{
			Clock_Minute[i]=30;
		}
		
		Clock_Swt[i] = EEPROM_Read(0x2400+i);		// 读取0x2002这个地址的内容,赋值给闹钟的开关变量
		if(Clock_Swt[i]>1)										// 如果读取到的闹钟开关数值不正常,则重新赋值
		{
			Clock_Swt[i]=0;
		}		
	}  	
	
	while(DS18B20_ReadTemp() == 850)		// 等待温度传感器初始化完成
	{
		DelayMs(10);
	}
	
	Led_Flash(2);  					// 指示灯 闪 ,表示前期工作完成; 
	
	while(1)
	{		 
		// 时钟显示; 
		DS1302_Read_Time();			// 获取当前时钟芯片的时间,存在数组time_buf中
		Led1602_Flash_Time();				// 刷新时间显示
		
		// 闹钟; 
		Clock_Judge();				// 闹钟工作的判断
		
		// 温度传感就器; 
		temp = DS18B20_ReadTemp();	// 读取温度
		Lcd1602_Goto_XY(1,9);		// 定位到显示温度的地方
		Lcd1602_Print_Temp(temp);	// 显示温度
		
		// 按键 控制; 
		// Key_Time_Set();
		//KeyScanf1();
		Key_Time_Set();				// 按键扫描(时间的设置)
		
		//KeyScanf2();				// 按键扫描(闹钟的设置)		
		Key_Clock_Set();			// 按键扫描(闹钟的设置)
		
		//KeyScanf3();				// 按键扫描(进入和退出秒表)
		Key_Look_Set();				// 查看 定时 设置情况 ;
		
		//Key_Volume();				// 调整 音量大小;
		Key45_Long_Short(); 		// 
	
		DelayMs(100);				// 延时0.1秒
 
		Lcd1602_Led_On_Off();    	// 打开 背光灯; 
	}
}


/*********************************************************
// 闹钟判断

void Clock_Judge()
{
	if(Clock_Swt==1)			// 判断闹钟的开关是否开启
	{
		if((Clock_Hour==TimeBuff[4])&&(Clock_Minute==TimeBuff[5]))		// 当前小时和分钟,和闹钟的小时和分钟是否一致
		{
			if(TimeBuff[6]==0)									// 秒数是否等于0
			{
				Buzzer_Flag=1;									// 开启蜂鸣器报警标志
			}
		}
	}
	
	if(TimeBuff[6]==59)											// 如果当前秒数为59秒
	{
		Buzzer_Flag=0;											// 关闭蜂鸣器报警标志
	}
	
	if((K4==0)||(K5==0))								// 如果加按键或减按键被按下
	{
		Buzzer_Flag=0;											// 关闭蜂鸣器报警标志
	}
	
	if(Buzzer_Flag==1)											// 如果蜂鸣器报警标志为启动
	{
		Buzzer_P=0;												// 启动蜂鸣器
		DelayMs(100);											// 延时0.1秒
		Buzzer_P=1;												// 关闭蜂鸣器
		DelayMs(100);											// 延时0.1秒
	}
}
*********************************************************/

/*********************************************************
// 定时器初始化,用于秒表

void TimerInit()
{
	TMOD = 0x10;					// 使用定时器1,工作方式是1	 
	ET1  = 1;						// 定时器1中断使能
	EA   = 1;						// 打开总中断
}
/*********************************************************/

/*********************************************************
定时器1服务程序,用于秒表
定时器 1 中断; 

void Timer1(void) interrupt 3
{
	TH1 = 216;					// 给定时器1的TH0装初值
	TL1 = 240;					// 给定时器1的TL0装初值
	
	Stop_Watch_Count++;
	if(Stop_Watch_Count>=100)
	{
		Stop_Watch_Count=0;
		Stop_Watch_Second++;
	}
} 

*********************************************************/

/*********************************************************
定时器1服务程序,用于秒表
定时器 0 中断; 
20次中断 = 1s; 如设置 10 秒,则需要 200次;
机器周期为 1us, 执行 50000次 = 50ms; 1s=1000ms; 1000ms/50ms = 20;  

void Timer0_Over(void) interrupt 1 using 1
{
	TH0 = (65536-50000)/256;   	// 中断后,赋初值; 
	TL0 = (65536-50000)%256;
	count_x++;  				// 每次中断,计数 累加 1		
	
	if( count_x >= 100)
	{	
		count_x = 0; 
		LCD1602_LED = 1; 		// 工作指示灯 灭;
		Delay_Nms(200);	
		
		TR0 = 0; 				// 关闭 T0 定时器;
		ET0 = 0; 				// 关闭 T0 定时器中断  
	} 
}

*********************************************************/ 



//关灯
void Lcd1602_Led_On_Off()
{	
	if(!K5)
	{ 
		Led_Flash(1);
		LCD1602_LED = ~LCD1602_LED;   			// P2^1 输出 低电平; // LCD1602 背光灯 亮;
		while(!K5);		
	}
	
	if(!K4)
	{ 
		Led_Flash(1);
		LCD1602_LED = ~LCD1602_LED;   			// P2^1 输出 低电平; // LCD1602 背光灯 亮;
		while(!K4);		
	}	 
	
	//TH0 = (65536-50000)/256;  	// 中断后,赋初值; 
	//TL0 = (65536-50000)%256;	
	//TR0 = 1; 						// 开启 T0 定时器;
	//ET0 = 1; 						// 允许 T0 定时器中断;
}




























联系我们

联系人:客服在线

手机:全工:13903011251

电话:李R:13530006400

邮箱:729986191@qq.com

地址: GUANGDONG PROVINCE

用手机扫描二维码关闭
二维码