嵌入式开发学习(STC51-14-时钟)
内容
在数码管上显示时间,时分秒,格式为“XX-XX-XX”;
DS1302时钟芯片介绍
简介
DS1302是DALLAS公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和31字节静态RAM,通过简单的串行接口与单片机进行通信;
实时时钟/日历电路提供秒、分、时、日、周、月、年的信息,每月的天数和闰年的天数可自动调整;
时钟操作可通过AM/PM指示决定采用24或12小时格式;
DS1302与单片机之间能简单地采用同步串行的方式进行通信,仅需用到三根通信线:RES复位、I/O数据线、SCLK串行时钟;
时钟/RAM的读/写数据以一个字节或多达31个字节的字符组方式通信;
DS1302工作时功耗很低保持数据和时钟信息时功率小于1mW;
结构
物理结构
1,VCC2:主电源引脚
2,X1、X2:DS1302外部晶振引脚,通常需外接32.768K晶振
3,GND:电源地
4,CE:使能引脚,也是复位引脚(新版本功能变)
5,I/O:串行数据引脚,数据输出或者输入都从这个引脚
6,SCLK:串行时钟引脚
7,VCC1:备用电源
程序结构
DS1302有一个控制寄存器、12 个日历、时钟寄存器和31个RAM
控制寄存器
控制寄存器用于存放DS1302的控制命令字,DS1302的RST引脚回到高电平后写入的第一个字节就为控制命令;
它用于对DS1302读写过程进行控制;
格式如下:
1、第7位永远都是1;
2、第6位,1表示RAM,寻址内部存储器地址;0表示CK,寻址内部寄存器;
3、第5到第1位,为RAM或者寄存器的地址;
4、最低位,高电平表示RD,即下一步操作将要“读”;低电平表示W,即下一步操作将要“写”;(与AT24C02寄存器类似,这点要理解好)
比如读秒寄存器命令为1000 0001,反之写秒寄存器命令为1000 0000
日历/时钟寄存器
DS1302共有12个寄存器,其中有7个与日历、时钟相关,存放的数据为BCD码形式;
格式如下:
- 秒寄存器:低四位为秒的个位,高的次三位为秒的十位;最高位CH为DS1302的运行标志,当CH=0时,DS1302内部时钟运行,反之CH=1时停止;
- 小时寄存器:最高位为12/24小时的格式选择位,该位为1时表示12小时格式;当设置为12小时显示格式时,第5位的高电平表示下午(PM);而当设置为24小时格式时,第5位为具体的时间数据;
- 写保护寄存器:当该寄存器最高位WP为1时,DS1302只读不写,所以要在往DS1302写数据之前确保WP为0;
- 慢充电寄存器(涓细电流充电)寄存器:我们知道,当DS1302掉电时,可以马上调用外部电源保护时间数据,该寄存器就是配置备用电源的充电选项的;其中高四位(4个TCS)只有在1010的情况下才能使用充电选项;低四位的情况与DS1302内部电路有关;
使用
BCD码
在日历/时钟寄存器中一般都是以BCD码存放数据;
BCD码是通过4位二进制码来表示1位十进制中的0~9这10个数码;
如下所示:
所以从DS1302中读取出来的时钟数据均为BCD码格式,需转换为我们习惯的10进制;
DS1302的读写时序
在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位(位0)开始;
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7;
其时序图如下所示:
上图就是DS1302的三个时序:复位时序,单字节写时序,单字节读时序;
- CE(RST):复位时序,即在RST引脚产生一个正脉冲,在整个读写期间,RST要保持高电平,一次字节读写完毕之后,要注意把RST返回低电平准备下次读写周期;
- 单字节读时序:注意读之前还是要先对寄存器写命令,从最低位开始写;可以看到,写数据是在SCLK的上升沿实现,而读数据在SCLK的下降沿实现;所以,在单字节读时序中,写命令的第八个上升沿结束后紧接着的第八个下降沿就将要读寄存器的第一位数据读到数据线上了,这个就是DS1302操作中最特别的地方;当然读出来的数据也是最低位开始;
- 单字节写时序:两个字节的数据配合16个上升沿将数据写入即可;
使用步骤
1 将数据写入DS1302的寄存器,设置它当前的时间的格式;
2 使DS1302开始运作,DS1302时钟会按照设置情况运转,再用单片机将其寄存器内的数据读出;
3 再用液晶显示,就是我们常说的简易电子钟;
原理图
从上图中可知,DS1302芯片的控制管脚SCLK、I/O、CE接至单片机P3.6、P3.4、P3.5上;
芯片的X1、X2管脚处外接了一个32.768KHZ晶振,为时钟运行提供一个稳定的时钟频率,C2和C3为旁路电容,目的是消除晶振起振时产生的电感干扰;
如果有外部电源还能将电源接入第8脚VCC1;
思路
按照时序图编写DS1302的初始化和读写程序;
读取时间并显示在数码管上;
(读取数据时注意将BCD格式转换为十进制,其实就是,把十进制数取个十百单位时的,除10余10操作,换成除16余16)
编码
User
main.c
/** @Description: 在数码管上显示时间,时分秒,格式为“XX-XX-XX”*/
#include "public.h"
#include "smg.h"
#include "ds1302.h"void main()
{u8 time_buf[8];// 设置初始时间// 原本初始化时间2000年01月01日星期六0点0分0秒//---存储顺序是秒分时日月周年,存储格式是用BCD码---//gDS1302_TIME[0] = 0x06; // 秒gDS1302_TIME[1] = 0x06; // 分gDS1302_TIME[2] = 0x06; // 时// gDS1302_TIME[3] = {}; // 日// gDS1302_TIME[4] = {}; // 月// gDS1302_TIME[5] = {}; // 周// gDS1302_TIME[6] = {}; // 年ds1302_init(); // 初始化DS1302while (1){ds1302_read_time();time_buf[0] = gsmg_code[gDS1302_TIME[2] / 16];time_buf[1] = gsmg_code[gDS1302_TIME[2] & 0x0f];time_buf[2] = 0x40;time_buf[3] = gsmg_code[gDS1302_TIME[1] / 16];time_buf[4] = gsmg_code[gDS1302_TIME[1] & 0x0f];time_buf[5] = 0x40;time_buf[6] = gsmg_code[gDS1302_TIME[0] / 16];time_buf[7] = gsmg_code[gDS1302_TIME[0] & 0x0f];smg_display(time_buf, 1);}
}
Public
public.h
#ifndef _public_H
#define _public_H#include "reg52.h"typedef unsigned int u16; // 对系统默认数据类型进行重定义
typedef unsigned char u8;void delay_10us(u16 ten_us);
void delay_ms(u16 ms);#endif
public.c
#include "public.h"/*** @description: 延时函数,ten_us=1时,大约延时10us* @param {u16} ten_us 延时倍数* @return {*}*/
void delay_10us(u16 ten_us)
{while (ten_us--);
}/**ms延时函数,ms=1时,大约延时1ms**** @param {u16} ms 延时倍数* @return {*}*/
void delay_ms(u16 ms)
{u16 i, j;for (i = ms; i > 0; i--)for (j = 110; j > 0; j--);
}
App/ds1302
ds1302.h
#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
#include "ds1302.h"
#include "intrins.h"//---DS1302写入和读取时分秒的地址命令---//
//---秒分时日月周年 最低位读写位;-------//
u8 gREAD_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
u8 gWRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};//---DS1302时钟初始化2000年01月01日星期六0点0分0秒---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
u8 gDS1302_TIME[7] = {0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x00};/*** @description: DS1302写单字节* @param {u8} addr 地址/命令* @param {u8} dat 要写入的数据* @return {*}*/
void ds1302_write_byte(u8 addr, u8 dat)
{u8 i = 0;DS1302_RST = 0;_nop_();DS1302_CLK = 0; // CLK低电平_nop_();DS1302_RST = 1; // RST由低到高变化_nop_();for (i = 0; i < 8; i++) // 循环8次,每次写1位,先写低位再写高位{DS1302_IO = addr & 0x01;addr >>= 1;DS1302_CLK = 1;_nop_();DS1302_CLK = 0; // CLK由低到高产生一个上升沿,从而写入数据_nop_();}for (i = 0; i < 8; i++) // 循环8次,每次写1位,先写低位再写高位{DS1302_IO = dat & 0x01;dat >>= 1;DS1302_CLK = 1;_nop_();DS1302_CLK = 0;_nop_();}DS1302_RST = 0; // RST拉低_nop_();
}/*** @description: DS1302读单字节* @param {u8} addr 地址/命令* @return {u8} 读取的数据*/
u8 ds1302_read_byte(u8 addr)
{u8 i = 0;u8 temp = 0;u8 value = 0;DS1302_RST = 0;_nop_();DS1302_CLK = 0; // CLK低电平_nop_();DS1302_RST = 1; // RST由低到高变化_nop_();for (i = 0; i < 8; i++) // 循环8次,每次写1位,先写低位再写高位{DS1302_IO = addr & 0x01;addr >>= 1;DS1302_CLK = 1;_nop_();DS1302_CLK = 0; // CLK由低到高产生一个上升沿,从而写入数据_nop_();}for (i = 0; i < 8; i++) // 循环8次,每次读1位,先读低位再读高位{temp = DS1302_IO;value = (temp << 7) | (value >> 1); // 先将value右移1位,然后temp左移7位,最后或运算DS1302_CLK = 1;_nop_();DS1302_CLK = 0;_nop_();}DS1302_RST = 0; // RST拉低_nop_();DS1302_CLK = 1; // 对于实物中,P3.4口没有外接上拉电阻的,此处代码需要添加,使数据口有一个上升沿脉冲。_nop_();DS1302_IO = 0;_nop_();DS1302_IO = 1;_nop_();return value;
}/*** @description: DS1302初始化时间* @return {*}*/
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, 0X80);
}/*** @description: DS1302读取时间* @return {*}*/
void ds1302_read_time(void)
{u8 i = 0;for (i = 0; i < 7; i++){gDS1302_TIME[i] = ds1302_read_byte(gREAD_RTC_ADDR[i]);}
}
App/smg
smg.h
#ifndef _smg_H
#define _smg_H#include "public.h"#define SMG_A_DP_PORT P0 // 使用宏定义数码管段码口// 定义数码管位选信号控制脚
sbit LSA = P2 ^ 2;
sbit LSB = P2 ^ 3;
sbit LSC = P2 ^ 4;extern u8 gsmg_code[17]; // 使“共阴极数码管显示0~F的段码数据”这个变量定义为外部可用void smg_display(u8 dat[], u8 pos);#endif
smg.c
#include "smg.h"// 共阴极数码管显示0~F的段码数据
u8 gsmg_code[17] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};/*** @description: 动态数码管显示函数* @param {u8} dat 要显示的数据* @param {u8} pos 从左开始第几个位置开始显示,范围1-8* @return {*}*/
void smg_display(u8 dat[], u8 pos)
{u8 i = 0;u8 pos_temp = pos - 1;for (i = pos_temp; i < 8; i++){switch (i) // 位选{case 0:LSC = 1;LSB = 1;LSA = 1;break;case 1:LSC = 1;LSB = 1;LSA = 0;break;case 2:LSC = 1;LSB = 0;LSA = 1;break;case 3:LSC = 1;LSB = 0;LSA = 0;break;case 4:LSC = 0;LSB = 1;LSA = 1;break;case 5:LSC = 0;LSB = 1;LSA = 0;break;case 6:LSC = 0;LSB = 0;LSA = 1;break;case 7:LSC = 0;LSB = 0;LSA = 0;break;}SMG_A_DP_PORT = dat[i - pos_temp]; // 传送段选数据delay_10us(100); // 延时一段时间,等待显示稳定SMG_A_DP_PORT = 0x00; // 消影}
}
编译和结果
按F7编译,无错误,生成.hex文件,使用pz-isp将hex文件下载到单片机
结果:成功显示时间,并正常计时
相关文章:

嵌入式开发学习(STC51-14-时钟)
内容 在数码管上显示时间,时分秒,格式为“XX-XX-XX”; DS1302时钟芯片介绍 简介 DS1302是DALLAS公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和31字节静态RAM,通过简单的串行接口与单片机进行通信…...

ES新特性部分
文章目录 Symbol创建使用拓展对象的方法直接添加 控制对象控制类型检查控制是否展开 遍历迭代器自定义遍历 生成器函数(实现异步编程)解决回调地狱 Promise连续读文件 SetMap类静态属性继承ES5ES6 GET与SET 数值Object方法模块化导入另一种导入 babel ES…...

数据结构——搜索二叉树
文章目录 一. 概念二. 二叉搜索树的操作1.查找2.插入3.删除(重点)4.遍历5.拷贝构造与析构 三.二叉搜索树的递归实现1.递归查找2.递归插入3.递归删除 四.二叉搜索树的性能分析五.二叉树搜索的应用六.源码 前言: 本章我们将认识一种新的二叉树—…...
3.3 Makefile的嵌套包含
一、Makefile包含子Makefile的示例 下面是一个示例Makefile和sub.mk的内容。 首先是sub.mk文件的内容: VAR := Hello from sub.mksay_hello:@echo $(VAR)然后是Makefile文件的内容: include sub.mkall: say_hellosay_hello:@echo "Hello from Makefile"在这个例…...

爬虫获取电影数据----以沈腾参演电影为例
数据可视化&分析实战 1.1 沈腾参演电影数据获取 文章目录 数据可视化&分析实战前言1. 网页分析2. 构建数据获取函数2.1 网页数据获取函数2.2 网页照片获取函数 3. 获取参演影视作品基本数据4. 电影详细数据获取4.1 导演、演员、描述、类型、投票人数、评分信息、电影海…...

网页版Java(Spring/Spring Boot/Spring MVC)五子棋项目(二)前后端实现用户的登录和注册功能【用户模块】
网页版Java五子棋项目(二)前后端实现用户的登录和注册功能【用户模块】 在用户模块我们要清楚要完成的任务一、MyBatis后端操作数据库1. 需要在数据库创建用户数据库1. 用户id2. 用户名3. 密码4. 天梯积分5. 总场数6. 获胜场数 2. 创建用户类User和数据库…...

2023年华数杯数学建模A题思路代码分析 - 隔热材料的结构优化控制研究
# 1 赛题 A 题 隔热材料的结构优化控制研究 新型隔热材料 A 具有优良的隔热特性,在航天、军工、石化、建筑、交通等 高科技领域中有着广泛的应用。 目前,由单根隔热材料 A 纤维编织成的织物,其热导率可以直接测出;但是 单根隔热…...

阿里云二级域名配置
阿里云二级域名配置 首先需要进入阿里云控制台的域名管理 1.选择域名点击解析 2.添加记录 3.选择A类型 4.主机记录设置【可以aa.bb或者aa.bb.cc】 到时候会变成:aa.bb.***.com 5.解析请求来源设置为默认 6.记录值 设置为要解析的服务器的ip地址 7.TTL 默认即…...
Webpack5 动态导入按需加载
文章目录 一、 什么是动态导入和按需加载?二、 具体用法示例二、 总结 一、 什么是动态导入和按需加载? 传统上,在Webpack中,我们使用import语句可以在代码中静态地导入模块。这意味着所有的模块都会在构建时被打包到bundle中。然…...
【Linux操作系统】Ubuntu和center两个Linux发行版本中指令的区别
Ubuntu和center是Linux的两个发行版本,本文将详细介绍两个发行版的使用命令区别,分析两者的优缺点。 文章目录 常见的区别:细节差异:两个发行版本各自的优点和缺点Ubuntu 的优点:Ubuntu 的缺点:CentOS 的优…...

c++基本数据结构
void insert(const node *head, node *p) {node *x, *y;yhead;do{xy;yx->next;} while ((y!NULL) && (y->value < p->value);x->nextp;p->nexty; } 二.栈 (1) 栈的实现! 操作规则:先进后出,先出后进。 int stack[N], top0; /…...

路由器DHCP实验
拓扑图 配置 # 配置ip地址并开启dhcp [Huawei]int g0/0/0 [Huawei-GigabitEthernet0/0/0]ip addr 192.168.1.1 255.255.255.0 [Huawei-GigabitEthernet0/0/0]dhcp enable## 配置dns地址 [Huawei-GigabitEthernet0/0/0]dhcp dns-list 192.168.1.5## 指定某个接口开通DHCP 功能…...
Linux 电源子系统之充电、放电、低功耗
在嵌入式产品中,有三个重要模块:充电、放电、低功耗。 1、充电 charging 1、开关电源基本原理 2、线性充电和开关电源硬件电路图分析 3、Battery_Charging_v1.2 spec 4、typec spec 5、typec-PD spec 6、Uevent 在 Android 层的实现 7、battery service 监听 uevent 事件以…...

捕捉时刻:将PDF文件中的图像提取为个性化的瑰宝(从pdf提取图像)
应用场景: 该功能的用途是从PDF文件中提取图像。这在以下情况下可能会很有用: 图片提取和转换:可能需要将PDF文件中的图像提取出来,并保存为单独的图像文件,以便在其他应用程序中使用或进行进一步处理。例如ÿ…...
【基础类】—HTTP协议类
一、HTTP协议的主要特点 简单快速:每个资源URI是固定的,访问某个资源输入URI即可灵活:在每一个HTTP协议中,请求头部分有一个数据类型,通过一个HTTP协议可以完成不同的数据类型传输无连接:连接一次就会断开…...
【Qt高级】QThread与QTimer组合使用引出的信号槽执行在哪个线程的思考【2023.08.06】
源码见 testQThread_QTimer… Qt 版本5.6.3 视频讲解:https://www.bilibili.com/video/BV15P411C79i/ 链接: 视频讲解 简介 想法很单纯,就是主线程启动一个子线程,子线程里启动一个定时器,定时执行一些任务,然鹅实际开…...

用于大型图像模型的 CNN 内核的最新内容
一、说明 由于OpenAI的ChatGPT的巨大成功引发了大语言模型的繁荣,许多人预见到大图像模型的下一个突破。在这个领域,可以提示视觉模型分析甚至生成图像和视频,其方式类似于我们目前提示 ChatGPT 的方式。 用于大型图像模型的最新深度学习方法…...
索尼电视怎么完全关机
索尼电视怎么完全关机 当用户想要关闭索尼电视时,可能会遇到一些问题。例如,他们可能会遇到如何完全关闭电视的问题。在本文中,我们将介绍如何完全关闭索尼电视。 首先,您需要找到索尼电视的电源按钮。通常,该按钮位…...

AI介绍——chat gpt/文心一言/claude/bard/星火大模型/bing AI
AI体验 1. AI 介绍(注册和使用)1.1 Chat GPT1.2 文心一言1.3 Slack 上的 Claude1.3.1 Claude 介绍1.3.2 Claude 使用 1.4 Google的Bard1.4.1 Bard 介绍1.4.2 Bard 使用 1.5 科大讯飞的星火大模型1.5.1 星火大模型 介绍1.5.2 星火大模型 使用 1.6 new bin…...

C++ 访问控制——公有继承、私有继承、保护继承
派生类继承了基类的全部数据成员和除了构造函数和析构函数之外的全部函数成员,但是这些成员的访问属性在派生的过程中是可以调整的。从基类继承的成员,其访问属性由继承方式控制。 基类的成员有public(公有)、protectedÿ…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...

华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...
API网关Kong的鉴权与限流:高并发场景下的核心实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中,API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关,Kong凭借其插件化架构…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...
[USACO23FEB] Bakery S
题目描述 Bessie 开了一家面包店! 在她的面包店里,Bessie 有一个烤箱,可以在 t C t_C tC 的时间内生产一块饼干或在 t M t_M tM 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC,tM≤109)。由于空间…...