/******************************************************
写头文件和相关参数声明
*******************************************************/
#include<reg52.h> //52系列单片机头文件
#include<intrins.h>
#define uchar unsigned char //宏定义
#define uint unsigned int
sbit RST=P2^2; //使能线
sbit IO=P2^1; //数据线
sbit CLK=P2^0; //时钟线
sbit Beep=P3^5; //设置蜂鸣器端口
sbit s1=P2^4; //设定键
sbit s2=P2^5; //增加键
sbit s3=P2^6; //减少键
sbit s4=P2^7; //设定闹钟键
uchar code duan[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff}; //数码管段选
uchar code wei[]={
0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //数码管位选
char hour_h,hour_l,min_h,min_l,sec_h,sec_l; //分别表示高位和低位
uchar sec=0x00,min=0x00,hour=0x18; //数码管上初始化的显示数字
uchar s1num; //加减标志位
uchar Dis_Str[8]; //数码管段选显示位
uchar min2,hour2,min2_h,min2_l,hour2_h,hour2_l,sec2,sec2_h,sec2_l; //写闹钟的时分秒
uchar flag;
/****************************************************
写控制1302的地址和数据的函数
******************************************************/
//============1302读数据=============================//
uchar Read_DS1302(uchar address) //读1302的一个字节数据
{
uchar i,temp;
RST=0; //给使能低电平
IO=1; //数据线拉高
CLK=0; //时钟线拉低
RST=1; //使能高电平
for (i=0;i<8;i++) //循环8次 写入地址数据
{
CLK=0; //给时钟一个高脉冲
IO=address&0x01; //每次传输低字节
address>>=1; //右移一位,移动8次就正好把address的一个字节送入了IO
CLK=1;
}
if(IO) //如果IO口的第1位为低即读状态
temp|=0x80; //那么每次传输低字节,保留最高位
CLK=0;
temp>>=1;
for (i=0;i<7;i++) //循环8次 读取数据
{
CLK=0;
if(IO)
temp|=0x80; //每次传输低字节
CLK=1;
temp>>=1; //右移一位
}
CLK=1;
RST=0;
IO=0;
return(temp);
}
//==========DS1302写一个字节的地址,写一个字节的数据======//
void Write_DS1302(uchar address,uchar dat) //送入地址和数据
{
uchar i;
RST=0;
CLK=0;
RST=1;
for (i=0;i<8;i++) //循环8次 写入地址数据
{
CLK=0;
_nop_(); //延时一个机器周期,写nop时一定要在头文件声明intrins.h
IO=address&0x01; //每次传输低字节
address>>=1; //每一次右移一位,将一个字节的数据保留在IO里
CLK=1;
_nop_();
}
for (i=0;i<8;i++) //循环8次 写入数据
{
CLK=0;
_nop_();
IO=dat&0x01; //每次传输低字节
dat>>=1; //右移一位
CLK=1;
_nop_();
}
RST=0;
_nop_();
}
//=============写DS1302的初始化==============//
void DS1302_initW()
{
Write_DS1302(0x8e,0x00); //写保护关
Write_DS1302(0x90,0xaa); //充电寄存器命令
Write_DS1302(0x80,sec); //秒
Write_DS1302(0x82,min); //分
Write_DS1302(0x84,hour); //时
/* Write_DS1302(0x86,date); //日
Write_DS1302(0x88,month); //月
Write_DS1302(0x8a,day); //周
Write_DS1302(0x8c,year); //年 */
Write_DS1302(0x8e,0x80); //写保护开
}
//==========读取DS1302中的数据================//
void DS1302_initR()
{
sec=Read_DS1302(0x81); //读秒数据
min=Read_DS1302(0x83); //读分钟数据
hour=Read_DS1302(0x85); //读小时数据
/* day=Read_DS1302(0x8b); //读星期数据
date=Read_DS1302(0x87); //读日数据
month=Read_DS1302(0x89); //读月数据
year=Read_DS1302(0x8d); //读年数据 */
}
//==========延时程序=================//
void delay1ms(uint ms) //延时1MS子函数
{
uint i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
/******************************************
数码管相关函数部分
*******************************************/
//==================LED数码管扫描==========//
void LED_saomiao() //LED数码管扫描
{
uchar i;
for(i=0;i<8;i++)
{
P0=Dis_Str[i]; //数码管显示段选
P1=wei[i]; //数码管显示位选
delay1ms(1);
}
}
//==============LED数码管显示=============//
void LED_Dis() //LED数码管显示
{
LED_saomiao();
DS1302_initR(); //读取DS1302中的数据
sec_l=sec%16; //将十进制转换成BCD码
sec_h=sec/16;
Dis_Str[6]=duan[sec_h]; //第7个数码管显示秒的高位(利用LED扫描的形式将段码的数据依次写入数码管中显示)
Dis_Str[7]=duan[sec_l]; //第8个数码管显示秒的低位
min_l=min%16;
min_h=min/16;
Dis_Str[3]=duan[min_h]; //第4个数码管显示分的高位
Dis_Str[4]=duan[min_l]; //第5个数码管显示分的低位
Dis_Str[5]=duan[10]; //第6个数码管显示“-”
hour_l=hour%16;
hour_h=hour/16;
Dis_Str[0]=duan[hour_h]; //第1个数码管显示时的高位
Dis_Str[1]=duan[hour_l]; //第2个数码管显示时的低位
Dis_Str[2]=duan[10]; //第3个数码管显示“-”
}
/************************************************
按键检测函数
*************************************************/
void keyscan()
{
if(s1==0)
{
delay1ms(10);
if(s1==0)
{
s1num++;
while(!s1);
if(s1num==4)
{
s1num=0;
}
}
}
if(s1num!=0)
{
if(s2==0)
{
if(flag==1)
{
switch(s1num)
{
case 1:
sec_h=sec/16; //把时间数据转换成压缩的BCD码
sec_l=sec%16;
//也可以这样写 sec_l=sec&0x0f; //保留低4位数据赋给sec的低位
// sec_h=sec>>4; //右移4位保留高4位数据给sec的高位
sec_l++;
if(sec_l==10) //如果低位秒等于10
{
sec_l=0; //低位秒清0
sec_h++;
}
if(sec_h==6) //如果把高位秒等于6
sec_h=0; //高位秒清0
sec=sec_h*16+sec_l; //把BCD码转换成十进制码
DS1302_initW(); //将改变后的值写入1302
break; //然后在LED_Dis()中第一条DS1302_initR()中读出来显示在数码管上。
case 2: min_h=min/16;
min_l=min%16;
min_l++;
if(min_l==10)
{
min_l=0;
min_h++;
}
if(min_h==6)
min_h=0;
min=min_h*16+min_l;
DS1302_initW();
break;
case 3: hour_h=hour/16; //写小时增加
hour_l=hour%16;
hour_l++;
if(hour_l==10)
{
hour_l=0;
hour_h++;
}
if((hour_h==2)&&(hour_l>3)) //如果小时高位等于2
{ //并且小时的低位大于3
hour_h=0; //那么同时清0
hour_l=0;
}
hour=hour_h*16+hour_l;
DS1302_initW();
break;
}
}
/* else
{
flag==1;
Dis_Str[6]=duan[0];
Dis_Str[7]=duan[0];
Dis_Str[3]=duan[0];
Dis_Str[4]=duan[0];
Dis_Str[1]=duan[0];
Dis_Str[0]=duan[0];
Dis_Str[2]=Dis_Str[5]=duan[10];
DS1302_initW();
} */
}
}
if(s1num!=0)
{
if(s3==0) //如果s3被按下
{
delay1ms(10); //去抖动
if(s3==0) //确定s3被按下
{
while(!s3); //松手检测
switch(s1num)
{
case 1: sec_h=sec/16; //写秒钟减少
sec_l=sec%16;
sec_l--;
if(sec_l==-1)
{
sec_l=9;
sec_h--;
}
if(sec_h==-1)
sec_h=5;
sec=sec_h*16+sec_l;
DS1302_initW();
break;
case 2: min_h=min/16; //写分钟减少
min_l=min%16;
min_l--;
if(min_l==-1)
{
min_l=9;
min_h--;
}
if(min_h==-1)
min_h=5;
min=min_h*16+min_l;
DS1302_initW();
break;
case 3: hour_h=hour/16; //写小时减少
hour_l=hour%16;
hour_l--;
if(hour_l==-1)
{
hour_l=9;
hour_h--;
}
if(hour_h==-1)
{
hour_h=2;
hour_l=3;
}
hour=hour_h*16+hour_l;
DS1302_initW();
break;
}
}
}
}
/* if(s4==0)
{
delay1ms(10);
if(s4==0)
{
clock_flag++;
while(!s4);
if(clock_flag==3)
{
clock_flag=0;
}
}
}
if(clock_flag==1)
{
if(s2==0)
{
delay1ms(10);
if(s2==0)
{
while(!s2);
}
switch(clock_flag)
{
case 1:
}
}
} */
}
//=========================主函数=========================//
void main()
{
DS1302_initW(); //写DS1302初始化部分
DS1302_initR(); //DS1302读数据部分
delay1ms(5);
while(1)
{
LED_Dis(); //LED数码管显示
keyscan(); //按键检测部分
}
}
|
|