一乐电子

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 7980|回复: 34

[其他综合] 新手写DS1302程序,参考了好几个程序,可时间显示还是有问题,大家帮看下

  [复制链接]
发表于 2012-6-8 08:17 | 显示全部楼层 |阅读模式
本帖最后由 356053261 于 2012-6-8 08:19 编辑

这几天在调DS1302,读出来的时间一直有问题,

也按照参考的程序改了好几个BCD码到十进制的转换方法,

可显示出来的数据还是没有规律,

秒位在00、01、00、03、07、)#等等这样的数字间变化,

各位帮看下是什么情况,难道是DS1302有问题?

我换了一个也是这样的啊?

下面帖上我用的两段不同的程序,大家帮看下:

第一段:

//**************DS1302相关子函数**************//
//DS1302写入字节(底层协议)
uchar clock_in()
{
    clock_dat=1;
    a0=clock_dat;
    clock_clk=1;
clock_clk=0;
a1=clock_dat;
    clock_clk=1; clock_clk=0; a2=clock_dat;
    clock_clk=1; clock_clk=0; a3=clock_dat;
    clock_clk=1; clock_clk=0; a4=clock_dat;
    clock_clk=1; clock_clk=0; a5=clock_dat;
    clock_clk=1; clock_clk=0; a6=clock_dat;
    clock_clk=1; clock_clk=0; a7=clock_dat;
    return(ACC);
}
//1302驱动程序(底层协议)
void clock_out(uchar dd){
    ACC=dd;
    clock_dat=a0; clock_clk=1; clock_clk=0;
    clock_dat=a1; clock_clk=1; clock_clk=0;
    clock_dat=a2; clock_clk=1; clock_clk=0;
    clock_dat=a3; clock_clk=1; clock_clk=0;
    clock_dat=a4; clock_clk=1; clock_clk=0;
    clock_dat=a5; clock_clk=1; clock_clk=0;
    clock_dat=a6; clock_clk=1; clock_clk=0;
    clock_dat=a7; clock_clk=1; clock_clk=0;
}
//DS1302读数据(底层协议)
uchar read_clock(uchar ord){
    uchar dd=0;
    clock_clk=0;
    clock_Rst=0;
    clock_Rst=1;
    clock_out(ord);
    dd=clock_in();
    clock_Rst=0;
    clock_clk=1;
    return(dd);
}
//DS1302写数据(底层协议)
void write_clock(uchar ord, uchar dd){
    clock_clk=0;
    clock_Rst=0;
    clock_Rst=1;
    clock_out(ord);
    clock_out(dd);
    clock_Rst=0;
    clock_clk=1;
}
//设置1302的初始时间
void Init_1302(){//(2008年1月1日00时00分00秒星期二)
    if(read_clock(0xc1) != 0xf0)
    {
       write_clock(0x8e,0x00);//允许写操作
       write_clock(0x8c,0x08);//年
       write_clock(0x8a,0x03);//星期
       write_clock(0x88,0x05);//月
       write_clock(0x86,0x28);//日
       write_clock(0x84,0x00);//小时
       write_clock(0x82,0x33);//分钟
       write_clock(0x80,0x40);//秒
       write_clock(0x90,0xa5);//充电
       write_clock(0xc0,0xf0); //判断是否初始化一次标识写入
       write_clock(0x8e,0x80);//禁止写操作
    }
}
//常用时钟数据读取
void read_clocks()
{
    timedata[0] = read_clock(0x81);//读取秒数据
    timedata[1] = read_clock(0x83);//读取分钟数据
    timedata[2] = read_clock(0x85);//小时
    timedata[3] = read_clock(0x87);//日
    timedata[4] = read_clock(0x89);//月
    timedata[5] = read_clock(0x8b);//星期
    timedata[6] = read_clock(0x8d);//年
}


void set_display(uchar com, uchar dat)   //调整时间时显示函数
{
    lcd_wcom(com);
    lcd_wdat(dat/16+0x30);  
    lcd_wdat(dat%16+0x30);
}
void set_selfdisplay(uchar com, uchar dat)    //调整星期时自定义字符显示函数
{
    lcd_wcom(com);
    lcd_wdat(dat);
}




/*********************************************************************************************

/********************************************************************************************/

下面是第二段:


/************************************
名称:write1302
说明:先写地址,再写数据
功能:向add相应地址中写入一个字节的数据
调用:weite1302byte
输入:add:要先写入的控制字,dat:要写入的数据
*************************************/
void write1302(uchar date,uchar add)
{
ce=0;  //初始设置为0
sclk=0;  //时钟初始设置为0
ce=1;  //ce拉高,传输开始
write1302byte(date); //传输要写入的地址
write1302byte(add); //写入要修改的数据
sclk=1;  //时钟线拉高
ce=0;  //结束传输,
}

/*************************************
名称:write1302byte
功能:写入8位数据
输入:add;要写入的数据
/************************************/
void write1302byte(uchar add)
{
uchar i;
sclk=0;
for(i=8;i>0;i--)
{
  dio=add&0x01; //每次只取一位数据
  sclk=1;   //发送一个字节后,时钟送一个高脉冲,上升沿传送数据
  sclk=0;
  add>>=1;  //右移一位,准备传输下一位数据
}
}
/************************************
名称:read1302byte()
功能:读取8位数据
输出:dat:读取的数据
**************************************/
uchar read1302byte()
{
uchar i,dat;
for(i=8;i>0;i--)
{
  dat>>=1;  //要读回的数据右移一位
  if(dio==1)  //数据线为高时,证明该位数据为1;
   dat=dat|0x80; //要传输数据的当前值置为1,若不是,则为0
  sclk=1;   //拉高时钟总线
  sclk=0;   //送一个下降沿
}
return dat;   //返回读取到数据
}
/**************************************
名称:uchar read1302()
说明:先写地址,再读数据
功能:从ADD相应地址中读取一个字节的数据
调用:write1302byte,read1302byte
输入:cma:要读取的控制地址
输出:dat;读取的数据
**************************************/
uchar read_1302(uchar cmd)
{
uchar dat;
{
  ce=0;
  sclk=0;
  ce=1;  //传输开始
  write1302byte(cmd); //传输地址命令
  dat=read1302byte(); //读取得到的时间日期
  sclk=1;
  ce=0;    //结束数据传输
}
return dat;   //将读出的数据返回
}
/*************************************
名称:DS1302初始化子函数
功能:向DS1302写入初始值
秒位置:写 0X80,读 0X81
/*************************************/
void init_1302()
{
write1302(0X8e,0X00); //禁止写保护
write1302(0x80,0x56); //秒位初始化
write1302(0X82,0x34); //分钟初始化
write1302(0X84,0x12); //小时初始化
write1302(0X86,0x25); //日期初始化
write1302(0X88,0x12); //月份初始化
write1302(0X8A,0x10); //星期初始化
write1302(0X8C,0x06); //年份初始化
write1302(0x90,0xab);  //写充电器
write1302(0X8E,0x80); //写保护开

}

void main()
{
init_1302(); //1302初始化
LCD_init();  //LCD初始化
init_nyr();  //日期初始化
init_sfm();  //时间初始化
while(1)
{
  display();
// LCD_init();
}
}
/****************************************************
显示子函数
功能:com:要读取的地址,
/****************************************************/
void display()
{
uchar miao,miao1,fen,shi;
miao=read_1302(0x81);  //读秒数据
fen=read_1302(0x83);  //读分数据
shi=read_1302(0x85);  //读小时数据
miao1=miao/16;    //进制转换
miao=miao%16;
P1=miao;
write_com(0x80+0x40+12); //秒显示的LCD地址
write_date(0x30+miao);  //秒位送显示
// write_com(0x80+0x40+9);  
// write_date(0x30+miao1);
// write_sfm(8,miao);
write_sfm(5,fen);  //分位送显示
write_sfm(2,shi);  //小时位送显示
}
发表于 2012-6-8 09:09 | 显示全部楼层
你的时钟是多少的?是否符合1302的要求?
回复

使用道具 举报

 楼主| 发表于 2012-6-8 09:14 | 显示全部楼层
记得是拿的32.768,楼上说可能是时钟的问题,那中午回去再确定下时钟晶体有没有用错
回复

使用道具 举报

发表于 2012-6-8 09:21 | 显示全部楼层
你能否把整个程序打包上来?
如果是51的话就是keil的整个工程,
其他人好去调试,这样发现问题会快些.
回复

使用道具 举报

发表于 2012-6-8 09:22 | 显示全部楼层
本帖最后由 飞雪008 于 2012-6-8 09:25 编辑

拿这个用用看,我以前在网上找的,还可以

//DS1302管脚定义
sbit T_CLK  = P3^5;
sbit T_IO   = P3^6;   
sbit T_RST  = P3^7;

sbit ACC0   = ACC^0;
sbit ACC1   = ACC^1;
sbit ACC2   = ACC^2;
sbit ACC3   = ACC^3;
sbit ACC4   = ACC^4;
sbit ACC5   = ACC^5;
sbit ACC6   = ACC^6;
sbit ACC7   = ACC^7;
//------------------------------------------------------------------------------------------
//时钟数据(7字节BCD码)格式为: 秒   分   时   日    月星期   年-----------------------------
unsigned char idata Time[7];//={0x30,0x42,0x23,0x18,0x06,0x04,0x09};
//------------------------------------------------------------------------------------------
bit flag; //flag-闰年标记
unsigned char idata second,minute,hour,day,month,week,year;
unsigned char BCD2HEX(unsigned char BCDChar);
unsigned char HEX2BCD(unsigned char HEXChar);
void WriteByteDS1302(unsigned char Data);
unsigned char ReadByteDS1302(void);
void WriteDS1302(unsigned char Addr,unsigned char Data);
unsigned char ReadDS1302(unsigned char Addr);
void Set(unsigned char sel,unsigned char selby);
void SetTime(unsigned char  *pClock);
void ReadTime();
void WriteTime();
void StopTime();
void StartTime();
void bucang(void);
/*******************************************************************************************
*  函数名: BCD2HEX   
*  功能描述:  
*  入口参数:  无
*  出口参数:  无
*******************************************************************************************/
unsigned char BCD2HEX(unsigned char BCDChar)     
{
    unsigned char temp;
    temp=(BCDChar/16*10+BCDChar%16);
    return temp;
}
/*******************************************************************************************
*  函数名: HEX2BCD   
*  功能描述:  
*  入口参数:  无
*  出口参数:  无
*******************************************************************************************
unsigned char HEX2BCD(unsigned char HEXChar)
{
    unsigned char temp;
    temp=(HEXChar/10*16+HEXChar%10);
    return temp;
}
/*******************************************************************************************
*  函数名: WriteByteDS1302   
*  功能描述:  
*  入口参数:  无
*  出口参数:  无
*******************************************************************************************/  
void WriteByteDS1302(unsigned char Data)
{
    unsigned char i;
    ACC = Data;
    for(i=8; i>0; i--)
    {
        T_IO = ACC0;         
        T_CLK = 1;
        T_CLK = 0;
        ACC = ACC >> 1;
    }
}
/*******************************************************************************************
*  函数名: ReadByteDS1302   
*  功能描述:  
*  入口参数:  无
*  出口参数:  无
*******************************************************************************************/  
unsigned char ReadByteDS1302(void)
{
    unsigned char i;
    for(i=8; i>0; i--)
    {
        ACC = ACC >>1;      
        ACC7 = T_IO;
        T_CLK = 1;
        T_CLK = 0;
    }
    return(ACC);
}
/*******************************************************************************************
*  函数名: WriteDS1302   
*  功能描述:  
*  入口参数:  无
*  出口参数:  无
*******************************************************************************************/  
void WriteDS1302(unsigned char Addr,unsigned char Data)
{
    T_RST = 0;
    T_CLK = 0;
    T_RST = 1;
    WriteByteDS1302(Addr);   
    WriteByteDS1302(Data);  
    T_CLK = 1;
    T_RST = 0;
}
/*******************************************************************************************
*  函数名: ReadDS1302   
*  功能描述:  
*  入口参数:  无
*  出口参数:  无
*******************************************************************************************/  
unsigned char ReadDS1302(unsigned char Addr)
{
    unsigned char Data;
    T_RST = 0;
    T_CLK = 0;
    T_RST = 1;
    WriteByteDS1302(Addr);         
    Data = ReadByteDS1302();     
    T_CLK = 1;
    T_RST = 0;
    return(Data);
}
/*******************************************************************************************
*  函数名: Set   
*  功能描述:  
*  入口参数:  无
*  出口参数:  无
*******************************************************************************************/
void Set(unsigned char sel,unsigned char selby)
{
    unsigned char address;
        char item;
    unsigned char max,min;

    if(sel==0)  {address=0x80; max=59;min=0;}    //秒
    if(sel==1)  {address=0x82; max=59;min=0;}    //分钟
    if(sel==2)  {address=0x84; max=23;min=0;}    //小时
        if(month==2)
                if(flag==1)
                {
                        if(sel==3)  {address=0x86; max=28;min=1;}
                }
                else
                {
                        if(sel==3)  {address=0x86; max=27;min=1;}
                }
        else
        {
                   if(month==1|month==3|month==5|month==7|month==8|month==10|month==12)
                {   
                        if(sel==3)  {address=0x86; max=31;min=1;}
                }
                if(month==4|month==6|month==9|month==11)
                {   
                        if(sel==3)  {address=0x86; max=30;min=1;}
                }
        }
    if(sel==4)  {address=0x88; max=12;min=1;}    //月
    if(sel==5)  {address=0x8a; max=7; min=1;}    //星期
    if(sel==6)  {address=0x8c; max=99;min=0;}    //年
    item=ReadDS1302(address+1)/16*10+ReadDS1302(address+1)%16;
    if (selby==0) item++;  else item--;
    if(item>max) item=min;   
    if(item<min) item=max;
           
    WriteDS1302(0x8e,0x00);
    WriteDS1302(address,item/10*16+item%10);
    WriteDS1302(0x90,0xa5);
    WriteDS1302(0x8e,0x80);  
}
/*******************************************************************************************
*  函数名: SetTime   
*  功能描述:  
*  入口参数:  无
*  出口参数:  无
*******************************************************************************************  
void SetTime(unsigned char  *pClock)
{
    unsigned char  h;
    unsigned char  Addr=0x80;
    WriteDS1302(0x8e,0x00);        
    for(h=7; h>0; h--)
    {
        WriteDS1302(Addr,*pClock);
        pClock++;
        Addr+=2;
    }
    WriteDS1302(0x90,0xa5);
        WriteDS1302(0x8e,0x80);      
}
/*******************************************************************************************
*  函数名: ReadTime   
*  功能描述:  
*  入口参数:  无
*  出口参数:  无
*******************************************************************************************/  
void ReadTime()
{
    second = BCD2HEX(Time[0]=ReadDS1302(0x81));
        minute = BCD2HEX(Time[1]=ReadDS1302(0x83));
        hour   = BCD2HEX(Time[2]=ReadDS1302(0x85));
        day    = BCD2HEX(Time[3]=ReadDS1302(0x87));
        month  = BCD2HEX(Time[4]=ReadDS1302(0x89));
        year   = BCD2HEX(Time[5]=ReadDS1302(0x8d));
    week   = BCD2HEX(Time[6]=ReadDS1302(0x8b));
}
/*******************************************************************************************
*  函数名: WriteTime   
*  功能描述:  
*  入口参数:  无
*  出口参数:  无
*******************************************************************************************
void WriteTime()
{
    WriteDS1302(0x8e,0x00);
    WriteDS1302(0x80,HEX2BCD(second));
        WriteDS1302(0x82,HEX2BCD(minute));
        WriteDS1302(0x84,HEX2BCD(hour));
        WriteDS1302(0x86,HEX2BCD(day));
        WriteDS1302(0x88,HEX2BCD(month));
        WriteDS1302(0x8A,HEX2BCD(week));
    WriteDS1302(0x8C,HEX2BCD(year));
    WriteDS1302(0x90,0xa5);
        WriteDS1302(0x8e,0x80);
}
/*******************************************************************************************
*  函数名: StopTime   
*  功能描述:  
*  入口参数:  无
*  出口参数:  无
*******************************************************************************************
void StopTime()
{
    second = BCD2HEX(Time[0]=ReadDS1302(0x81));
    WriteDS1302(0x8e,0x00);
    WriteDS1302(0x80,HEX2BCD(second)|0x80);
    WriteDS1302(0x90,0xa5);
        WriteDS1302(0x8e,0x80);
}
/*******************************************************************************************
*  函数名: StartTime   
*  功能描述:  
*  入口参数:  无
*  出口参数:  无
*******************************************************************************************
void StartTime()
{
    WriteDS1302(0x8e,0x00);
    WriteDS1302(0x80,HEX2BCD(second)&0x7f);
    WriteDS1302(0x90,0xa5);
        WriteDS1302(0x8e,0x80);
}
/*****************************************************************************/
//设置1302的初始时间(自动初始化)
void Init_1302(void){//-设置1302的初始时间(2007年1月1日00时00分00秒星期一)
        unsigned char f;
        if(ReadDS1302(0xc1) != 0xaa){
                WriteDS1302(0x8e,0x00);//允许写操作
                WriteDS1302(0x8c,0x10);//年
                WriteDS1302(0x8a,0x05);//星期
                WriteDS1302(0x88,0x06);//月
                WriteDS1302(0x86,0x11);//日
                WriteDS1302(0x84,0x16);//小时
                WriteDS1302(0x82,0x09);//分钟
                WriteDS1302(0x80,0x00);//秒
                WriteDS1302(0x90,0xa5);//充电        
                WriteDS1302(0xc0,0xaa);//写入初始化标志RAM(第00个RAM位置)
                for(f=0;f<60;f=f+2){//清除闹钟RAM位为0
                        WriteDS1302(0xc2+f,0x00);
                }
                WriteDS1302(0x8e,0x80);//禁止写操作
        }
}
回复

使用道具 举报

发表于 2012-6-8 09:23 | 显示全部楼层
记得是拿的32.768,楼上说可能是时钟的问题,那中午回去再确定下时钟晶体有没有用错
356053261 发表于 2012-6-8 09:14 https://www.yleee.com.cn/images/common/back.gif



   不是32768的时钟,是单片机的时钟。1302对时序有一定限制的,5v工作电压下,一个clk脉冲宽度至少要在400ns以上。建议在2us以上。周期太短,1302反应不过来的。
回复

使用道具 举报

 楼主| 发表于 2012-6-8 09:28 | 显示全部楼层
89c52,11.0592,
LCD显示每秒数字会动一下,只是数据比较混乱,不是正常的秒数据显示,
回复

使用道具 举报

 楼主| 发表于 2012-6-8 09:31 | 显示全部楼层
电子钟第一版keil工程.rar (54.24 KB, 下载次数: 1758) DS1302.rar (44.57 KB, 下载次数: 1705)

两个文件,第一个文件是在一乐论坛上下别人成功案例,改了下接口定义

第二个是自己参照别人的写的,都有数字显示,只是显示数字不正确
回复

使用道具 举报

 楼主| 发表于 2012-6-8 09:40 | 显示全部楼层
把数据送到开发板上的流水灯上显示,可以看到每秒的低四位数据都有变化,只是送显示后,就不正常,怀疑是数据转换问题
回复

使用道具 举报

发表于 2012-6-8 16:50 | 显示全部楼层
第一版那个总觉得这个函数有问题

//**************DS1302相关子函数**************//
//DS1302写入字节(底层协议)
uchar clock_in()
{
    clock_dat=1;
    a0=clock_dat;
    clock_clk=1;
        clock_clk=0;

        a1=clock_dat;

    clock_clk=1; clock_clk=0; a2=clock_dat;
    clock_clk=1; clock_clk=0; a3=clock_dat;
    clock_clk=1; clock_clk=0; a4=clock_dat;
    clock_clk=1; clock_clk=0; a5=clock_dat;
    clock_clk=1; clock_clk=0; a6=clock_dat;
    clock_clk=1; clock_clk=0; a7=clock_dat;
    return(ACC);
}
回复

使用道具 举报

本版积分规则

QQ|一淘宝店|手机版|商店|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2025-11-3 17:23 , Processed in 0.036677 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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