单片机蓝桥杯——DS1302

1、原理

对 DS1302的操作就是对其内部寄存器的操作,DS1302内部共有12个寄存器,其中有:7 个寄存器与日历、时钟相关,存放的数据位为 BCD 码形式。
此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器
及与 RAM 相关的寄存器等。如下图所示,时钟日历包含在 7 个读/写寄存器内,读/写寄存器中的数据是BCD 码。
DS1302数据地址和传输格式
秒寄存器的 BIT7 定义为时间暂停位,当 BIT1 为 1 时,时钟振荡器停止工作,DS1302 进入低功耗模式,电源消耗小于 100 微安,当 BIT1 为 0 时,时钟振荡器启动,DS1302 正常工作。

小时寄存器的 BIT7 定义为 12 或 24 小时工作模式选择位,当 BIT7 为高时,为 12 小时工作模式,此时 BIT5 为 AM/PM 位,低电平标示 AM,高电平标示PM,在 24 小时模式下,BIT5 为第二个 10 小时位标示(20~23 时)。

写保护寄存器的 BIT7:WP 是写保护位,工作时,出 WP 外的其他位都置为0,对时钟/日历寄存器或 RAM 进行写操作之前,WP 必须为 0,当 WP 为高电平的时候,不能对任何时钟/日历寄存器或 RAM 进行写操作。

此外,DS1302还有突发模式(burst mode 或称多字节传输模式)可以指定任何的时钟/日历或者 RAM 寄存器为突发模式,此处不再赘述。

2、代码

代码功能:初始时间为2021年5月9日23时59分50秒,八位数码管从左到右依次显示“时-分-秒”。
DS1302 的初始化部分:只需要调用一次,写入一个初始值即可

#include "STC15F2K60S2.h"
#include "intrins.h"
#include "ds1302.h"
#define uchar unsigned char
#define uint unsigned int
uchar segCode[25]={
    
    0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,       //0~9的段码(不带小数点)
								 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff,0xbf}; //0.~9.的段码(带小数点) 以及0xff全灭
uchar segVal[]={
    
    20,20,20,20,20,20,20,20};  //数码管初始化显示1 2 3 4 1. 2. 3. 4.

uchar DS1302r_add[] = {
    
    0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};	//DS1302读数据的地址
uchar DS1302w_add[] = {
    
    0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};	//DS1302写数据的地址
uchar Timer[] = {
    
    0x50,0x59,0x23,0x05,0x09,0x07,0x21};				//2021年,5月9日,23时59分50秒

void InitDS1302()//DS1302初始化时间
{
    
    
	uchar i;
	Write_Ds1302_Byte(0x8e,0x00);//0x8e为写保护寄存器
	for(i=0; i<7; i++)
		Write_Ds1302_Byte(DS1302w_add[i],Timer[i]);
	Write_Ds1302_Byte(0x8e,0x80);
}
void ReadDS1302()//读取DS1302时间
{
    
    
	uchar i;
	for(i=0; i<7; i++)
		  [i] = Read_Ds1302_Byte(DS1302r_add[i]);
}
void SelectHC573(uchar val) 
{
    
    
	switch(val)
	{
    
    
		case 4 : P2 = (P2 & 0x1f) | 0x80; break;
		case 5 : P2 = (P2 & 0x1f) | 0xa0; break;
		case 6 : P2 = (P2 & 0x1f) | 0xc0; break;
		case 7 : P2 = (P2 & 0x1f) | 0xe0; break;
		default: P2 = (P2 & 0x1f); break;		
	}
}
void InitSystem()//系统初始化关闭蜂鸣器、继电器、LED
{
    
    
	SelectHC573(5);
	P0 = 0xbf;      //由于不同板子的引脚接法不同,此时的初始值也不同
	SelectHC573(4);	
	P0 = 0xff;     //LED全灭
}
void Timer0Init(void)		//1毫秒@12.000MHz
{
    
    
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
	EA = 1;
}
uchar segFlag = 0;//数码管显示位标志位
uint count300ms = 0;//1s定时标志位
bit timerFlag = 1;//DS1302读时间的标志位,为1时读,为0时不
void ServiceTimer0() interrupt 1
{
    
    
	uchar pushp0,pushp2;
	pushp0 = P0;
	pushp2 = P2;//入栈
//数码管
	SelectHC573(6);
	P0 = (0x01<<segFlag);
	SelectHC573(7);	
	P0 = segCode[segVal[segFlag]];
	segFlag++;
	if(segFlag == 8) segFlag = 0;
//1s定时,DS18B20读温度
	count300ms++;
	if(count300ms>300)//300ms更新一次数值
	{
    
    
		count300ms = 0;
		timerFlag = 1;
	}
	P2 = pushp2;//出栈
	P0 = pushp0;
}
uchar tem;
void main()
{
    
    
	InitSystem();
	Timer0Init();
InitDS1302();
	while(1)
	{
    
    	
		if(timerFlag==1)
		{
    
    
			ReadDS1302();
			timerFlag=0;
		}
		segVal[0] = Timer[2] / 16;
		segVal[1] = Timer[2] % 16;
		segVal[2] = 21;
		segVal[3] = Timer[1] / 16;
		segVal[4] = Timer[1] % 16;
		segVal[5] = 21;
		segVal[6] = Timer[0] / 16;
		segVal[7] = Timer[0] % 16;

	}
}

显示结果如下:

请添加图片描述

猜你喜欢

转载自blog.csdn.net/weixin_52801934/article/details/123595514
今日推荐