#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]="20 - - week ";
uchar code table1[]=" --:--:-- ";
uchar code read_add[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; //秒分时日月周年 读的寄存器地址
uchar code write_add[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年 写的寄存器地址
uchar time_to_set[7]={0,27,11,13,10,1,10}; //秒分时日月星期年// 可随时更改
uchar key1; //保存k1键的按下次数,移动时钟设置光标
//uchar key4; //保存k4键的按下次数,移动闹钟设置光标
bit flag; // 是否读取时间的标志位,1时处于时钟设置阶段,2时处于闹钟设置阶段
/*DS1302时钟*/
uchar clk_time[7]; //秒,分,时寄存器初始值
sbit T_RST=P1^4; //ds1302-5
sbit T_IO=P1^3; //ds1302-6
sbit T_CLK=P1^2; //ds1302-7
/*LCD1602*/
sbit en=P2^1;
sbit rw=P2^3;
sbit rs=P2^2;
sbit deng=P2^5;
sbit ACC0=ACC^0; //ds1302数据的第0位
sbit ACC7=ACC^7; //ds1302数据的第7位
uchar num,b;
uchar clock_ss,clock_sg,clock_fs,clock_fg,clock_ms,clock_mg,clock_s,clock_g; //时,分,秒变量
uchar clock_ris,clock_rig,clock_yues,clock_yueg,
clock_days,clock_dayg,clock_years,clock_yearg; //日,月,年变量
//红外遥控全局变量
uchar irtime; //红外每接收一位的时长
uchar startflag; //红外接收起始标志位
uchar bitnum; //红外接收的位
uchar irdate[33]; //红外接收位存储在数组里
uchar irreceok; //红外接收结束标志位
uchar ircode[4]; //红外字节组成的字节
uchar irprosok; //红外存储字节完毕标志位
/*****************红外的子程序***************************/
//定时器初始化
void timer0init()
{
TMOD=0X02;
TH0=0X00;
TL0=0x00;
ET0=1;
EA=1;
TR0=1;
}
//外部中断初始化
void int0init()
{
IT0=1;
EX0=1;
EA=1;
}
//将接收的红外为组成4个字节存放在数组里
void irpros()
{
uchar i,j,k=1;
uchar value;
for(i=0;i<4;i++) //4次存放4个字节
{
for(j=0;j<8;j++) //每8位组成一个字节
{
value=value>>1;
if(irdate[k]>6) // 1
{
value=value|0x80;
}
k++;
}
ircode[i]=value;
}
irprosok=1;
}
/******************DS1302:写入操作(上升沿)****************************************************/
void write_byte(uchar da)
{
uchar i;
ACC=da;
for(i=8;i>0;i--)
{
T_IO=ACC0;
T_CLK=0;
T_CLK=1;//此时一位数据写进
ACC=ACC>>1;
}
}
/******************DS1302:读取操作(下降沿)***************************************************/
uchar read_byte(void)
{
uchar i;
for(i=0;i<8;i++)
{
ACC=ACC>>1;
T_CLK = 1;
T_CLK = 0;
ACC7 = T_IO;
}
return(ACC);
}
/******************DS1302:写入数据(先送地址,再写数据)****************************************/
void write_1302(uchar addr,uchar da)
{
T_RST=0; //停止工作
T_CLK=0;
T_RST=1; //重新工作
write_byte(addr); //写入地址
write_byte(da);
T_RST=0;
T_CLK=1;
}
/******************DS1302:读取数据(先送地址,再读数据)****************************************/
uchar read_1302(uchar addr)
{
uchar temp;
T_RST=0; //停止工作
T_CLK=0;
T_RST=1; //重新工作
write_byte(addr); //写入地址
temp=read_byte();
T_RST=0;
T_CLK=1; //停止工作
return(temp);
}
/***********************延时程序=Z*1ms*********************************************************/
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/**********************************************************************************************/
/*液晶写指令*/
void write_com(uchar com)
{
rs=0;
P0=com;
delay(5);
en=1;
delay(5);
en=0;
}
/*液晶写数据*/
void write_data(uchar date)
{
rs=1;
P0=date;
delay(5);
en=1;
delay(5);
en=0;
}
/*液晶,led,DS1302初始化设置*/
void init_dis()
{
rw=0;
en=0;
write_com(0x38);//设置液晶
write_com(0x0c);//设光标等
write_com(0x06);//写一个字符地址指针加1且光标加1
write_com(0x01);//清屏
write_com(0x80);//设置s地址指针
}
/*********************************************************************************************/
/*设定日历*/
void Set_RTC(void)
{
uchar i,*p,tmp;
for(i=0;i<7;i++)
{ //BCD处理,将十进制转换成十六进制
tmp=time_to_set[i]/10;
time_to_set[i]=time_to_set[i]%10;
time_to_set[i]=time_to_set[i]+tmp*16;
}
write_1302(0x8E,0X00); //关闭写保护
p=write_add; //传要写的寄存器地址
for(i=0;i<7;i++) //7次写入秒分时日月周年
{
write_1302(*p,time_to_set[i]);
p++;
}
write_1302(0x8E,0x80);//打开写保护
}
/**********************液晶显示程序*************************************************************/
void lcd_display()
{
static uchar i=0,temp[2];
switch(i)
{
case 0: write_com(0x80+0x4a);break;//秒
case 1: write_com(0x80+0x47);break;//分
case 2: write_com(0x80+0x44);break;//时
case 3: write_com(0x80+0x08);break;//日
case 4: write_com(0x80+0x05);break;//月
case 5: write_com(0x80+0x0e);break;//星期
case 6: write_com(0x80+0x02);break;//年
}
temp[0]=clk_time[i]/16;//数据的转换
temp[1]=clk_time[i]%16;
write_data(0x30+temp[0]);
write_data(0x30+temp[1]);
// if(i==5)
// {
// write_com(0x80+0x0e); //清除星期显示后面的乱码
// write_data(0x20); //写入空白字符
// }
i++;
if(i==7)
i=0;
}
/*********************************读取日历****************************************************/
void Read_RTC(void) //
{
uchar i,*p;
p=read_add; //读的地址传递
for(i=0;i<7;i++) //分7次读取 秒分时日月周年
{
clk_time[i]=read_1302(*p);
p++;
}
}
/***************************十六进制转换成十进制********************************************/
uchar change(uchar x)
{
uchar tep,y;
y=x;
tep=y/16;
y=y%16;
y=y+tep*10;
return y;
}
/*************************键盘设定时间程序*****************************************************/
void key_set_time()
{
//uchar keytemp;
uchar tem[2],tp;//存储要更改的时间数据
if(ircode[2]==0x45)//液晶背光灯 开 或 关
deng=~deng;
if(ircode[2]==0x46)
{
flag=1;
key1++;
if(key1==1)
{
write_com(0x80+0x4b);//将光标移动到秒个位
write_com(0x0f); //显示光标并且闪烁
}
if(key1==2)
{
write_com(0x80+0x48);//将光标移动到分个位
write_com(0x0f); //显示光标并且闪烁
}
if(key1==3)
{
write_com(0x80+0x40+5);//将光标移动到时个位
write_com(0x0f); //显示光标并且闪烁
}
if(key1==4)
{
write_com(0x80+0x0f); //星期
write_com(0x0f);
}
if(key1==5)
{
write_com(0x80+0x09); //日
write_com(0x0f);
}
if(key1==6)
{
write_com(0x80+0x06);// 月
write_com(0x0f);
}
if(key1==7)
{
write_com(0x80+0x03); //年
write_com(0x0f);
}
if(key1==8)
{
key1=0;
flag=0;//时钟正常运行
write_com(0x0c);//光标停止闪烁
}
}
/****************************************************************************************/
if(ircode[2]==0x47)//时钟正常运行
{
key1=0;
flag=0;
write_com(0x0c);//光标停止闪烁
}
/****************************************************************************************/
if(ircode[2]==0x09) //通过按键增加数值
{
Read_RTC();
if(key1==1)
{
clk_time[0]=change(clk_time[0]);
clk_time[0]++;
if(clk_time[0]==60)
clk_time[0]=0;
tp=clk_time[0]/10;
clk_time[0]=clk_time[0]%10;
clk_time[0]=clk_time[0]+tp*16;
write_1302(0x8E,0X00); //关闭写保护
write_1302(write_add[0],clk_time[0]);
write_1302(0x8E,0x80); //打开写保护
tem[0]=clk_time[0]/16;//数据的转换
tem[1]=clk_time[0]%16;
write_com(0x80+0x40+10);
评论2