我看了你回答的DS1302时钟的程序,但还是写了不对,您能否帮一下忙。我的外接了纽扣电池。

 我来答
百度网友8692aa5
2011-12-12 · TA获得超过1291个赞
知道小有建树答主
回答量:201
采纳率:100%
帮助的人:82.8万
展开全部
AVR MEGE16 DS1302程序,分别保存为DS1302.C DS1302.H
后面是51 DS1302程序,分别保存为DS1302.h main.c
用哪个下哪个吧。

#include "DS1302.h"
#include "ym12864.h"
#include "delay.h"

/*******************************************
函数名称: DS1302_init
功 能: 初始化DS1302的数据接口
参 数: 无
返回值 : 无
/********************************************/
void DS1302_portinit(void)
{
DDRB|=BIT(RTC_CLK)|BIT(RTC_DATA)|BIT(RTC_CS);//将时钟端(RTC_CLK)数据端(RTC_DATA)片选端(RTC_CS)设置为输出
}
/*******************************************
函数名称: DS1302_writeB
功 能: 向DS1302写入一个字节数据(没有RST操作)
参 数: byte--要写入的数据
返回值 : 无
/********************************************/
void DS1302_writeB(uchar byte)
{
uchar i;
for(i=0;i<8;i++) //8位数据计数
{
CLR_CLK; //拉低时钟端
if(byte&0x01) //当前位是否是1
{
SET_DATA; //当前位是1,拉高数据端
}
else
{
CLR_DATA; //当前位是0,拉低数据端
}
delay_us(10); //调整时钟和脉冲宽度
SET_CLK; //时钟上升沿(DS1302采样数据)
byte>>=1; //数据右移1位,为送出新数据位做准备
}
}
/*******************************************
函数名称: DS1302_readB
功 能: 从DS1302读出一个字节数据(没有RST操作)
参 数: 无
返回值 : byte--读出的数据
/********************************************/
uchar DS1302_readB(void)
{
uchar i,byte=0;
DATA_IN; //将数据端口设置为输入
CLR_DATA; //无上拉电阻
for(i=0;i<8;i++) //8位数据计数
{
byte>>=1; //保存读入的数据位
SET_CLK; //时钟上升沿
delay_us(10); //延时,调整时钟脉冲宽度
CLR_CLK; //时钟下降沿,DS1302输出数据位
delay_us(10); //等待数据变化(MEGA16太快,必须等待DS1302的数据位输出,否则不能正确读出)
if(PINB&BIT(RTC_DATA)) //当前位是否是高电平
{
byte|=BIT(PB7); //是高电平就将返回数据的当前位置1
}
else
{
byte&=~BIT(PB7); //是低电平就将返回数据的当前位置0
}
}
DATA_OUT; //最后将数据端口设置为输出
return byte; //返回读出的数据
}
/*******************************************
函数名称: DS1302_writeD
功 能: 向DS1302的某个地址写入一个字节数据
参 数: addr--地址值(寄存器或RAM)
data--要写入的地址
返回值 : 无
/********************************************/
void DS1302_writeD(uchar addr,uchar data)
{
CLR_CS; //拉低片选端
CLR_CLK; //拉低时钟端
delay_us(10);
SET_CS //拉高片选端
delay_us(10); //调整片选脉冲
DS1302_writeB(addr); //写入操作命令(地址)
delay_us(10);
CLR_CLK; //拉低时钟端
delay_us(10);
DS1302_writeB(data); //写入数据
CLR_CLK; //拉低时钟端
delay_us(10); //调整片选脉冲
CLR_CS; //拉低片选端
}
/*******************************************
函数名称: DS1302_readD
功 能: 从DS1302的某个地址读出一个字节数据
参 数: addr--地址值(寄存器或RAM)
返回值 : data--读出的数据
/********************************************/
uchar DS1302_readD(uchar addr)
{
uchar data;
CLR_CS; //拉低片选端
CLR_CLK; //拉低时钟端
delay_us(10);
SET_CS; //拉高片选端
delay_us(10); //调整片选脉冲
DS1302_writeB(addr); //写入操作命令(地址)
delay_us(10);
data=DS1302_readB(); //读出数据
delay_us(10);
CLR_CLK; //拉低时钟端
CLR_CS; //拉低片选端
return data; //返回读出的数据
}
/*******************************************
函数名称: DS1302_setT
功 能: 设置DS1302的时间
参 数: ptTimeD--设置时间数组指针
返回值 : 无
/********************************************/
void DS1302_setT(uchar ptTimeD[])
{
uchar i;
uchar addr = 0x80; //写入地址从秒寄存器开始
DS1302_writeD(C_WP|WR,UPROTECT); //控制命令,WP位为0,允许写操作
delay_ms(5);
for(i=0;i<7;i++)
{
DS1302_writeD(addr|WR,ptTimeD[i]); // 秒 分 时 日 月 星期 年
addr+=2;
delay_ms(1);
}
DS1302_writeD(C_WP|WR,PROTECT); //控制命令,WP位为1,不允许写操作
}
/*******************************************
函数名称: DS1302_getT
功 能: 读取DS1302的当前时间
参 数: time[]--读取的时间数组
返回值 : 无
/********************************************/
void DS1302_getT(uchar time[])
{
uchar i;
////////下面的是单次读写//////////////////////////
/* uchar addr = 0x80; //读取地址从秒寄存器开始
for(i=0;i<7;i++)
{
time[i]=DS1302_readD(addr|RD); // 秒 分 时 日 月 星期 年
addr+=2;
}*/
////////////////////////////////////////////////////
/////////下面是多字节读取///////////////
CLR_CS; //拉低片选端
delay_us(10);
SET_CS; //拉高片选端
delay_us(10); //调整片选脉冲
DS1302_writeB(0xbf); // 0xbf:时钟多字节读取命令
for (i=0;i<8;i++) //时间数据的存放格式是:
{ //秒,分,时,日,月,星期,年,控制
time[i]=DS1302_readB(); //【7个数据(BCD格式)+1个控制】
}

CLR_CS; //拉低片选端
///////////////////////////////////////////////
CLR_CLK; //拉低时钟端(时钟端在不操作时为低)
}
/*******************************************
函数名称: DS1302_check
功 能: 检测DS1302是否正常工作
参 数: 无
返回值 : exist--为TRUE为检测到DS1302,为FALSE为没检测到
/********************************************/
/*uchar DS1302_check(void)
{
uchar exist;
DS1302_writeD(C_WP|WR,UPROTECT); //写入写允许命令
DS1302_writeD(C_RAMBASE|WR,0xA5); //RAM0写入0xA5
exist=DS1302_readD(C_RAMBASE|RD); //读取RAM0
if(exist==0xA5)
{
exist=TRUE; //如果读取值与写入值相等,返回TRUE
}
else
{
exist=FALSE; //如果读取值与写入值不相等,返回FALSE
}
return exist;
}*/
/*******************************************
函数名称: DS1302_init
功 能: 初始化DS1302
参 数: 无
返回值 : 无
/********************************************/
void DS1302_init(void)
{
DS1302_writeD(C_WP|WR,UPROTECT); //写入写允许命令
DS1302_writeD(C_SEC|WR,CLK_START); //启动振荡器,DS1302开始工作
DS1302_writeD(C_WP|WR,PROTECT); //控制命令,WP位为1,不允许写操作
}
/*******************************************
函数名称: BCD_ASCII
功 能: 将压缩BCD码转换成ascii码
参 数: BCD--将要转换的压缩BCD码
ptasc--转换后的ASCII码数组指针
返回值 : 无
/********************************************/
void BCD_ASCII(uchar BCD,uchar ptasc[])
{
ptasc[0]=BCD/16|0x30; //0X58 35 38 //转换十位
ptasc[1]=BCD&0x0F|0x30; //转换个位
}
/*******************************************
函数名称: Disp_time
功 能: 在1602液晶上显示当前时间(第1行格式:年-月-日 星期;第2行格式:时-分-秒)
参 数: time[]--时间数组
返回值 : 无
/********************************************/
void Disp_time(uchar time[])
{
uchar i,asc[2];
uchar line1[11]={0,0,'-',0,0,'-',0,0,' ',0,'\0'};//显示第1行的字符数组
uchar line2[9]={0,0,':',0,0,':',0,0,'\0'}; //显示第2行的字符数组
for(i=0;i<3;i++) //为第2行的字符数组赋值
{
BCD_ASCII(time[2-i],asc);
line2[i*3]=asc[0];
line2[i*3+1]=asc[1];
}
BCD_ASCII(time[6],asc); //为第1行的年赋值
line1[0]=asc[0];
line1[1]=asc[1];
BCD_ASCII(time[4],asc); //为第1行的月赋值
line1[3]=asc[0];
line1[4]=asc[1];
BCD_ASCII(time[3],asc); //为第1行的日赋值
line1[6]=asc[0];
line1[7]=asc[1];
BCD_ASCII(time[5],asc); //为第1行的星期赋值
line1[9]=asc[1];
Disp_String(0,16,"20"); //第1行从第3个位置开始显示,将07年显示为2007的形式
Disp_String(0,32,line1);
Disp_String(3,32,line2); //第2行从第5个位置开始显示,/第2行显示
}

#ifndef __DS1302_H
#define __DS1302_H
#include <iom16v.h>
#include <macros.h>

typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;

/******************RTC常量******************/
#define RTC_CLK PB1
#define RTC_DATA PB0
#define RTC_CS PB4

#define SET_CLK PORTB|=BIT(RTC_CLK);
#define CLR_CLK PORTB&=~BIT(RTC_CLK);
#define SET_DATA PORTB|=BIT(RTC_DATA);
#define CLR_DATA PORTB&=~BIT(RTC_DATA);
#define SET_CS PORTB|=BIT(RTC_CS);
#define CLR_CS PORTB&=~BIT(RTC_CS);

#define DATA_OUT DDRB|=BIT(RTC_DATA);
#define DATA_IN DDRB&=~BIT(RTC_DATA);

//命令
#define RD 0x01
#define WR 0x00
#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 地址需左移一位

void DS1302_portinit(void);
void DS1302_writeB(unsigned char byte);
unsigned char DS1302_readB(void);
void DS1302_writeD(unsigned char addr,unsigned char data);
unsigned char DS1302_readD(unsigned char addr);
void DS1302_setT(unsigned char ptTimeD[]);
void DS1302_getT(unsigned char time[]);
void DS1302_init(void);
void BCD_ASCII(unsigned char BCD,unsigned char ptasc[]);
void Disp_time(unsigned char time[]);

extern void DS1302_portinit(void);
extern void DS1302_setT(unsigned char ptTimeD[]);
extern void DS1302_getT(unsigned char time[]);
extern void DS1302_init(void);
extern void Disp_time(unsigned char time[]);

#endif

#include<reg52.h>

#define uint unsigned int
#define uchar unsigned char

sbit dsrst=P1^4;
sbit dssclk=P1^1;
sbit dsio=P1^0;

uint a[24]={0,0,0,0,0,0,1,0,0,1,9,0,0,0,0,0,0,0,1,0,1,0,9,0};
//分别对应秒秒分分时时日日月月年年
//后12位为闹钟位,用于存储闹钟数据

//1302write DS1302写数据
void dswrite(uchar dswrite)
{
uchar i,temp;
delay(1);
temp=dswrite;
for(i=0;i<8;i++)
{
dsio=temp&0x01;
delay(1);
dssclk=1;
delay(1);
dssclk=0;
temp=temp>>1;
}
}

//1302read Ds1302读数据
uchar dsread()
{
uchar i,temp;
delay(1);
temp=0;
for(i=0;i<8;i++)
{
temp=temp>>1;
if(dsio==1)temp=temp+0x80;
delay(1);
dssclk=1;
delay(1);
dssclk=0;
}
return temp;
}

//1302addshuju DS1302向某地址写入某数据
void dsaddshuju(uchar add,uchar dsshuju)
{
dsrst=0;
dssclk=0;
dsrst=1;
dswrite(add);// 地址,命令
dswrite(dsshuju);// 写1Byte数据
dssclk=1;
dsrst=0;
dsio=0;

}

//1302on DS1302初始化
void dson()
{
uchar i;
dsaddshuju(0x8c,(a[11]<<4)+a[10]);
for(i=0;i<5;i++)
{
dsaddshuju(0x88-i*2,(a[9-i*2]<<4)+a[8-i*2]);
}
}

/***********************************************************************/
/***********************************************************************/
/*************************** ****************************/
/***********************************************************************/
/************************** ***************************/
/************************** ***************************/
/***********************************************************************/
/***********************************************************************/
/************************ ************************/
/******************** 温度时钟显示 C语言程序 **********************/
/************************ ************************/
/***********************************************************************/
/***********************************************************************/

/***********************************************************************

硬件连接: DS1302 io - P1.0 rst - P1.4 clk - P1.1
DS18B20 dq - P1.5
LCD1602 RS- P2.2 RW - P2.3 EN - P2.4 DATAPORT - P0

/***********************************************************************/

#include<reg52.h>
#include"lcd1602.h"
#include"ds1302.h"
#include"ds18b20.h"

#define uint unsigned int
#define uchar unsigned char

uint b[6];
//年月日时分秒

uchar code row1[]={"2009-10-01 "};
uchar code row2[]={"00:00:00"};
uchar year1[12]={31,28,31,30,31,30,31,31,30,31,30,31};//平年
uchar year2[12]={31,29,31,30,31,30,31,31,30,31,30,31};//润年
uchar j[6]={0x85,0x88,0x8b,0x84+0x40,0x87+0x40,0x8a+0x40};//LCD地址

uchar i,k,jj=0,w,clock=0,bigclock=0,c=0,num;
//i循环数 k温度缓存 jj地址位
uint temp;

sbit b1=P3^0;//设置
sbit b2=P3^1;//上调
sbit b3=P3^2;//下调
sbit b4=P3^3;//转换
sbit b5=P3^4;//闹钟
sbit speaker=P3^5;

lcdscan()
{
for(i=0;i<6;i++)
{
lcdwrite(j[i]);
lcdshuju(a[11-i*2]+0x30);
lcdwrite(j[i]+0x01);
lcdshuju(a[10-i*2]+0x30);
}
}

void key()
{
if(b1==0)
{
dsaddshuju(0x80,(a[1]<<4)+a[0]+0x80);
while(b1==0)
{
for(i=0;i<6;i++)
{
b[i]=a[11-i*2+clock]*10+a[10-i*2+clock];
}

if(b4==0)
{
delay(3);
jj++;
if(jj==6)
{
jj=0;
}
}
if(b2==0)
{
delay(3);
b[jj]++;
if(b[5]==60)b[5]=0;
if(b[4]==60)b[4]=0;
if(b[3]==24)b[3]=0;
if((b[0]%4==0 && b[0]%100!=0) || b[0]%400==0){if(b[2]>year2[b[1]-1])b[2]=1;}
else {if(b[2]>year1[b[1]-1])b[2]=1;}
if(b[1]==13)b[1]=1;
if(b[0]==100)b[0]=0;

}
if(b3==0)
{
delay(3);
b[jj]--;
if(b[5]==-1)b[5]=59;
if(b[4]==-1)b[4]=59;
if(b[3]==-1)b[3]=23;
if((b[0]%4==0 && b[0]%100!=0) || b[0]%400==0){if(b[2]<=0)b[2]=year2[b[1]-1];}
else {if(b[2]<=0)b[2]=year1[b[1]-1];}
if(b[1]==0)b[1]=12;
if(b[0]==-1)b[0]=99;
}

for(i=0;i<6;i++)
{
a[11-i*2+clock]=b[i]/10;
a[10-i*2+clock]=b[i]%10;
}

lcdwrite(j[jj]);
lcdshuju(0);
lcdwrite(j[jj]+1);
lcdshuju(0);
delay(200);
lcdwrite(j[jj]);
lcdshuju(a[11-2*jj+clock]+0x30);
lcdwrite(j[jj]+1);
lcdshuju(a[10-2*jj+clock]+0x30);
delay(200);

if(b1==1)
{
dsaddshuju(0x80,(a[1]<<4)+a[0]);
dson();
}
if(b5==0)clock=12;
}
}
}

void main()
{
speaker=0;
lcdrw=0;
dson();
lcdon();
lcdwrite(0x83);
for(i=0;i<10;i++)
{
lcdshuju(row1[i]);
delay(1);
}
lcdwrite(0x84+0x40);
for(i=0;i<8;i++)
{
lcdshuju(row2[i]);
delay(1);
}
dsrst=0;
dssclk=0;
while(1)
{
for(i=0;i<5;i++)
{
dsrst=1;
dswrite(0x81+i*2);
k=dsread();
dsrst=0;
a[i*2]=k&0x0f;
a[i*2+1]=(k>>4)&0x0f;
}
dsrst=1;
dswrite(0x8d);
k=dsread();
dsrst=0;
a[10]=k&0x0f;
a[11]=(k>>4)&0x0f;

delay(100);

lcdscan();
key();
if(b5==0)
{
for(i=0;i<12;i++)
{
if(a[i+12]==a[i])num++;
}
if(num==12)bigclock=1;
else num=0;
lcdwrite(0x8e);
lcdshuju('&');
}
else
{
lcdwrite(0x8e);
lcdshuju(0x00);
}
if(bigclock==1)
{
speaker=1;
c++;
if(c==100){bigclock=0;speaker=0;}
}
temp=readtemperature();//temp是uint型的。不然会出现温度到25后回00的现象。可能是由于十六进制与十进制的差异。
lcdwrite(0x8d+0x40);
lcdshuju(temp/100+0x30);
lcdwrite(0x8e+0x40);
lcdshuju(temp/10%10+0x30);
}
}

自己看看,看不明白HI我。
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式