1
搞了好久,终于写好了,
//**** 功能说明:时钟+数码管显示*************************************//
//*** key1功能按键,按一次,进入调分模式(key2加,key3减,**********//
//*** 按二次key1,进入调时模式(key2加,key3减,)******************//
//*** 按三次key1,进入正常模式**************************************//
//*** 同时开机蜂鸣器响一声,按键按下都响一声************************//
#include
#include
#define uint unsigned int
#define uchar unsigned char
***it SCK=P3^6;
***it SDA=P3^5;
***it RST=P3^7;
***it key1=P3^0; // 功能按键
***it key2=P3^1;//key2加,
***it key3=P3^2;//key3减,
***it SPK=P3^3; // 蜂鸣器
/*复位脚*/
#define RST_CLR RST=0/*电平置低*/
#define RST_SET RST=1/*电平置高*/
/*双向数据*/
#define IO_CLR SDA=0/*电平置低*/
#define IO_SET SDA=1/*电平置高*/
#define IO_R SDA/*电平读取*/
/*时钟信号*/
#define SCK_CLR SCK=0/*时钟信号*/
#define SCK_SET SCK=1/*电平置高*/
#define ds1302_sec_add 0x80 //秒数据地址
#define ds1302_min_add 0x82 //分数据地址
#define ds1302_hr_add 0x84 //时数据地址
#define ds1302_date_add 0x86 //日数据地址
#define ds1302_month_add 0x88 //月数据地址
#define ds1302_day_add 0x8a //星期数据地址
#define ds1302_year_add 0x8c //年数据地址
#define ds1302_control_add 0x8e //控制数据地址
#define ds1302_charger_add 0x90
#define ds1302_clkburst_add 0xbe
bit flng=0; //anjian标志位
uchar wei[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uchar code tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xbf};// 显示段码值0-9和-
uchar time_buf1[8] = {20,9,3,13,18,51,00,6};//空年月日时分秒周
uchar time_buf[8] ;//空年月日时分秒周
uchar disp[8];
uchar com=0;
void adjust(); //调整后写入函数
void keyscan(); //按键函数
uchar spe_ak(uchar y,uchar x) ; //蜂鸣器函数
void delayus(uchar a) //延迟
{
uchar i,j;
for(i=0;i
for(j=0;j<110;j++);
}
/*向DS1302写入一字节数据*/
void ds1302_write_byte( uchar addr, uchar d) {
unsigned char i;
RST_SET; /*启动DS1302总线*/
/*写入目标地址:addr*/
addr = addr & 0xFE;/*最低位置零*/
for (i = 0; i < 8; i ++) {
if (addr & 0x01) {
IO_SET;
}
else {
IO_CLR;
}
SCK_SET;
SCK_CLR;
addr = addr >> 1;
}
/*写入数据:d*/
for (i = 0; i < 8; i ++) {
if (d & 0x01) {
IO_SET;
}
else {
IO_CLR;
}
SCK_SET;
SCK_CLR;
d = d >> 1;
}
RST_CLR; /*停止DS1302总线*/
}
/*从DS1302读出一字节数据*/
uchar ds1302_read_byte(uchar addr) {
unsigned char i;
unsigned char temp;
RST_SET; /*启动DS1302总线*/
/*写入目标地址:addr*/
addr = addr | 0x01;/*最低位置高*/
for (i = 0; i < 8; i ++) {
if (addr & 0x01) {
IO_SET;
}
else {
IO_CLR;
}
SCK_SET;
SCK_CLR;
addr = addr >> 1;
}
/*输出数据:temp*/
for (i = 0; i < 8; i ++) {
temp = temp >> 1;
if (IO_R) {
temp |= 0x80;
}
else {
temp &= 0x7F;
}
SCK_SET;
SCK_CLR;
}
RST_CLR; /*停止DS1302总线*/
return temp;
}
/*向DS302写入时钟数据*/
void ds1302_write_time(void) {
unsigned char i,tmp;
for(i=0;i<8;i++){ //BCD处理
tmp=time_buf1[i]/10;
time_buf[i]=time_buf1[i]%10;
time_buf[i]=time_buf[i]+tmp*16;
}
ds1302_write_byte(ds1302_control_add,0x00); //关闭写保护
ds1302_write_byte(ds1302_sec_add,0x80); //暂停
//ds1302_write_byte(ds1302_charger_add,0xa9); //涓流充电
ds1302_write_byte(ds1302_year_add,time_buf[1]); //年
ds1302_write_byte(ds1302_month_add,time_buf[2]); //月
ds1302_write_byte(ds1302_date_add,time_buf[3]); //日
ds1302_write_byte(ds1302_day_add,time_buf[7]); //周
ds1302_write_byte(ds1302_hr_add,time_buf[4]); //时
ds1302_write_byte(ds1302_min_add,time_buf[5]); //分
ds1302_write_byte(ds1302_sec_add,time_buf[6]); //秒
ds1302_write_byte(ds1302_day_add,time_buf[7]); //周
ds1302_write_byte(ds1302_control_add,0x80); //打开写保护
}
/*从DS302读出时钟数据*/
void ds1302_read_time()
{
unsigned char i,tmp;
time_buf[1]=ds1302_read_byte(ds1302_year_add); //年
time_buf[2]=ds1302_read_byte(ds1302_month_add); //月
time_buf[3]=ds1302_read_byte(ds1302_date_add); //日
time_buf[4]=ds1302_read_byte(ds1302_hr_add); //时
time_buf[5]=ds1302_read_byte(ds1302_min_add); //分
time_buf[6]=(ds1302_read_byte(ds1302_sec_add))&0x7F;//秒
time_buf[7]=ds1302_read_byte(ds1302_day_add); //周
for(i=0;i<8;i++)
{ //BCD处理
tmp=time_buf[i]/16;
time_buf1[i]=time_buf[i]%16;
time_buf1[i]=time_buf1[i]+tmp*10;
}
}
/*DS302初始化函数*/
void ds1302_init(void) {
RST_CLR; /*RST脚置低*/
SCK_CLR; /*SCK脚置低*/
ds1302_write_byte(ds1302_sec_add,0x00);
}
uchar spe_ak(uchar y,uchar x) //y声音持续时间 ,x 发声的频率
{ uint i;
for(i=0;i
{
delayus(x); //参数决定发声的频率,估算值,可以自行更改参数并
SPK=!SPK;
}
SPK=1; //喇叭停止工作,间歇的时间,可更改
delayus(x);
return 0 ;
}
void display() //显示函数
{
uchar i;
// P1=0x01;
disp[0]=time_buf1[4]/10;
disp[1]=time_buf1[4]%10;
disp[2]=10;
disp[3]=time_buf1[5]/10;
disp[4]=time_buf1[5]%10;
disp[5]=10;
disp[6]=time_buf1[6]/10;
disp[7]=time_buf1[6]%10;
for(i=0;i<8;i++)
{
P1=wei[i];
P2=tab[disp[i]];
delayus(5);
}
delayus(1);
}
void timer0() interrupt 1 //定时器0
{
TH0=(65635-50000)/256;
TL0=(65635-50000)%256;
if(key1==0)
{
delayus(20);
if(key1==0)
{ TR0=0;
spe_ak(250,1);
flng=1;
com++;
if(com==3)
com=0;
}
while(!key1) ; //等待 按起
TR0=1;
}
}
void keyscan() //按键函数
{
switch(com)
{
case 0: { // adjust();
flng=0;
}
break;
case 1:{
ds1302_write_byte(ds1302_sec_add,0x80); //暂停
if(key2==0)
{ delayus(20);
if(key2==0)
{ spe_ak(250,1);
time_buf[5]=(++time_buf1[5])%60; //加分
if(time_buf1[5]==60)
{ time_buf1[5]=0; }
}
while(!key2); //等待 按起
}
if(key3==0)
{ delayus(20);
if(key3==0)
{ spe_ak(250,1);
time_buf1[5]=(--time_buf1[5])%60; //减分
if(time_buf1[5]==0)
{ time_buf1[5]=59; }
}
while(!key3); //等待 按起
}
ds1302_write_byte(ds1302_sec_add,0x00); //结束暂停
}
break;
case 2:{ ds1302_write_byte(ds1302_sec_add,0x80); //暂停
if(key2==0)
{ delayus(20);
if(key2==0)
{ spe_ak(250,1);
time_buf1[4]=(++time_buf1[4])%24; //加时
if(time_buf1[4]==23)
{ time_buf1[4]=0; }
}
while(!key2); //等待 按起
}
if(key3==0)
{ delayus(20);
if(key3==0)
{ spe_ak(250,1);
time_buf[4]=(--time_buf1[4])%24; //减时
if(time_buf1[4]==0)
{ time_buf1[4]=23; }
}
while(!key3); //等待 按起
}
ds1302_write_byte(ds1302_sec_add,0x00); //结束暂停
}
break;
}
adjust();
}
void adjust()//时钟调节
{
ds1302_write_byte(ds1302_control_add,0x00); //关闭写保护
ds1302_write_byte(ds1302_hr_add,(time_buf1[4]/10<<4)|(time_buf1[4]%10)); //时
ds1302_write_byte(ds1302_min_add,(time_buf1[5]/10<<4)|(time_buf1[5]%10)); //分
ds1302_write_byte(ds1302_control_add,0x80); //打开写保护
}
void timer_init() //定时器初始化
{
IE=0X82;
TMOD=0X01;
TH0=(65635-50000)/256;
TL0=(65635-50000)%256;
TR0=1;
}
main()
{
P0=0XFF;
spe_ak(250,1);
timer_init();//定时器初始化
ds1302_init();
ds1302_write_time();
while(1)
{ if(flng==1)
{
keyscan();
delayus(2);
ds1302_read_time();
display();
}
else
{ ds1302_read_time();
delayus(2);
display(); }
}
}
说明:只显示时、分、秒,其他(年,月...)的已读出,自己修改,
仿真已通过
|
|