DS1302 搞了几天了都无果,我要发狂了

2020-01-20 18:53发布

本帖最后由 酷爱diy 于 2014-12-20 16:52 编辑

读写时序与BCD转16进制,10进制转BCD;这些怎么改都不对,要么时钟不走,要么时钟走就是显示的数字不对,我真的要疯掉了,发狂中

现在不知道是时序的问题还是BCD转码的问题?   

还有就是读写时序:手册是读为下降沿,写为上升沿;为什么我按手册时序写的就不能运转;看网上的代码读写都是下降沿,读写都改为下降沿
,可以运转了,为什么?难道手册有问题?还是怎么?
#include <reg52.h>
#include "intrins.h"

typedef unsigned char uChar;
typedef unsigned int uInt;
//typedef unsigned long uInt32;
#define SEG_dat_IO P0
#define LED        P1

uChar SEG_su[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,         //0,1,2,3,4,5,6,7,8,9,
                              0x6f,0x77,0x7c,0x58,0x5e,0x79,0x71,0x76,0x40}; //        A,b,c,d,E,F,H,-
                          

#define Waddress_Seconds 0x80
#define Raddress_Seconds 0x81

#define Waddress_Minutes 0x82
#define Raddress_Minutes 0x83

#define Waddress_Hour          0x85
#define Raddress_Hour         0x84

//#define Waddress_Date          0x86
//#define Raddress_Date         0x87
//
//#define Waddress_Month          0x88
//#define Raddress_Month         0x89
//
//#define Waddress_Day          0x8A
//#define Raddress_Day         0x8B
//
//#define Waddress_Year    0x8C
//#define Raddress_Year          0x8D

#define Waddress_WP      0x8E

sbit ds1302_CE = P1^0;
sbit ds1302_IO = P1^1;
sbit ds1302_SCK = P1^2;
sbit SEG_WEL = P2^7;
sbit SEG_DUL = P2^6;
sbit LED_EN  = P2^5;

void delay_ms(uChar time);
void mcu_Init();
void why_Init();
//void display_LED(uInt32 dis_date);
void dis(uChar ma,uChar mb,uChar mc);
void Write_byte(uChar Add,uChar Data);
uChar Read_byte(uChar Adds);
void ds1302_Write(uChar WRaddress);
uChar ds1302_Read();

uChar m1,s1,f1,m2,s2,f2;

void main()
{       
        uChar miao,shi,fend,miao1,fend1,shi1;       
        mcu_Init();
        why_Init();

        while(1)
        {
                miao =         Read_byte(Raddress_Seconds);
                miao1 = ((miao >> 4)&0x0f)*10 + (miao & 0x0f);
                fend =  Read_byte(Raddress_Minutes);
                fend1 = ((fend >> 4)&0x0f)*10 + (fend & 0x0f);
                shi = Read_byte(Raddress_Hour);
                shi1 = ((shi >> 4)&0x0f)*10 + (shi & 0x0f);
                dis(shi1,fend1,miao1);
                delay_ms(1);       
               
        }
}

void delay_ms(uChar time)
{
        uChar i;
        uInt j;
        for(i = time;i > 0;i--)
                for(j = 200;j > 0;j--)
                        _nop_();
}


void mcu_Init()
{
         LED_EN = 1;
         LED = 0xff;
         LED_EN = 0;
                
         SEG_dat_IO = 0;
         SEG_DUL = 0;
         SEG_DUL = 1;
         SEG_dat_IO = 0xff;
         SEG_WEL = 0;
         SEG_WEL = 1;
}

void why_Init()
{
        ds1302_CE = 0;
        ds1302_SCK = 0;
        ds1302_IO = 1;
       
        Write_byte(Waddress_WP,0);
       
        Write_byte(Waddress_Seconds,20);       
       
        Write_byte(Waddress_Minutes,12);
       
        Write_byte(Waddress_Hour,10);

        Write_byte(Waddress_WP,80);
               

//        BCD <----(HEX /10 )*16 + (HEX % 10)           HEX--->BCD
//  10(D)--->16(H)  D = (D%16 = m; m%16 = n;n%16 = k;)   H = knm(H)  
}

void dis(uChar ma,uChar mb,uChar mc)
{
        static uChar num1 = 1;
        m1 = ma/10;
        m2 = ma%10;
        s1 = mb/10;
        s2 = mb%10;
        f1 = mc/10;
        f2 = mc%10;
        switch(num1)
        {
                case 1:{SEG_DUL = 1;SEG_dat_IO = SEG_su[m1];SEG_DUL = 0;SEG_dat_IO = 0xff;
                                SEG_WEL = 1;SEG_dat_IO = 0xfe;SEG_WEL = 0;num1++;}break;
                case 2:{SEG_DUL = 1;SEG_dat_IO = SEG_su[m2];SEG_DUL = 0;SEG_dat_IO = 0xff;
                                SEG_WEL = 1;SEG_dat_IO = 0xfd;SEG_WEL = 0;num1++;}break;
                case 3:{SEG_DUL = 1;SEG_dat_IO = SEG_su[s1];SEG_DUL = 0;SEG_dat_IO = 0xff;
                                SEG_WEL = 1;SEG_dat_IO = 0xfb;SEG_WEL = 0;num1++;}break;
                case 4:{SEG_DUL = 1;SEG_dat_IO = SEG_su[s2];SEG_DUL = 0;SEG_dat_IO = 0xff;
                                SEG_WEL = 1;SEG_dat_IO = 0xf7;SEG_WEL = 0;num1++;}break;
                case 5:{SEG_DUL = 1;SEG_dat_IO = SEG_su[f1];SEG_DUL = 0;SEG_dat_IO = 0xff;
                                SEG_WEL = 1;SEG_dat_IO = 0xef;SEG_WEL = 0;num1++;}break;
                case 6:{SEG_DUL = 1;SEG_dat_IO = SEG_su[f2];SEG_DUL = 0;SEG_dat_IO = 0xff;
                                SEG_WEL = 1;SEG_dat_IO = 0xdf;SEG_WEL = 0;num1 = 1;}break;
                default:SEG_dat_IO = 0xff;break;
        }               

}

void ds1302_Write(uChar WRaddress)
{
        uChar a;
        for(a = 0;a < 8;a++)
        {
//                ds1302_SCK = 0;
//                _nop_();_nop_();
                ds1302_IO = WRaddress & 0x01;
                _nop_();_nop_();
                ds1302_SCK = 1;
                _nop_();_nop_();
                ds1302_SCK = 0;
                _nop_();_nop_();
                WRaddress >>= 1;
        }
}

uChar ds1302_Read()
{
        uChar m,tm = 0;
        for(m = 0;m < 8;m++)
        {       
               
                ds1302_SCK = 1;
                _nop_();_nop_();
                tm >>= 1;
                ds1302_SCK = 0;
                _nop_();_nop_();
                if(ds1302_IO)
                tm = ds1302_IO | 0x80;
        }

//        H = tm / 16;
//        L = tm % 16;
//        S = H * 10 + L;
       
        return tm;
}
                                                                                                                                                                                          
void Write_byte(uChar Add,uChar Data)
{
        ds1302_CE = 0;
        _nop_();_nop_();
        ds1302_SCK = 0;
        _nop_();_nop_();
        ds1302_CE = 1;
        _nop_();_nop_();
        ds1302_Write(Add);
        ds1302_Write((Data/10)<<4)+((Data%10)&0x0f));
        ds1302_SCK = 1;
        _nop_();_nop_();
        ds1302_CE = 0;
        _nop_();_nop_();
        ds1302_IO = 1;
        _nop_();_nop_();
}
//((Data/10)<<4)+((Data%10)&0x0f)
uChar Read_byte(uChar Adds)
{
        uChar tab;
        ds1302_CE = 0;
        _nop_();_nop_();
        ds1302_SCK = 0;
        _nop_();_nop_();
        ds1302_CE = 1;
        _nop_();_nop_();
        ds1302_Write(Adds);
        tab = ds1302_Read();
        ds1302_SCK = 1;
        _nop_();_nop_();
        ds1302_CE = 0;
        _nop_();_nop_();
        ds1302_IO = 1;
        _nop_();_nop_();
        return tab;
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
32条回答
lovejp1981
1楼-- · 2020-01-23 00:14
酷爱diy 发表于 2014-12-20 17:45
读写时序与BCD转16进制,10进制转BCD?
;读写时序:手册是读为下降沿,写为上升沿;为什么我按手册时序写 ...

时序图来看 明明是上升沿写数   给你看看我的程序已经量产的。但是DS1302不大稳定,最后换了RX8205了。

#include"DS1302.h"
#include"delay.h"
/************************************************************************/
#define DS1302_RST_PORT    PORTD
#define DS1302_RST_DDR     DDRD
#define DS1302_CLK_PORT    PORTD
#define DS1302_CLK_DDR     DDRD

#define DS1302_IO_PORT           PORTD
#define DS1302_IO_DDR           DDRD
#define DS1302_IO_PIN           PIND

#define DS1302_RST_BIT           PD7
#define DS1302_IO_BIT           PD6
#define DS1302_CLK_BIT           PD5
/************************************************************************/
#define DS1302_CLK_H       DS1302_CLK_PORT |= (1<<DS1302_CLK_BIT)
#define DS1302_CLK_L       DS1302_CLK_PORT &= ~(1<<DS1302_CLK_BIT)

#define DS1302_RST_H       DS1302_RST_PORT |= (1<<DS1302_RST_BIT)
#define DS1302_RST_L       DS1302_RST_PORT &= ~(1<<DS1302_RST_BIT)

#define DS1302_IO_OUT           DS1302_IO_DDR |= 1<<DS1302_IO_BIT
#define DS1302_IO_IN       DS1302_IO_DDR &= ~(1<<DS1302_IO_BIT)

#define DS1302_WRITE_1     DS1302_IO_PORT |= 1<<DS1302_IO_BIT
#define DS1302_WRITE_0     DS1302_IO_PORT &= ~(1<<DS1302_IO_BIT)
#define DS1302_READ_1      DS1302_IO_PIN&(1<<DS1302_IO_BIT)

#define XTAL  8

unsigned char g_TimeRead[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};  //从DS1302读出的时间
unsigned char g_DateDay = 0;
unsigned char g_TimeWrite[8]={0x80,0x14,0x18,0x30,0x03,0x01,0x13,0x00}; //需要写入DS1302的时间
/*
extern unsigned char g_Time_Read[8];  //从DS1302读出的时间
extern unsigned char g_Time_Write[8]; //需要写入DS1302的时间
*/
/*
//任意XTAL频率下计算出延时时间
void delay_nus(unsigned int nus)
{
   while(nus--)
      {
       delay_nus(1);
      }
}

void delay_ms(unsigned int nms)
{
    while(nms--)
    {
       delay_1ms();
    }
}
*/

//初始化DS1302的数据接口
void DS1302_portinit(void)                  
{
    DS1302_CLK_DDR |= (1<<DS1302_CLK_BIT);
        DS1302_RST_DDR |= (1<<DS1302_RST_BIT);
        DS1302_IO_DDR |= (1<<DS1302_IO_BIT);
}

//向DS1302写入一个字节数据(没有RST操作)
// byte--要写入的数据
void DS1302_writeB(unsigned char byte)
{
    unsigned char i;
   
    for(i=0;i<8;i++)          //8位数据计数
    {
        DS1302_CLK_L;                  //拉低时钟端
        if(byte&0x01)          //当前位是否是1
        {
            DS1302_WRITE_1;          //当前位是1,拉高数据端
        }
        else                                            
        {
            DS1302_WRITE_0;          //当前位是0,拉低数据端
        }
        
        delay_nus(10);          //调整时钟和脉冲宽度
        DS1302_CLK_H;                  //时钟上升沿(DS1302采样数据)
        byte>>=1;          //数据右移1位,为送出新数据位做准备
    }
}

/*********************************************
功  能: 从DS1302读出一个字节数据
返回值: byte--读出的数据
********************************************/
unsigned char DS1302_readB(void)
{
    unsigned char i,byte=0;
    DS1302_IO_IN;                             //将数据端口设置为输入                  
    //PORTB&=~BIT(RTC_DATA);        //无上拉电阻
    for(i=0;i<8;i++)                        //8位数据计数
    {
        byte>>=1;                               //保存读入的数据位
        DS1302_CLK_H;                         //时钟上升沿
        delay_nus(10);                         //延时,调整时钟脉冲宽度
        DS1302_CLK_L;                         //时钟下降沿,DS1302输出数据位
        delay_nus(10);                         //等待数据变化(MEGA16太快,必须等待DS1302的数据位输出,否则不能正确读出)
        if(DS1302_READ_1)                 //当前位是否是高电平
        {
            byte|= 0x80;                //是高电平就将返回数据的当前位置1
        }
        else
        {
            byte&=~0x80;                //是低电平就将返回数据的当前位置0
        }
    }
    DS1302_IO_OUT;                                 //最后将数据端口设置为输出
    return byte;                                //返回读出的数据
}

/*******************************************
功    能: 向DS1302的某个地址写入一个字节数据
参    数: addr--地址值(寄存器或RAM)
          data--要写入的数据
********************************************/
void DS1302_writeD(unsigned char addr,unsigned char data)
{
    addr &= 0xFE;                         //将地址最低位置零,写使能
   
    DS1302_RST_L;                         //拉低片选端
    DS1302_CLK_L;                         //拉低时钟端
    delay_nus(10);
    DS1302_RST_H;                         //拉高片选端
    delay_nus(10);                                           //调整片选脉冲
    DS1302_writeB(addr);                          //写入操作命令(地址)
    delay_nus(10);
    DS1302_CLK_L;                         //拉低时钟端
    delay_nus(10);
    DS1302_writeB(data);                          //写入数据
    DS1302_CLK_L;                         //拉低时钟端
    delay_nus(10);                                          //调整片选脉冲
    DS1302_RST_L;                         //拉低片选端
}

/*******************************************
功    能: 从DS1302的某个地址读出一个字节数据
参    数: addr--地址值(寄存器或RAM)
返回值  : data--读出的数据
********************************************/
unsigned char DS1302_readD(unsigned char addr)
{
    unsigned char data;
   
    addr |= 0x01;          //将地址最低位置一,读使能
   
    DS1302_RST_L;               //拉低片选端
    DS1302_CLK_L;                      //拉低时钟端
    delay_nus(10);
    DS1302_RST_H;                    //拉高片选端
    delay_nus(10);                    //调整片选脉冲
    DS1302_writeB(addr);   //写入操作命令(地址)
    delay_nus(10);
    data=DS1302_readB();   //读出数据
    delay_nus(10);
    DS1302_RST_L;                    //拉低片选端
    DS1302_CLK_L;                    //拉低时钟端
    return data;                   //返回读出的数据
}

/*******************************************
功    能: 设置DS1302的时间
参    数: ptTimeD--设置时间数组指针
返回值  : 无
********************************************/
void DS1302_Set_Time(unsigned char ptTimeD[])
{
    unsigned char i;
    unsigned char addr = 0x80;                  //写入地址从秒寄存器开始
    DS1302_writeD(C_WP,UPROTECT);        //控制命令,WP位为0,允许写操作
    delay_nms(5);
   
    for(i=0;i<7;i++)
    {
        DS1302_writeD(addr,ptTimeD);  // 秒 分 时 日 月 星期 年         
        addr+=2;
            delay_nms(1);
    }
   
    DS1302_writeD(0x80,ptTimeD[0]&0x7f);  // 秒
   
    DS1302_writeD(C_WP,PROTECT);          //控制命令,WP位为1,不允许写操作
       
        //下一语句不可放在初始化中,否则每次上电秒都为零
        DS1302_writeD(C_SEC,CLK_START);                //启动振荡器,DS1302开始工作
}

/*******************************************
功    能: 读取DS1302的当前时间
参    数: time[]--读取的时间数组
返回值  : 无
********************************************/
void DS1302_Get_Time(unsigned char time[])
{
    unsigned char i;
    ////////下面的是单次读写//////////////////////////       
    /* uchar addr = 0x80;                           //读取地址从秒寄存器开始
    for(i=0;i<7;i++)
    {
    time=DS1302_readD(addr|RD);    // 秒 分 时 日 月 星期 年        
    addr+=2;
    }*/
    ////////////////////////////////////////////////////       
    /////////下面是多字节读取///////////////
    DS1302_CLK_L;       
    DS1302_RST_H;         //拉高片选端
    delay_nus(10);
    DS1302_RST_L;         //拉低片选端
    delay_nus(10);
    //RESET_H;         //拉高片选端
    delay_nus(10);                //调整片选脉冲
    DS1302_RST_H;         //拉高片选端
    DS1302_CLK_L;
    DS1302_writeB(0xBF);       // 0xbf:时钟多字节读取命令
   
    for (i=0;i<8;i++)//时间数据的存放格式是:
    {//秒,分,时,日,月,星期,年,控制
        time=DS1302_readB(); //【7个数据(BCD格式)+1个控制】
    }
   
    DS1302_RST_L;          //拉低片选端
    ///////////////////////////////////////////////
    DS1302_CLK_L;        //拉低时钟端(时钟端在不操作时为低)
}

/*******************************************
功    能: 初始化DS1302
********************************************/
void DS1302_init(void)
{
    DS1302_portinit();
        DS1302_writeD(C_WP,UPROTECT);                //写入写允许命令
    DS1302_writeD(C_WP,PROTECT);                 //控制命令,WP位为1,不允许写操作          
}

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
头文件
#ifndef _DS1302_H
#define _DS1320_H

#include<iom64v.h>

#define C_SEC                0x80        //秒
#define C_MIN                0x82        //分
#define C_HR                0x84        //时
#define C_DAY                0x86        //日
#define C_MTH                0x88        //月
#define C_WK                0x8A        //星期 DATE
#define C_YR                0x8C        //年
#define C_WP                0x8E        //控制(写保护)
#define C_CHARGE        0x90        //涓流充电
#define C_BURST                0xBE        //时钟多字节

//配置
#define CLK_HALT                0x80        //停止时钟控制位    SECOND        bit7
#define CLK_START                0x00        //启动时钟
#define M12_24                        0x80        //12/24小时值选择位 HOUR                bit7
#define PROTECT                        0x80        //写保护控制位      CONTROL        bit7
#define UPROTECT                0x00        //写保护控制位      CONTROL        bit7
        //涓流充电控制常量
#define TC_D1R2                        0xA5        //high 1 Diode +2K Resistors  
#define TC_D2R8                        0xAB        //low  2 Diodes+8K Resistors  
#define TC_DISABLED                0x00        //Disabled(TCS<>1010 or DS=00 or RS=00)
        //RAM 命令
#define C_RAMBASE                0xC0        //RAM0~RAM30<<1 地址需左移一位

//任意XTAL频率下计算出延时时间
/*
extern void delay_nus(unsigned int nus);
extern void delay_nms(unsigned int nms);
*/
void DS1302_portinit(void);
//向DS1302写入一个字节数据(没有RST操作)
// byte--要写入的数据
void DS1302_writeB(unsigned char byte);
/*********************************************
功  能: 从DS1302读出一个字节数据
返回值: byte--读出的数据
********************************************/
unsigned char DS1302_readB(void);
/*******************************************
功    能: 向DS1302的某个地址写入一个字节数据
参    数: addr--地址值(寄存器或RAM)
          data--要写入的数据
********************************************/
void DS1302_writeD(unsigned char addr,unsigned char data);
/*******************************************
功    能: 从DS1302的某个地址读出一个字节数据
参    数: addr--地址值(寄存器或RAM)
返回值  : data--读出的数据
********************************************/
unsigned char DS1302_readD(unsigned char addr);
/*******************************************
功    能: 设置DS1302的时间
参    数: ptTimeD--设置时间数组指针
返回值  : 无
********************************************/
void DS1302_Set_Time(unsigned char ptTimeD[]);
/*******************************************
功    能: 读取DS1302的当前时间
参    数: time[]--读取的时间数组
返回值  : 无
********************************************/
void DS1302_Get_Time(unsigned char time[]);
/*******************************************
功    能: 初始化DS1302
********************************************/
void DS1302_init(void);
/*******************************************/
#endif
酷爱diy
2楼-- · 2020-01-23 02:44
对照别人的修改了下,读函数有问题,改过来了,现在是分钟与秒走时正常了;小时显示不对,显示字母+数字  
酷爱diy
3楼-- · 2020-01-23 07:27
 精彩回答 2  元偷偷看……
酷爱diy
4楼-- · 2020-01-23 11:16
仔细想了下,看了下;是我误导了手册的时序错误;原来是我的时序程序一直在作怪,还有就是BCD码转换,都是遇到的问题;期间也学到了不少的东西;先看的感觉可以了时序图,再按照自己的思路照着手册时序写,刚开始不知道怎么写 从低字节到高,参考了别人的思路在自己写;折腾几天的问题,今晚算是解决了当前的问题了,学知识就得要折腾来折腾去才能学得明白学的懂,谢谢大家,谢谢各位,虚心请教
lyllkw
5楼-- · 2020-01-23 11:37
1302网上程序很多,应该可用。但是很不好整,我的经验是注意匹配电容。最好选择配套的晶振
lyllkw
6楼-- · 2020-01-23 14:10
没有合适的晶振,可以在程序中添加判断是否正常工作的程序,不正常是重启1302,重启多次也会有成功

一周热门 更多>