当前位置: 首页 > news >正文

51单片机-第七节-DS1302实时时钟

 一、DS1302介绍:

实时时钟芯片,可对年,月,日,周,时,分,秒计时,是一种集成电路。

二、DS1302原理:

1.寄存器定义:

Command:操作模式,决定要进行的操作是读/写,以及读写内容(秒、分、时。。。)

如下图,其中最左侧的值即为进行对应操作的Command的值。

例:对小时进行读取,Command = 0x85;

2.引脚定义与电路:

其中Vcc1/2是电源,X1/X2是晶振。重点在于后三个。

后三个的作用为输入和读取数据。

其中后三个的原理与_74HC595_完全类似,均为1位1位输入,详细过程见上一节。

CE:总开关,置1时开始工作;

I/O:传入的数据,0/1;

SCLK:来回置01,由0到1时依次传入I/O中的数据。

3.时序:

怎么看?--- 低为0高为1,画一条竖线,在同一竖线上的事是同时发生的。

例:下图中读操作:

将CE = 1,随后使SCLK在01切换,每次上升沿(0到1)依次将I/O口的数据传给R/W、A0等。

(注:R/W-1的8位即为Command)

8次上升后,确定Command,在下降沿(1到0)读取数据给I/O口。

(其中具体8位,每一位代表什么,详见上面的RTC图)

三、集成DS1302:

.h文件:

//时钟初始化
void DS1302_Init();
//数组:储存时钟的时间:年月日时分秒周(0-6)
unsigned char DS1302_Time[];
//用于设置和读取时钟数据,设置会将数组中的时间传入,读取会将时钟数据导出存在上面数组中
void DS1302_SetTime();
void DS1302_ReadTime();

.c文件:

sbit DS1302_SCLK = P3 ^ 6;
sbit DS1302_IO = P3 ^ 4;
sbit DS1302_CE = P3 ^ 5;#define DS1302_SECOND    0x80
#define DS1302_MINUTE    0x82
#define DS1302_HOUR    0x84
#define DS1302_DATE    0x86
#define DS1302_MONTH    0x88
#define DS1302_DAY    0x8A
#define DS1302_YEAR    0x8C
#define DS1302_WP    0x8E//储存时钟的时间:年月日时分秒周
unsigned char DS1302_Time[] = { 19,11,16,12,59,55,6 };
//时钟初始化
void DS1302_Init()
{DS1302_CE = 0;DS1302_SCLK = 0;
}
//写入数据,参数:Command,Data
void DS1302_WriteByte(unsigned char Command, unsigned char Data)
{unsigned char i;DS1302_CE = 1;for (i = 0; i < 8; i++){DS1302_IO = Command & (0x01<<i);DS1302_SCLK = 1;DS1302_SCLK = 0;}	for (i = 0; i < 8; i++){DS1302_IO = Data & (0x01<<i);DS1302_SCLK = 1;DS1302_SCLK = 0;}DS1302_CE = 0;
}
//读取数据,参数:Command,返回值:Data
unsigned char DS1302_ReadByte(unsigned char Command)
{unsigned char i;unsigned char Data = 0x00;DS1302_CE = 1;Command |= 0x01;for (i = 0; i < 8; i++){DS1302_IO = Command & (0x01 << i);DS1302_SCLK = 0;DS1302_SCLK = 1;}	for (i = 0; i < 8; i++){DS1302_SCLK = 1;DS1302_SCLK = 0;if (DS1302_IO) { Data |= (0x01<<i); }}DS1302_CE = 0;DS1302_IO = 0;return Data;
}
//用于设置和读取时钟数据
void DS1302_SetTime()
{DS1302_WriteByte(DS1302_WP, 0x00);DS1302_WriteByte(DS1302_YEAR, DS1302_Time[0] / 10 * 16 + DS1302_Time[0] % 10);DS1302_WriteByte(DS1302_MONTH, DS1302_Time[1] / 10 * 16 + DS1302_Time[1] % 10);DS1302_WriteByte(DS1302_DATE, DS1302_Time[2] / 10 * 16 + DS1302_Time[2] % 10);DS1302_WriteByte(DS1302_HOUR, DS1302_Time[3] / 10 * 16 + DS1302_Time[3] % 10);DS1302_WriteByte(DS1302_MINUTE, DS1302_Time[4] / 10 * 16 + DS1302_Time[4] % 10);DS1302_WriteByte(DS1302_SECOND, DS1302_Time[5] / 10 * 16 + DS1302_Time[5] % 10);DS1302_WriteByte(DS1302_DAY, DS1302_Time[6] / 10 * 16 + DS1302_Time[6] % 10);DS1302_WriteByte(DS1302_WP, 0x80);
}
void DS1302_ReadTime()
{DS1302_Time[0] = DS1302_ReadByte(DS1302_YEAR) / 16 * 10 + DS1302_ReadByte(DS1302_YEAR) % 16;DS1302_Time[1] = DS1302_ReadByte(DS1302_MONTH) / 16 * 10 + DS1302_ReadByte(DS1302_YEAR) % 16;DS1302_Time[2] = DS1302_ReadByte(DS1302_DATE) / 16 * 10 + DS1302_ReadByte(DS1302_YEAR) % 16;DS1302_Time[3] = DS1302_ReadByte(DS1302_HOUR) / 16 * 10 + DS1302_ReadByte(DS1302_YEAR) % 16;DS1302_Time[4] = DS1302_ReadByte(DS1302_MINUTE) / 16 * 10 + DS1302_ReadByte(DS1302_YEAR) % 16;DS1302_Time[5] = DS1302_ReadByte(DS1302_SECOND) / 16 * 10 + DS1302_ReadByte(DS1302_YEAR) % 16;DS1302_Time[6] = DS1302_ReadByte(DS1302_DAY) / 16 * 10 + DS1302_ReadByte(DS1302_YEAR) % 16;}

四、实战:显示秒:

利用LCD1602调试:

unsigned char Second;
void main()
{LCD_Init();DS1302_Init();LCD_ShowString(1, 1, "RTC");DS1302_WriteByte(0x80, 0x03);while (1){Second = DS1302_ReadByte(0x81);LCD_ShowNum(2, 1, Second, 3);}
}

问题:此时调试会出现问题,由9直接变为16。

原因:DS1302不是以正常的2进制转10进制表示的,而是用BCD码。(详见:寄存器定义)

BCD码:用4位二进制数表示一位10进制数:

例:0001 0011 = 13 ; 1000 0101 = 85 ; 即 0x85 = 85 ;

解决方法:利用LCD1602中显示16进制的函数即可:LCD_ShowHexNum

正确版:

unsigned char Second;
void main()
{LCD_Init();DS1302_Init();LCD_ShowString(1, 1, "RTC");DS1302_WriteByte(0x80, 0x03);while (1){Second = DS1302_ReadByte(0x81);LCD_ShowHexNum(2, 1, Second, 3);}
}

五:实战:实时时钟:

void main()
{LCD_Init();DS1302_Init();LCD_Showstring(1, 1, "  -  -  ");LCD_Showstring(2, 1, "  :  :  ");DS1302_SetTime();while (1){DS1302_ReadTime();LCD_ShowNum(1, 1, DS1302_Time[0], 2);LCD_ShowNum(1, 4, DS1302_Time[1], 2);LCD_ShowNum(1, 7, DS1302_Time[2], 2);LCD_ShowNum(2, 1, DS1302_Time[3], 2);LCD_ShowNum(2, 4, DS1302_Time[4], 2);LCD_ShowNum(2, 7, DS1302_Time[5], 2);}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 6.3 第三方库的安装与使用
  • 51单片机—串口
  • 【Material-UI】使用指南:快速入门与核心功能解析
  • 单细胞组学与RNA转录组技术的深度对比:揭示基因表达的微观与宏观世界
  • 打破老美垄断,潘展乐商业价值起飞
  • 基于VEH的无痕HOOK
  • 【Python】解决“TypeError: __init__() got an unexpected keyword argument ‘XXX‘”的方法
  • 同态加密和SEAL库的介绍(六)BGV 方案
  • Android开发 java回调
  • 学习日志8.8--防火墙精细化策略管控
  • 【算法模板】基础:反悔贪心
  • NAT、服务代理、内网穿透
  • WPF篇(3)- WrapPanel控件(瀑布流布局)+DockPanel控件(停靠布局)
  • 全新博客X主题/简约WordPress主题模板/主题巴巴/免授权版源码+自适应设计
  • Vue+Element Plus后台管理主界面搭建实现
  • docker-consul
  • Python_网络编程
  • Python学习笔记 字符串拼接
  • socket.io+express实现聊天室的思考(三)
  • TCP拥塞控制
  • Vue ES6 Jade Scss Webpack Gulp
  • 阿里云Kubernetes容器服务上体验Knative
  • 分享几个不错的工具
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 给github项目添加CI badge
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 看域名解析域名安全对SEO的影响
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 小程序测试方案初探
  • 应用生命周期终极 DevOps 工具包
  • ​​​【收录 Hello 算法】9.4 小结
  • ​LeetCode解法汇总2304. 网格中的最小路径代价
  • ​数据结构之初始二叉树(3)
  • # Redis 入门到精通(七)-- redis 删除策略
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • #systemverilog# 之 event region 和 timeslot 仿真调度(十)高层次视角看仿真调度事件的发生
  • $().each和$.each的区别
  • (HAL库版)freeRTOS移植STMF103
  • (java)关于Thread的挂起和恢复
  • (办公)springboot配置aop处理请求.
  • (分布式缓存)Redis分片集群
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (附源码)springboot太原学院贫困生申请管理系统 毕业设计 101517
  • (附源码)ssm高校实验室 毕业设计 800008
  • (七)Knockout 创建自定义绑定
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转)chrome浏览器收藏夹(书签)的导出与导入
  • (转)shell中括号的特殊用法 linux if多条件判断
  • (转)可以带来幸福的一本书
  • **CI中自动类加载的用法总结
  • **PHP二维数组遍历时同时赋值
  • .Net 6.0 处理跨域的方式
  • .NET Core 将实体类转换为 SQL(ORM 映射)