寻求以浅显的言语让小白能够更简略上手学单片机,在此同时稳固知识(许多图片来自江科大和普中,作者也是学这个来的,只是经过自己的言语想把它复述出来)。
何为实时时钟
经过外接晶振以冲激的方式每隔固定时刻给出高/低电平,从而使芯片有了计时计数的功能。本文章主要介绍实时时钟的一个芯片DS1302.
简略介绍
下图为其芯片结构图
-
这个芯片有两个vcc,引脚1的VCC为外接电源引脚;引脚8的VCC为芯片配的备用电源(能够在无外电源的情况下供给一定的作业能力,比方电脑关机了,但或许还能计时便是因为其含有备用电源)不过本项目用的试验板是没有配备备用电源,因而咱们能够跳过,大概了解这个点就行。
-
X1和X2外接的是晶振,其作用是供给固定频率(即每隔固定的时刻会供给一个冲激使得这个芯片计时或许计数),也是这块芯片的共同之处。
-
SCLK归于时序的领域。其作用是帮助该芯片写读指令或许数据。当上升沿时为写,下降沿时为读。后面会具体讲。
-
CE也归于时序的领域,当他为高电平时,发动时钟的读写功能,低电平时中止/闲置。
-
I/O即数据的输入输出,包含地址码和数据码。
(这种图才是熟悉的感jio) 可知该芯片在单片机中占用的三个引脚分别为
P3_4 为I/O;
P3_5 为CE;
P3_6 为SLCK
也便是说在后面写代的码时分,你必定能看到这仨的出现
实时时钟用来干什么
做项目时咱们常常会有时刻上的处理,比方计时器。如果你想做个计时器,那你肯定不能少了时钟模块,可见其价值如此。
完成计时
记住51中,完成时钟的读写数据,就必须靠时序来完成
中心
操控存放器
即咱们输入命令,操控该芯片什么作业方式–开启/中止/读/写 下图是上图的细化,在操控发动,读/写的基础上,加上了日历存放器的挑选,经过表中的输入地址码,咱们能够操控时钟来存放什么数据。
日历存放器
看了图,你会晕,这些存放器,上面不是也有吗?确实,你没有看错,确实再次出现了。不过这儿的存放器和上面的要区分开,这儿的是数据的写入,上面的是方式的挑选/或许你能够用挑选存放器地址来了解。
该图展现了取值范围,和位/值的输入及一些说明,值得注意的是,这儿的数据写入是经过BCD码来键入的
0000~1001代表1~9,而四位一体的码0X?? 可保证了更大数值的输入。可输入00~99的数值。
操控时序
这是最最重要的,单看前面的,你也没办法下手,必须有个先后顺序才干切入问题。
这儿分为两种情况,够咱们新手完成许多东西了,你想想:咱们要完成计时,不便是给一个时刻开端计时或许读取一个时刻吗? 关于该时序图的解读如下
单字节写:
1.要在作业之前将CE置高电平,作业之后将CE置低电平(这就归于初始化的领域了)。
2.看I/O左面是指地址的挑选,咱们挑选了写并挑选了哪个存放器。右边为数据的输入
3.要完成输入(包含地址/数据),就必须一个一个来,且依照低位在先准则,每输入一个数,就给一个上升沿。代码上怎样了解呢?咱们写一个值,然后将SCLK置1,给一个延时函数,此时现已输入了该位数据,再置0,便能够开端下一位的输入。
单字节读:
同上面的前两点
3.左面要输入,右边要读取(输出)。左面依照上面3的做法,输入作业方式(记得是读!!!),读到最后一位,上升沿下降后,再置高,再下降沿(这时才有数据的读取)。相当于空了一个下降沿。
我怎样利用实时时钟来做一些工作
小比如–使用DS1302完成时钟功能
主函数
#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"
#include "Delay.h"
unsigned char Second;unsigned char Min;
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);
}
}
延时函数
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
DS1302写入和读取 要写的函数包含 设置时刻,读取时刻,输入,读取数据
#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
unsigned char DS1302_Time[]={19,11,16,12,59,55,6};//输入的时刻(以数组方式)
void DS1302_Init() {//初始化
DS1302_CE=0;//把CE给清除状况,这儿不是CE=1,咱们将CE=1放在设置时刻和读取时刻那里就可,
DS1302_SCLK=0;//把SCLK清除状况
}
void DS1302_WriteByte(unsigned char Command,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;
}
unsigned char DS1302_ReadByte(unsigned char Command)//读字节
{
unsigned char i,Data=0x00;
Command|=0x01; //
DS1302_CE=1;
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);}//获取数据经过IO,用并集
}
DS1302_CE=0;
DS1302_IO=0;
return Data;
}
void DS1302_SetTime(void)//设置时刻
{
DS1302_WriteByte(DS1302_WP,0x00);
DS1302_WriteByte(DS1302_YEAR,DS1302_Time[0]/10*16+DS1302_Time[0]%10);//写数字,将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);
}
void DS1302_ReadTime(void)//获取时刻
{
unsigned char Temp;
Temp=DS1302_ReadByte(DS1302_YEAR);
DS1302_Time[0]=Temp/16*10+Temp%16;//BCD码转化为10进制
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;
}