IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> (九)51单片机——DS1302时钟 -> 正文阅读

[嵌入式](九)51单片机——DS1302时钟

目录

DS1302介绍

引脚定义和应用电路

寄存器定义

命令字?

时序定义

代码编写


????????今天,我们的任务是要编写一个用51开发板编写的可调小时钟,接下来就让我们一步一步来实现它吧!

DS1302介绍

  • DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等多种功能
  • RTC(Real Time Clock):实时时钟,是一种集成电路,通常称为时钟芯片?

????????我们51单片机的就是这样一个DS1302芯片。?

?

引脚定义和应用电路

????????这边是DS1302与CPU之间的一个关系,我先列一个表格来介绍一下各个部分的功能。

引脚名作用

VCC2

主电源

VCC1

备用电池

GND

接地

X1X2

32.768KHz晶振

CE

芯片使能

IO

数据输入/输出

SCLK

串行时钟

????????首先是电源部分,VCC2接的是外部电源,而VCC1接的是内置电源(51开发板上没有内置电源,所以不能看到掉电之后继续走的现象了,但我的闹钟可以掉电后走,hahaha!)?,之后就是GND接地。

????????之后就是晶振部分,接的是32.768KH的晶振,而单片机本身是11.0592MHZ,这个要注意区分,主要作用就是提供一个稳定的计数脉冲,用来计时。

????????之后的CE就是芯片使能,不使能就不能读取,但时钟还是可以运行滴;IO数据输入输出,用来获取和修改数据;SCLK串行时钟,和之前的SERCLK是类似的。

????????这个是更为详细的图片:

寄存器定义

????????DS1302的寄存器比较多,我们来一一介绍一下:

????????从上往下,依次是秒,分,时,天,月,星期几(1~7),年。之后的WP是写入保护,置1则写入无效哎,但还可以读数。再下面一行,就是涓流充电模式,也就是内置电源,51单片机没有,我们就先不写这个。

注:CH是时钟停止引脚

命令字?

????????命令字要解决的问题就是,我要去哪操作,以及,我要读出还是写入这两个问题。第一位,就是看是读出还是写入,当为0时,是写入,为1是读出;2~6位是地址,7位是操控的地方是时钟还是RAM;8位都是1。命令字其实都已经在前两列表示出来了。

时序定义

????????这部分内容是数电的第六章内容,我还没学到,呜呜呜,就只能先浅显的理解一下了。?

????????首先,我们需要写好刚刚介绍的命令字部分,每一个上升沿就是一次写入,而下降沿就是输出,所以输入输出主要的区别就是后面部分,从D0~D7,就是我们要操作的数据。

代码编写

接下来,我们就开始着手来编写一下代码了,先把原理图放上来。

// DS1302.c的代码
#include <REGX52.H>

// 根据原理图,应该可以写出下面几个引脚定义
sbit DS1302_SCLK = P3^6;
sbit DS1302_IO = P3^4;
sbit DS1302_CE = P3^5;

// 初始化函数,因为单片机接电后默认为1
void DS1302_Init(void)
{
	DS1302_CE = 0;
	DS1302_SCLK = 0;
}
// 写入函数
void DS1302_WriteByte(unsigned char Command, Data)
{
	unsigned char i;
	DS1302_CE = 1;
	// 读取低位
	for(i=0;i<8;i++){
	DS1302_IO = Command&(0x01<<i);
	// 可能需要加延时函数,因为切换太快了,但是51可以不加
	DS1302_SCLK = 1;
	DS1302_SCLK = 0;
	}
	for(i=0;i<8;i++){
	DS1302_IO = Data&(0x01<<i);
	// 可能需要加延时函数,因为切换太快了,但是51可以不加
	DS1302_SCLK = 1;
	DS1302_SCLK = 0;
	}
	DS1302_CE = 0;
}
// 读取的话,周期是15个,与写入的16个周期不同,所以才有下面代码的转变
unsigned char DS1302_ReadByte(unsigned char Command)
{
	unsigned char i, Data = 0x00;
	DS1302_CE = 1;
	// 读取低位
	for(i=0;i<8;i++){
	DS1302_IO = Command&(0x01<<i);
	// 这么做的原因就是在第8个脉冲下降沿的时候,数据已经读出了
	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;
	// 返回前先将IO口置为0
	DS1302_IO = 0;
	return Data;
}	
// DS1302.h的代码
#ifndef __DS1302_H__
#define __DS1302_H__

unsigned char DS1302_ReadByte(unsigned char Command);
void DS1302_WriteByte(unsigned char Command, Data);
void DS1302_Init(void);

#endif
// 主函数代码
#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"
#include "Delay.h"
unsigned char Second;
void main(){
	LCD_Init();
	DS1302_Init();
	LCD_ShowString(1, 1,"RTC");
	// 解除写入保护
	DS1302_WriteByte(0x8E,0x00);
	DS1302_WriteByte(0x80,0x03);
	
	
	while(1){
		Second = DS1302_ReadByte(0x81);
		LCD_ShowNum(2,1,Second,3);
	}
}

????????如果这样写的话,代码是可以运行的,但是会遇到问题,如下所示,直接从9跳到了16,主要原因就是码制的原因,这个地方用到了数电里的BCD码,如有不清楚的小伙伴,可以去看看我的数电笔记。

所以我们要对代码进行修改,如下所示:

#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"
#include "Delay.h"
unsigned char Second;
void main(){
	LCD_Init();
	DS1302_Init();
	LCD_ShowString(1, 1,"RTC");
	// 解除写入保护
	DS1302_WriteByte(0x8E,0x00);
	DS1302_WriteByte(0x80,0x03);
	
	
	while(1){
		Second = DS1302_ReadByte(0x81);
		// 将BCD码变成十进制
		LCD_ShowNum(2,1,Second/16*10+Second%16,3);
	}
}

????????最后,我们把最终优化的代码写出来。(其实还可以优化,但是会使代码不容易理解,因为代码还是要使人看懂,所以就不优化了)

#include <REGX52.H>

// 根据原理图,应该可以写出下面几个引脚定义
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

//时间数组,索引0~6分别为年、月、日、时、分、秒、星期
unsigned char DS1302_Time[]={22,7,3,11,57,55,7};

// 初始化函数,因为单片机接电后默认为1
/**
  * @brief  DS1302初始化
  * @param  无
  * @retval 无
  */
void DS1302_Init(void)
{
	DS1302_CE = 0;
	DS1302_SCLK = 0;
}

// 写入函数
/**
  * @brief  DS1302写一个字节
  * @param  Command 命令字/地址
  * @param  Data 要写入的数据
  * @retval 无
  */

void DS1302_WriteByte(unsigned char Command, Data)
{
	unsigned char i;
	DS1302_CE = 1;
	// 读取低位
	for(i=0;i<8;i++){
	DS1302_IO = Command&(0x01<<i);
	// 可能需要加延时函数,因为切换太快了,但是51可以不加
	DS1302_SCLK = 1;
	DS1302_SCLK = 0;
	}
	for(i=0;i<8;i++){
	DS1302_IO = Data&(0x01<<i);
	// 可能需要加延时函数,因为切换太快了,但是51可以不加
	DS1302_SCLK = 1;
	DS1302_SCLK = 0;
	}
	DS1302_CE = 0;
}

// 读取的话,周期是15个,与写入的16个周期不同,所以才有下面代码的转变
/**
  * @brief  DS1302读一个字节
  * @param  Command 命令字/地址
  * @retval 读出的数据
  */
unsigned char DS1302_ReadByte(unsigned char Command)
{
	unsigned char i, Data = 0x00;
	//为了统一数据,因为读的时候,末尾一定是1
	Command|=0x01;
	DS1302_CE = 1;
	// 读取低位
	for(i=0;i<8;i++){
	DS1302_IO = Command&(0x01<<i);
	// 这么做的原因就是在第8个脉冲下降沿的时候,数据已经读出了
	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;
	// 返回前先将IO口置为0
	DS1302_IO = 0;
	return Data;
}

/**
  * @brief  DS1302设置时间,调用之后,DS1302_Time数组的数字会被设置到DS1302中
  * @param  无
  * @retval 无
  */
void DS1302_SetTime(void)
{
	DS1302_WriteByte(DS1302_WP,0x00);
	DS1302_WriteByte(DS1302_YEAR,DS1302_Time[0]/10*16+DS1302_Time[0]%10);//十进制转BCD码后写入
	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);	
}

/**
  * @brief  DS1302读取时间,调用之后,DS1302中的数据会被读取到DS1302_Time数组中
  * @param  无
  * @retval 无
  */
void DS1302_ReadTime(void)
{
	unsigned char Temp;
	Temp=DS1302_ReadByte(DS1302_YEAR);
	DS1302_Time[0]=Temp/16*10+Temp%16;//BCD码转十进制后读取
	Temp=DS1302_ReadByte(DS1302_MONTH);
	DS1302_Time[1]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_DATE);
	DS1302_Time[2]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_HOUR);
	DS1302_Time[3]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_MINUTE);
	DS1302_Time[4]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_SECOND);
	DS1302_Time[5]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_DAY);
	DS1302_Time[6]=Temp/16*10+Temp%16;
}
#ifndef __DS1302_H__
#define __DS1302_H__

//外部可调用时间数组,索引0~6分别为年、月、日、时、分、秒、星期
extern unsigned char DS1302_Time[];

void DS1302_Init(void);
void DS1302_WriteByte(unsigned char Command,Data);
unsigned char DS1302_ReadByte(unsigned char Command);
void DS1302_SetTime(void);
void DS1302_ReadTime(void);

#endif
#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"

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);//显示秒
	}
}

运行结果如下所示:

(未完待续)

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 23:07:47  更:2022-07-04 23:09:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 0:51:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码