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