闹铃程序转换1602界面时候乱码。。求指导
时间:10-02
整理:3721RD
点击:
/*******************************************************************************
*标题: 可调的DS1302时钟在LCD1602上显示 *
* *
********************************************************************************
*接线:JP8接JP5、蜂鸣器短路帽的左端接到P2^1(用一根杜邦线) *
*用杜邦线把P2^0连到led灯上(任意一个) *
*说明:本实验是在普中科技单片机开发板HC6800EM3上实现的 *
********************************************************************************/
#include<reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SCK=P3^6; //时钟
sbit SDA=P3^4; //数据
sbit RST=P3^5; // DS1302复位
sbit lcdrs=P2^6;
sbit lcdrw=P2^5;
sbit lcden=P2^7;
sbit key1=P1^0; //开调时键
sbit key2=P1^1; //调时加键
sbit key3=P1^2; //调时减键
sbit key4=P1^3; //开设定闹铃键
sbit key5=P1^4; //返回正常显示键
sbit key6=P1^5; //闹铃开关键
sbit DQ=P3^7; //温度传感器数据通信位
sbit beep = P2^1; //蜂鸣器控制IO口
sbit led1 = P2^0; //led灯,闹铃响标志
bit ReadRTC_Flag,Display_Flag,Alarm_Flag,flag; //定义标志位
uchar miao,fen,shi,ri,yue,week,nian,T,C=0,k=0,m=0,n=0;
uchar set_miao,set_fen,set_shi,set_ri,set_yue,set_nian,TempBuffer[5],temp_value;
char l_tmpdate[7]={0x50,0x08,0x011,0x07,0x10,0x01,0x12};//设置初始时间,秒分时日月周年12-10-07 01:08:50
uchar code write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年 最低位写位
uchar code read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; //秒分时日月周年 最低位读位
uchar code table1[]="SUN"; //星期字表
uchar code table2[]="MON";
uchar code table3[]="TUE";
uchar code table4[]="WED";
uchar code table5[]="THU";
uchar code table6[]="FRI";
uchar code table7[]="SAT";
uchar code tab1[]="20 - - ";
uchar code tab2[]=" : : ";
uchar code tab3[14]=" Set Alarm! ";
char tab4[]={0,0,12};
/******************************************************************/
/* 函数声明 */
/******************************************************************/
void Init_DS18B20(void);
unsigned char ReadOneChar(void);
void WriteOneChar(uchar dat);
void ReadTemp(void);
void temp_to_str(); //温度数据转换成液晶字符显示
void Write_Ds1302_byte(uchar temp);
void Write_Ds1302( uchar address,uchar dat );
uchar Read_Ds1302 ( uchar address );
void Read_RTC(void);
void Set_RTC(void);
void delay(uchar a);
void delay1(uchar a);
void di();
void lcd_mang();
void write_lcd1602(uchar cmd,uchar i);
void ini_lcd1602();
void write_week(uchar xq);
void write_nyr(uchar add,uchar dat);
void write_sfm(uchar add,uchar dat);
void display();
void keyscan();
void alarm();
/******************************************************************/
/* 主函数 */
/******************************************************************/
void main(void)
{
ini_lcd1602();
Init_DS18B20();
//Set_RTC(); //写入时钟值,如果使用备用电池时候,不需要没每次上电写入,此程序应该屏蔽
while(1)
{
ReadTemp();
temp_to_str();
keyscan();
if(ReadRTC_Flag==0)
{
Read_RTC();
if(Display_Flag==0)
{
display();
}
if(flag==1)
{
alarm();
}
}
}
}
/******************************************************************/
/* 毫秒级延时函数 */
/******************************************************************/
void delay(uchar a)
{
uchar i;
while(a--)
{
for(i=0;i<250;i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
void delay1(uchar a)
{
uchar i;
while(a--)
{
for(i=0;i<5;i++)
{}
}
}
/******************************************************************/
/* 蜂鸣器发声函数 */
/******************************************************************/
void di()
{
uchar i;
while(key1==0||key2==0||key3==0||key4==0||key5==0||key6==0)
{
for(i=0;i<50;i++)
{
delay1(4);
beep=~beep;
}
}
}
/******************************************************************/
/* ds18b20延迟子函数(晶振12MHz) */
/******************************************************************/
void delay_18B20(unsigned int i)
{
while(i--);
}
/******************************************************************/
/* ds18b20初始化函数 */
/******************************************************************/
void Init_DS18B20(void)
{
unsigned char x=0;
DQ = 1; //DQ复位
delay_18B20(8); //稍做延时
DQ = 0; //单片机将DQ拉低
delay_18B20(80); //精确延时 大于 480us
DQ = 1; //拉高总线
delay_18B20(14);
x = DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
delay_18B20(20);
DQ = 1;
}
/******************************************************************/
/* ds18b20读一个字节 */
/******************************************************************/
unsigned char ReadOneChar(void)
{
uchar i=0;
uchar dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(4);
}
return(dat);
}
/******************************************************************/
/* ds18b20写一个字节 */
/******************************************************************/
void WriteOneChar(uchar dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay_18B20(5);
DQ = 1;
dat>>=1;
}
}
/******************************************************************/
/* 读取ds18b20当前温度 */
/******************************************************************/
void ReadTemp(void)
{
unsigned char a=0;
unsigned char b=0;
unsigned char t=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
delay_18B20(100); // this message is wery important
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
delay_18B20(100);
a=ReadOneChar(); //读取温度值低位
b=ReadOneChar(); //读取温度值高位
temp_value=b<<4;
temp_value+=(a&0xf0)>>4;
}
/******************************************************************/
/* 温度数据转换 */
/******************************************************************/
void temp_to_str() //温度数据转换成液晶字符显示
{
TempBuffer[0]=temp_value/10+'0'; //十位
TempBuffer[1]=temp_value%10+'0'; //个位
//TempBuffer[2]=0xdf; //温度符号
//TempBuffer[3]='C';
//TempBuffer[4]='\0';
}
/******************************************************************/
/* LCD1602判忙函数 */
/******************************************************************/
void lcd_mang()
{
lcdrs=0;
lcdrw=1;
lcden=1;
_nop_();
_nop_();
_nop_();
_nop_();
while(P0&0x80);
lcden=0;
}
/******************************************************************/
/* LCD1602写指令(i=0)、数据(i=1)函数 */
/******************************************************************/
void write_lcd1602(uchar cmd,uchar i)
{
lcd_mang();
lcdrs=i;
lcdrw=0;
lcden=0;
_nop_();
_nop_();
lcden=1;
_nop_();
_nop_();
P0=cmd;
_nop_();
_nop_();
_nop_();
_nop_();
lcden=0;
}
/******************************************************************/
/* LCD1602初始化函数 */
/******************************************************************/
void ini_lcd1602()
{
uchar i;
led1=1;
Alarm_Flag=0;
write_lcd1602(0x38,0);
delay(1);
write_lcd1602(0x0c,0);
delay(1);
write_lcd1602(0x06,0);
delay(1);
write_lcd1602(0x01,0);
delay(1);
write_lcd1602(0x80+1,0);
for(i=0;i<8;i++)
{
write_lcd1602(tab1,1);
}
write_lcd1602(0x80+0x40+2,0);
for(i=0;i<6;i++)
{
write_lcd1602(tab2,1);
}
write_lcd1602(0x80+0x40+14,0);
write_lcd1602(0xdf,1);
write_lcd1602('C',1);
}
/******************************************************************/
/* BCD转换成LCD1602能显示的16进制数,秒、分、时 */
/******************************************************************/
void write_sfm(uchar add,uchar dat)
{
uchar gw,sw;
gw=dat%10;
sw=dat/10;
write_lcd1602(0x80+0x40+add,0);
write_lcd1602(sw+'0',1);
write_lcd1602(gw+'0',1);
}
/******************************************************************/
/* BCD转换成LCD1602能显示的16进制数,日、月、年 */
/******************************************************************/
void write_nyr(uchar add,uchar dat)
{
uchar gw,sw;
gw=dat%10;
sw=dat/10;
write_lcd1602(0x80+add,0);
write_lcd1602(sw+'0',1);
write_lcd1602(gw+'0',1);
}
/******************************************************************/
/* 显示星期 */
/******************************************************************/
void write_week(uchar xq)
{
uchar x;
write_lcd1602(0x80+12,0);
switch(xq)
{
case 1:
for(x=0;x<3;x++)
{
write_lcd1602(table1[x],1);
}
break;
case 2:
for(x=0;x<3;x++)
{
write_lcd1602(table2[x],1);
}
break;
case 3:
for(x=0;x<3;x++)
{
write_lcd1602(table3[x],1);
}
break;
case 4:
for(x=0;x<3;x++)
{
write_lcd1602(table4[x],1);
}
break;
case 5:
for(x=0;x<3;x++)
{
write_lcd1602(table5[x],1);
}
break;
case 6:
for(x=0;x<3;x++)
{
write_lcd1602(table6[x],1);
}
break;
case 7:
for(x=0;x<3;x++)
{
write_lcd1602(table7[x],1);
}
break;
}
write_lcd1602(0x80+12,0);
}
/******************************************************************/
/* 显示函数 */
/******************************************************************/
void display()
{
uchar i;
Read_RTC();
write_sfm(8,miao);
write_sfm(5,fen);
write_sfm(2,shi);
write_nyr(3,nian);
write_nyr(6,yue);
write_nyr(9,ri);
write_week(week);
ReadTemp();
temp_to_str();
write_lcd1602(0x80+0x40+12,0);
for(i=0;i<2;i++)
{
write_lcd1602(TempBuffer,1);
}
}
/******************************************************************/
/* DS1302写一个字节 */
/******************************************************************/
void Write_Ds1302_Byte(uchar temp)
{
uchar i;
for (i=0;i<8;i++) //循环8次 写入数据
{
SCK=0;
SDA=temp&0x01; //每次传输低字节
temp>>=1; //右移一位
SCK=1;
}
}
/******************************************************************/
/* 写入DS1302 */
/******************************************************************/
void Write_Ds1302( uchar address,uchar dat )
{
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_(); //启动
Write_Ds1302_Byte(address); //发送地址
Write_Ds1302_Byte(dat); //发送数据
RST=0; //恢复
}
/******************************************************************/
/* 读出DS1302数据 */
/******************************************************************/
uchar Read_Ds1302 ( uchar address )
{
uchar i,temp=0x00;
RST=0;
_nop_();
_nop_();
SCK=0;
_nop_();
_nop_();
RST=1;
_nop_();
_nop_();
Write_Ds1302_Byte(address);
for (i=0;i<8;i++) //循环8次 读取数据
{
if(SDA)
temp|=0x80; //每次传输低字节
SCK=0;
temp>>=1; //右移一位
_nop_();
_nop_();
_nop_();
SCK=1;
}
RST=0;
_nop_(); //以下为DS1302复位的稳定时间
_nop_();
RST=0;
SCK=0;
_nop_();
_nop_();
_nop_();
_nop_();
SCK=1;
_nop_();
_nop_();
SDA=0;
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
return (temp); //返回
}
/******************************************************************/
/* 读时钟数据 */
/******************************************************************/
void Read_RTC(void) //读取 日历
{
uchar i,*p;
p=read_rtc_address; //地址传递
for(i=0;i<7;i++) //分7次读取 秒分时日月周年
{
l_tmpdate=Read_Ds1302(*p);
p++;
miao=((l_tmpdate[0]&0x70)>>4)*10 + (l_tmpdate[0]&0x0f);
fen =((l_tmpdate[1]&0x70)>>4)*10 + (l_tmpdate[1]&0x0f);
shi =((l_tmpdate[2]&0x70)>>4)*10 + (l_tmpdate[2]&0x0f);
ri =((l_tmpdate[3]&0x70)>>4)*10 + (l_tmpdate[3]&0x0f);
yue =((l_tmpdate[4]&0x70)>>4)*10 + (l_tmpdate[4]&0x0f);
week=((l_tmpdate[5]&0x70)>>4)*10 + (l_tmpdate[5]&0x0f);
nian=((l_tmpdate[6]&0x70)>>4)*10 + (l_tmpdate[6]&0x0f);
}
}
/******************************************************************/
/* 设定时钟数据 */
/******************************************************************/
void Set_RTC(void) //设定 日历
{
uchar i,*p;
/*for(i=0;i<7;i++)
{ //BCD处理
tmp=l_tmpdate/10;
l_tmpdate=l_tmpdate%10;
l_tmpdate=l_tmpdate+tmp*16;
}*/
Write_Ds1302(0x8E,0X00); //允许写,禁止写保护
p=write_rtc_address; //传地址
for(i=0;i<7;i++) //7次写入 秒分时日月周年
{
Write_Ds1302(*p,l_tmpdate);
p++;
}
Write_Ds1302(0x8E,0x80); //打开写保护
}
/******************************************************************/
/* 键盘扫描函数 */
/******************************************************************/
void keyscan()
{
uchar i;
if(Display_Flag==0)
{
if(key1==0) //调时功能键
{
delay(9);
if(key1==0)
{
di();
while(!key1); //松手检测
++n;
ReadRTC_Flag=1; //停止走时
switch(n)
{
case 1: write_lcd1602(0x80+0x40+9,0); //按一次功能键秒闪烁
write_lcd1602(0x0f,0);
Write_Ds1302(0x8e,0x00); //允许写,禁止写保护
Write_Ds1302(0x80,((miao/10)*16+miao%10)); //写入DS1302秒位
Write_Ds1302(0x8e,0x80); //打开写保护
break;
case 2: write_lcd1602(0x80+0x40+6,0); //按两次功能键分闪烁
break;
case 3: write_lcd1602(0x80+0x40+3,0); //按三次功能键时闪烁
break;
case 4: write_lcd1602(0x80+10,0); //按四次功能键日闪烁
break;
case 5: write_lcd1602(0x80+7,0); //按五次功能键月闪烁
break;
case 6:write_lcd1602(0x80+4,0); //按六次功能键年闪烁
break;
case 7: write_lcd1602(0x80+12,0); //按七次功能键周闪烁
break;
case 8: n=0; //按八次功能键开始走时,停止闪烁
ReadRTC_Flag=0;
write_lcd1602(0x0c,0);
Write_Ds1302(0x8e,0x00);
Write_Ds1302(0x80,((miao/10)*16+miao%10));
Write_Ds1302(0x8e,0x80);
C=0;
break;
}
}
}
}
if(key4==0) //闹铃功能键
{
delay(9);
if(key4==0)
{
di();
while(!key4);
m++;
Display_Flag=1; //屏蔽调时功能键,进入调闹铃功能
Alarm_Flag=0; //初始化闹铃标志位,闹铃不响
flag=1; //开启闹钟检测
write_lcd1602(0x80+0x40,0); //在时间前面显示闹钟开启标志‘A’
write_lcd1602('A',1);
switch(m)
{
case 1: n=0;
ReadRTC_Flag=0; //开显示
write_lcd1602(0x0c,0); //停止闪烁
Write_Ds1302(0x8e,0x00);
Write_Ds1302(0x80,((miao/10)*16+miao%10));
Write_Ds1302(0x8e,0x80);
write_lcd1602(0x80+1,0); //首行写入Set Alarm!
for(i=0;i<14;i++)
{
write_lcd1602(tab3,1);
}
write_lcd1602(0x80+0x40+2,0); //第二行写入设定的时间
for(i=0;i<6;i++)
{
write_lcd1602(tab2,1);
}
write_lcd1602(0x80+0x40+8,0);
write_lcd1602(tab4[0]/10+'0',1);
write_lcd1602(tab4[0]%10+'0',1);
write_lcd1602(0x80+0x40+5,0);
write_lcd1602(tab4[1]/10+'0',1);
write_lcd1602(tab4[1]%10+'0',1);
write_lcd1602(0x80+0x40+2,0);
write_lcd1602(tab4[2]/10+'0',1);
write_lcd1602(tab4[2]%10+'0',1);
break;
case 2: write_lcd1602(0x80+0x40+9,0); //开始设定闹铃,秒位闪烁可调
write_lcd1602(0x0f,0);
break;
case 3: write_lcd1602(0x80+0x40+6,0); //分位闪烁可调
break;
case 4: write_lcd1602(0x80+0x40+3,0); //时位闪烁可调
break;
case 5: Display_Flag=0; //关闭对调时功能间的屏蔽
m=0; //关闭更更改闹铃时间
C=0; //屏蔽掉在正常显示时间时key5复位键对显示的影响
write_lcd1602(0x0c,0);
write_lcd1602(0x80+1,0); //清掉Set Alarm
for(i=0;i<11;i++)
{
write_lcd1602(tab1,1);
}
display(); //返回时间显示
}
}
}
if(n!=0||m!=0) //功能加键
{
if(key2==0)
{
delay(9);
if(key2==0)
{
di();
while(!key2);
if(Display_Flag==0)
{
switch(n)
&nb
*标题: 可调的DS1302时钟在LCD1602上显示 *
* *
********************************************************************************
*接线:JP8接JP5、蜂鸣器短路帽的左端接到P2^1(用一根杜邦线) *
*用杜邦线把P2^0连到led灯上(任意一个) *
*说明:本实验是在普中科技单片机开发板HC6800EM3上实现的 *
********************************************************************************/
#include<reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SCK=P3^6; //时钟
sbit SDA=P3^4; //数据
sbit RST=P3^5; // DS1302复位
sbit lcdrs=P2^6;
sbit lcdrw=P2^5;
sbit lcden=P2^7;
sbit key1=P1^0; //开调时键
sbit key2=P1^1; //调时加键
sbit key3=P1^2; //调时减键
sbit key4=P1^3; //开设定闹铃键
sbit key5=P1^4; //返回正常显示键
sbit key6=P1^5; //闹铃开关键
sbit DQ=P3^7; //温度传感器数据通信位
sbit beep = P2^1; //蜂鸣器控制IO口
sbit led1 = P2^0; //led灯,闹铃响标志
bit ReadRTC_Flag,Display_Flag,Alarm_Flag,flag; //定义标志位
uchar miao,fen,shi,ri,yue,week,nian,T,C=0,k=0,m=0,n=0;
uchar set_miao,set_fen,set_shi,set_ri,set_yue,set_nian,TempBuffer[5],temp_value;
char l_tmpdate[7]={0x50,0x08,0x011,0x07,0x10,0x01,0x12};//设置初始时间,秒分时日月周年12-10-07 01:08:50
uchar code write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年 最低位写位
uchar code read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; //秒分时日月周年 最低位读位
uchar code table1[]="SUN"; //星期字表
uchar code table2[]="MON";
uchar code table3[]="TUE";
uchar code table4[]="WED";
uchar code table5[]="THU";
uchar code table6[]="FRI";
uchar code table7[]="SAT";
uchar code tab1[]="20 - - ";
uchar code tab2[]=" : : ";
uchar code tab3[14]=" Set Alarm! ";
char tab4[]={0,0,12};
/******************************************************************/
/* 函数声明 */
/******************************************************************/
void Init_DS18B20(void);
unsigned char ReadOneChar(void);
void WriteOneChar(uchar dat);
void ReadTemp(void);
void temp_to_str(); //温度数据转换成液晶字符显示
void Write_Ds1302_byte(uchar temp);
void Write_Ds1302( uchar address,uchar dat );
uchar Read_Ds1302 ( uchar address );
void Read_RTC(void);
void Set_RTC(void);
void delay(uchar a);
void delay1(uchar a);
void di();
void lcd_mang();
void write_lcd1602(uchar cmd,uchar i);
void ini_lcd1602();
void write_week(uchar xq);
void write_nyr(uchar add,uchar dat);
void write_sfm(uchar add,uchar dat);
void display();
void keyscan();
void alarm();
/******************************************************************/
/* 主函数 */
/******************************************************************/
void main(void)
{
ini_lcd1602();
Init_DS18B20();
//Set_RTC(); //写入时钟值,如果使用备用电池时候,不需要没每次上电写入,此程序应该屏蔽
while(1)
{
ReadTemp();
temp_to_str();
keyscan();
if(ReadRTC_Flag==0)
{
Read_RTC();
if(Display_Flag==0)
{
display();
}
if(flag==1)
{
alarm();
}
}
}
}
/******************************************************************/
/* 毫秒级延时函数 */
/******************************************************************/
void delay(uchar a)
{
uchar i;
while(a--)
{
for(i=0;i<250;i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
void delay1(uchar a)
{
uchar i;
while(a--)
{
for(i=0;i<5;i++)
{}
}
}
/******************************************************************/
/* 蜂鸣器发声函数 */
/******************************************************************/
void di()
{
uchar i;
while(key1==0||key2==0||key3==0||key4==0||key5==0||key6==0)
{
for(i=0;i<50;i++)
{
delay1(4);
beep=~beep;
}
}
}
/******************************************************************/
/* ds18b20延迟子函数(晶振12MHz) */
/******************************************************************/
void delay_18B20(unsigned int i)
{
while(i--);
}
/******************************************************************/
/* ds18b20初始化函数 */
/******************************************************************/
void Init_DS18B20(void)
{
unsigned char x=0;
DQ = 1; //DQ复位
delay_18B20(8); //稍做延时
DQ = 0; //单片机将DQ拉低
delay_18B20(80); //精确延时 大于 480us
DQ = 1; //拉高总线
delay_18B20(14);
x = DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
delay_18B20(20);
DQ = 1;
}
/******************************************************************/
/* ds18b20读一个字节 */
/******************************************************************/
unsigned char ReadOneChar(void)
{
uchar i=0;
uchar dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(4);
}
return(dat);
}
/******************************************************************/
/* ds18b20写一个字节 */
/******************************************************************/
void WriteOneChar(uchar dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay_18B20(5);
DQ = 1;
dat>>=1;
}
}
/******************************************************************/
/* 读取ds18b20当前温度 */
/******************************************************************/
void ReadTemp(void)
{
unsigned char a=0;
unsigned char b=0;
unsigned char t=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
delay_18B20(100); // this message is wery important
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
delay_18B20(100);
a=ReadOneChar(); //读取温度值低位
b=ReadOneChar(); //读取温度值高位
temp_value=b<<4;
temp_value+=(a&0xf0)>>4;
}
/******************************************************************/
/* 温度数据转换 */
/******************************************************************/
void temp_to_str() //温度数据转换成液晶字符显示
{
TempBuffer[0]=temp_value/10+'0'; //十位
TempBuffer[1]=temp_value%10+'0'; //个位
//TempBuffer[2]=0xdf; //温度符号
//TempBuffer[3]='C';
//TempBuffer[4]='\0';
}
/******************************************************************/
/* LCD1602判忙函数 */
/******************************************************************/
void lcd_mang()
{
lcdrs=0;
lcdrw=1;
lcden=1;
_nop_();
_nop_();
_nop_();
_nop_();
while(P0&0x80);
lcden=0;
}
/******************************************************************/
/* LCD1602写指令(i=0)、数据(i=1)函数 */
/******************************************************************/
void write_lcd1602(uchar cmd,uchar i)
{
lcd_mang();
lcdrs=i;
lcdrw=0;
lcden=0;
_nop_();
_nop_();
lcden=1;
_nop_();
_nop_();
P0=cmd;
_nop_();
_nop_();
_nop_();
_nop_();
lcden=0;
}
/******************************************************************/
/* LCD1602初始化函数 */
/******************************************************************/
void ini_lcd1602()
{
uchar i;
led1=1;
Alarm_Flag=0;
write_lcd1602(0x38,0);
delay(1);
write_lcd1602(0x0c,0);
delay(1);
write_lcd1602(0x06,0);
delay(1);
write_lcd1602(0x01,0);
delay(1);
write_lcd1602(0x80+1,0);
for(i=0;i<8;i++)
{
write_lcd1602(tab1,1);
}
write_lcd1602(0x80+0x40+2,0);
for(i=0;i<6;i++)
{
write_lcd1602(tab2,1);
}
write_lcd1602(0x80+0x40+14,0);
write_lcd1602(0xdf,1);
write_lcd1602('C',1);
}
/******************************************************************/
/* BCD转换成LCD1602能显示的16进制数,秒、分、时 */
/******************************************************************/
void write_sfm(uchar add,uchar dat)
{
uchar gw,sw;
gw=dat%10;
sw=dat/10;
write_lcd1602(0x80+0x40+add,0);
write_lcd1602(sw+'0',1);
write_lcd1602(gw+'0',1);
}
/******************************************************************/
/* BCD转换成LCD1602能显示的16进制数,日、月、年 */
/******************************************************************/
void write_nyr(uchar add,uchar dat)
{
uchar gw,sw;
gw=dat%10;
sw=dat/10;
write_lcd1602(0x80+add,0);
write_lcd1602(sw+'0',1);
write_lcd1602(gw+'0',1);
}
/******************************************************************/
/* 显示星期 */
/******************************************************************/
void write_week(uchar xq)
{
uchar x;
write_lcd1602(0x80+12,0);
switch(xq)
{
case 1:
for(x=0;x<3;x++)
{
write_lcd1602(table1[x],1);
}
break;
case 2:
for(x=0;x<3;x++)
{
write_lcd1602(table2[x],1);
}
break;
case 3:
for(x=0;x<3;x++)
{
write_lcd1602(table3[x],1);
}
break;
case 4:
for(x=0;x<3;x++)
{
write_lcd1602(table4[x],1);
}
break;
case 5:
for(x=0;x<3;x++)
{
write_lcd1602(table5[x],1);
}
break;
case 6:
for(x=0;x<3;x++)
{
write_lcd1602(table6[x],1);
}
break;
case 7:
for(x=0;x<3;x++)
{
write_lcd1602(table7[x],1);
}
break;
}
write_lcd1602(0x80+12,0);
}
/******************************************************************/
/* 显示函数 */
/******************************************************************/
void display()
{
uchar i;
Read_RTC();
write_sfm(8,miao);
write_sfm(5,fen);
write_sfm(2,shi);
write_nyr(3,nian);
write_nyr(6,yue);
write_nyr(9,ri);
write_week(week);
ReadTemp();
temp_to_str();
write_lcd1602(0x80+0x40+12,0);
for(i=0;i<2;i++)
{
write_lcd1602(TempBuffer,1);
}
}
/******************************************************************/
/* DS1302写一个字节 */
/******************************************************************/
void Write_Ds1302_Byte(uchar temp)
{
uchar i;
for (i=0;i<8;i++) //循环8次 写入数据
{
SCK=0;
SDA=temp&0x01; //每次传输低字节
temp>>=1; //右移一位
SCK=1;
}
}
/******************************************************************/
/* 写入DS1302 */
/******************************************************************/
void Write_Ds1302( uchar address,uchar dat )
{
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_(); //启动
Write_Ds1302_Byte(address); //发送地址
Write_Ds1302_Byte(dat); //发送数据
RST=0; //恢复
}
/******************************************************************/
/* 读出DS1302数据 */
/******************************************************************/
uchar Read_Ds1302 ( uchar address )
{
uchar i,temp=0x00;
RST=0;
_nop_();
_nop_();
SCK=0;
_nop_();
_nop_();
RST=1;
_nop_();
_nop_();
Write_Ds1302_Byte(address);
for (i=0;i<8;i++) //循环8次 读取数据
{
if(SDA)
temp|=0x80; //每次传输低字节
SCK=0;
temp>>=1; //右移一位
_nop_();
_nop_();
_nop_();
SCK=1;
}
RST=0;
_nop_(); //以下为DS1302复位的稳定时间
_nop_();
RST=0;
SCK=0;
_nop_();
_nop_();
_nop_();
_nop_();
SCK=1;
_nop_();
_nop_();
SDA=0;
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
return (temp); //返回
}
/******************************************************************/
/* 读时钟数据 */
/******************************************************************/
void Read_RTC(void) //读取 日历
{
uchar i,*p;
p=read_rtc_address; //地址传递
for(i=0;i<7;i++) //分7次读取 秒分时日月周年
{
l_tmpdate=Read_Ds1302(*p);
p++;
miao=((l_tmpdate[0]&0x70)>>4)*10 + (l_tmpdate[0]&0x0f);
fen =((l_tmpdate[1]&0x70)>>4)*10 + (l_tmpdate[1]&0x0f);
shi =((l_tmpdate[2]&0x70)>>4)*10 + (l_tmpdate[2]&0x0f);
ri =((l_tmpdate[3]&0x70)>>4)*10 + (l_tmpdate[3]&0x0f);
yue =((l_tmpdate[4]&0x70)>>4)*10 + (l_tmpdate[4]&0x0f);
week=((l_tmpdate[5]&0x70)>>4)*10 + (l_tmpdate[5]&0x0f);
nian=((l_tmpdate[6]&0x70)>>4)*10 + (l_tmpdate[6]&0x0f);
}
}
/******************************************************************/
/* 设定时钟数据 */
/******************************************************************/
void Set_RTC(void) //设定 日历
{
uchar i,*p;
/*for(i=0;i<7;i++)
{ //BCD处理
tmp=l_tmpdate/10;
l_tmpdate=l_tmpdate%10;
l_tmpdate=l_tmpdate+tmp*16;
}*/
Write_Ds1302(0x8E,0X00); //允许写,禁止写保护
p=write_rtc_address; //传地址
for(i=0;i<7;i++) //7次写入 秒分时日月周年
{
Write_Ds1302(*p,l_tmpdate);
p++;
}
Write_Ds1302(0x8E,0x80); //打开写保护
}
/******************************************************************/
/* 键盘扫描函数 */
/******************************************************************/
void keyscan()
{
uchar i;
if(Display_Flag==0)
{
if(key1==0) //调时功能键
{
delay(9);
if(key1==0)
{
di();
while(!key1); //松手检测
++n;
ReadRTC_Flag=1; //停止走时
switch(n)
{
case 1: write_lcd1602(0x80+0x40+9,0); //按一次功能键秒闪烁
write_lcd1602(0x0f,0);
Write_Ds1302(0x8e,0x00); //允许写,禁止写保护
Write_Ds1302(0x80,((miao/10)*16+miao%10)); //写入DS1302秒位
Write_Ds1302(0x8e,0x80); //打开写保护
break;
case 2: write_lcd1602(0x80+0x40+6,0); //按两次功能键分闪烁
break;
case 3: write_lcd1602(0x80+0x40+3,0); //按三次功能键时闪烁
break;
case 4: write_lcd1602(0x80+10,0); //按四次功能键日闪烁
break;
case 5: write_lcd1602(0x80+7,0); //按五次功能键月闪烁
break;
case 6:write_lcd1602(0x80+4,0); //按六次功能键年闪烁
break;
case 7: write_lcd1602(0x80+12,0); //按七次功能键周闪烁
break;
case 8: n=0; //按八次功能键开始走时,停止闪烁
ReadRTC_Flag=0;
write_lcd1602(0x0c,0);
Write_Ds1302(0x8e,0x00);
Write_Ds1302(0x80,((miao/10)*16+miao%10));
Write_Ds1302(0x8e,0x80);
C=0;
break;
}
}
}
}
if(key4==0) //闹铃功能键
{
delay(9);
if(key4==0)
{
di();
while(!key4);
m++;
Display_Flag=1; //屏蔽调时功能键,进入调闹铃功能
Alarm_Flag=0; //初始化闹铃标志位,闹铃不响
flag=1; //开启闹钟检测
write_lcd1602(0x80+0x40,0); //在时间前面显示闹钟开启标志‘A’
write_lcd1602('A',1);
switch(m)
{
case 1: n=0;
ReadRTC_Flag=0; //开显示
write_lcd1602(0x0c,0); //停止闪烁
Write_Ds1302(0x8e,0x00);
Write_Ds1302(0x80,((miao/10)*16+miao%10));
Write_Ds1302(0x8e,0x80);
write_lcd1602(0x80+1,0); //首行写入Set Alarm!
for(i=0;i<14;i++)
{
write_lcd1602(tab3,1);
}
write_lcd1602(0x80+0x40+2,0); //第二行写入设定的时间
for(i=0;i<6;i++)
{
write_lcd1602(tab2,1);
}
write_lcd1602(0x80+0x40+8,0);
write_lcd1602(tab4[0]/10+'0',1);
write_lcd1602(tab4[0]%10+'0',1);
write_lcd1602(0x80+0x40+5,0);
write_lcd1602(tab4[1]/10+'0',1);
write_lcd1602(tab4[1]%10+'0',1);
write_lcd1602(0x80+0x40+2,0);
write_lcd1602(tab4[2]/10+'0',1);
write_lcd1602(tab4[2]%10+'0',1);
break;
case 2: write_lcd1602(0x80+0x40+9,0); //开始设定闹铃,秒位闪烁可调
write_lcd1602(0x0f,0);
break;
case 3: write_lcd1602(0x80+0x40+6,0); //分位闪烁可调
break;
case 4: write_lcd1602(0x80+0x40+3,0); //时位闪烁可调
break;
case 5: Display_Flag=0; //关闭对调时功能间的屏蔽
m=0; //关闭更更改闹铃时间
C=0; //屏蔽掉在正常显示时间时key5复位键对显示的影响
write_lcd1602(0x0c,0);
write_lcd1602(0x80+1,0); //清掉Set Alarm
for(i=0;i<11;i++)
{
write_lcd1602(tab1,1);
}
display(); //返回时间显示
}
}
}
if(n!=0||m!=0) //功能加键
{
if(key2==0)
{
delay(9);
if(key2==0)
{
di();
while(!key2);
if(Display_Flag==0)
{
switch(n)
&nb