ds1302,感觉数据没写进芯片。求助啊。高手们。不知道为什么总是显示0。编译显示没错误

2024-12-14 01:35:13
推荐回答(2个)
回答1:

********************************************************
文件:DS1302.C
环境:编译为ICC AVR6.25A,仿真为AVR Studio4.10
硬件:ATMEGA64L芯片
日期:2008年3月7日
功能:驱动时钟芯片DS1302
备注:
*******************************************************************************/

/*=======================硬件说明===============================================
指令 指令码 功能

==============================================================================*/

//=======================头文件=================================================
#include
#include
#include
#include
#include
#include

#include "main.h"
#include "Variable.h"
#include "DS1302.h"
//==============================================================================

/****************************************************************
* 名称 : void Reset_3wire(void)
* 功能描述: reset and enable the 3-wire interfaT_CE
* 输入参量: 无
* 输出参量: 无
* 调用子程: 无
* 使用方法: 对3-wire 操作的话,首先要使能
-------------------------------------------------*/
void Reset_3wire(void)
{
DS1302_RST_OUT// 输出
DS1302_CLK_OUT
DS1302_IO_OUT
DS1302_CLK_LOW
Delay_nus(10);
DS1302_RST_LOW
Delay_nus(10);
DS1302_RST_HIGH
Delay_nus(10);
}
/****************************************************************
* 名称 : void Write_Byte_3W(unsigned char W_Byte)
* 功能描述: write one byte to the deviT_CE
* 输入参量: 需要写的字节
* 输出参量: 无
* 调用子程: 无
* 使用方法: 无论读写,都首先要写东西
-------------------------------------------------*/
void Write_Byte_3W(unsigned char W_Byte)
{
unsigned char i;
for(i = 0; i < 8; i++)
{
DS1302_IO_LOW
if(W_Byte & 0x01)
{
DS1302_IO_HIGH /* set port pin high to read data */
}
Delay_nus(10);
DS1302_CLK_LOW
Delay_nus(10);
DS1302_CLK_HIGH
Delay_nus(10);
W_Byte >>= 1;
}
}
//****************************************************************
/****************************************************************
* 名称 : unsigned char Read_Byte_3W()
* 功能描述: read one byte from the deviT_CE
* 输入参量: 需要写的字节
* 输出参量: 读出的数据
* 调用子程: 无
* 使用方法: 从3 线器件读数据
----------------------------*/
unsigned char Read_Byte_3W(void)
{
unsigned char i;
unsigned char R_Byte;
unsigned char TmpByte;
R_Byte = 0x00;
DS1302_IO_IN //0xF7;//改变io 口的方向为输入
Delay_nus(10);
for(i = 0; i < 8; i++)
{
DS1302_CLK_HIGH
Delay_nus(10);
DS1302_CLK_LOW //下降沿数据有效
Delay_nus(10);
if(READ_DS1302_IO)
TmpByte=1;//位操作要小心
else
TmpByte=0;
TmpByte <<= 7;
R_Byte >>= 1;
R_Byte |= TmpByte;
}
return R_Byte;
}
//******************************************************************
/****************************************************************
* 名称 : Get_Time
* 功能描述: 读取DS1302 当前时间
* 输入参量: ucCurtime: 保存当前时间地址。当前时间格式为: 秒 分 时 日 月 星期 年
7Byte (BCD 码) 1B 1B 1B 1B 1B 1B 1B
* 输出参量: 无
* 调用子程: 无
* 使用方法:
----------------------------*/
void DS1302_Get_Time(unsigned char ucCurtime[])
{
unsigned char i;
Reset_3wire();
Write_Byte_3W(0xBF); /* clock burst */
for(i=0;i<7;i++)
ucCurtime[i]=Read_Byte_3W();
//Reset_3wire();
DS1302_RST_LOW
}
/****************************************************************
* 名称 : Set_Time
* 功能描述: initialize time & date from user entries
* 输入参量: unsigned char yr, mn, date, dy, hr, min, sec, day;设置时间并启动
* 输出参量: OK --- 设置成功
* ERROR --- 时间格式错误,无法设置
* 调用子程: 无
* 使用方法:
----------------------------*/
unsigned char DS1302_Set_Time(unsigned char *pClock)
{
unsigned char i;

i = Check_Time(pClock);
if(i == ERROR)
return ERROR;

pClock[5] = Get_Day(pClock[6],pClock[4],pClock[3]); //取星期

//hr = hr & 0x3f; /* forT_CE clock to 24 hour mode */
Reset_3wire();
Write_Byte_3W(0x8e); /* control register */
Write_Byte_3W(0); /* disable write protect */
Reset_3wire();
//Write_Byte_3W(0x90); /* trickle charger register */
//Write_Byte_3W(0xab); /* enable, 2 dT IOdes, 8K resistor */
//Reset_3wire();
Write_Byte_3W(0xbe); /* clock burst write (eight registers) */
for(i=0;i<7;i++)
{
Write_Byte_3W(*(pClock++));
}
Write_Byte_3W(0); /* must write control register in burst mode */
//Reset_3wire();
DS1302_RST_LOW
return OK;
}//******************************************************************

//------------------------------------------------------------------------------
//函数名称:Get_Day
//函数功能:根据年月日算出星期
//函数参数:year --- 年
// month --- 月
// date --- 日
//函数返回:day --- 星期
//------------------------------------------------------------------------------
//计算公式使用著名的蔡勒(Zeller)公式。即:
//w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1
//公式中的符号含义如下,
//w:星期;
//c:世纪-1;
//y:年(两位数);
//m:月(m大于等于3,小于等于14,即在蔡勒公式中,
// 某年的1、2月要看作上一年的 13、14月来计算,
// 比如2003年1月1日要看作2002年的13月1日来计算);
//d:日;[ ]代表取整,即只要整数部分。

//C是世纪数减一,y是年份后两位,M是月份,d是日数。
//1月和2月要按上一年的13月和 14月来算,这时C和y均按上一 年取值。
//------------------------------------------------------------------------------
unsigned char Get_Day(unsigned char year,unsigned char month,unsigned char date)
{
unsigned char day;
unsigned int temp;
unsigned char century;
year = Hex_To_Decimal(year);
month = Hex_To_Decimal(month);
date = Hex_To_Decimal(date);

century = 20;
if(month < 3)
{
month += 12;
if(year == 0)
{
year = 99;
century --;
}
else
year --;
}
temp = (month + 1) * 26;
temp = temp / 10;
temp += year;
temp += (year >> 2);
temp += (century >> 2);
temp -= (century << 1);
temp += date;
temp --;
day = temp % 7;
if(day == 0)
day = 7;
return day;
}

//=======================函 数===============================================
//函数名称:Check_Time
//函数功能:检查时间格式是否正确,只能检查2000-2099年
//函数参数:buffer --- 时间:字节从高到低,年 星期 月 日 时 分 秒
//函数返回:result --- OK: 格式正确
// ERROR:格式错误
//==============================================================================
unsigned char Check_Time(unsigned char *buffer)
{
unsigned char year;
unsigned char month;
unsigned char date;
unsigned char hour;
unsigned char minute;
unsigned char second;
year = Hex_To_Decimal(buffer[6]);
month = Hex_To_Decimal(buffer[4]);
date = Hex_To_Decimal(buffer[3]);
hour = Hex_To_Decimal(buffer[2]);
minute = Hex_To_Decimal(buffer[1]);
second = Hex_To_Decimal(buffer[0]);

if(second >= 60)
buffer[0] = 0x30;
if(minute >= 60)
return ERROR;
if(hour >= 24)
return ERROR;
if(month >= 13)
return ERROR;
if(month & 1)
{
if(date >= 32)
return ERROR;
}
else if(month == 2)
{
if(year % 4)
{
if(date >= 29)
return ERROR;
}
else
{
if(date >= 30)
return ERROR;
}
}
else
{
if(date >= 31)
return ERROR;
}
return OK;
}

从芯片读出来的已经是ASCII码了,所以直接显示到数码管就可以了。

回答2:

首先确保你接外部晶振了,电路没有问题,你试一下是不是这个问题,DS1302在首次上电使用时,需要打开外部晶振,若没有打开时间不会走,若使用过了,就不需要调用次函数了。函数如下
void DS1302_SetRTC(void) //设定 日历,相当于初始化1302
{
unsigned char i,*p,tmp;
for(i=0;i<7;i++)
{ //BCD处理,这里处理时,使秒的CH位为0,开启振荡器,使小时位的12/24为0,使用24小时制
tmp=RTC[i]/10;
RTC[i]=RTC[i]%10;
RTC[i]=RTC[i]+tmp*16;
}
DS1302_WriteData(0x8E,0x00);//取消写保护

p=write_rtc_address; //传地址
for(i=0;i<7;i++) //7次写入 秒分时日月周年
{
DS1302_WriteData(*p,RTC[i]);
p++;
}
DS1302_WriteData(0x8E,0x80);//写保护设置
}
自己看了。若还不行,尝试将要是还不行,告诉我,我在看看,我也是初学。