蓝桥杯单片机之DS1302时钟模块的使用

DS1302简介

DS1302是美国DALLAS公司推出的高性能、低功耗的实时时钟,采用SPI三线接口与MCU进行同步通信,实时时钟可提供秒、分、时、日、星期、月和年。 简单来说,DS1302可以理解为一个电子手表,可以设定时间,也可以读取时间。
在DS1302中有两块存储器:日历时钟寄存器和RAM存储器。前者用于记录实时时间,后者用于记录其他数据。重点是对日历时钟寄存器得理解,设定时间参数就是往该寄存器写入内容,同时读取时间是也是在该寄存器中读取。

SPI串口简介

SPI总线是同步、全双工双向的4线式串行接口总线。

BCD码

BCD码(Binary-Coded Decimal‎),用4位二进制数来表示1位十进制数中的0~9这10个数码,是一种二进制的数字编码形式,用二进制编码的十进制代码。BCD码这种编码形式利用了四个位元来储存一个十进制的数码,使二进制和十进制之间的转换得以快捷的进行。(来自百度百科
在这里使用的是最基本的BCD码——8421有权BCD码;
对照表:

十进制数8421码
00
11
210
311
4100
5101
6110
7111
81000
91001

8为8421码的计算方法:合四为一

例如: 8421码: 0010 0011 ——>十进制:24
0010——>2
0011——>4
2*10 + 4 =24

阅读手册获取寄存器信息

日历时钟寄存器

手册中的描述:
在这里插入图片描述
DS1302可以在12小时或24小时模式下运行。小时寄存器(85H、84H)的BIT7定义为12或24小时模式选择位。高电平时,选择12小时模式。在12小时模式下,BIT5是AM/PM位,逻辑高电平为PM。在24小时模式下,第5位是第二个10小时位(20–23小时)。

CH :时钟暂停标志位

  • CH=0;时钟停止
  • CH=1;时钟运行

WP:写保护位

  • WP=0:可以对时钟或RAM寄存器进行写操作
  • WP=1:禁止一切对任一寄存器的写操作

控制字

手册中的描述:
DS1302将地址和读写控制放到一个字节(功能寄存器)里面,形成一个控制字,格式如下:
在这里插入图片描述

BIT7:必须为1,如果等于0,则无法将数据写入DS1302
BIT6:0表示存取日历时钟数据,1表示存取RAM数据
BIT5~BIT1:表示操作单元的地址
BIT0:0表示写操作,1表示读操作

将手册中的数据进行分析可得

控制字作用时能够在一个功能寄存器中进行两种功能操作(写与读)!!!
所以我们进行功能操作时是发送控制字到主机对应的功能寄存器。

寄存器名称读控制字写控制字BIT7BIT6BIT5BIT4BIT3BIT2BIT1BIT0Range
81H80HCH10 SecondsSeconds00-59
83H82H10 MinutesMinutes00-59
85H84H12制/24制010HourHour1-12/0-23
AM/PM
87H86H0010 DateDate1—31
89H88H00010 MonthMonth1—12
星期8BH8AH00000Day1—7
8DH8CH10 YearYear0-99

完整代码示例:

#include "reg52.h"  
#include "ds1302.h"
#include "intrins.h"      

unsigned char code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};   //读对应的控制字
unsigned char code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};  //写对应的控制字
unsigned char TIME[7] = {0x30, 0x50, 0x23, 0x17, 0x02, 0x06, 0x18};     //时间数据存储数组,读数据之前存放了时间初始化参数

unsigned char SMG_NoDot[19] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x80, 0xc6, 0xc0, 0x86, 0x8e, 0xbf, 0x7f, 0xff}; //0-9、A-F、'-'、'.'

void Delay500us();
void Timer_Display();
void DisplaySMG_Temperature(unsigned int dat);
void Digital_Tube(unsigned char Position, unsigned char Typeface);

void Delay500us()       //@12.000MHz
{
    unsigned char i, j;

    i = 6;
    j = 211;
    do
    {
        while (--j);
    }
    while (--i);
}
void DS1302_Config()    //时间参数初始化
{
        unsigned char n;
        Write_Ds1302_Byte(0x8E,0x00);   //打开读写保护,允许写入
        for (n=0; n<7; n++) 
        {
                Write_Ds1302_Byte(WRITE_RTC_ADDR[n],TIME[n]);           //将时间初始化参数写入对应寄存器
        }
        Write_Ds1302_Byte(0x8E,0x80);   //关闭读写保护,禁止写入
}

void DS1302_ReadTime()
{
        unsigned char n;
        for (n=0; n<7; n++) 
        {
            TIME[n] = Read_Ds1302_Byte(READ_RTC_ADDR[n]);           //将寄存器中的数据读入TIME缓冲区
        }                
}
void Digital_Tube(unsigned char Position, unsigned char Typeface)   //Position是数码管第几位(从左到右,0开始),Typeface是显示的字样
{
    unsigned char Bit[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
    P2 = P2 & 0x1f | 0xc0;
    P0 = Bit[Position];
    P2 = P2 & 0x1f | 0xe0;
    P0 = Typeface;
    Delay500us();
    
    P0 = 0XFF;
    P2 = P2 & 0x1f ;    //数码管消影
}

void Timer_Display()
{

        Digital_Tube(0,SMG_NoDot[TIME[2]/16]);      //取十位
        Digital_Tube(1,SMG_NoDot[TIME[2]&0x0f]);	//取个位
    
        Digital_Tube(2,SMG_NoDot[16]);

        Digital_Tube(3,SMG_NoDot[TIME[1]/16]);      //取十位
        Digital_Tube(4,SMG_NoDot[TIME[1]&0x0f]);    //取个位
    
        Digital_Tube(5,SMG_NoDot[16]);

        Digital_Tube(6,SMG_NoDot[TIME[0]/16]);      //取十位
        Digital_Tube(7,SMG_NoDot[TIME[0]&0x0f]);    //取个位

    	/*数码管全灭,消影作用*/
        P2 = P2 & 0x1f | 0xc0;		
        P0 = 0XFF;
        P2 = P2 & 0x1f | 0xe0;
        P0 = 0XFF;
}

main()
{
        DS1302_Config();    //DS1302初始化时间参数
        while(1)
        {
            DS1302_ReadTime();  //读取时间参数
            Timer_Display();    //显示时间参数
        }
}

总结

其实对DS1302的基本操作就是设定时间参数(void DS1302_Config();)与读取实时时间参数(DS1302_ReadTime(););
单个字节的读写函数在赛点资料包底层驱动已经存在,我们需要做的就是调用对应的函数,将我们想要的数据写入对应的寄存器或者在对应的寄存器读出时间数据。这里利用的就是C语言的数组部分知识。

  • 4
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于51单片机DS1302时钟模块使用代码示例: ```c #include <REG52.h> #include <intrins.h> #define uchar unsigned char #define uint unsigned int sbit RST = P3^4; sbit DAT = P3^5; sbit CLK = P3^6; // 延时函数 void Delay(uint i) { while(i--); } // 向DS1302写入一个字节 void DS1302_WriteByte(uchar dat) { uchar i; for (i = 0; i < 8; i++) { DAT = dat & 0x01; CLK = 0; CLK = 1; dat >>= 1; } } // 从DS1302读取一个字节 uchar DS1302_ReadByte() { uchar i, dat = 0; for (i = 0; i < 8; i++) { dat >>= 1; if (DAT) dat |= 0x80; CLK = 0; CLK = 1; } return dat; } // 启动DS1302时钟 void DS1302_Start() { RST = 1; CLK = 1; _nop_(); _nop_(); _nop_(); RST = 0; DS1302_WriteByte(0x8e); DS1302_WriteByte(0x00); RST = 1; } // 停止DS1302时钟 void DS1302_Stop() { RST = 0; CLK = 0; _nop_(); _nop_(); _nop_(); RST = 1; DS1302_WriteByte(0x8e); DS1302_WriteByte(0x80); RST = 1; } // 写入DS1302时间 void DS1302_WriteTime(uchar year, uchar month, uchar day, uchar hour, uchar minute, uchar second) { DS1302_Start(); DS1302_WriteByte(0xbe); DS1302_WriteByte(second); DS1302_WriteByte(minute); DS1302_WriteByte(hour); DS1302_WriteByte(day); DS1302_WriteByte(month); DS1302_WriteByte(year); DS1302_Stop(); } // 读取DS1302时间 void DS1302_ReadTime(uchar *year, uchar *month, uchar *day, uchar *hour, uchar *minute, uchar *second) { DS1302_Start(); DS1302_WriteByte(0xbf); *second = DS1302_ReadByte(); *minute = DS1302_ReadByte(); *hour = DS1302_ReadByte(); *day = DS1302_ReadByte(); *month = DS1302_ReadByte(); *year = DS1302_ReadByte(); DS1302_Stop(); } void main() { uchar year, month, day, hour, minute, second; DS1302_WriteTime(0x21, 0x10, 0x13, 0x10, 0x30, 0x00); while (1) { DS1302_ReadTime(&year, &month, &day, &hour, &minute, &second); printf("20%d-%d-%d %d:%d:%d\n", year, month, day, hour, minute, second); Delay(1000); } } ``` 在上述代码中,定义了DS1302的RST、DAT、CLK引脚,以及自定义了延时函数`Delay`。然后定义了向DS1302写入一个字节的函数`DS1302_WriteByte`,从DS1302读取一个字节的函数`DS1302_ReadByte`,启动DS1302时钟的函数`DS1302_Start`,停止DS1302时钟的函数`DS1302_Stop`,写入DS1302时间的函数`DS1302_WriteTime`,以及读取DS1302时间的函数`DS1302_ReadTime`。 在`main`函数中,首先调用`DS1302_WriteTime`函数设置初始时间,然后通过`DS1302_ReadTime`函数读取当前时间,并通过串口输出。最后通过`Delay`函数延迟1秒,实现时钟的运行。需要注意的是,DS1302时钟模块的时间格式为BCD码,需要进行转换才能得到实际的时间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值