该模块使用的芯片是:DS1302芯片,DS1302芯片是一个自动计时的时钟模块,有6个时钟寄存器,秒,分,时,日,月,年(其实不止,其它的暂且不管了)
使用不同的命令字来控制相应的寄存器:
0x80 ~ 0x8c ,分别控制秒到年寄存器的读和写
上表中,如果想读当前是多少秒,直接将0x81给read_DS1302()函数作为参数,该函数返回值对应的就是当前的秒
unsigned int current_second = read_DS1302(0x81);current_second 就是返回的秒
DS1302和单片机通过I/0口进行连接:
具体实现两种通信:
单片机通过发送指令,让时钟寄存器获得初始化时间
单片机从DS1302芯片获取时钟信息
DS1302封装图:
下面介绍从DS1302读取时钟的过程:
首先请看时序图:
/*
dat是需要读入命令字,函数返回该命令字要求返回的寄存器的数据
*/
u8 Read_DS1302(u8 dat) //
{
u8 i,temp,dat1,dat2;
DS1302_CE = 0;
DS1302_SCLK = 0;
DS1302_CE = 1;
for(i = 8;i>0;i--) //用8个上升沿把dat中的8位bit送到IO种选择读取的地址
{
DS1302_SCLK = 0;
temp = dat;
DS1302_IO = (bit)(temp&0x01);// temp的最右边一位送到IO上
dat >>=1; //dat右移一位
DS1302_SCLK = 1; //上升沿触发
}
for(i =8 ;i>0 ; i--) //采用先接收IO口数据,再用下降沿触发,循环结束后ACC获得读取数据
{
ACC_7 = DS1302_IO; //从最高位接收
DS1302_SCLK = 1;
ACC >>= 1; //ACC为累加器
DS1302_SCLK = 0;
}
DS1302_SCLK = 1;
DS1302_CE = 0;
dat1 = ACC;
dat2 = dat1 /16;
dat1 = dat1 %16;
dat1 = dat1+dat2*10;
return (dat1);
}
往DS1302写数据:
写时序如图:(RST = CE)
/*
addr写入命令字,dat根据写入的命令字把dat数据放入相应的寄存器
*/
void Write_DS1302(u8 addr,u8 dat)
{
u8 i,temp;
DS1302_CE = 0;
DS1302_SCLK = 0;
DS1302_CE = 1;
for(i=8 ; i>0 ; i--)
{
DS1302_SCLK = 0;
temp = addr;
DS1302_IO = (bit)(temp&0x01);
addr >>= 1;
DS1302_SCLK = 1;
}
for(i=8;i>0;i--)
{
DS1302_SCLK = 0;
temp = dat;
DS1302_IO = (bit)(temp&0x01);
dat >>= 1;
DS1302_SCLK = 1;
}
DS1302_SCLK = 1;
DS1302_CE = 0;
}
下面是使用DS1302已经封装完成的头文件:
DS1302.h
#ifndef _DS1302_H_
#define _DS1302_H_
#include <reg52.h>
sbit DS1302_SCLK = P1^4;
sbit DS1302_IO = P1^5;
sbit DS1302_CE = P1^6;
#define WRITE_SECOND 0x80 、
#define WRITE_MINUTE 0X82
#define WRITE_HOUR 0X84
#define WRITE_DATE 0X86
#define WRITE_MONTH 0X88
#define WRITE_WEEK 0X8A
#define WRITE_YEAR 0X8C
#define READ_SECOND 0X81 //读秒
#define READ_MINUTE 0X83 //读分
#define READ_HOUR 0X85 //读时
#define READ_DATE 0X87 //读日
#define READ_MONTH 0X89 // 读月
#define READ_WEEK 0X8B // 读星期
#define READ_YEAR 0x8D // 读年
#define WRITE_PROTECT 0x8E
sbit ACC_7 = ACC^7;
u8 Read_DS1302(u8 dat);
void Write_DS1302(u8 addr,u8 dat);
u8 data time[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00};//秒,分,时,日,月、星期、年
u8 Read_DS1302(u8 dat)
{
u8 i,temp,dat1,dat2;
DS1302_CE = 0;
DS1302_SCLK = 0;
DS1302_CE = 1;
for(i = 8;i>0;i--) //写入需要读入数据对应的地址 采用先接受IO口数据,再用
{
DS1302_SCLK = 0;
temp = dat;
DS1302_IO = (bit)(temp&0x01);
dat >>=1;
DS1302_SCLK = 1;
}
for(i =8 ;i>0 ; i--) //采用先接收IO口数据,再用下降沿触发
{
ACC_7 = DS1302_IO;
DS1302_SCLK = 1;
ACC >>= 1;
DS1302_SCLK = 0;
}
DS1302_SCLK = 1;
DS1302_CE = 0;
dat1 = ACC;
dat2 = dat1 /16;
dat1 = dat1 %16;
dat1 = dat1+dat2*10;
return (dat1);
}
void Write_DS1302(u8 addr,u8 dat)
{
u8 i,temp;
DS1302_CE = 0;
DS1302_SCLK = 0;
DS1302_CE = 1;
for(i=8 ; i>0 ; i--) //这个循环用于向DS1302写入addr命令字
{
DS1302_SCLK = 0;
temp = addr;
DS1302_IO = (bit)(temp&0x01);
addr >>= 1;
DS1302_SCLK = 1;
}
for(i=8;i>0;i--)//这个循环用于向DS1302对应的命令字中写dat
{
DS1302_SCLK = 0;
temp = dat;
DS1302_IO = (bit)(temp&0x01);
dat >>= 1;
DS1302_SCLK = 1;
}
DS1302_SCLK = 1;
DS1302_CE = 0;
}
void DS1302_init()
//给DS1302初始化,其中0x46是当时做闭塞是当时做毕设的时间,DS1302内部接收的是16进制,所 //以直接输入16进制就好了,
{
Write_DS1302(WRITE_MINUTE,0x46);
Write_DS1302(WRITE_HOUR,0x18);
Write_DS1302(WRITE_DATE,0x13);
Write_DS1302(WRITE_MONTH,4);
Write_DS1302(WRITE_YEAR,0x19);
Write_DS1302(WRITE_WEEK,6);
Write_DS1302(0x80,0);
}
void Read_time()
{
time[0] = Read_DS1302(0x81);
time[1] = Read_DS1302(0x83);
time[2] = Read_DS1302(0x85);
time[3] = Read_DS1302(0x87);
time[4] = Read_DS1302(0x89);
time[5] = Read_DS1302(0x8b);
time[6] = Read_DS1302(0x8d);
}
#endif
基于单片机的智能窗帘控制系统的设计与实现
单片机各模块设计脑图
时钟模块设计
时钟模块设计详细设计
光照感应模块
光照感应模块详细设计