打印
[51单片机]

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

[复制链接]
1764|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
酷爱diy|  楼主 | 2014-12-20 18:00 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
se, AD, TE, IO, ADDR
这些怎么改都不对,要么时钟不走,要么时钟走就是显示的数字不对,我真的要疯掉了,发狂中

读写时序与BCD转16进制,10进制转BCD?
现在不知道是时序的问题还是BCD转码的问题?:Q :Q :Q  



还有就是读写时序:手册是读为下降沿,写为上升沿;为什么我按手册时序写的就不能运转;看网上的代码读写都是下降沿,读写都改为下降沿
,可以运转了,为什么?难道手册有问题?还是怎么?
#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;
}

相关帖子

沙发
coody| | 2014-12-20 18:49 | 只看该作者
一个DS1302都搞这么久??

使用特权

评论回复
板凳
as564335sa| | 2014-12-20 20:01 | 只看该作者
引脚上拉

使用特权

评论回复
地板
原野之狼| | 2014-12-20 21:31 | 只看该作者
对着别人可用的代码来分析下自己的代码吧

使用特权

评论回复
5
coody| | 2014-12-20 21:59 | 只看该作者
按3#所说的,上拉10K电阻看看

使用特权

评论回复
6
落雪绽菊| | 2014-12-20 22:15 | 只看该作者
没有那么多nop的,一个都不用。说实在的,程序我没看懂,不知道显示用的什么。

使用特权

评论回复
7
酷爱diy|  楼主 | 2014-12-20 22:47 | 只看该作者
主要是对BCD码转换不是很了解,还有就是为什么按照正常的时序写就是不行?

使用特权

评论回复
8
落雪绽菊| | 2014-12-20 23:00 | 只看该作者
看看这个,我最近刚搞定1302,还是有些心得的。
http://bbs.mydigit.cn/read.php?tid=1082112

使用特权

评论回复
9
hnkf118| | 2014-12-21 14:52 | 只看该作者
程序问题。 搞的不怎么规范。所以遇到这些问题也很正常的。

使用特权

评论回复
10
NE5532| | 2014-12-21 17:24 | 只看该作者
不知道就退而求其次,不要写一大堆代码然后说“不对”,楼主研究“程序调试黑宝书”

使用特权

评论回复
11
天秤骑猪去兜风| | 2014-12-21 19:01 | 只看该作者
正好我也刚弄完1302,也弄了一两天,这是我的程序,你可以看一下,键盘那部分我没写好,直接忽略
#include<reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int

/*定义ds1302时钟寄存器*/
uchar code write_register[]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};             //秒 分 时 日 月 星期 年
uchar code read_register[]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
uchar time[]={0x00,0x30,0x17,0x19,0x12,0x05,0x14};                                   //秒 分 时 日 月 星期 年  ,用来存储时钟数据

uchar code biao[]={0x4d,0x4a,0x47,0x08,0x05,0x0b,0x02};                              //按键中定义光标位置的数组

uchar code table1[]="20";                                                              //LCD1602初始显示字符的数组
uchar code table2[]="JIVU";
uchar code table3[]="ZXJ";

/*定义ds1302控制口*/
sbit DSIO=P3^4;
sbit CE=P3^5;
sbit SCLK=P3^6;

/*定义LCD1602控制口*/
sbit rs=P2^6;                          
sbit wr=P2^5;
sbit lcden=P2^7;

/*定义键盘接口*/
sbit k1=P2^0;
sbit k2=P2^1;
sbit k3=P2^3;
sbit k4=P2^4;
sbit k5=P1^0;

/*定义蜂鸣器*/
sbit beep=P1^1;

void delay(uint x);                         //延时函数

void write_com(uchar com);                  //LCD1602的写入指令和数据的函数声明
void write_data(uchar dat);
void lcd1602_init();                               //1602初始化

void display();                                               //万年历显示函数

void ds1302_init();                                                   //ds1302初始化
uchar ds1302_read(uchar add);                           //ds1302读写函数
void ds1302_write(uchar add,data3);

void keycan();                                                           //键盘扫描

void read_time();                                                   //读取ds1302时间的函数

uchar data2,hour,min;
void main()
{
        uchar i;
        lcd1602_init();
//        ds1302_init();

        write_com(0x80);
        for(i=0;i<2;i++)
        {
                write_data(table1[i]);
        }
        write_com(0x80+0x40);
        for(i=0;i<4;i++)
        {                                                                                                 
                write_data(table2[i]);
        }
        write_com(0x80+0x13);
        for(i=0;i<3;i--)
                write_data(table3[i]);
               
        while(1)
        {
                read_time();
                display();
                keycan();
        }
}



uchar ds1302_read(uchar add)                    //读ds1302数据
{
        uchar i,dat;
        data2=0x00;
        CE=0;
        delay(1);
        SCLK=0;
        delay(1);
        CE=1;
        delay(3);
        SCLK=0;
        for(i=0;i<8;i++)
        {
                DSIO=(bit)(add&0x01);
                add>>=1;
                SCLK=1;
                delay(3);
                SCLK=0;
                delay(3);
        }
        for(i=0;i<8;i++)
        {
                /*temp=DSIO&0x01;//-------1 <<= ------1-        |  00000001
                data2=(bit)(temp|data2);
                data2=_crol_(data2,1);
                SCLK=1;
                delay(3);
                SCLK=0;
                delay(3);*/
                dat = DSIO;//从最低位开始接收
                data2 = (data2>>1) | (dat<<7);
                SCLK = 1;
                delay(3);
                SCLK = 0;//DS1302下降沿时,放置数据
                delay(3);
        }
        CE=0;
        delay(3);
        SCLK=1;
        delay(3);
        DSIO=0;
        delay(3);
        DSIO=1;
        delay(3);
        dat=data2/16;                                          //0001 0011 & 1111 0000 =0001 00000
        data2=data2%16;
        data2=dat*10+data2;
        return data2;
}
                                                                                          
void ds1302_write(uchar add,data3)                    //写ds1302数据
{
        uchar i;
        CE=0;
        delay(1);   
        SCLK=0;
        delay(1);
        CE=1;
        SCLK=0;
        for(i=0;i<8;i++)
        {
                delay(1);
                DSIO=add&0x01;
                add>>=1;
                SCLK=1;
                delay(1);
                SCLK=0;
        }
        for(i=0;i<8;i++)
        {
                delay(1);
                DSIO=data3&0x01;
                data3>>=1;
                SCLK=1;
                delay(1);
                SCLK=0;
        }
        delay(1);
        CE=0;
        delay(1);
}
void read_time()                                                //读取·ds1302时间
{
        uchar n;
        for(n=0;n<7;n++)
        {
                ds1302_read(read_register[n]);
                time[n]=data2;
        }
}


void ds1302_init()                             //初始化ds1302
{
        uchar n;
        ds1302_write(0x8e,0x00);          //禁止写保护
        ds1302_write(0x8f,0x00);        //禁止读保护
        for(n=0;n<7;n++)
        {
                ds1302_write(write_register[n],time[n]);
        }
        ds1302_write(0x8e,0x80);          //允许写保护
}

void delay(uint x)
{
        uchar i,j;
        for(i=x;i>0;i--)
        {
                for(j=120;j>0;j--);
        }         

}


void write_com(uchar com)                       //写LCD1602指令
{
        rs=0;
        wr=0;
        lcden=0;
        P0=com;
        lcden=1;
        delay(5);
        lcden=0;
}


void write_data(uchar dat)                            //写LCD1602数据
{
        rs=1;
        wr=0;
        lcden=0;
        P0=dat;
        lcden=1;
        delay(3);
        lcden=0;
}

void lcd1602_init()                                    //初始化LCD1602
{
        write_com(0x38);
        write_com(0x08);
        write_com(0x01);
        write_com(0x06);
        write_com(0x0c);                     //开光标0x0f
}                                                                                                                                                                                                                                                                                                                     //___13-09-30___1_          JIVU__21:30:30__          
void display()                                        //LCD1602数据显示
{
        write_com(0x80+0x00);
        write_data(time[6]/10+0x30);
        write_data(time[6]%10+0x30);                  //uchar time[]={0x00,0x30,0x21,0x30,0x09,0x02,0x13};         //秒 分 时 日 月 星期 年
        write_data('-');
        write_data(time[4]/10+0x30);
        write_data(time[4]%10+0x30);
        write_data('-');
        write_data(time[3]/10+0x30);
        write_data(time[3]%10+0x30);
        write_data(' ');
        write_data(' ');
        write_data(time[5]%10+0x30);
        write_com(0x80+0x46);
        write_data(time[2]/10+0x30);
        write_data(time[2]%10+0x30);
        write_data(':');
        write_data(time[1]/10+0x30);
        write_data(time[1]%10+0x30);
        write_data(':');
        write_data(time[0]/10+0x30);
        write_data(time[0]%10+0x30);
}

使用特权

评论回复
12
ningling_21| | 2014-12-22 10:14 | 只看该作者
酷爱diy 发表于 2014-12-20 22:47
主要是对BCD码转换不是很了解,还有就是为什么按照正常的时序写就是不行? ...

因为你写的时序不对,用示波器测试你自己的实际波形和手册里的波形对比就会发现差异...

使用特权

评论回复
13
ayb_ice| | 2014-12-22 10:50 | 只看该作者
简单看了一下,至少读时序有问题
用下面的试试
uChar ds1302_Read()
{
                ds1302_IO = 1;
        uChar m,tm = 0;
        for(m = 0;m < 8;m++)
        {

                ds1302_SCK = 1;
                _nop_();_nop_();
                tm >>= 1;
                                if(ds1302_IO){
                                        tmp |= 0x80
                                }
                ds1302_SCK = 0;
                _nop_();_nop_();
        }

//        H = tm / 16;
//        L = tm % 16;
//        S = H * 10 + L;

        return tm;
}

使用特权

评论回复
14
ayb_ice| | 2014-12-22 10:53 | 只看该作者
这句话也有问题
if(ds1302_IO)
                tm = ds1302_IO | 0x80;

这个完全不明白什么意思

使用特权

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

本版积分规则

11

主题

97

帖子

2

粉丝