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);
}
}