/*********************************************************
红外遥控;(用 遥控 来设置 时间)
// 按键 长按 短按 控制;
// 标准化 音频 模块 ;
// 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