这程序感觉哪都不正常
1、1302时钟芯片不能断电保存
2、整点报时函数开启蜂鸣器像个不停
3、设置年月日显示总是不正常
4、闹钟函数也不正常
本人新手,基本上啥也不大懂,请高手看一下,打算加上时钟芯片实现断电保存,这是从原来写的时钟程序改的,弄了两天了,焦头烂额的也理不出个头绪。
不胜感激!!!
源程序如下(闹钟函数已屏蔽)
#include<reg52.h> //包含单片机寄存器的头文件
#include<intrins.h> //包含_nop_()函数定义的头文件
#define uint unsigned int
#define uchar unsigned char
//DS1302相关的变量和引脚定义 //WriteSet1302(0x82,((0/10)<<4|(0%10)));
sbit DATA=P2^5; //位定义1302芯片的接口,数据输出端定义在P2.5引脚
sbit RST=P2^0; //位定义1302芯片的接口,复位端口定义在P2.0引脚
sbit SCLK=P2^1; //位定义1302芯片的接口,时钟输出端口定义在P2.1引脚
sbit DS=P2^2;//18B20
sbit fm=P2^3; //蜂鸣器
sbit dula=P2^6; //寄存器选择位,将RS位定义为P2.0引脚
sbit wela=P2^7; //读写选择位,将RW位定义为P2.1引脚
sbit s1=P3^4; //s1按键,设置调时
sbit s2=P3^5; //s2按键,加1
sbit s3=P3^6; //s3按键,减1
sbit s4=P3^7; //s4按键,切换显示
sbit led1=P1^0;
sbit led2=P1^1;
sbit led3=P1^2;
//sbit led4=P1^3;
sbit led5=P1^4;
sbit led6=P1^5;
sbit led7=P1^6;
//sbit led8=P1^7;
//uchar sec_1,minu_1,hour_1,day_1,year_1,mon_1;
uchar sec,minu,hour,day,year,mon;
uchar n_minu,n_hour;
uchar set_1=1,set_4=1;
uchar hs,hg,mis,mig,ss,sg;
uchar ys,yg,ms,mg,ds,dg;
uchar nhs,nhg,nmis,nmig;
uchar a1,a2,a3,a4,a5,a6;
//uint temp;
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0};//0-9,-,共阴
uchar code table_d[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,
0x87,0xff,0xef}; //0~9数组,带小数点
uchar table1[]={31,31,29,31,30,31,30,31,31,30,31,30,31}; //闰年
uchar table2[]={31,31,28,31,30,31,30,31,31,30,31,30,31}; //非闰年
void delay(uint); //延时函数
//void timer0(); //走时中断函数
//void jishi(); //计时函数
void key_change(); //切换显示按键函数
void key_set(); //设置时间按键函数
//void disp_1(uchar,uchar,uchar,uchar,uchar,uchar); //显示shijian函数
void disp(uchar,uchar,uchar,uchar,uchar,uchar); //显示函数
void zd_clock(); //整点报时函数
void nz_clock(); //闹钟函数
uchar incone(uchar); //加1函数
uchar decone(uchar); //减1函数
void set_time(); //设置时间函数
void set_clock(); //设置闹钟函数
void set_ymd(); //设置月日星期函数
void display(uint);
/*****************************************************
函数功能:延时若干微秒
入口参数:n
***************************************************/
void delaynus(unsigned char n)
{
unsigned char i;
for(i=0;i<n;i++);
}
/*****************************************************
函数功能:向1302写一个字节数据
入口参数:x
***************************************************/
void Write1302(unsigned char dat)
{
unsigned char i;
SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备
delaynus(2); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续写8个二进制位数据
{
DATA=dat&0x01; //取出dat的第0位数据写入1302
delaynus(2); //稍微等待,使硬件做好准备
SCLK=1; //上升沿写入数据
delaynus(2); //稍微等待,使硬件做好准备
SCLK=0; //重新拉低SCLK,形成脉冲
dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位
}
}
/*****************************************************
函数功能:根据命令字,向1302写一个字节数据
入口参数:Cmd,储存命令字;dat,储存待写的数据
***************************************************/
void WriteSet1302(unsigned char Cmd,unsigned char dat)
{
RST=0; //禁止数据传递
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输
delaynus(2); //稍微等待,使硬件做好准备
Write1302(Cmd); //写入命令字
Write1302(dat); //写数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //禁止数据传递
}
/*****************************************************
函数功能:从1302读一个字节数据
入口参数:x
***************************************************/
unsigned char Read1302(void)
{
unsigned char i,dat;
delaynus(2); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续读8个二进制位数据
{
dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位
if(DATA==1) //如果读出的数据是1
dat|=0x80; //将1取出,写在dat的最高位
SCLK=1; //将SCLK置于高电平,为下降沿读出
delaynus(2); //稍微等待
SCLK=0; //拉低SCLK,形成脉冲下降沿
delaynus(2); //稍微等待
}
return dat; //将读出的数据返回
}
/*****************************************************
函数功能:根据命令字,从1302读取一个字节数据
入口参数:Cmd
***************************************************/
unsigned char ReadSet1302(unsigned char Cmd)
{
unsigned char dat;
RST=0; //拉低RST
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输
Write1302(Cmd); //写入命令字
dat=Read1302(); //读出数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //禁止数据传递
return dat; //将读出的数据返回
}
/*****************************************************
函数功能: 1302进行初始化设置
***************************************************/
void Init_DS1302(void)
{
WriteSet1302(0x90,0x00); //充电禁止
WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令
WriteSet1302(0x80,((59/10)<<4|(59%10))); //根据写秒寄存器命令字,写入秒的初始值
WriteSet1302(0x82,((59/10)<<4|(59%10))); //根据写分寄存器命令字,写入分的初始值
WriteSet1302(0x84,((23/10)<<4|(23%10))); //根据写小时寄存器命令字,写入小时的初始值(24h)
WriteSet1302(0x86,((2/10)<<4|(2%10))); //根据写日寄存器命令字,写入日的初始值
WriteSet1302(0x88,((9/10)<<4|(9%10))); //根据写月寄存器命令字,写入月的初始值
WriteSet1302(0x8c,((13/10)<<4|(13%10))); //根据写年寄存器命令字,写入年的初始值
WriteSet1302(0x8E,0x80); //寄存器写禁止
}
/*********************************************************
延时函数
*********************************************************/
void delay(uint k) //延时函数
{
uint i,j;
for(i=k;i>0;i--)
for(j=110;j>0;j--);
}
/************************************************************
按键函数
*************************************************************/
void key_change() //s4按键扫描
{
if(s4==0)
{
delay(50);
if(s4==0)
{
set_4++;
while(!s4);
delay(50);
while(!s4);
if(set_4==7)
{set_4=1;}
}
}
}
void key_set() //s1按键扫描
{
if(s1==0)
{
delay(50);
if(s1==0)
{
set_1++;
while(!s1);
delay(50);
while(!s1);
if(set_1==4)
{set_1=1;}
}
}
}
/********************************************************
整点报时,闹钟函数
********************************************************/
/*void zd_clock() //整点报时函数
{
if((minu==0)&&(sec==0))
{
fm=0;
}
else
fm=1;
}*/
void nz_clock() //闹钟函数
{
if((hour==n_hour)&&(minu==n_minu))
if((sec%2==0)&&(sec<31))
{
fm=0;
//if(s1==0||s2==0||s3==0||s4==0)
//{fm=1;}
}
}
/********************************************
按键设置函数
********************************************/
void set_time() //设置时间函数
{
if(set_4==2)
{
if(set_1==1)
{
{
if(sec%2==0)
{led1=~led1;}
else
{led1=1;}
led2=1;led3=1;led5=1;led6=1;led7=1;
}
hour=incone(hour);
if(hour==24)
{hour=0;}
if(hour==-1)
{hour=23;}
hour=decone(hour);
WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令
WriteSet1302(0x84,((hour/10)<<4|(hour%10))); //根据写小时寄存器命令字,写入调整后的小时(24h)
WriteSet1302(0x8E,0x80); //寄存器写禁止
}
if(set_1==2)
{
{
if(sec%2==0)
{led5=~led5;}
else
{led5=1;}
led2=1;led3=1;led1=1;led6=1;led7=1;
}
minu=incone(minu);
if(minu==60)
{minu=0;}
if(minu==-1)
{minu=59;}
// if(minu<0)
// {minu=59;}
minu=decone(minu);
WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令
WriteSet1302(0x82,((minu/10)<<4|(minu%10))); //根据写分寄存器命令字,写入调整后的分
WriteSet1302(0x8E,0x80); //寄存器写禁止
}
if(set_1==3)//秒清零操作
{
{
if(sec%2==0)
{
led1=~led1;
led5=~led5;
}
else
{
led1=1;
led5=1;
}
led2=1;led3=1;led6=1;led7=1;
}
sec=0;
WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令
WriteSet1302(0x80,((sec/10)<<4|(sec%10))); //根据写秒寄存器命令字,写入调整后的秒
WriteSet1302(0x8E,0x80); //寄存器写禁止
}
}
}
void set_ymd() //设置年月日函数
{
if(set_4==4)
{
if(set_1==1)//设置年份
{
{
if(sec%2==0)
{led2=~led2;}
else
{led2=1;}
led1=1;led3=1;led5=1;led6=1;led7=1;
}
year=incone(year);
year=decone(year);
WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令
WriteSet1302(0x8c,((year/10)<<4|(year%10))); //根据写年寄存器命令字,写入调整后的年
WriteSet1302(0x8E,0x80); //寄存器写禁止
}
if(set_1==2)//设置月份
{
{
if(sec%2==0)
{led6=~led6;}
else
{led6=1;}
led1=1;led3=1;led5=1;led2=1;led7=1;
}
mon=incone(mon);
if(mon==13)
{mon=1;}
mon=decone(mon);
if(mon==0)
{mon=12;}
WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令
WriteSet1302(0x88,((mon/10)<<4|(mon%10))); //根据写月寄存器命令字,写入调整后的月
WriteSet1302(0x8E,0x80); //寄存器写禁止
}
if(set_1==3)//设置日
{
{
if(sec%2==0)
{led6=~led6;
led2=~led2;}
else
{led6=1;led2=1;}
led3=1;led5=1;led1=1;led7=1;
}
day=incone(day);
if(day==32)
{day=1;}
if(day==0)
{day=31;}
day=decone(day);
WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令
WriteSet1302(0x86,((day/10)<<4|(day%10))); //根据写日寄存器命令字,写入调整后的日
WriteSet1302(0x8E,0x80); //寄存器写禁止
}
/*if(set_2==3)
{
week=incone(week);
if(week==8)
{week=0;}
week=decone(week);*/
// if(week==0)
// {week=7;}
}
}
void set_clock() //设置闹钟函数
{
if(set_4==6)
{
if(set_1==1)
{
{
if(sec%2==0)
{led3=~led3;}
else
{led3=1;}
led2=1;led1=1;led5=1;led6=1;led7=1;
}
n_hour=incone(n_hour);
if(n_hour==24)
{n_hour=0;}
if(n_hour==-1)
{n_hour=23;}
n_hour=decone(n_hour);
}
if(set_1==2)
{
{
if(sec%2==0)
{led7=~led7;}
else
{led7=1;}
led2=1;led3=1;led5=1;led6=1;led1=1;
}
n_minu=incone(n_minu);
if(n_minu==60)
{n_minu=0;}
if(n_minu==-1)
{n_minu=59;}
n_minu=decone(n_minu);
}
}
}
uchar incone(uchar aa) //加1函数
{
if(s2==0)
{
delay(50);
if(s2==0)
{
aa++;
while(!s2);
}
}
return(aa);
}
uchar decone(uchar m) //减1函数
{
if(s3==0)
{
delay(50);
if(s3==0)
{
m--;
while(!s3);
if(m<0)
{m=0;}
}
}
return(m);
}
/********************************************************
显示函数
********************************************************/
void disp(uchar a1,uchar a2,uchar a3,uchar a4,uchar a5,uchar a6) //显示函数
{
dula=0;
P0=table[a1]; //段码送P0口
dula=1; //选定段选
dula=0; //关段选
wela=0;
P0=0xfe; //位选(第1个数码管)送P0
wela=1; //选定位选
wela=0; //关位选
delay(1); //延时一小会
P0=table[a2]; //第2个数码管显示
dula=1;
dula=0;
wela=0;
P0=0xfd;
wela=1;
wela=0;
delay(1);
P0=table[a3]; //第3个数码管显示
dula=1;
dula=0;
wela=0;
P0=0xfb;
wela=1;
wela=0;
delay(1);
P0=table[a4]; //第4个数码管显示
dula=1;
dula=0;
P0=0xf7;
wela=1;
wela=0;
delay(1);
dula=0; //第5个数码管显示
P0=table[a5];
dula=1;
dula=0;
wela=0;
P0=0xef;
wela=1;
wela=0;
delay(1);
P0=table[a6]; //第6个数码管显示
dula=1;
dula=0;
P0=0xdf;
wela=1;
wela=0;
delay(1);
}
/*****************************************************
函数功能:主函数
***************************************************/
void main(void)
{
unsigned char sec,minu,hour,day,mon,year; //分别储存苗、分、小时,日,月,年
unsigned char ReadValue; //储存从1302读取的数据
Init_DS1302(); //将1302初始化
n_hour=12;
n_minu=12;
while(1)
{
ReadValue = ReadSet1302(0x81); //从秒寄存器读数据
sec=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//将读出数据转化
ss=sec/10;
sg=sec%10;
ReadValue = ReadSet1302(0x83); //从分寄存器读
minu=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化
mis=minu/10;
mig=minu%10;
ReadValue = ReadSet1302(0x85); //从时寄存器读
hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化
hs=hour/10;
hg=hour%10;
ReadValue = ReadSet1302(0x87); //从天寄存器读
day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化
ds=day/10;
dg=day%10;
ReadValue = ReadSet1302(0x89); //从月寄存器读
mon=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化
ms=mon/10; //月日-星期MM.DD.
mg=mon%10;
ReadValue = ReadSet1302(0x8d); //从年寄存器读
year=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化
ys=year/10; //月日-星期MM.DD.
yg=year%10;
nhs=n_hour/10; //闹钟定时HH.MM.SS
nhg=n_hour%10;
nmis=n_minu/10;
nmig=n_minu%10;
// nss=n_sec/10;
// nsg=n_sec%10;
key_change(); //s4按键扫描
key_set(); //s1按键扫描
set_time(); //设置时间
set_ymd(); //设置月日星期
set_clock(); //设置闹钟
if(set_4==1) //正常走时显示
{
a1=hs;
a2=hg;
a3=mis;
a4=mig;
a5=ss;
a6=sg;
P1=0xff;
disp(hs,hg,mis,mig,ss,sg);
}
if(set_4==2) //设置时间,LED1闪亮
{
disp(hs,hg,mis,mig,ss,sg);
if(sec%2==0)
{led1=~led1;}
else
{led1=1;}
}
if(set_4==3) //正常显示年月日
{
P1=0xff;
disp(ys,yg,ms,mg,ds,dg);
}
if(set_4==4) //设置年月日,LED2闪亮
{
disp(ys,yg,ms,mg,ds,dg);
if(sec%2==0)
{led2=~led2;}
else
{led2=1;}
}
if(set_4==5) //正常显示定时
{
P1=0xff;
disp(nhs,nhg,nmis,nmig,10,10);
}
if(set_4==6) //设置闹钟定时,LED3闪亮
{
disp(nhs,nhg,nmis,nmig,10,10);
if(sec%2==0)
{led3=~led3;}
else
{led3=1;}
}
//zd_clock(); //整点报时
nz_clock(); //闹钟
}
} |
|