找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3322|回复: 4
打印 上一主题 下一主题
收起左侧

DS1302编写万年历出现了问题求解答

[复制链接]
跳转到指定楼层
楼主
ID:76675 发表于 2015-7-14 20:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 安乐晨 于 2015-7-15 09:17 编辑

#include"stc12c5a.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
uchar lcddate;
uchar dis_time_buf[16]={0};
uchar time_buf[8]={0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x02};
sbit        lcdrs=P3^5;
sbit        lcden=P3^4;
sbit        lcdrw=P3^6;
sbit         RES=P4^5;
sbit         IO=P2^7;
sbit         SCK=P4^0;
#define ds_second_add                0x80
#define ds_minute_add                0x82
#define ds_hour_add                    0x84
#define ds_day_add                        0x86
#define ds_month_add                0x88
#define ds_week_add                        0x8a
#define ds_year_add                        0x8c
#define ds_control_add                0x8e
#define ds_charger_add                0x90
#define ds_clkburst_add                0xbe
void delayms(uint x)
//晶振为12M时,j<112;当晶振为11.0592M时,j<122                        
{
  uint i,j;
  for(i=0;i<x;i++)
    for(j=0;j<122;j++);
}
void delayus(uint t)
//微秒延时                                          
{
  for(;t>0;t--)
   {
         _nop_();
   }
}
void write_com(uchar com)                                  //给液晶指令
{
        lcdrs=0;
        P0=com;
        delayus(20);   //delayms(5);
        lcden=1;
        delayus(20);
        lcden=0;
}
void write_date(uchar date)                                  //向液晶写数据
{
        lcdrs=1;
        P0=date;
        delayus(20);
        lcden=1;
        delayus(20);
        lcden=0;
}
void lcd_xy(uchar x,uchar y)                           //液晶两行的地址
{
        uchar address;
        if(y==0)
                address=0x80+x;
        else
                address=0xc0+x;
        write_com(address);
}
void lcd_write_date(uchar x,uchar y,uchar date)           //确定液晶地址并输入数据
{
        lcd_xy(x,y);
        write_date(date);        
}
void lcd_init()                                                                                //初始化液晶
{
        lcden=0;
        lcdrw=0;
        write_com(0x38);
        write_com(0x0c);
        write_com(0x06);
        write_com(0x01);
}
void ds_init(void)                                                                         //初始化ds1302时钟芯片
{
        RES=0;                        //RST脚置低
        SCK=0;                        //SCK脚置低
}
void ds_write_date(uchar add,uchar date)                        //向DS1302地址写入数据
{
        uchar i,temp,m,n;
        RES=0;
        SCK=0;
        RES=1;
        //最低位置零,寄存器0位为0时写,为1时读
        for(i=0;i<8;i++)
        {
                SCK=0;
                temp=add;
                IO=(bit)(temp&0x01);
                add=add>>1;
                SCK=1;
        }
        m=date/10;
        n=date%10;
        date=m*16+n;
        for(i=0;i<8;i++)
        {
                SCK=0;
                temp=date;
                IO=(bit)(temp&0x01);
                date=date>>1;
                SCK=1;
        }
        RES=0;
}
uchar ds_read_date(uchar add)                                                 //选中地址后从DS中读出该地址数据
{
        uchar i,temp,date1,date2;
        RES=0;
        SCK=0;
        RES=1;
        add=add|0x01;
        for(i=0;i<8;i++)
        {
                SCK=0;
                temp=add;
                IO=(bit)(temp&0x01);
                add=add>>1;
                SCK=1;
        }
        for(i=0;i<8;i++)
        {
                SCK=1;
                SCK=0;
                lcddate=(IO&0x80);
                lcddate>>=1;
        }
        RES=0;
        date1=lcddate;
        date2=date1/16;
        date1=date1%16;
        date1=date1+date2*10;
        return (date1);
}
void ds_write_time()                                                   //将时间数据按照各自地址输入DS
{
        ds_write_date(ds_control_add,0x00);                        //关闭写保护
        ds_write_date(ds_second_add,0x80);                        //暂停时钟
        ds_write_date(ds_year_add,time_buf[1]);
        ds_write_date(ds_month_add,time_buf[2]);
        ds_write_date(ds_day_add,time_buf[3]);
        ds_write_date(ds_hour_add,time_buf[4]);
        ds_write_date(ds_minute_add,time_buf[5]);
        ds_write_date(ds_second_add,time_buf[6]);
        ds_write_date(ds_week_add,time_buf[7]);
        ds_write_date(ds_control_add,0x80);                         //打开写保护
}
void ds_read_time()                                                                   //从DS中按照各自地址读出时间数据
{
        time_buf[1]=ds_read_date(ds_year_add);
        time_buf[2]=ds_read_date(ds_month_add);
        time_buf[3]=ds_read_date(ds_day_add);
        time_buf[4]=ds_read_date(ds_hour_add);
        time_buf[5]=ds_read_date(ds_minute_add);
        time_buf[6]=ds_read_date(ds_second_add)&0x7f;
        time_buf[7]=ds_read_date(ds_week_add);
}
void display()                                                                                 //将数据输入到液晶上
{
        lcd_write_date(1,0,dis_time_buf[0]+'0');
        lcd_write_date(2,0,dis_time_buf[1]+'0');
        lcd_write_date(3,0,dis_time_buf[2]+'0');
        lcd_write_date(4,0,dis_time_buf[3]+'0');
        lcd_write_date(5,0,'-');
        lcd_write_date(6,0,dis_time_buf[4]+'0');
        lcd_write_date(7,0,dis_time_buf[5]+'0');
        lcd_write_date(8,0,'-');
        lcd_write_date(9,0,dis_time_buf[6]+'0');
        lcd_write_date(10,0,dis_time_buf[7]+'0');
        lcd_write_date(12,0,dis_time_buf[14]+'0');
        lcd_write_date(4,1,dis_time_buf[8]+'0');
        lcd_write_date(5,1,dis_time_buf[9]+'0');
        lcd_write_date(6,1,':');
        lcd_write_date(7,1,dis_time_buf[10]+'0');
        lcd_write_date(8,1,dis_time_buf[11]+'0');
        lcd_write_date(9,1,':');
        lcd_write_date(10,1,dis_time_buf[12]+'0');
        lcd_write_date(11,1,dis_time_buf[13]+'0');
}
void time0() interrupt 1
{
        
        static uchar t;
        TL0 = (65535-60000)%256; // 初始值
        TH0 = (65535-60000)/256;
        TF0=0;
        t++;
        if(t==4)
        {
                t=0;
                ds_read_time();
                dis_time_buf[0]=(time_buf[0]>>4);
                dis_time_buf[1]=(time_buf[0]&0x0f);
                dis_time_buf[2]=(time_buf[1]>>4);
                dis_time_buf[3]=(time_buf[1]&0x0f);
                dis_time_buf[4]=(time_buf[2]>>4);
                dis_time_buf[5]=(time_buf[2]&0x0f);
                dis_time_buf[6]=(time_buf[3]>>4);
                dis_time_buf[7]=(time_buf[3]&0x0f);
                dis_time_buf[14]=(time_buf[7]&0x07);
                dis_time_buf[8]=(time_buf[4]>>4);
                dis_time_buf[9]=(time_buf[4]&0x0f);
                dis_time_buf[10]=(time_buf[5]>>4);
                dis_time_buf[11]=(time_buf[5]&0x0f);
                dis_time_buf[12]=(time_buf[6]>>4);
                dis_time_buf[13]=(time_buf[6]&0x0f);
        }
}
void init_time0()
{
        TMOD=0x01;
        TL0 = (65535-60000)%256; // 初始值
        TH0 = (65535-60000)/256;
        TR0=1;
        ET0=1;
        EA=1;
}
void main()
{
        delayms(50);
        lcd_init();
        ds_init();
        delayms(10);
        ds_write_time();
        init_time0();
        while(1)
        {
                display();
        }
}

IMG_20150714_204135.jpg (1.71 MB, 下载次数: 90)

运行结果

运行结果
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1 发表于 2015-7-14 22:58 | 只看该作者
秒表不走??
回复

使用道具 举报

板凳
ID:76675 发表于 2015-7-15 09:13 | 只看该作者

是的。年的前两位可以通过初始的time_buf改变,其他的写入初始数据却不能正常显示,只是显示零。而且,我的问题是不知道ds1302中的SCLK是怎么工作的,它工作的时候需要外部的定时器么?

评分

参与人数 1黑币 +35 收起 理由
admin + 35 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

地板
ID:85868 发表于 2015-7-16 19:54 | 只看该作者
我有完整程序,20天前做的课程设计
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表