蓝桥杯——使用DS1302设置时间

一、原理部分

命令字节

图三
命令字节启动每个数据传输。MSB(位7)必须是逻辑1。如果为0,则将禁用对DS1302的写入。如果逻辑0,则位6指定时钟/日历数据;如果逻辑1,则指定RAM数据。位1到5指定要输入或输出的指定寄存器,LSB(位0)指定逻辑0时的写入操作(输入)或逻辑1时的读取操作(输出)。命令字节总是从LSB(位0)开始输入。

时钟和日历

在这里插入图片描述
时间和日历信息是通过读取适当的寄存器字节获得的。表1说明了RTC寄存器。通过写入适当的寄存器字节来设置或初始化时间和日历。时间和日历寄存器的内容采用二进制编码十进制(BCD)格式。

实时通信

在这里插入图片描述
设置时分秒的地址分别为0x84,0x82,0x80,读取的地址分别为0x85,0x83,0x81
0x8e为保护位地址,第七位为1时打开保护位,为0时关闭保护位.其他位都为0
所以在ds1302.c中编写以下代码

void set_sfm(unsigned char shi,unsigned char fen,unsigned char miao)
{
	Write_Ds1302_Byte(0x8e,0x00);//关闭保护位
	Write_Ds1302_Byte(0x80,(miao/10)*16+miao%10);//设置秒BCD码下同
	Write_Ds1302_Byte(0x82,(fen/10)*16+fen%10);//设置分
	Write_Ds1302_Byte(0x84,(shi/10)*16+shi%10);//设置小时
	Write_Ds1302_Byte(0x8e,0x80);//打开保护位
}

在主函数中编写以下代码来设置时间并且获得时间

		set_sfm(23,59,55);//设置时间
		//读取时间
		shi_temp =Read_Ds1302_Byte(0x85);
		fen_temp=Read_Ds1302_Byte(0x83);
		miao_temp=Read_Ds1302_Byte(0x81);

		//将读取到的BCD码转化为十进制
		shi = shi_temp/16*10+shi_temp%16;
		fen = fen_temp/16*10+fen_temp%16;
		miao = miao_temp/16*10+miao_temp%16;

二、完整代码

实验平台:CT107D
实验芯片:stc15f2k60s2
实验现象:设置时间为23:59:55,显示在数码管上
代码如下

ds1302.c

#include <stc15f2k60s2.h>
#include <intrins.h>

sbit SCK=P1^7;		
sbit SDA=P2^3;		
sbit RST = P1^3;   // DS1302复位												

void Write_Ds1302(unsigned  char temp) 
{
	unsigned char i;
	for (i=0;i<8;i++)     	
	{ 
		SCK=0;
		SDA=temp&0x01;
		temp>>=1; 
		SCK=1;
	}
}   

void Write_Ds1302_Byte( unsigned char address,unsigned char dat )     
{
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1; 	_nop_();  
 	Write_Ds1302(address);	
 	Write_Ds1302(dat);		
 	RST=0; 
}

unsigned char Read_Ds1302_Byte ( unsigned char address )
{
 	unsigned char i,temp=0x00;
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1;	_nop_();
 	Write_Ds1302(address);
 	for (i=0;i<8;i++) 	
 	{		
		SCK=0;
		temp>>=1;	
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
	SCK=1;	_nop_();
	SDA=0;	_nop_();
	SDA=1;	_nop_();
	return (temp);			
}

void set_sfm(unsigned char shi,unsigned char fen,unsigned char miao)
{
	Write_Ds1302_Byte(0x8e,0x00);//关闭保护位
	Write_Ds1302_Byte(0x80,(miao/10)*16+miao%10);//设置秒
	Write_Ds1302_Byte(0x82,(fen/10)*16+fen%10);//设置分
	Write_Ds1302_Byte(0x84,(shi/10)*16+shi%10);//设置小时
	Write_Ds1302_Byte(0x8e,0x80);//打开保护位
}

ds1302.h

#ifndef __DS1302_H
#define __DS1302_H

void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );
void set_sfm(unsigned char shi,unsigned char fen,unsigned char miao);
#endif

main.c

#include<stc15f2k60s2.h>
#include<ds1302.h>

#define uchar unsigned char
#define uint unsigned int

sbit buzz = P0^6;


uchar code duan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00};//定义段码数组
uchar disbuff[8];//定义显示数字数字
uchar boot_time = 0;
uchar shi,fen,miao;

void closebuzz()
{
	P2 = 0xa0;
	buzz = 0;
	P2 = 0x00;
}

void shownum()//显示数字函数
{
	disbuff[0]=shi/10;
	disbuff[1]=shi%10;
	disbuff[2]=10;
	disbuff[3]=fen/10;
	disbuff[4]=fen%10;
	disbuff[5]=10;
	disbuff[6]=miao/10;
	disbuff[7]=miao%10;
}

void display()//数码管扫描函数
{
	static uchar index = 0;
	P2 = 0xe0;
	P0 = 0xff;
	P2 = 0x00;

	P2 = 0xc0;
	P0 = 1<<index;
	P2 = 0x00;

	P2 = 0xe0;
	P0 = ~duan[disbuff[index]];
	P2 = 0x00;

	index++;
	index &= 0x07;

}

void Timer0Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x40;		//设置定时初值
	TH0 = 0xA2;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
	EA = 1 ; 
}

void time0() interrupt 1
{
	display();		
}

void main()
{
	uchar shi_temp,fen_temp,miao_temp;
	closebuzz();
	Timer0Init();
	set_sfm(23,59,55);//设置时间

	while(1)
	{
		shownum();
		//读取时间
		shi_temp =Read_Ds1302_Byte(0x85);
		fen_temp=Read_Ds1302_Byte(0x83);
		miao_temp=Read_Ds1302_Byte(0x81);

		//将读取到的BCD码转化为十进制
		shi = shi_temp/16*10+shi_temp%16;
		fen = fen_temp/16*10+fen_temp%16;
		miao = miao_temp/16*10+miao_temp%16;

	}
}
发布了22 篇原创文章 · 获赞 34 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/FuckerGod/article/details/104181170