day08DS1302时钟

DS1302时钟

1.1 需求描述

本案例讲解如何使用DS1302时钟芯片将时间信息显示在LCD上。

1.2 硬件设计

1.2.1 硬件原理图

在这里插入图片描述
在这里插入图片描述

1.2.3 DS1302工作原理

引脚名称引脚作用备注
sclk时钟线上升沿发送数据,下降沿读取数据
io数据线高电平为1,低电平为0
ce(rst)使能线高电平有效,低电平无效

1.3软件设计

1)Int_DS1302N.h

在Int目录下创建Int_DS1302N.h,写入以下内容。

#ifndef __INT_DS1302N_H__
#define __INT_DS1302N_H__
#include <STC89C5xRC.H>
#include "Util.h"

typedef struct
{
    u8 second;
    u8 minute;
    u8 hour;
    u8 day;
    u8 month;
    u8 year;
    u8 day_of_week;
} Struct_Date;

/**
 * @brief DS1302N时钟初始化
 *
 */
void Int_DS1302N_Init();

/**
 * @brief 设置1302时钟的时间
 *
 * @param p_st_date 时间结构体
 */
void Int_DS1302N_SetDate(Struct_Date *p_st_date);

/**
 * @brief 获取1302时间
 *
 * @param p_st_date 时间结构体
 */
void Int_DS1302N_GetDate(Struct_Date *p_st_date);

#endif

2)Int_DS1302N.c

在Int目录下创建Int_DS1302N.c,写入以下内容。

#include "Int_DS1302N.h"

#define SECOND      0x80
#define MINUTE      0x82
#define HOUR        0x84
#define DAY         0x86
#define MONTH       0x88
#define DAY_OF_WEEK 0x8A
#define YEAR        0x8C
#define WP          0x8E

#define SCLK        P37
#define IO          P40
#define RST         P41

/**
 * @brief 发送数据,低位先发
 *
 * @param dat
 */
static void Int_DS1302N_WriteByte(u8 dat)
{
    u8 i;
    SCLK = 0;

    for (i = 0; i < 8; i++)
    {
        IO   = dat & 0x1;
        SCLK = 1;
        SCLK = 0;
        dat >>= 1;
    }
}

/**
 * @brief 读取数据,低位先回
 *
 * @return u8
 */
static u8 Int_DS1302N_ReadByte()
{
    u8 i, temp = 0;
    // 读数据之前,拉高IO
    IO = 1;

    for (i = 0; i < 7; i++)
    {
        // 由于发送方法已经拉了下降沿,这里我们需要先接收数据
        if (IO == 1)
        {
            temp |= 0x80;
        }
        temp >>= 1;
        SCLK = 1;
        SCLK = 0;
    }

    if (IO == 1)
    {
        temp |= 0x80;
    }

    return temp;
}

/**
 * @brief 给具体某个寄存器设置值
 *
 * @param addr 寄存器地址
 * @param dat 要设置的值
 */
static void Int_DS1302N_SetRegister(u8 addr, u8 dat)
{
    RST = 1;
    Int_DS1302N_WriteByte(addr);
    Int_DS1302N_WriteByte(dat);
    RST = 0;
}

/**
 * @brief 从某个寄存器读值
 *
 * @param addr 寄存器地址
 * @return u8 读取的值
 */
static u8 Int_DS1302N_GetRegister(u8 addr)
{
    u8 temp;

    RST = 1;
    Int_DS1302N_WriteByte(addr | 1);
    temp = Int_DS1302N_ReadByte();
    RST  = 0;

    return temp;
}

void Int_DS1302N_Init()
{
    SCLK = 0;
    RST  = 0;
    IO   = 0;
}

void Int_DS1302N_SetDate(Struct_Date *p_st_date)
{
    u8 temp;

    // 关闭写保护
    Int_DS1302N_SetRegister(WP, 0x0);

    // 设置秒
    temp = (p_st_date->second % 10) | ((p_st_date->second / 10) << 4);
    Int_DS1302N_SetRegister(SECOND, temp);

    // 设置分钟
    temp = (p_st_date->minute % 10) | ((p_st_date->minute / 10) << 4);
    Int_DS1302N_SetRegister(MINUTE, temp);

    // 设置小时
    temp = (p_st_date->hour % 10) | ((p_st_date->hour / 10) << 4);
    Int_DS1302N_SetRegister(HOUR, temp);

    // 设置日
    temp = (p_st_date->day % 10) | ((p_st_date->day / 10) << 4);
    Int_DS1302N_SetRegister(DAY, temp);

    // 设置月
    temp = (p_st_date->month % 10) | ((p_st_date->month / 10) << 4);
    Int_DS1302N_SetRegister(MONTH, temp);

    // 设置年
    temp = (p_st_date->year % 10) | ((p_st_date->year / 10) << 4);
    Int_DS1302N_SetRegister(YEAR, temp);

    // 设置星期
    Int_DS1302N_SetRegister(DAY_OF_WEEK, p_st_date->day_of_week % 10);

    // 开启写保护
    Int_DS1302N_SetRegister(WP, 0x80);
}

void Int_DS1302N_GetDate(Struct_Date *p_st_date)
{
    u8 temp;
    // 获取秒
    temp              = Int_DS1302N_GetRegister(SECOND);
    p_st_date->second = (temp >> 4) * 10 + (temp & 0x0F);

    temp              = Int_DS1302N_GetRegister(MINUTE);
    p_st_date->minute = (temp >> 4) * 10 + (temp & 0x0F);

    temp            = Int_DS1302N_GetRegister(HOUR);
    p_st_date->hour = (temp >> 4) * 10 + (temp & 0x0F);

    temp           = Int_DS1302N_GetRegister(DAY);
    p_st_date->day = (temp >> 4) * 10 + (temp & 0x0F);

    temp             = Int_DS1302N_GetRegister(MONTH);
    p_st_date->month = (temp >> 4) * 10 + (temp & 0x0F);

    temp            = Int_DS1302N_GetRegister(YEAR);
    p_st_date->year = (temp >> 4) * 10 + (temp & 0x0F);

    temp                   = Int_DS1302N_GetRegister(DAY_OF_WEEK);
    p_st_date->day_of_week = (temp >> 4) * 10 + (temp & 0x0F);
}

3)Main.c

在main.c写入以下内容。

#include <STC89C5xRC.H>
#include <STDIO.H>
#include "Int_DS1302N.h"
#include "Int_LCD1602.h"
#include "Int_DS18B20.h"

code char *WEEK_NAME[] = {
    "Mon",
    "Tue",
    "Wed",
    "Thu",
    "Fri",
    "Sat",
    "Sun"};

void main()
{
    u8 str[17];
    u8 temperature;
    Struct_Date st_date;
    st_date.year        = 23;
    st_date.month       = 12;
    st_date.day         = 29;
    st_date.day_of_week = 5;
    st_date.hour        = 11;
    st_date.minute      = 32;
    st_date.second      = 00;

    // 初始化时钟并设置时间
    Int_DS1302N_Init();
    Int_LCD1602_Init();
    Int_DS1302N_SetDate(&st_date);

    while (1)
    {
        Int_DS1302N_GetDate(&st_date);
        temperature = Int_DS18B20_GetTemperature();

        sprintf(str, "20%02d/%02d/%02d %s",
                (int)st_date.year,
                (int)st_date.month,
                (int)st_date.day,
                WEEK_NAME[st_date.day_of_week - 1]);

        Int_LCD1602_ShowStr(0, 0, str);

        sprintf(str, "%02d:%02d:%02d Temp:%d",
                (int)st_date.hour,
                (int)st_date.minute,
                (int)st_date.second,
                (int)temperature);

        Int_LCD1602_ShowStr(1, 0, str);
        Delay1ms(50);
    }
}

602_ShowStr(0, 0, str);

    sprintf(str, "%02d:%02d:%02d Temp:%d",
            (int)st_date.hour,
            (int)st_date.minute,
            (int)st_date.second,
            (int)temperature);

    Int_LCD1602_ShowStr(1, 0, str);
    Delay1ms(50);
}

}


  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路x飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值