打印
[技术问答]

这DS1302可调时钟程序能实现吗,别的帖子复制过来的,为什么我不行

[复制链接]
1025|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
caibao3311|  楼主 | 2016-5-30 22:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit spk=P1^7;
sbit led=P1^5;
sbit DQ=P1^0;
sbit RS=P2^4;
sbit RW=P2^5;
sbit EN=P2^6;
sbit key1=P2^0;
sbit key2=P2^1;
sbit key3=P2^2;
sbit key4=P2^3;
sbit IO=P3^6;
sbit RST=P3^7;
sbit SCLK=P3^5;
uchar code table[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
int nian,xing,yue,ri,shi,fen,miao;
uchar num,temp,c,d,time[7],a,b,aa,bb,ns,ng,ys,yg,rs,rg,ss,sg,fs,fg,ms,mg,flag;

/*******************1602************************/

void delay(int z)
{
int x,y;
for(x=z;x>0;x--)
  for(y=100;y>0;y--);
}

void write_com(uchar com)   //写命令
{
RS=0;
P0=com;
delay(5);
EN=1;
delay(5);
EN=0;
}

void write_data(uchar date)      //写数据
{
RS=1;
P0=date;
delay(5);
EN=1;
delay(5);
EN=0;
}
void init()          //初始化
{
RW=0;
EN=0;
write_com(0x38);    //显示模式设置
write_com(0x0c);    //开显示 不显示光标 不闪
write_com(0x06); //写一个字符 地址指针 光标 加一 整屏不移动
write_com(0x01);    //显示清零

write_com(0x80+0x04);
write_data('2');     
write_com(0x80+0x05);
write_data('0');     
write_com(0x80+0x00);
write_data('c');     
write_com(0x80+0x01);
write_data('a');
write_com(0x80+0x02);
write_data('i');      
write_com(0x80+0x4e);
write_data(0xdf);   
write_com(0x80+0x4f);
write_data('C');     
write_com(0x80+0x4b);
write_data(0x2e);       //显示"。"
}

/**************DS18B20****************/

void delay1(unsigned int t) //延时函数
{
while(t--);
}

void init1()  //初始化
{
uchar n=0;
DQ=1;      //DQ复位
delay1(8);  
DQ=0;      //主机将DQ拉低
delay1(80);     //大于480us的延时
DQ=1;
delay1(5);    //延时15~60us
n=DQ;
delay1(5);   //若n=0初始成功 n=1初始失败(可设置返回值查看n是否为1)
}

void write_byte(uchar dat)    //写入一个字节
{
uint i;
for(i=0;i<8;i++)
{
  DQ=0;
  DQ=dat&0x01;
  delay1(12);
  DQ=1;
  dat>>=1;
}
delay1(4);
}

uchar read_byte()    //读入一个字节
{
uint k=0;
uchar value=0;
for(k=0;k<8;k++)
{
  DQ=0;
  value>>=1;
  DQ=1;
  if(DQ)
  value|=0x80;
  delay1(4);
}
return value;
}

uchar read_temp()    //读取温度函数
{
uchar a=0,b=0;
init1();
write_byte(0xcc);
write_byte(0x44);
delay1(200);

init1();
write_byte(0xcc);
write_byte(0xbe);
a=read_byte();  
b=read_byte();
c=b;
d=a;
b<<=4;
b+=(a&0xf0)>>4;
return b;
}

/***********************1302**********************/

void wirte_byte1(uchar date)    //写入一个字节
{
uchar i;
for(i=8;i>0;i--)
{
  IO=date&0x01;
  SCLK=0;
  SCLK=1;
  date=date>>1;
   }
}

uchar read_byte1()       //读一个字节
{
uchar dat,i;
for(i=8;i>0;i--)
{
  dat=dat>>1;
  SCLK=0;
  if(IO)
  dat=dat|0x80;
  SCLK=1;
}
return(dat);
}

void write_ds1302(uchar add,uchar date)     //将数据写入1302中
{
RST=0;
SCLK=0;
RST=1;
wirte_byte1(add);
wirte_byte1(date);
RST=0;
SCLK=1;
}

uchar read_ds1302(uchar add)  //读出1302中数据
{
uchar temp;
RST=0;
SCLK=0;
RST=1;
wirte_byte1(add);
temp=read_byte1();
RST=0;
SCLK=0;
return (temp);
}

uchar huan_BCD(uint z)   //将数据 转换成BCD
{
uint a,b;
  a=z/10;
  b=z%10;
  a=a&0xff;
  b=b&0xff;
  a<<=4;
  a=a|b;
return (a);
}

void xian_shi()       //液晶显示函数
{
if(b==0&a==0)
{
  ms=time[0]/16;
  mg=time[0]%16;

  fs=time[1]/16;
  fg=time[1]%16;
  fen=fs*10+fg;

  ss=time[2]/16;
  sg=time[2]%16;
  shi=ss*10+sg;

  rs=time[3]/16;
  rg=time[3]%16;
  ri=rs*10+rg;

  ys=time[4]/16;
  yg=time[4]%16;
  yue=ys*10+yg;

  ns=time[6]/16;
  ng=time[6]%16;
  nian=ns*10+ng;

  xing=time[5];
}
if(a==1|b==1)
{
  ss=shi/10;
  sg=shi%10;

  write_com(0x80+0x41);
  write_data(0xff);

  write_com(0x80+0x40);   
  write_data(table[ss]);
  write_com(0x80+0x41);   
  write_data(table[sg]);

}
if(a==2|b==2)
    {
  fs=fen/10;
  fg=fen%10;

  write_com(0x80+0x44);
  write_data(0xff);

  write_com(0x80+0x43);   
  write_data(table[fs]);
  write_com(0x80+0x44);   
  write_data(table[fg]);
}

if(a==3)
    {
  rs=ri/10;
  rg=ri%10;

  write_com(0x80+0x0d);
  write_data(0xff);

  write_com(0x80+0x0c);   
  write_data(table[rs]);
  write_com(0x80+0x0d);   
  write_data(table[rg]);
}
if(a==4)
    {
  ys=yue/10;
  yg=yue%10;

  write_com(0x80+0x0a);
  write_data(0xff);

  write_com(0x80+0x09);   
  write_data(table[ys]);
  write_com(0x80+0x0a);   
  write_data(table[yg]);
}
if(a==5)
    {
  ns=nian/10;
  ng=nian%10;

  write_com(0x80+0x07);
  write_data(0xff);

  write_com(0x80+0x06);   
  write_data(table[ns]);
  write_com(0x80+0x07);   
  write_data(table[ng]);
}
if(a==6)
    {
  write_com(0x80+0x0f);
  write_data(0xff);
  write_com(0x80+0x0f);   
  write_data(table[xing]);
}
  write_com(0x80+0x06); //在液晶第一行第七八位显示  年   
  write_data(table[ns]);
  write_com(0x80+0x07);   
  write_data(table[ng]);

  write_com(0x80+0x08);   
  write_data('-');

  write_com(0x80+0x09); //在液晶第一行第十十一位显示  月   
  write_data(table[ys]);
  write_com(0x80+0x0a);   
  write_data(table[yg]);

  write_com(0x80+0x0b);   
  write_data('-');

  write_com(0x80+0x0c); //在液晶第一行第十三 十四位显示  日   
  write_data(table[rs]);
  write_com(0x80+0x0d);   
  write_data(table[rg]);

  write_com(0x80+0x0f);   //在液晶第一行第十七位显示  星期
  write_data(table[xing]);

  write_com(0x80+0x40);   //在液晶第二行第二三位显示    时
  write_data(table[ss]);
  write_com(0x80+0x41);   
  write_data(table[sg]);

  write_com(0x80+0x42);   
  write_data(':');

  write_com(0x80+0x43);   //在液晶第二行第五六位显示  分
  write_data(table[fs]);
  write_com(0x80+0x44);   
  write_data(table[fg]);

  write_com(0x80+0x45);   
  write_data(':');

  write_com(0x80+0x46);   //在液晶第二行第**位显示  秒
  write_data(table[ms]);
  write_com(0x80+0x47);   
  write_data(table[mg]);
}

void keyscan()    //按键设置函数  可任意设置年月日时分秒星期的数值
{
if(key4!=0)
{
  if(key1==0)   //key1按键 选择需设置的位
  {
   if(key1==0)
   {
    a++;
    delay(1);
   }
         while(!key1)
   {      
    delay(1);
   }      
  }

  if(a!=0)
  {
   if(key2==0)    //key2按键 可将需设置的数 调大
   {
    if(a==1)
    {
     shi++;
     if(shi>=24)
     {
      shi=0;
     }
    }
    if(a==2)
    {
     fen++;
     if(fen>=60)
     {
      fen=0;
     }
    }
    if(a==3)
    {
     ri++;
     if(ri>=32)
     {
      ri=1;
     }
    }
    if(a==4)
    {
     yue++;
     if(yue>=12)
     {
      yue=1;
     }
    }
    if(a==5)
    {
     nian++;
     if(nian>=99)
     {
      nian=0;
     }
    }
    if(a==6)
    {
     xing++;
     if(xing>=8)
     {
      xing=1;
     }
    }
   }
   if(key3==0)    //key3按键 可将需设置的数 调小
   {
   
    if(a==1)
    {
     shi--;
     if(shi<0)
     {
      shi=23;
     }
    }
    if(a==2)
    {
     fen--;
     if(fen<0)
     {
      fen=59;
     }
    }
    if(a==3)
    {
     ri--;
     if(ri<1)
     {
      ri=31;
     }
    }
    if(a==4)
    {
     yue--;
     if(yue<1)
     {
      yue=12;
     }
    }
    if(a==5)
    {
     nian--;
     if(nian<0)
     {
      nian=99;
     }
    }
    if(a==6)
    {
     xing--;
     if(xing<1)
     {
      xing=7;
     }
    }
   }
   if(a==7)       //当按下key1 7次后  将个数据写入1302
   {
    a=0;
    write_ds1302(0x8e,0x00);   //WP=0 写操作
    write_ds1302(0x80,0x00);   //0x80是写秒数据
    write_ds1302(0x82,huan_BCD(fen)); //0x82是写分数据
    write_ds1302(0x84,huan_BCD(shi)); //0x84是写时数据
    write_ds1302(0x86,huan_BCD(ri)); //0x84是写日数据
    write_ds1302(0x88,huan_BCD(yue)); //0x84是写月数据
    write_ds1302(0x8a,huan_BCD(xing)); //0x84是写星期数据
    write_ds1302(0x8c,huan_BCD(nian)); //0x84是写年数据
    write_ds1302(0x8e,0x80);   //WP=1 写保护   
   }
  }
}
}

void naozhong()      //通过按键设置闹钟  时 分
{
if(key1!=0)
{
  if(key4==0)
  {
   if(key4==0)
   {
    b++;
    delay(1);
   }
         while(!key4)
   {      
    delay(1);
   }
  }
  if(b!=0)
  {
   if(key2==0)    //key2按键 可将需设置的数 调大
   {
    if(b==1)
    {
     shi++;
     if(shi>=24)
     {
      shi=0;
     }
    }
    if(b==2)
    {
     fen++;
     if(fen>=60)
     {
      fen=0;
     }
    }
   }
   if(key3==0)    //key3按键 可将需设置的数 调小
   {
    if(b==1)
    {
     shi--;
     if(shi<0)
     {
      shi=23;
     }
    }
    if(b==2)
    {
     fen--;
     if(fen<0)
     {
      fen=59;
     }
    }
   }
   aa=huan_BCD(shi);   //将设置的时钟 赋值给aa
   bb=huan_BCD(fen); //将设置的分钟 赋值给bb
   if(b==3)       //当按下key4 3次后 闹钟设置完成
   {
    b=0;
   }
  }
}
}

void main()
{
uint i,temp;
init();
TMOD=0x10;
EA=1;
TH1=(65536-51200)/256;
TL1=(65536-51200)%256;
ET1=1;
while(1)
{
  temp=0x81;          //读的初始地址                  
        for(i=0;i<7;i++)             //分别把秒分时日月年星期数据读出分7次读好一次地址加2" temp+=2;"
      {
         time[i]=read_ds1302(temp);
      temp+=2;
        }
  if(bb==time[1]&aa==time[2]&!time[0])  //如果读出来的时钟 分钟与1302读出来的值相等且读出来的秒钟为零时 进入中断
  {
   TR1=1;
   flag=1;   //标志位设置为1
  }
  if(key3==0)   //进入闹钟后 可由key3按下 停止中断 标志位置零 允许调时闹钟设置按键动作 停止闹铃
  {
   led=1;
   spk=1;
   flag=0;
   TR1=0;
  }
        if(flag!=1)   //当进入闹钟中断后 调时与设置闹钟的按键  无效
     {
         naozhong();
   keyscan();
  }
  xian_shi();
  temp=read_temp();
  write_com(0x80+0x49);   
  write_data(table[temp/10]);    //在液晶第二行第十位显示温度的十位
  write_com(0x80+0x4a);  
  write_data(table[temp%10]);    //在液晶第二行第十一位显示温度的个位
  write_com(0x80+0x4c);   
  write_data(table[(d&0x0f)*625/1000]);   //在液晶第二行第十三位显示温度的小数点后一位
  write_com(0x80+0x4d);   
  write_data(table[(d&0x0f)*625/100%10]);   //在液晶第二行第十四位显示温度的小数点后二位
}
}


void timer1() interrupt 3     //定时器
{
uint t;
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
t++;
spk=0;      //蜂鸣器  发出 滴答 声
led=!led;      //发光二极管  不停闪烁
delay1(10);
if(t==1120)    //约1分钟后 闹钟自动停止 标志位
{
  led=1;
  spk=1;
  t=0;
  TR1=0;
  flag=0;
}

}
沙发
玛尼玛尼哄| | 2016-5-31 10:47 | 只看该作者
这么长怎么看,你 要先搭建好你的电路,显示电路先测试是否正常,不要全部照搬,只把DS1302的搞进去就行了。

使用特权

评论回复
板凳
734774645| | 2016-5-31 12:57 | 只看该作者
STCMCU-DS1302.rar (48.93 KB)



这个是百分百可以在51内核运行的,官方出品。

使用特权

评论回复
地板
734774645| | 2016-5-31 12:58 | 只看该作者
/**************************************
从DS1302读1字节数据
**************************************/
BYTE DS1302_ReadByte()
{
    BYTE i;
    BYTE dat = 0;

    for (i=0; i<8; i++)             //8位计数器
    {
        SCLK = 0;                   //时钟线拉低
        _nop_();                    //延时等待
        _nop_();
        dat >>= 1;                  //数据右移一位
        if (IO) dat |= 0x80;        //读取数据
        SCLK = 1;                   //时钟线拉高
        _nop_();                    //?óê±μè′y
        _nop_();
    }

    return dat;
}


使用特权

评论回复
5
734774645| | 2016-5-31 12:58 | 只看该作者
/**************************************
向DS1302写1字节数据
**************************************/
void DS1302_WriteByte(BYTE dat)
{
    char i;

    for (i=0; i<8; i++)             //8位计数器
    {
        SCLK = 0;                   //时钟线拉低
        _nop_();                    //延时等待
        _nop_();
        dat >>= 1;                  //移出数据
        IO = CY;                    //送出到端口
        SCLK = 1;                   //时钟线拉高
        _nop_();                    //延时等待
        _nop_();
    }
}


使用特权

评论回复
6
734774645| | 2016-5-31 12:59 | 只看该作者



/**************************************
读DS1302某地址的的数据
**************************************/
BYTE DS1302_ReadData(BYTE addr)
{
    BYTE dat;

    RST = 0;
    _nop_();                        //延时等待
    _nop_();
    SCLK = 0;
    _nop_();                        //延时等待
    _nop_();
    RST = 1;
    _nop_();                        //延时等待
    _nop_();
    DS1302_WriteByte(addr);         //写地址
    dat = DS1302_ReadByte();        //读数据
    SCLK = 1;
    RST = 0;

    return dat;
}

/**************************************
往DS1302的某个地址写入数据
**************************************/
void DS1302_WriteData(BYTE addr, BYTE dat)
{
    RST = 0;
    _nop_();                        //延时等待
    _nop_();
    SCLK = 0;
    _nop_();                        //延时等待
    _nop_();
    RST = 1;
    _nop_();                        //延时等待
    _nop_();
    DS1302_WriteByte(addr);         //写地址
    DS1302_WriteByte(dat);          //写数据
    SCLK = 1;
    RST = 0;
}


使用特权

评论回复
7
734774645| | 2016-5-31 13:00 | 只看该作者
/**************************************
写入初始时间
**************************************/
void DS1302_SetTime(BYTE *p)
{
    BYTE addr = 0x80;
    BYTE n = 7;

    DS1302_WriteData(0x8e, 0x00);   //允许写操作
    while (n--)
    {
        DS1302_WriteData(addr, *p++);
        addr += 2;
    }
    DS1302_WriteData(0x8e, 0x80);   //写保护
}


/**************************************
读取当前时间
**************************************/
void DS1302_GetTime(BYTE *p)
{
    BYTE addr = 0x81;
    BYTE n = 7;

    while (n--)
    {
        *p++ = DS1302_ReadData(addr);
        addr += 2;
    }
}


使用特权

评论回复
8
734774645| | 2016-5-31 13:06 | 只看该作者
/**************************************
初始化DS1302
**************************************/
void DS1302_Initial()
{
    RST = 0;
    SCLK = 0;
    DS1302_WriteData(0x8e, 0x00);   //允许写操作
    DS1302_WriteData(0x80, 0x00);   //时钟启动
    DS1302_WriteData(0x90, 0xa6);   //一个二极管+4K电阻充电
    DS1302_WriteData(0x8e, 0x80);   //写保护
}


使用特权

评论回复
9
zhuomuniao110| | 2016-5-31 20:39 | 只看该作者
参考上面那位朋友发的代码,非常好用。

使用特权

评论回复
10
mmuuss586| | 2016-5-31 22:17 | 只看该作者
可以用示波器看看时序是否正确;
时序对的话,也有可能芯片问题

使用特权

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

本版积分规则

4

主题

8

帖子

0

粉丝