前段时间用pcf8563芯片做了个电子时钟,这个芯片自动走时间,我只用去读和写就行了,pcf8563要加一个后备电池,这样就不怕单片机掉电了。这个不太符合你的要求,不过这是我现成的,我可不想在这里重新写代码。代码不是很规范,但是能正常运行。
你在Keil里建个工程,下面一段是display.c的代码:
#include "at89x51.h"
#include "PCF8563.h"
//#include "TG12232.h"
#define Key_Set P2_2
#define Key_Add P2_1
#define Key_Sub P2_0
//#define LCD_CS P2_5
//#define LCD_DATA P2_6
//#define LCD_CLK P2_7
void Key_down()
void Displaybuffer(char Location)
//void LCD_Display()
unsigned char LedTable[10]={0x3f,0x03,0x6d,0x67,0x53,0x76,0x7e,0x23,0x7f,0x77}
bit state=0
char set=0
void main()
{
unsigned char i,j,n=2
P1=0
TMOD=0x01
TH0=0x4c
TL0=0x00
ET0=1
EA=1
// P8563_init()
P2=0xff
P3=0x02
P1=LedTable[8]
// while(n--)
for(i=0i<250i++)
for(j=0j<6j++)
{
delay(10)
P3<<=1
if(P3==0x80)
P3=0x02
delay(10)
}
delay(5000)
// lcd_init()
// set_lcd_position(0,1) //汉字定位到上行左端
// lcd_display(0,0,"Welcome to use!")
// lcd_display(1,0," Leo.Zheng ")
// delay(1000)
// lcd_send_com(0x01)//清除
// lcd_display(0,0,"20 / /")
while(1)
{
Key_down()
Displaybuffer(set)
// LCD_Display()
}
}
void Time0_H() interrupt 1
{
static unsigned char i=0
TH0=0x4c
TL0=0x00
i++
if(i==8)
{
i=0
state=~state
}
}
/*
void LCD_Display()
{
lcd_display_char(0,2,((g8563_Store[6]&0xf0)>>4)+0x30)//年
lcd_display_char(0,3,(g8563_Store[6]&0x0f)+0x30)//
}*/
void Key_down()
{
// static char set=0
unsigned char buffer
if(!Key_Set)
for(buffer=0buffer<250buffer++)
_nop_()
if(!Key_Set)
{
if(set==0)
{
writeData(0x0,0x20)//使时间停止
TR0=1
}
set++
if(set==4)
{
set=0
TR0=0
writeData(0x0,0x00)
}
while(!Key_Set)
Displaybuffer(set)
}
if(!Key_Add)
for(buffer=0buffer<250buffer++)
_nop_()
if(!Key_Add)
{
if(set==0)
return
P8563_gettime()
buffer= g8563_Store[set-1]
buffer=((buffer&0xf0)>>4)*10+(buffer&0x0f)
if(buffer>=59)
buffer=0
else if(buffer>=23 && set==3)
buffer=0
else
buffer++
buffer=(buffer/10<<4)+(buffer%10)
writeData(set+1,buffer)
while(!Key_Add)
Displaybuffer(set)
}
if(!Key_Sub)
for(buffer=0buffer<250buffer++)
_nop_()
if(!Key_Sub)
{
if(set==0)
return
P8563_gettime()
buffer= g8563_Store[set-1]
buffer=((buffer&0xf0)>>4)*10+(buffer&0x0f)
if(buffer == 0)
{
if(set==3)
buffer=23
else
buffer=59
}
else
buffer--
buffer=(buffer/10<<4)+(buffer%10)
writeData(set+1,buffer)
while(!Key_Sub)
Displaybuffer(set)
}
}
void Displaybuffer(char Location)
{
unsigned char i
P8563_gettime()
/*****************************************/
if(Location==1 && state==0)
{
P1=0
P3=0
goto sec_bit1
}
P3=0x02
P1=LedTable[g8563_Store[0]&0x0f] //sec
sec_bit1:
for(i=0i<250i++)
P1=0
if(Location==1 && state==0)
{
P1=0
P3=0
goto sec_bit2
}
P3=0x04
P1=LedTable[(g8563_Store[0]&0xf0)>>4]
sec_bit2:
for(i=0i<250i++)
P1=0
/*****************************************/
if(Location==2 && state==0)
{
P1=0
P3=0
goto min_bit1
}
P3=0x08
P1=LedTable[g8563_Store[1]&0x0f] //min
min_bit1:
for(i=0i<250i++)
P1=0
if(Location==2 && state==0)
{
P1=0
P3=0
goto min_bit2
}
P3=0x10
P1=LedTable[(g8563_Store[1]&0xf0)>>4]
min_bit2:
for(i=0i<250i++)
P1=0
/*****************************************/
if(Location==3 && state==0)
{
P1=0
P3=0
goto hour_bit1
}
P3=0x20
P1=LedTable[g8563_Store[2]&0x0f] //hour
hour_bit1:
for(i=0i<250i++)
P1=0
if(Location==3 && state==0)
{
P1=0
P3=0
goto hour_bit2
}
P3=0x40
P1=LedTable[(g8563_Store[2]&0xf0)>>4]
hour_bit2:
for(i=0i<250i++)
P1=0
P3=0x02
/*****************************************/
}
这下面一段是pcf8563.h的代码:
#ifndef __PFC8563_H__
#define __PFC8563_H__
#include <intrins.h>
#define uchar unsigned char
sbit SDA=P2^4
sbit SCL=P2^3
//extern void _nop_ (void)
//extern void delay(unsigned int ms)
uchar g8563_Store[7] /*时间交换区,全局变量声明*/
uchar code c8563_Store[7]={0x01,0x02,0x07,0x09,0x04,0x02,0x12} /*写入时间初值:秒,分,时,日,周,月,年(BCD码)
07:59:00*/
void delay(long time)
{while(time--)
}
/********************************************
内部函数,延时1
********************************************/
void DD()
{
//delay(1)
// uchar i
// for(i=0i<250i++)
_nop_()
_nop_() /*根据晶振频率制定延时时间*/
}
/********************************************
内部函数,I2C开始
********************************************/
void Start()
{ EA=0
SDA=1
SCL=1
DD()
SDA=0
DD()
SCL=0
}
/********************************************
内部函数,I2C结束
********************************************/
void Stop()
{
SDA=0
SCL=0
DD()
SCL=1
DD()
SDA=1
DD()
EA=1
}
/********************************************
内部函数,输出ACK ,每个字节传输完成,输出ack=0,结束读数据,ack=1
********************************************/
void WriteACK(uchar ack)
{
SDA=ack
DD()
SCL=1
DD()
SCL=0
}
/********************************************
内部函数,等待ACK
********************************************/
void WaitACK()
{ uchar errtime=20
SDA=1
DD() /*读ACK*/
SCL=1
DD()
while(SDA)
{ errtime--
if(!errtime)
{
Stop()
SDA=0 //自己加的******
}
}
SDA=1 //自己加的******
SCL=0
DD()
}
/********************************************
内部函数.输出数据字节
入口:B=数据
********************************************/
void writebyte(uchar wdata)
{
uchar i
for(i=0i<8i++)
{
if(wdata&0x80) SDA=1
else SDA=0
wdata<<=1
SCL=1
DD()
SCL=0
}
WaitACK() //I2C器件或通讯出错,将会退出I2C通讯
}
/********************************************
内部函数.输入数据
出口:B
********************************************/
uchar Readbyte()
{
uchar i,bytedata
SDA=1
for(i=0i<8i++)
{
SCL=1
bytedata<<=1
bytedata|=SDA
SCL=0
DD()
}
return(bytedata)
}
/********************************************
输出数据->pcf8563
********************************************/
void writeData(uchar address,uchar mdata)
{
Start()
writebyte(0xa2) /*写命令*/
writebyte(address) /*写地址*/
writebyte(mdata) /*写数据*/
Stop()
}
/********************************************
输入数据<-pcf8563
********************************************/
uchar ReadData(uchar address) /*单字节*/
{ uchar rdata
Start()
writebyte(0xa2) /*写命令*/
writebyte(address) /*写地址*/
Start()
writebyte(0xa3) /*读命令*/
rdata=Readbyte()
WriteACK(1)
Stop()
return(rdata)
}
void ReadData1(uchar address,uchar count,uchar * buff) /*多字节*/
{ uchar i
Start()
writebyte(0xa2) /*写命令*/
writebyte(address) /*写地址*/
Start()
writebyte(0xa3) /*读命令*/
for(i=0i<counti++)
{
buff[i]=Readbyte()
if(i<count-1) WriteACK(0)
}
WriteACK(1)
Stop()
}
/********************************************
内部函数,读入时间到内部缓冲区
********************************************/
void P8563_Read()
{ uchar time[7]
ReadData1(0x02,0x07,time)
g8563_Store[0]=time[0]&0x7f /*秒*/
g8563_Store[1]=time[1]&0x7f /*分*/
g8563_Store[2]=time[2]&0x3f /*小时*/
g8563_Store[3]=time[4]&0x07 /*星期*/
g8563_Store[4]=time[3]&0x3f /*日*/
g8563_Store[5]=time[5]&0x1f /*月*/
g8563_Store[6]=time[6] /*年*/
}
/********************************************
读入时间到内部缓冲区----外部调用
********************************************/
void P8563_gettime()
{
P8563_Read()
if(g8563_Store[0]==0)
P8563_Read() /*如果为秒=0,为防止时间变化,再读一次*/
}
/********************************************
写时间修改值
********************************************/
//void P8563_settime()
//{
// uchar i
// for(i=2i<=8i++) { writeData(i,g8563_Store[i-2]) }
// writeData(6,g8563_Store[3])
//}
/********************************************
P8563的初始化-----外部调用
********************************************/
/*
void P8563_init()
{
uchar i
if((ReadData(0xa)&0x3f)!=0x8) //检查是否第一次启动,是则初始化时间
{
// for(i=0i<=6i++) g8563_Store[i]=c8563_Store[i] //初始化时间
// P8563_settime()
writeData(0x0,0x00)
writeData(0xa,0x8) //8:00报警
writeData(0x1,0x12) //报警有效
writeData(0xd,0xf0)
}
}
*/
#endif
C51单片机六位数码管时钟用数码管dot分隔时分秒
用三个按键设置时间:
SET键:小时设定->分钟设定->结束设定,小时设定状态时表示小时的两位数码管闪烁,分钟设定时表示分钟的两位数码管闪烁
CHANGE键:在小时设定状态和分钟设定状态改变数值
SET S键:秒置零
C语言代码:
//main.c
#include <REGX52.H>
typedef unsigned int UINT
typedef unsigned char UCHAR
#define KEY P2
#define KEYMASK 0x07
sbit LE1 = P2^6 //定义位控口
sbit LE2 = P2^7 //定义段控口
UCHAR KeyPressDown = 0x00
UCHAR KeyRelease = 0x00
UCHAR LastKey = 0x00
UCHAR MODE
extern UCHAR HH
extern UCHAR MM
extern UCHAR SS
extern bit T_CYCLE
extern void T0_Init(void) //初始化定时器,函数定义在Timer.c
UCHAR code NUM[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}
void delay(UINT t) //延时t时钟周期
{
while (t--)
}
void H_Increase(void) //小时增1
{
if(HH<23) HH++
else
{
HH = 0
}
}
void M_Increase(void) //分钟增1
{
if(MM<59) MM++
else
{
MM = 0
H_Increase()
}
}
void S_Increase(void) //秒增1
{
if(SS<59) SS++
else
{
SS = 0
M_Increase()
}
}
void display(UCHAR SEG,UCHAR Digi) //显示一位数码管,SEG = 0-9数字,Digi = 第0-6位
{
LE2 = 1
P0 = (0x01<<Digi)
LE2 = 0
P0 = 0x00
LE1 = 1
P0 = NUM[SEG]
if (Digi==1||Digi==3) P0 &= 0x7f //显示分隔符
delay(50)
P0 = 0xff
LE1 = 0
}
void main(void)
{
P0 = 0xff
LE1 = 0
LE2 = 0
T0_Init()
while(1)
{
if(MODE != 1 || T_CYCLE)
{
display(HH/10,0) //显示小时十位数
display(HH%10,1) //显示小时个位数
}
if(MODE != 2 || T_CYCLE)
{
display(MM/10,2) //显示分钟十位数
display(MM%10,3) //显示分钟个位数
}
display(SS/10,4) //显示秒十位数
display(SS%10,5) //显示秒个位数
}
}
void key_Process(void) //按键处理程序
{
UCHAR CurrKey
KEY |= KEYMASK //将按键对应的IO设置为输入状态
CurrKey = (~KEY) &KEYMASK
KeyPressDown = (~LastKey) &CurrKey
KeyRelease = LastKey &(~CurrKey)
LastKey = CurrKey
switch(KeyRelease)
{
case 1:
if(MODE == 2) MODE = 0
else MODE ++
break
case 2:
if(MODE == 1) H_Increase()
if(MODE == 2) M_Increase()
break
case 4:
SS = 0
break
default: break
}
}
//Timer.c
#include <reg52.h>
typedef unsigned int UINT
typedef unsigned char UCHAR
UCHAR HH = 14 //小时初始值
UCHAR MM = 2 //分钟初始值
UCHAR SS = 55 //秒初始值
UINT u_10ms = 0//10ms计数
bit T_CYCLE = 0
extern void key_Process(void)
extern void S_Increase(void)
void T0_Init(void)
{
TMOD &= 0xf0
TMOD |= 0x01
//定时器赋初始值,定时时间为10ms。
TH0 = 0xd8
TL0 = 0xf0
TR0 = 1
IE = 0x82
}
void T0_INTSrv(void) interrupt 1
{
//定时器重新开始计时。
TH0 = 0xd8
TL0 = 0xf0
u_10ms ++
if (u_10ms%20==0) // 200 ms
{
T_CYCLE = ! T_CYCLE//闪烁循环
}
if (u_10ms>99) // 1000 ms = 1 second
{
u_10ms = 0
S_Increase()
}
key_Process() //SET按键处理
}
Proreus仿真电路:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)