#include <STC12C5A60S2.h>
#include <intrins.h>
//宏定义,11.0592M晶振
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
//位定义
sbit a1=P0^0;// 秒按键
sbit a2=P0^1;//分按键
sbit a3=P0^2;//时按键
//数码管显示数组
uchar code xianshi[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90};//共阳数码管0到9显示BCD码
//变量声明
bit Time_FLAG=0;//定义一个时间间隔标志,用来控制写EEPROM间隔时间
bit Yanshi_FLAG=0;
uchar Sec;//秒计数定义并初始化变量
uchar Min;//分计数
uchar Hour;//时计数
uchar m=0;//中断计数
uchar cnt=0;
//定义IAP/ISP/EEPROM命令
#define CMD_IDLE 0 //空闲模式
#define CMD_READ 1 //IAP字节读命令
#define CMD_PROGRAM 2 //IAP字节编程命令
#define CMD_ERASE 3 //IAP扇区擦除命令
#define ENABLE_IAP 0x82 //if SYSCLK<20MHz
#define IAP_ADDRESS 0x0000 //定义EEPROM地址
void delay(uint k);//延时函数
void timechuli();//时间处理函数
void anjian();//按键扫描函数
void timexianshi();//时间显示函数
void IapIdle();
uchar IapReadunsigned_char(uint addr);
void IapProgramunsigned_char(uint addr, uchar dat);
void IapEraseSector(uint addr);
void Write_EEPROM();
//----------------------------
//关闭IAP,初始化函数
//---------------------------*/
void IapIdle()
{
IAP_CONTR = 0; //关闭IAP功能
IAP_CMD = 0; //清除命令寄存器
IAP_TRIG = 0; //清除触发寄存器
IAP_ADDRH = 0x80; //将地址设置到非IAP区域
IAP_ADDRL = 0;
}
//---------------------------
//从ISP/IAP/EEPROM区域读取一字节
//---------------------------
uchar IapReadunsigned_char(uint addr)
{
uchar dat; //数据缓冲区
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_READ; //设置IAP命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //等待ISP/IAP/EEPROM操作完成
dat = IAP_DATA; //读ISP/IAP/EEPROM数据
IapIdle(); //关闭IAP功能
return dat; //返回
}
//----------------------------
//写一字节数据到ISP/IAP/EEPROM区域
//----------------------------
void IapProgramunsigned_char(uint addr, uchar dat)
{
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_PROGRAM; //设置IAP命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_DATA = dat; //写ISP/IAP/EEPROM数据
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //等待ISP/IAP/EEPROM操作完成
IapIdle();
}
//----------------------------
//扇区擦除
//---------------------------
void IapEraseSector(uint addr)
{
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_ERASE; //设置IAP命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //等待ISP/IAP/EEPROM操作完成
IapIdle();
}
void Write_EEPROM()//将数据写入EEPROM
{
IapEraseSector(IAP_ADDRESS); //扇区擦除
delay(2); //延时
IapProgramunsigned_char(IAP_ADDRESS,Hour);//写入时
delay(2); //延时
IapProgramunsigned_char(IAP_ADDRESS+1,Min);//写入分
delay(2); //延时
IapProgramunsigned_char(IAP_ADDRESS+2,Sec); //写入秒
}
void delay(uint k)
{
uchar i;
while((k--)!=0)
{
for(i=0;i<100;i++);
}
}
void timechuli()
{
if(Sec==60)
{
Sec=0;
Min++;
if(Min==60)
{
Min=0;
Hour++;
if(Hour==24)
{Hour=0;}
}
}
}
void delay123(uchar w)
{
uchar n;
for(n=0;n<w;n++)
{
timexianshi();
}
}
void anjian()
{
if(a1==0)
{
delay(500);//按键消抖 怎么改成显示的程序
if(a1==0)
{
Sec++;
if(Sec==60)
{
Sec=0;
Min++;
}
}
}
if(a2==0)
{
delay(500);
if(a2==0)
{
P1=(xianshi[Min%10])|0x80;//显示分的个位
P2=0x08;
delay(5);
P1=xianshi[Min/10];//显示分的十位
P2=0x10;
delay(5);
Min++;
if(Min==60)
{
Min=0;
Hour++;
}
}
}
if(a3==0)
{
delay(500);
if(a3==0)
{
Hour++;
if(Hour==24)
{
Hour=0;
}
}
}
}
void timexianshi() //P2口位选 P1口段选
{
P1=xianshi[Sec%10];//显示秒的个位
P2=0x01;
delay(5);
P1=xianshi[Sec/10];//显示秒的十位
P2=0x02;
delay(5);
P1=(xianshi[Min%10])|0x80;//显示分的个位
P2=0x08;
delay(5);
P1=xianshi[Min/10];//显示分的十位
P2=0x10;
delay(5);
P1=(xianshi[Hour%10])|0x80;//显示时的个位
P2=0x40;
delay(5);
P1=xianshi[Hour/10];//显示时的个位
P2=0x80;
delay(5);
}
void timer0() interrupt 1
{
TH0=(65536-45872)/256; //放入初值,11.0592M,50ms
TL0=(65536-45872)%256;
m++;
if(m==20)
{
m=0;
Sec++;
cnt++;
if(cnt==5)
{
Time_FLAG = 1;
cnt=0;
}
}
}
void main()
{
P0=0xff;
P2=0;
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TH0=(65536-45872)/256; //放入初值,11.0592M,50ms
TL0=(65536-45872)%256;
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1; //开总中断
EX0=1;
ET0=1; //开定时器0中断
//从EEPROM读取时间信息
Hour = IapReadunsigned_char(IAP_ADDRESS); //小时
delay(2);
Min = IapReadunsigned_char(IAP_ADDRESS+1); //分钟
delay(2);
Sec = IapReadunsigned_char(IAP_ADDRESS+2); //秒钟
delay(2);
while(1)
{
timexianshi();//时间显示函数
anjian();//按键扫描函数
timechuli();//时间处理函数
//每隔一段时间,将Time_FLAG置1,写一次EEPROM,这个时间看你自己需求了
if(Time_FLAG==1)
{
Write_EEPROM();//写EEPROM
Time_FLAG = 0; //写完EEPROM将Time_FLAG标志清0
}
}
}
这是完整的一个电子时钟,带eeprom一个程序
|