打印

大家帮忙看看程序分析一下问题

[复制链接]
1221|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
天下统帅|  楼主 | 2013-9-3 14:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这程序感觉哪都不正常
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(); //闹钟

}
}

相关帖子

沙发
南宫云明| | 2013-9-3 14:12 | 只看该作者
既然这么多不正常,你就一个功能一个功能去调试嘛,代码越多越容易出错。先搞定一个,再在这基础上加代码。。

这么多代码,谁有那么多时间去看你的代码。

使用特权

评论回复
板凳
dirtwillfly| | 2013-9-3 14:30 | 只看该作者
大家都很忙的

使用特权

评论回复
地板
小蚊子专属| | 2013-9-3 14:54 | 只看该作者
代码多多

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

8

帖子

0

粉丝