哈哈 有个1602显示的 不过程序太长 贴不上 给你个数码管的吧 不行再联系
1302.c
#include<DS1302.h>
#include<key.h>
uchar bit_ser[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf}
uchar seven_seg[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}
/***********************时间显示*****************/
void timer0_init(void) //T0初始化函数,用于时间的动态显示
{
TMOD = 0x21
TL0 = (65536-5000) % 256
TH0 = (65536-5000) / 256
EA = 1
ET0 = 1
TR0 = 1
}
void timer0_isr(void) interrupt 1 //T0中断处理函数
{
char flag //flag用于表示调整时闪烁的亮或灭
TR0 = 0
TL0 = (65536-5000) % 256
TH0 = (65536-5000) / 256
TR0 = 1
flag = x / 100 * 0xff //设置闪烁标志,如果x大于100则flag为0xff,小于100则为0x00
x++
if(x > 200)
x = 0
switch(i)
{
case 0:
P2 = bit_ser[0]
if(setflag == 3) //根据setflag的值判断当前位是否需要闪烁
P0 = flag | seven_seg[dis_buffer[0]]
else
P0 = seven_seg[dis_buffer[0]]
break
case 1:
P2 = bit_ser[1]
if(setflag == 3)
P0 =flag | seven_seg[dis_buffer[1]]
else
P0 =seven_seg[dis_buffer[1]]
break
case 2:
P2 = bit_ser[2]
if(setflag == 2)
P0 =flag | seven_seg[dis_buffer[2]]
else
P0 =seven_seg[dis_buffer[2]]
break
case 3:
P2 = bit_ser[3]
if(setflag == 2)
P0 =flag | seven_seg[dis_buffer[3]]
else
P0 =seven_seg[dis_buffer[3]]
break
case 4:
P2 = bit_ser[4]
if(setflag == 1)
P0 =flag | seven_seg[dis_buffer[4]]
else
P0 =seven_seg[dis_buffer[4]]
break
case 5:
P2 = bit_ser[5]
if(setflag == 1)
P0 =flag | seven_seg[dis_buffer[5]]
else
P0 =seven_seg[dis_buffer[5]]
break
}
i++
if(i >= 6)
{
i = 0
if(j == 10)
{
j = 0
if(setflag == 0)
DS1302_GetTime(&Time) //如果setflag是0,就从1302中读出时间,因为setflag不是0时,说明处于调整状态,不需要读时间
dis_buffer[5] = Time.Second % 10 //把当前时间放入显示缓冲区
dis_buffer[4] = Time.Second / 10
dis_buffer[3] = Time.Minute % 10
dis_buffer[2] = Time.Minute / 10
dis_buffer[1] = Time.Hour % 10
dis_buffer[0] = Time.Hour / 10
}
j++
}
}
void main()
{
Initial_DS1302(Time)
timer0_init()
while(1)
{
set_down()
timer_down()
up_down()
down_down()
beepflag_down()
if(setflag == 0 && Time.Hour == romhour && Time.Minute == romminute && Beepflag == 1) //判断蜂鸣器是否要响
Beep = !Beep
}
}
//key.c
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
uchar i = 0,j = 0,x = 0,setflag,flag_set,flag_timer //setflag用来表示调整的位置,flag_set和flag_timer分别表示当前处于调整状态还是定时状态
SYSTEMTIME Time={0,20,15,3,30,6,10} //系统时间的初始值2010年6月30日星期三,15时20分0秒
char dis_buffer[6] //存放显示数据的缓冲区
sbit Beep_flag = P3^2 //蜂鸣器的接口
sbit key_timer = P3^4 //定时按钮
sbit key_set = P3^5 //调整按钮
sbit key_up = P3^6 //增加按钮
sbit key_down = P3^7 //减小按钮
char romhour,romminute,romsec //分别存放定时的时,分,秒
bit Beepflag //标记闹钟是否开启
//延时函数
void delays(uchar x)
{
while(x) x--
}
//设置键的处理函数
void set()
{
setflag ++
flag_set = 1
if(setflag >= 4)
{
setflag = 0
flag_set = 0
Initial_DS1302(Time)
}
}
//定时间的处理函数
void timer()
{
setflag ++
flag_timer = 1
if(setflag == 1)
{
Time.Hour = romhour
Time.Minute = romminute
Time.Second = romsec
}
else if(setflag >= 4)
{
setflag = 0
flag_timer = 0
romhour = Time.Hour
romminute = Time.Minute
romsec = Time.Second
}
}
//增加键的处理函数
void up()
{
switch(setflag)
{
case 0:
break
case 1:
Time.Second ++
if(Time.Second >= 60)
Time.Second = 0
break
case 2:
Time.Minute ++
if(Time.Minute >= 60)
Time.Minute = 0
break
case 3:
Time.Hour ++
if(Time.Hour >= 24)
Time.Hour = 0
break
}
}
//减小键的处理函数
void down()
{
switch(setflag)
{
case 0:
break
case 1:
Time.Second --
if(Time.Second < 0)
Time.Second = 59
break
case 2:
Time.Minute --
if(Time.Minute < 0)
Time.Minute = 59
break
case 3:
Time.Hour --
if(Time.Hour < 0)
Time.Hour = 23
break
}
}
//设置键的扫描函数
void set_down()
{
if(key_set == 0 && flag_timer == 0)
{
delays(100)
if(key_set == 0)
{
set()
}
while(!key_set)
}
}
//定时键的扫描函数
void timer_down()
{
if(key_timer == 0 && flag_set == 0)
{
delays(100)
if(key_timer == 0)
{
timer()
}
while(!key_timer)
}
}
//增加键的扫描函数
void up_down()
{
if(key_up == 0 && setflag != 0)
{
delays(100)
if(key_up == 0)
{
up()
while(!key_up)
}
}
}
//减少键的处理函数
void down_down()
{
if(key_down == 0 && setflag != 0)
{
delays(100)
if(key_down == 0)
{
down()
while(!key_down)
}
}
}
//定时开关的扫描处理函数
void beepflag_down()
{
if(Beep_flag == 0)
{
delays(100)
{
Beepflag = !Beepflag
while(!Beep_flag)
}
}
}
//ds1302.h
#ifndef _REAL_TIMER_DS1302
#define _REAL_TIMER_DS1302
#include <REG51.h>
sbit DS1302_CLK = P1^1 //实时时钟时钟线引脚
sbit DS1302_IO = P1^2 //实时时钟数据线引脚
sbit DS1302_RST = P1^3 //实时时钟复位线引脚
sbit ACC0 = ACC^0
sbit ACC7 = ACC^7
sbit Beep = P2^7
typedef struct __SYSTEMTIME__
{ char Second
char Minute
char Hour
char Week
char Day
char Month
char Year
}SYSTEMTIME //定义的时间类型
#define AM(X) X
#define PM(X) (X+12) // 转成24小时制
#define DS1302_SECOND 0x80 //秒寄存器
#define DS1302_MINUTE 0x82 //分寄存器
#define DS1302_HOUR 0x84
#define DS1302_WEEK 0x8A
#define DS1302_DAY 0x86
#define DS1302_MONTH 0x88
#define DS1302_YEAR 0x8C
#define DS1302_RAM(X) (0xC0+(X)*2) //用于计算 DS1302_RAM 地址的宏
void DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数)
{ unsigned char i
ACC = d
for(i=8 i>0 i--)
{ DS1302_IO = ACC0 //相当于汇编中的 RRC
DS1302_CLK = 1
DS1302_CLK = 0 //发一个高跳变到低的脉冲
ACC = ACC >> 1
}
}
unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数)
{ unsigned char i
for(i=8 i>0 i--)
{ ACC = ACC >>1 //相当于汇编中的 RRC
ACC7 = DS1302_IO
DS1302_CLK = 1
DS1302_CLK = 0 //发一个高跳变到低的脉冲
}
return(ACC)
}
void Write1302(unsigned char ucAddr, unsigned char ucDa)//ucAddr: DS1302地址, ucData: 要写的数据
{ DS1302_RST = 0
DS1302_CLK = 0
DS1302_RST = 1
DS1302InputByte(ucAddr) // 地址,命令
DS1302InputByte(ucDa) // 写1Byte数据
DS1302_CLK = 1
DS1302_RST = 0 //RST 0->1->0,CLK 0->1
}
unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据
{ unsigned char ucData
DS1302_RST = 0
DS1302_CLK = 0
DS1302_RST = 1 //enable
DS1302InputByte(ucAddr|0x01) // 地址,命令
ucData = DS1302OutputByte() // 读1Byte数据
DS1302_CLK = 1 //RST 0->1->0,CLK 0->1
DS1302_RST = 0
return(ucData)
}
void DS1302_SetProtect(bit flag) //是否写保护
{ if(flag)
Write1302(0x8E,0x80) //WP=1,不能写入
else
Write1302(0x8E,0x00)//WP=0,可以写入
}
void DS1302_SetTime(unsigned char Address, unsigned char Value) // 设置时间函数
{ DS1302_SetProtect(0)
Write1302(Address, ((Value/10)<<4 | (Value%10))) //高4位为十位,低4位为个位
DS1302_SetProtect(1)
}
//获取时间函数,从DS1302内读取时间然后存入Time内
void DS1302_GetTime(SYSTEMTIME *Time)
{ unsigned char ReadValue
ReadValue = Read1302(DS1302_SECOND)
Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)//转换成10进制的秒
ReadValue = Read1302(DS1302_MINUTE)
Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)
ReadValue = Read1302(DS1302_HOUR)
Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)
ReadValue = Read1302(DS1302_DAY)
Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)
ReadValue = Read1302(DS1302_WEEK)
Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)
ReadValue = Read1302(DS1302_MONTH)
Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)
ReadValue = Read1302(DS1302_YEAR)
Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)
}
//利用STime初始化DS1302
void Initial_DS1302(SYSTEMTIME STime)
{ unsigned char Second=Read1302(DS1302_SECOND)
if(Second&0x80) DS1302_SetTime(DS1302_SECOND,0) //如果第七为1(表明没有启动), 则启动时钟
DS1302_SetTime(DS1302_SECOND,STime.Second) //设定起始时间
DS1302_SetTime(DS1302_MINUTE,STime.Minute)
DS1302_SetTime(DS1302_HOUR,STime.Hour)
DS1302_SetTime(DS1302_DAY,STime.Day)
DS1302_SetTime(DS1302_MONTH,STime.Month)
DS1302_SetTime(DS1302_YEAR,STime.Year)
DS1302_SetTime(DS1302_WEEK,STime.Week)
}
#endif
像做电子钟一般你要先确定你的各个模块用什么实现,比如显示是用LCD还是数码管,计时用定时器还是时钟芯片。对于你这个我推荐你用专门的日历时钟芯片,如DS1302。虽然看起来加个模块更复杂了,其实不然,对于你这个功能比较多的项目,不用时钟芯片,程序会变得很复杂。本人大学是做过这个,完全软件实现。后来又做过DS1302的,其实这个不难,你只需要通过SPI接口对它进行简单的读写,至于如何计时不用在程序中专门去写。欢迎分享,转载请注明来源:内存溢出
评论列表(0条)