蓝桥杯单片机竞赛学习计划(十)

蓝桥杯单片机学习计划之DS1302时钟


前言

上一节介绍了DS18B20温度传感器的通讯方式以及使用方法,编写程序实现数码管显示环境温度,这一节我们来学习DS1302时钟模块。

一、DS1302介绍

1.芯片介绍

DS1302是一款涓流充电计时芯片,其内部包含一个实时时钟和31字节的静态RAM。实时时钟可以提供秒、分、时、日、日期、月和年的信息,并且小时具有24小时和12小时两种格式。其掉电时保持数据和时钟走时的功耗能够小于1uw。下面来看下它的引脚分布和介绍:
在这里插入图片描述
1脚和8脚是两个双电源供电的引脚,1脚Vcc2是主电源引脚,8脚Vcc1是备用电源引脚用于在没有主电源的情况下保持时间和日期,当Vcc2引脚上的电压大于Vcc1 +0.2V时,Vcc2为DS1302供电,当Vcc2小于Vcc1电压是,Vcc1为DS1302供电。即Vcc2用于连接电源电压,Vcc1可连接一个纽扣电池,如果断开电源电压,纽扣电池可以为DS1302提供电源,保持其内部的数据和时钟。
X1和X2是外接晶振的引脚,连接32.768KHZ晶振。
SCLK、I/O、CE是三个用于数据通信的引脚,SCLK是时钟引脚,I/O是数据传输引脚,CE是芯片使能引脚。
来看下竞赛板原理图:
在这里插入图片描述
从上面原理图中我们可以看到,三个通信引脚分别连接到了P17、P23、P13三个引脚上。

2.通信方式介绍

1.命令字节

对于DS1302来说,不管是写数据还是读数据,主机都要先发送一个命令字节告诉DS1302要读写那个寄存器,这个命令字节如下图所示:
第七位固定为1;第6位选择RAM和时钟,"0"选择时钟,"1"选择RAM;第5位到第1位是各个寄存器的地址;第0位选择读写操作方式,"0"选择写数据,"1"选择读数据。
在这里插入图片描述
各个寄存器定义如下图所示:
每个寄存器的读写地址表里都给出来了,写代码时直接查表即可。下面来分别解析一下这几个时间的寄存器:
第一个为秒寄存器,第七位是时钟运行标志位,如果这一位为1,则时钟振荡器停止工作,DS1302进入低功耗待机模式,如果为0则时钟启动。第6位——第4位是秒的十位,第3位——第0位是秒的个位。
第二个为分寄存器,第七位选择24小时模式或者12小时模式,如果为0则表示24小时模式,第5位是24小时模式下的十位。
其他的寄存器都是前四个位为十位,后四位为个位。
在这里插入图片描述

2.写数据

向DS1302写入数据时,首先主机需要将使能引脚CE拉高,并且在整个通信过程中都需要保持高电平不变;然后在SCLK时钟的作用下通过I/O引脚将数据按位发送出去,即每来一个SCLK时钟,发送一位数据。发送数据时,第一个字节发送命令字节,然后发送数据字节。从下图中可以看到,数据需要在SCLK上升沿之前准备好,到达上升沿时会发送出去。(注意数据从低位先开始发)
在这里插入图片描述

3.读数据

读数据过程和写数据相同,只不过发送命令字节后是主机从DS1302读取数据。
在这里插入图片描述

三、代码

#include "ds1302.h"  									

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

//向DS1302寄存器写入数据
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; 
}

//从DS1302寄存器读出数据
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 Write_Ds1302_InitTime()
{
		Write_Ds1302_Byte(0x8E,0x00);
		Write_Ds1302_Byte(0x84,0x19);
		Write_Ds1302_Byte(0x82,0x20);
		Write_Ds1302_Byte(0x80,0x00);
}
#include <STC15F2K60S2.H>
#include "intrins.h"
#include "ds1302.h"  


unsigned char SEG_Code[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//0-9段码
unsigned char SEG_Buf[8];//显示数据缓冲区


bit timer_flag_1ms;


void Seg_Display()//数码管扫描函数
{
	static unsigned char seg_index=0;//显示数据索引
	static unsigned char seg_temp=0x01;//位索引
	
	P2 = (P2&0x1f) | 0xC0;  //消隐
	P0= 0x00;
	P2=0x00;
	
	P2 = (P2&0x1f) | 0xE0;//选通段锁存器
	P0=SEG_Buf[seg_index++]; //送入段码
	P2=0x00;
	
	P2 = (P2&0x1f) | 0xC0;//选通位锁存器
	P0= seg_temp;//送入位码
	P2=0x00;
	seg_temp<<=1;
	if(seg_index>7)
	{
		seg_index=0;
		seg_temp=0x01;
	}
}

void main()
{
	unsigned char Hr,sec,min;
	unsigned int cnt;
	Write_Ds1302_InitTime();
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0=1;//开启定时器0中断
	EA=1;//开启总中断
	while(1)
	{
		if(timer_flag_1ms)
		{
			timer_flag_1ms=0;
			if(++cnt>=500)
			{
				cnt=0;
				Hr=Read_Ds1302_Byte(0x85);
				min=Read_Ds1302_Byte(0x83);
				sec=Read_Ds1302_Byte(0x81);
				SEG_Buf[0]=SEG_Code[Hr>>4];
				SEG_Buf[1]=SEG_Code[Hr&0x0f];
				SEG_Buf[2]=0xBF;
				SEG_Buf[3]=SEG_Code[min>>4];
				SEG_Buf[4]=SEG_Code[min&0x0f];
				SEG_Buf[5]=0xBF;
				SEG_Buf[6]=SEG_Code[sec>>4];
				SEG_Buf[7]=SEG_Code[sec&0x0f];
			}
		}
	}
}
void Timer0_Rountine(void)   interrupt 1    //定时器0中断,1ms
{
	timer_flag_1ms=1;
	Seg_Display();//使用定时器进行数码管扫描
}
  • 25
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值