介绍
关于蓝桥杯单片机DS1302部分的一些代码,本期主要讲应用,就是基于题目给出的要求可以写出相对应的代码,至于原理后面会详细讲,在这里先了解一下
DS1302芯片
DS1302 是DALLAS 公司推出的涓流充电时钟芯片内含有一个实时时钟/日历和31 字节静态RAM
可通过简单的串行接口与单片机进行通信
可提供:
–年月日时分秒 日期 的信息
–每月的天数和闰年的天数可自动调整
–可通过AM/PM 指示决定采用24 或12 小时格式
管脚 | 说明 |
---|---|
GND | 接地 |
CE复位引脚 | 输入信号,在读、写数据期间,必须为高 |
X1 X2 | 32.768KHz晶振管脚 |
I/O输入/输出引脚 | 三线接口时的双向数据线 |
SCLK | 串行时钟,输入,控制数据的输入与输出 |
VCC2 | 备用电源 |
VCC1 | 主电源 |
特殊说明
(1)CE复位引脚:该引脚有两个功能:第一,CE开始控制字访问移位寄存器的控制逻辑;其次,CE提供结束单字节或多字节数据传输的方法。
(2)当Vcc2>Vcc1+0.2V时,由Vcc2向DS1302供电,当Vcc2<Vcc1时,由Vcc1向DS1302供电。
电路
参考电路
实际电路
注:CLK 和I/O虽然和IIC总线接在一条引脚上,但DS1302其实并不是使用IIC总线,而是一种三线式总线
内部结构
英 | 对应 |
---|---|
Power control | 电源控制模块 |
Input shift registers | 输入移位寄存器 |
Command and control logic | 通讯与逻辑控制器 |
Oscillator and divider | 晶体振荡器及分频器 |
控制字、寄存器、时序
(1)控制字的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入到DS1302中
(2)位6:如果为0,则表示存取日历时钟数据,为1表示存取RAM数据
(3)1~5(A4~A0):指示操作单元的地址
(4)位0(最低有效位):如为0,表示要进行写操作,为1表示进行读操作。控制字总是从最低位开始输出。在控制字指令输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从最低位(0位)开始。同样,在紧跟8 位的控制字指令后的下一个SCLK脉冲的下降沿,读出DS1302的数据,读出的数据也是从最低位到最高位。
如上图所示:
第一个组为单字节读操作,第二组则为单字节写操作
CE输入驱动高启动所有的数据传输。
SCLK时钟线,每当过来一个上升沿,单片机将地址/数据写到DS1302中,每当过来一个下降沿时,单片机从DS1302里读数据,即DS1302自动将时间数据发送给单片机。
I/O前八位为地址命令字,后八位为时间数据
CE拉高后,SCLK 每过来一个上升沿,单片机向DS1302发送地址命令字,以确定读写的地址
读的时候每来一个下降沿,DS1302向单片机发送数据,单片机读取时间,写就是每来一个上升沿,单片机向DS1302发送数据,设置时间
如上图所示
时钟日历包含在7个读/写寄存器内,读/写寄存器中的数据是二——十进制的BCD码。
前两列分别是读和写的命令字,对应本模块的第一张图片里面的最后一位,控制读写
秒寄存器的BIT7定义为时间暂停位,当BIT1为1时,时钟振荡器停止工作,DS1302 进入低功耗模式,电源消耗小于100微安,当BIT1为0时,时钟振荡器启动DS1302正常工作。
小时寄存器的BIT7定义为12或24小时工作模式选择位,当BIT7为高时,为12小时工作模式,此时BIT5为AM/PM位,低电平标示AM,高电平标示PM,在24小时模式下,BIT5为第二个10小时位标示(20~23时)。
写保护寄存器的BIT7:WP是写保护位,工作时,出WP外的其他位都置为0,对时钟/日历寄存器或RAM进行写操作之前,WP必须为0,当WP为高电平的时候,不能对任何时钟/日历寄存器或RAM进行写操作。
代码
又臭又长的写了一大坨,不如直接上代码来的实惠,下面就直接看代码
ds1302.c
#include "ds1302.h"
code unsigned char w_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年
code unsigned char r_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
unsigned char set[6] = {2,3,5,9,5,5};
unsigned char rtc[6];
/*
*/
void Write_Ds1302_Byte(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
void Write_Ds1302( unsigned char address,unsigned char dat )
{
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_();
Write_Ds1302_Byte(address);
Write_Ds1302_Byte(dat);
RST=0;
}
unsigned char Read_Ds1302 ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_();
Write_Ds1302_Byte(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0;
_nop_();
RST=0;
SCK=0;
_nop_();
SCK=1;
_nop_();
SDA=0;
_nop_();
SDA=1;
_nop_();
return (temp);
}
/*
*/
unsigned char* ReadRTC(void)
{
unsigned char i, *p;
unsigned char tmp[3];
p = (unsigned char *)r_rtc_address; //地址传递
for(i=0;i<3;i++){
tmp[i]=Read_Ds1302(*p);
p++;
}
rtc[0] = (tmp[2] >> 4);
rtc[1] = (tmp[2] & 0x0F);
rtc[2] = (tmp[1] >> 4);
rtc[3] = (tmp[1] & 0x0F);
rtc[4] = (tmp[0] >> 4);
rtc[5] = (tmp[0] & 0x0F);
return rtc;
}
/*
*/
void SetRTC(void)
{
Write_Ds1302(0x8E,0X00);
Write_Ds1302(w_rtc_address[0], (set[4]<<4) | (set[5]));
Write_Ds1302(w_rtc_address[1], (set[2]<<4) | (set[3]));
Write_Ds1302(w_rtc_address[2], (set[0]<<4) | (set[1]));
Write_Ds1302(0x8E,0x80);
}
ds1302.h
#ifndef __DS1302_H
#define __DS1302_H
#include "regx52.h"
#include "intrins.h"
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
void SetRTC(void);
unsigned char* ReadRTC(void);
unsigned char Read_Ds1302 ( unsigned char address );
void Write_Ds1302( unsigned char address,unsigned char dat );
#endif
实际读写时部分的代码
unsigned char Write_DS1302_adrr[7] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
unsigned char Read_DS1302_adrr[7] = {0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
unsigned char Timer[7] = {0x24,0x18,0x19,0x08,0x03,0x05,0x24};
void DS1302_peizhi()
{
unsigned char i;
Write_Ds1302(0x8e,0x00);
for(i=0;i<7;i++)
{
Write_Ds1302(Write_DS1302_adrr[i],Timer[i]);
}
Write_Ds1302(0x8e,0x80);
}
void DS1302_readtime()
{
unsigned char i;
for(i=0;i<7;i++)
{
Timer[i] = Read_Ds1302(Read_DS1302_adrr[i]);
}
}
//这后面在分别读取出Timer[i]里面的值,十位是Timer[i]/16,个位Timer[i]%16
上述代码并非所有代码,仅为DS1302部分代码,使代码运行许结合蓝桥杯单片机基础部分——1、基础模块代码使用
本人水平有限,所有代码都是自己的风格书写,但是大致的应该是没有什么问题,希望对大家有帮助如果有哪里出错或者有更好的解法可以与我私信或在评论区里进行讨论