这几天用DS1302,程序出来之后很不理想
先贴贴程序:
void WriteByte(uchar dat)
{
uchar i;
ACC=dat;
for(i=8;i>0;i--)
{
Dat_1302=ACC0;
CLK_1302=1;
_nop_();_nop_();_nop_();
CLK_1302=0; //产生上升沿输入数据
ACC=ACC>>1;
}
}
void WriteSet1302(uchar Cmd,uchar dat)
{
RST_1302=0;
CLK_1302=0; //确保写数居前SCLK被拉低
RST_1302=1; //启动数据传输
WriteByte(Cmd);
WriteByte(dat);
RST_1302=0;
CLK_1302=1;
}
uchar ReadByte(void)
{
uchar i;
for(i=8;i>0;i--)
{
ACC7=Dat_1302;//ds1302读数据的时候,第一个数据读取在发一个Byte命令后,在第八位的下降沿
ACC=ACC>>1;
CLK_1302=1;
CLK_1302=0;//产生下降沿输出一位数据
_nop_();_nop_();_nop_();
}
return(ACC);
}
uchar ReadSet1302(uchar Cmd)
{
uchar dat;
RST_1302=0;
CLK_1302=0; //确保写数居前SCLK被拉低
RST_1302=1; //启动数据传输
WriteByte(Cmd);
dat=ReadByte();
RST_1302=0;
CLK_1302=1;
return dat; //将读出的数据返回
}
void Init1302(void)
{
WriteSet1302(0x8e,0x00);
WriteSet1302(0x80,0x05);//初始化时分秒
WriteSet1302(0x82,0x10);
WriteSet1302(0x84,0x15);
WriteSet1302(0x90,0xab);
WriteSet1302(0x8e,0x80);
}
程序遇到的问题是读取时间时老是出错,有时候是秒的数据错了,有时候是分的数据,有时候是时间的数据
而且写进去时间后读出来的数据也有错
不知道是哪里的问题
在网上看了很多这方面的程序,感觉都没有错
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
试试我这个 DS1302.H
//DS1302功能函数
// 51 @ 12MHz
//elecfun @ 2010-11-6
#ifndef _DS1302_
#define _DS1302_
sbit DS1302_RST = P2^3; //引脚定义,移植请修改此处
sbit DS1302_CLK = P2^4; //
sbit DS1302_DAT = P2^5; //
#define DS1302_SECOND 0x80
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_WEEK 0x8A
#define DS1302_DAY 0x86
#define DS1302_MONTH 0x88
#define DS1302_YEAR 0x8C
#define BCD2DEC(X) (((X&0x70)>>4)*10 + (X&0x0F)) //用于将BCD码转成十进制的宏
#define DEC2BCD(X) ((X/10)<<4 | (X%10)) //用于将十进制转成BCD码的宏
typedef struct __SYSTEMTIME__
{
unsigned char Second;
unsigned char Minute;
unsigned char Hour;
unsigned char Week;
unsigned char Day;
unsigned char Month;
unsigned char Year;
}SYSTEMTIME; //定义的时间类型
/*********************************************************************************************
函数名:DS1302写字节函数
调 用:DS1302_WriteByte(uchar);
参 数:需要写入的数据
返回值:
备 注:内部函数
/**********************************************************************************************/
void DS1302_WriteByte(unsigned char wByte)
{
unsigned char i=0;
for (i=0; i<8; i++) {
if (wByte & 0x01)
DS1302_DAT = 1;
else
DS1302_DAT = 0;
DS1302_CLK = 1;
DS1302_CLK = 0;
wByte >>= 1;
}
}
/*********************************************************************************************
函数名:DS1302读字节函数
调 用:uchar DS1302_ReadByte();
参 数:
返回值:读出的一个字节
备 注:内部函数
/**********************************************************************************************/
unsigned char DS1302_ReadByte(void)
{
unsigned char i=0,result=0;
DS1302_DAT = 1;
for (i=0; i<8; i++) {
if (DS1302_DAT == 1)
result |= (0x01<<i);
DS1302_CLK = 1;
DS1302_CLK = 0;
}
DS1302_DAT = 0;
return (result);
}
/*********************************************************************************************
函数名:DS1302读字节函数
调 用:uchar DS1302_ReadData(uchar);
参 数:指定的地址
返回值:读出指定地址的一个字节数据
备 注:
/**********************************************************************************************/
unsigned char DS1302_ReadData(unsigned char rAdd)
{
unsigned char rDat=0;
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302_WriteByte(rAdd); //写地址
rDat = DS1302_ReadByte(); //读数据
DS1302_RST = 0;
DS1302_CLK = 1;
return (rDat);
}
/*********************************************************************************************
函数名:DS1302写字节函数
调 用:DS1302_WriteData(uchar,uchar);
参 数:指定的地址,指定的数据
返回值:
备 注:
/**********************************************************************************************/
void DS1302_WriteData(unsigned char wAdd, unsigned char wDat)
{
DS1302_CLK = 0;
DS1302_RST = 0;
DS1302_RST = 1;
DS1302_WriteByte(wAdd); //写地址
DS1302_WriteByte(wDat); //写数据
DS1302_RST = 0;
DS1302_CLK = 1;
}
/*********************************************************************************************
函数名:DS1302读数据函数
调 用:DS1302_GetTime_ALL(SYSTEMTIME);
参 数:存储数据的SYSTEMTIME结构体
返回值:
备 注:
/**********************************************************************************************/
void DS1302_GetTime_ALL(SYSTEMTIME *Time)
{
unsigned char ReadValue;
ReadValue = DS1302_ReadData(DS1302_SECOND+1);
Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = DS1302_ReadData(DS1302_MINUTE+1);
Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = DS1302_ReadData(DS1302_HOUR+1);
Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = DS1302_ReadData(DS1302_DAY+1);
Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = DS1302_ReadData(DS1302_WEEK+1);
Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = DS1302_ReadData(DS1302_MONTH+1);
Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = DS1302_ReadData(DS1302_YEAR+1);
Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
}
/*********************************************************************************************
函数名:DS1302设置时间数据函数
调 用:DS1302_SetTime(uchar, uchar);
参 数:存储数据的SYSTEMTIME结构体
返回值:
备 注:
/**********************************************************************************************/
void DS1302_SetTime(unsigned char sADD, unsigned char sDAT)
{
DS1302_WriteData(0x8e,0x00); //关闭写保护
DS1302_WriteData(sADD,DEC2BCD(sDAT));
/*DS1302_WriteData(DS1302_MONTH,DEC2BCD(Time->Month));
DS1302_WriteData(DS1302_WEEK,DEC2BCD(Time->Week));
DS1302_WriteData(DS1302_DAY,DEC2BCD(Time->Day));
DS1302_WriteData(DS1302_HOUR,DEC2BCD(Time->Hour)|Time_24_Hour);
DS1302_WriteData(DS1302_MINUTE,DEC2BCD(Time->Minute));
DS1302_WriteData(DS1302_SECOND,DEC2BCD(Time->Second)|Time_Start);*/
DS1302_WriteData(0x8e,0x80); //打开写保护
}
/*********************************************************************************************
函数名:DS1302辅助设置日期函数
调 用:unsigned char DS1302_GetTheDay();
参 数:
返回值:当月总天数
备 注:自动读取DS1302内部年、月,并计算当月总天数
/**********************************************************************************************/
unsigned char DS1302_GetTheDay(void)
{
unsigned char tYear,tMonth;
tYear = BCD2DEC(DS1302_ReadData(DS1302_YEAR+1)); //当前年
tMonth = BCD2DEC(DS1302_ReadData(DS1302_MONTH+1));//当前月
switch (tMonth)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:return 31; //1、3、5、7、8、10、12 月均为31天
case 4:
case 6:
case 9:
case 11:return 30; //4、6、9、11 月均为30天
case 2:
if (tYear%4 == 0) //2月闰年为29天
return 29;
else
return 28; //平年为28天
default: return 0;
}
}
/*********************************************************************************************
函数名:DS1302初始化函数
调 用:Init_DS1302();
参 数:存储数据的SYSTEMTIME结构体
返回值:
备 注:
/**********************************************************************************************/
void Init_DS1302(void) //-设置1302的初始时间(2007年1月1日00时00分00秒星期一)
{
unsigned char i;
if(DS1302_ReadData(0xc1) != 0x10){
DS1302_WriteData(0x8e,0x00); //允许写操作
DS1302_WriteData(0x8c,0x10); //年
DS1302_WriteData(0x8a,0x04); //星期
DS1302_WriteData(0x88,0x07); //月
DS1302_WriteData(0x86,0x01); //日
DS1302_WriteData(0x84,0x12); //小时
DS1302_WriteData(0x82,0x00); //分钟
DS1302_WriteData(0x80,0x00); //秒
DS1302_WriteData(0x90,0xACC5); //充电
DS1302_WriteData(0xc0,0x10); //写入初始化标志RAM(第00个RAM位置)
for(i=0; i<60; i+=2){ //清除闹钟RAM位为0
DS1302_WriteData(0xC2+i,0x00);
}
DS1302_WriteData(0x8E,0x80); //禁止写操作
}
}
#endif
anyone writing that kind of code has no business writing code at all.
其实我说的是两个问题. 一个是有没有中断, 另一个是时序对不对.
我的意思是:先检查中断 如果确认没有中断影响的话 则进一步检查时序(因为程序时序问题可能性小一些 而中断容易被忽视. 注意同样晶振频率 在不同51内核的单片机不一样,所以参考已有的程序时要注意,不要照搬)
另外, 你说"DS1302的时序是不受中断影响" 可能吗? 实际上,读写DS1302的接口是软件实现的,当然会有影响. 比如说中断处理时间太长,或者外部中断没处理好,造成本应只中断一次的却反复中断多次,能没影响吗
我做的一个带时钟遥控开关,
解码用定时器中断查询方式,定时器每256us频繁中断,
不关中断读取DS1302没发现什么问题
定时器每100us频繁中断解码时,读取DS1302也没发现什么问题
一周热门 更多>