【51单片机】程序实验16.DS1302时钟

主要参考学习资料:B站【普中官方】51单片机手把手教学视频

开发资料下载链接:http://www.prechin.cn/gongsixinwen/208.html

单片机套装:普中STC51单片机开发板A4标准版套餐7

目录

DS1302时钟芯片介绍

DS1302简介

DS1302是达拉斯公司生产的时钟芯片,其具体特点如下:

①具有涓流充电的充电方式,涓流充电通过小电流持续充电来补偿电池的自放电损失,可以有效延长电池使用寿命,保持高饱和度的电量状态。且有主电源和备用电源双电源管脚,避免断电后时钟数据损失。

②具有时钟、日历功能,可以计算2100年之前的时间信息,有闰年调整功能。

③工作电压为3.0~5.5V,在2.0V时电流为300nA,功耗极低。

④具有单字节传送和多字节传送字符组两种读写方式。

⑤具有DIP和SIOC两种封装方式,本实验板载为SIOC封装,体积非常小。

⑥通过三线制SPI串行接口与单片机通信,分别为复位信号线(使能线)、I/O数据线和时钟线,而标准的SPI分别由MISO和MOSI来实现数据的输出和输入。

⑦兼容TTL电平,可以直接跟单片机IO口连接。

⑧工作温度范围为-40℃~85℃。

DS1302八个管脚的功能如下:

名称 功能
VCC2/VCC1 主电源/备用电源
X1/X2 外部晶振管脚,提供晶振源
CE 使能管脚,高电平时芯片工作
I/O 串行数据输入输出引脚
SCLK 时钟引脚

DS1302使用

DS1302的使用分为两步:①从中读取时间②将读取到的时间转换到数码管或液晶显示

控制寄存器

控制寄存器用于存放DS1302的控制命令,对DS1302的读写进行控制。

7 6 5 4 3 2 1 0
1 RAM/CK A4 A3 A2 A1 A0 RD/WR
  • RAM/CK:设置操作对象,1为RAM,0为内部寄存器。
  • A0~A4:操作对象的操作地址位。
  • RD/WR:设置读写方向,1为读操作,2为写操作。

以下是内部寄存器和RAM的地址表:

日历/时钟寄存器

DS1302共有12个寄存器,其中7个与日历/时钟功能相关,它们的数据以BCD码格式存入。

BCD码用4位二进制位来表示1位十进制位中的0~9,表示两位数时高八位表示十位,低八位表示个位,在处理二进制数据时通过整除16提取十位,对16取余提取个位。

各个寄存器各个位的功能如下表所示:

特别说明:

  • 秒寄存器D7为DS1302运行标志位,0为工作状态,1为停止工作。
  • 小时寄存器D7为时间格式位,1为12小时制,0为24小时制,。D5和D6在12小时制下,D5区分AM/PM,D6存储小时的十位0/1;在24小时制下,D5和D6共同存储小时的十位0/1/2。
  • 写保护寄存器D7为写保护位,1开启写保护,0关闭写保护。
  • 慢充电寄存器控制涓流充电方式,很少用到,不作深入介绍。

读写时序

DS1302的数据传输方式和DS18B20相同,先传低位后传高位。

在读写操作过程中,CE必须保持高电平。读写操作完成后设置CE为低电平,等待下一次操作。

在时钟产生上升沿时数据一位一位由低到高进行写入,先写入控制命令,随后读字节在控制命令发送完成后的第一个下降沿开始读取,而写字节在控制命令发送完成后的第一个上升沿继续写入数据。

在进行写操作前,需先将写保护寄存器的WP位设置为0,写完后再设置为1。写和读的时候数据都以BCD码格式传输。

硬件设计

实验16 DS1302时钟

实现功能:数码管显示电子时钟时分秒,格式为"XX-XX-XX"。

数码管驱动沿用自实验14

DS1302驱动

ds1302.h

c 复制代码
#ifndef _ds1302_H
#define _ds1302_H

#include "public.h"

//定义复位线、时钟线和数据线管脚
sbit DS1302_RST = P3^5;
sbit DS1302_CLK = P3^6;
sbit DS1302_IO = P3^4;

//定义存储秒分时日月周年的数组
extern u8 gDS1302_TIME[7];

void ds1302_init(void);
void ds1302_read_time(void);

#endif

ds1302.c

c 复制代码
#include "ds1302.h"
#include "intrins.h"

//存储秒分时日月周年地址读写的命令
u8 gWRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
u8 gREAD_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};

//存储秒分时日月周年的数组
//赋值作为初始化的时间,以2025年星期二3月11日11点45分14秒为例
u8 gDS1302_TIME[7] = {0x14, 0x45, 0x11, 0x11, 0x03, 0x02, 0x25};

//写字节函数
void ds1302_write_byte(u8 addr, u8 dat)
{
	//循环控制变量
	u8 i = 0;
	//复位并将时钟设为低电平
	DS1302_RST = 0;
	_nop_();
	DS1302_CLK = 0;
	_nop_();
	DS1302_RST = 1;
	//由低到高写入地址
	for(i=0;i<8;i++)
	{
		//IO管脚准备好最低位信号
		DS1302_IO = addr & 0x01;
		//次低位移至最低位
		addr >>= 1;
		//产生上升沿使信号写入
		DS1302_CLK = 1;
		_nop_();
		DS1302_CLK = 0;
		_nop_();
	}
	//由低到高写入数据
	for(i=0;i<8;i++)
	{
		DS1302_IO = dat & 0x01;
		dat >>= 1;
		DS1302_CLK = 1;
		_nop_();
		DS1302_CLK = 0;
		_nop_();
	}
	//拉低复位线等待下次操作
	DS1302_RST = 0;
}

//读字节函数
u8 ds1302_read_byte(u8 addr)
{
	//循环控制变量
	u8 i = 0;
	//一位存储变量
	u8 temp = 0;
	//一字节存储变量
	u8 value = 0;
	//复位并拉低时钟
	DS1302_RST = 0;
	_nop_();
	DS1302_CLK = 0;
	_nop_();
	DS1302_RST = 1;
	//写入地址
	for(i=0;i<8;i++)
	{
		DS1302_IO = addr & 0x01;
		addr >>= 1;
		DS1302_CLK = 1;
		_nop_();
		DS1302_CLK = 0;
		_nop_();
	}
	//由低到高读取数据
	for(i=0;i<8;i++)
	{
		//存储一位
		temp = DS1302_IO;
		//将字节整体右移一位并将新数据移到最高位后放入
		value = (temp<<7) | (value>>1);
		DS1302_CLK = 1;
		_nop_();
		//产生下降沿读取下一位
		DS1302_CLK = 0;
		_nop_();
	}
	//拉低复位线等待下次操作
	DS1302_RST = 0;
	//如果板载P3.4没有外接上拉电阻需要手动产生上升沿脉冲
	DS1302_CLK = 1;
	_nop_();
	DS1302_IO = 0;
	_nop_();
	DS1302_IO = 1;
	_nop_();
	//返回读取到的字节
	return value;
}

//时间初始化函数
void ds1302_init(void)
{
	//循环控制变量
	u8 i = 0;
	//将写保护寄存器的写保护位置零以关闭写保护
	ds1302_write_byte(0x8e, 0x00);
	for(i=0;i<7;i++)
	{
		//将寄存器地址与时间数据一一对应写入
		ds1302_write_byte(gWRITE_RTC_ADDR[i], gDS1302_TIME[i]);
	}
	//打开写保护
	ds1302_write_byte(0x8e, 0x00);
}

//时间读取函数
//由于函数不便返回数组,因此直接用开头定义好的数组存储
void ds1302_read_time(void)
{
	//循环控制变量
	u8 i = 0;
	for(i=0;i<7;i++)
	{
		//将对应寄存器地址的时间数据读取到数组
		gDS1302_TIME[i] = ds1302_read_byte(gREAD_RTC_ADDR[i]);
	}
}

主函数

c 复制代码
#include "public.h"
#include "smg.h"
#include "ds1302.h"

void main()
{
	//存储数码管显示段码值数组
	u8 time_buf[8];
	//时间初始化
	ds1302_init();
	while(1)
	{
		//读取时间
		ds1302_read_time();
		//八位数码管依次存储时分秒的十位和个位,中间用杠隔开
		//BCD码整除16提取十位,对16取余提取个位
		time_buf[0] = gseg_code[gDS1302_TIME[2]/16];
		time_buf[1] = gseg_code[gDS1302_TIME[2]%16];
		time_buf[2] = 0x40;
		time_buf[3] = gseg_code[gDS1302_TIME[1]/16];
		time_buf[4] = gseg_code[gDS1302_TIME[1]%16];
		time_buf[5] = 0x40;
		time_buf[6] = gseg_code[gDS1302_TIME[0]/16];
		time_buf[7] = gseg_code[gDS1302_TIME[0]%16];
		//显示在数码管上
		seg_display(time_buf, 1);
	}
}
相关推荐
DOMINICHZL2 小时前
卡尔曼滤波算法从理论到实践:在STM32中的嵌入式实现
stm32·嵌入式硬件·算法
无际单片机编程2 小时前
单片机OTA升级中Bootloader怎么判断APP有没有问题?
java·stm32·单片机·嵌入式硬件·嵌入式
代码总长两年半2 小时前
STM32---FreeRTOS消息队列
stm32·单片机·嵌入式硬件
触角010100013 小时前
STM32 I2C驱动开发全解析:从理论到实战 | 零基础入门STM32第五十步
驱动开发·stm32·单片机·嵌入式硬件
大数据魔法师4 小时前
MongoDB(二) - MongoDB命令详解
数据库·mongodb
kse_music4 小时前
MySQL 与 MongoDB 的区别
数据库·mysql·mongodb
yqcoder4 小时前
Express + MongoDB 实现登录验证码
数据库·mongodb·express
沐欣工作室_lvyiyi5 小时前
基于单片机的防火防盗报警系统设计(论文+源码)
人工智能·stm32·单片机·嵌入式硬件·物联网·目标跟踪
廿二松柏木5 小时前
三级嵌入式学习ing 考点25、26
单片机·嵌入式硬件·学习
技术干货贩卖机6 小时前
0基础 | 看懂原理图Datasheet 系列1
笔记·stm32·单片机·嵌入式硬件·学习