DS1302 搞了几天了都无果,我要发狂了
本帖最后由 酷爱diy 于 2014-12-20 16:52 编辑读写时序与BCD转16进制,10进制转BCD;这些怎么改都不对,要么时钟不走,要么时钟走就是显示的数字不对,我真的要疯掉了,发狂中
现在不知道是时序的问题还是BCD转码的问题?{:mad:} {:mad:} {:mad:}
还有就是读写时序:手册是读为下降沿,写为上升沿;为什么我按手册时序写的就不能运转;看网上的代码读写都是下降沿,读写都改为下降沿
,可以运转了,为什么?难道手册有问题?还是怎么?
#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;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;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;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;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;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;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.768的负载电容 到网上下载实例再修改一下吧 一直觉得能去认真看别人贴出来的问题代码的人,都是牛逼! 读写时序与BCD转16进制,10进制转BCD?
;读写时序:手册是读为下降沿,写为上升沿;为什么我按手册时序写的就不能运转;看网上的代码读写都是下降沿,读写都改为下降沿
,可以运转了,为什么?难道手册有问题?还是怎么?
我的问题还没解答呢,求解答
楼主仔细看看时钟和数据的波形,起始和下降沿要对好。严格按照pdf来。年初我用非卡16位机调试时就是一直不行。最后在时钟波形产生函数里面加几个空操作就行了。好运! 连接单片机的那三根线加了上拉电阻没有,也就是CE、SCLK、IO要加上拉,以前我遇过不加上拉读数总是不对。 找个标准程序试试 先硬件一定要对,3条线加上拉电阻(实际调通后有2个好像不用,比较久了记不清了),当年用51+汇编搞定的,低速移到高速加NOP,直接榨干模拟IO性能,现在改玩C的了,痛苦中{:smile:} 调试方法:1、换芯片,DS1302很多是假芯片,2、数据线10K电阻上拉,特别是51单片机,3、时序问题,检查晶振频率和延时,4、更换晶振或者负载电容,5,时钟不走可以先write一个时间,一般就走起来了。 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; <------------------------此处 上升沿写入数据,第一次进此函数 IO口是低电平吗?
_nop_();_nop_();
ds1302_SCK = 0;
_nop_();_nop_();
WRaddress >>= 1;
}
}
酷爱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 XTAL8
unsigned char g_TimeRead={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//从DS1302读出的时间
unsigned char g_DateDay = 0;
unsigned char g_TimeWrite={0x80,0x14,0x18,0x30,0x03,0x01,0x13,0x00}; //需要写入DS1302的时间
/*
extern unsigned char g_Time_Read;//从DS1302读出的时间
extern unsigned char g_Time_Write; //需要写入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&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 //low2 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 对照别人的修改了下,读函数有问题,改过来了,现在是分钟与秒走时正常了;小时显示不对,显示字母+数字 实验板自带1302端口外加10K电阻,单片机与1302端口距离很短 仔细想了下,看了下;是我误导了手册的时序错误;原来是我的时序程序一直在作怪,还有就是BCD码转换,都是遇到的问题;期间也学到了不少的东西;先看的感觉可以了时序图,再按照自己的思路照着手册时序写,刚开始不知道怎么写 从低字节到高,参考了别人的思路在自己写;折腾几天的问题,今晚算是解决了当前的问题了,学知识就得要折腾来折腾去才能学得明白学的懂,谢谢大家,谢谢各位,虚心请教 1302网上程序很多,应该可用。但是很不好整,我的经验是注意匹配电容。最好选择配套的晶振 没有合适的晶振,可以在程序中添加判断是否正常工作的程序,不正常是重启1302,重启多次也会有成功 整来整去还是用了网上来的程序了 1302秒数不在正常范围内,是不走的 天天面对代码,一看楼主上一堆代码又没注释就头痛,代码就不看了,建议楼主,如果查了很多遍代码,就考虚一下硬件的问题
DS1302 我们常这个芯片,时间不走,或接收到数据不正常,并不代表你的代码可能会有问题,
硬件上的问题,一样导制这个问题 我的1302也不走,有时候还发热,,,后来发现是没有加电源滤波。。。。并联了一个电容,好了。。。 LZ可以参考下金沙滩小宋老师写的例程,讲得比较好 共同学习一下 学习学习 只用过12c887的爬过,学习了 酷爱diy 发表于 2014-12-20 17:45
读写时序与BCD转16进制,10进制转BCD?
;读写时序:手册是读为下降沿,写为上升沿;为什么我按手册时序写 ...
给楼主提醒下,有这么一种情况:
我之前在电子市场买的AD7705,研究很长一段时间,参考人家的代码,咋都调不通,最后参考国产山寨AD7705芯片的手册调通了。
请注意一下,你的芯片是不是国产的山寨芯片哦。 cainizi 发表于 2014-12-20 19:05
调试方法:1、换芯片,DS1302很多是假芯片,2、数据线10K电阻上拉,特别是51单片机,3、时序问题,检查晶振 ...
就是,我就吃过一次国产假AD7705的亏,差点崩溃了!大部分时序和功能和原厂的基本一样,但还是有些区别的,必须参考国产芯片的手册才能调通。 我买的1302在3.3不工作,只有在5V 才工作,这个问题我快搞了一个星期才发现,数据手册明明说支持3.3V 一般IIc来说 ,
注意三点:
1. 单片机上拉电阻是必须的。
2. 芯片本身是否是坏的。
3. 时序参照着写问题不大。 我这几天也是在调DS1302,但是我用的是汇编。 DS1302不准确啊,对外部晶振要求极高
页:
[1]