基于DS1302与数码管的可调电子表设计
一、系统概述
设计以DS1302实时时钟芯片为核心,结合数码管显示和按键调时功能,实现一款低成本、高精度的可调电子表。系统支持时分秒显示、时间调整(时/分/秒)、24小时制,并具备掉电走时功能(通过纽扣电池备份),适用于家庭、办公等场景的时间显示与校准。
二、系统组成与核心功能
1. 核心组件
| 模块 | 器件型号 | 功能 |
|---|---|---|
| 实时时钟 | DS1302 | 提供年/月/日/时/分/秒,支持掉电走时 |
| 显示模块 | 6位共阳数码管 | 显示时分秒(HH:MM:SS) |
| 主控制器 | STC89C52RC(51单片机) | 系统控制、数据处理、按键响应 |
| 调时模块 | 3个轻触按键 | 设置/加/减(调整时、分、秒) |
| 电源模块 | 5V DC + CR2032纽扣电池 | 主电源供电+掉电备份(3V) |
| 驱动芯片 | 74HC595移位寄存器 | 数码管段选驱动(节省IO口) |
2. 核心功能
- 实时显示:6位数码管动态扫描显示“时:分:秒”(如12:34:56);
- 时间调整:通过按键进入调时模式,依次调整时、分、秒;
- 掉电走时:DS1302内置涓流充电电路,纽扣电池备份时间(可维持数年);
- 低功耗:空闲时数码管可关闭背光(可选),降低能耗。
三、硬件设计
1. 电路原理图
+-----------------------------------+
| STC89C52RC |
| |
| P1.0-P1.7 → 74HC595 (D0-D7) | // 数码管段选
| P2.0 → 74HC595 (SHCP) | // 移位时钟
| P2.1 → 74HC595 (STCP) | // 锁存时钟
| P2.2-P2.4 → 数码管位选 (6位) | // 位选控制
| P3.0 → DS1302 (RST) | // 复位/片选
| P3.1 → DS1302 (SCLK) | // 串行时钟
| P3.2 → DS1302 (I/O) | // 数据线
| P3.3 → 按键1 (设置) | // 进入调时模式
| P3.4 → 按键2 (加) | // 时间加1
| P3.5 → 按键3 (减) | // 时间减1
| VCC → 5V, GND → GND |
+-----------------------------------+
关键电路说明
- DS1302接口:三线制(SCLK、I/O、RST),需外接32.768kHz晶振(X1、X2)和CR2032纽扣电池(BT1,3V备份);
- 数码管驱动:6位共阳数码管,段选通过74HC595输出(P1口),位选通过P2.2-P2.4(3-8译码器可选,简化位选控制);
- 按键电路:3个轻触按键(K1-K3)接P3.3-P3.5,上拉电阻(10kΩ)接VCC,按下时接地。
2. 元件清单
| 序号 | 名称 | 规格 | 数量 |
|---|---|---|---|
| 1 | STC89C52RC | 51单片机 | 1 |
| 2 | DS1302 | 实时时钟芯片 | 1 |
| 3 | 6位共阳数码管 | 0.56英寸 | 1 |
| 4 | 74HC595 | 8位移位寄存器 | 1 |
| 5 | 轻触按键 | 6×6×5mm | 3 |
| 6 | 纽扣电池 | CR2032 (3V) | 1 |
| 7 | 32.768kHz晶振 | 圆柱型 | 1 |
| 8 | 电阻 | 10kΩ (上拉) | 3 |
| 9 | 电阻 | 220Ω (限流) | 8 |
| 10 | 电容 | 30pF (晶振匹配) | 2 |
四、软件设计
1. 主程序流程
graph TD
A[系统初始化] --> B[DS1302初始化(启动时钟、设置初始时间)]
B --> C[数码管显示初始时间]
C --> D[扫描按键]
D -- 按键1按下 --> E[进入调时模式(选择时/分/秒)]
D -- 无按键 --> F[读取DS1302时间]
E --> G[按键2/3调整时间(时/分/秒)]
G --> H[更新DS1302时间]
H --> C
F --> C
2. 关键代码实现
(1)DS1302驱动(读写时间)
DS1302通过SPI-like接口通信,需实现写字节和读字节函数,时间数据以BCD码存储。
#include <reg52.h>
#include "ds1302.h"
// DS1302引脚定义
sbit DS1302_RST = P3^0;
sbit DS1302_SCLK = P3^1;
sbit DS1302_IO = P3^2;
// 写1字节到DS1302
void DS1302_WriteByte(unsigned char dat) {
unsigned char i;
for(i=0; i<8; i++) {
DS1302_IO = dat & 0x01; // 低位在前
DS1302_SCLK = 1;
_nop_(); _nop_();
DS1302_SCLK = 0;
dat >>= 1;
}
}
// 从DS1302读1字节
unsigned char DS1302_ReadByte() {
unsigned char i, dat=0;
for(i=0; i<8; i++) {
dat >>= 1;
if(DS1302_IO) dat |= 0x80;
DS1302_SCLK = 1;
_nop_(); _nop_();
DS1302_SCLK = 0;
}
return dat;
}
// 写时间到DS1302(时、分、秒)
void DS1302_WriteTime(unsigned char hour, unsigned char min, unsigned char sec) {
DS1302_RST = 0; _nop_();
DS1302_SCLK = 0; _nop_();
DS1302_RST = 1; _nop_();
// 写秒(0x80为写保护位,需先关闭)
DS1302_WriteByte(0x8E); // 控制寄存器
DS1302_WriteByte(0x00); // 关闭写保护
DS1302_WriteByte(0x80); // 秒寄存器地址
DS1302_WriteByte(sec); // 秒(BCD码,如0x59=59秒)
// 写分
DS1302_WriteByte(0x82); // 分寄存器地址
DS1302_WriteByte(min); // 分(BCD码)
// 写时
DS1302_WriteByte(0x84); // 时寄存器地址
DS1302_WriteByte(hour); // 时(BCD码,24小时制)
// 恢复写保护
DS1302_WriteByte(0x8E);
DS1302_WriteByte(0x80);
DS1302_RST = 0;
}
// 从DS1302读时间(时、分、秒)
void DS1302_ReadTime(unsigned char *hour, unsigned char *min, unsigned char *sec) {
DS1302_RST = 0; _nop_();
DS1302_SCLK = 0; _nop_();
DS1302_RST = 1; _nop_();
DS1302_WriteByte(0x81); // 读秒寄存器
*sec = DS1302_ReadByte();
DS1302_WriteByte(0x83); // 读分寄存器
*min = DS1302_ReadByte();
DS1302_WriteByte(0x85); // 读时寄存器
*hour = DS1302_ReadByte();
DS1302_RST = 0;
}
(2)数码管动态显示
6位数码管采用动态扫描,通过74HC595输出段选码,P2.2-P2.4控制位选(6位需2个IO口+译码器,或3个IO口直接控制)。
// 数码管段码表(0-9,共阳)
unsigned char code seg_table[] = {
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0xBF // 0-9, 冒号
};
// 显示缓存(6位:时十位、时个位、冒号、分十位、分个位、冒号、秒十位、秒个位?需6位则合并)
unsigned char display_buf[6] = {0};
// 更新显示缓存(时、分、秒转BCD码后拆分)
void UpdateDisplayBuf(unsigned char hour, unsigned char min, unsigned char sec) {
display_buf[0] = hour / 10; // 时十位
display_buf[1] = hour % 10; // 时个位
display_buf[2] = 10; // 冒号(段码表第10位)
display_buf[3] = min / 10; // 分十位
display_buf[4] = min % 10; // 分个位
display_buf[5] = 10; // 冒号(或秒十位,根据6位显示调整)
// 若为6位显示,可显示 HH:MM:SS 中的 HH:MM,或 HH MM SS(需调整位选)
}
// 数码管动态扫描
void DisplayScan() {
static unsigned char pos = 0;
P2 = (P2 & 0xF8) | pos; // 位选(假设P2.0-P2.2控制6位,需根据实际调整)
P1 = seg_table[display_buf[pos]]; // 段选(通过74HC595输出,此处简化直接P1口)
pos = (pos + 1) % 6;
_delay_ms(2); // 扫描间隔2ms,避免闪烁
}
(3)按键调时逻辑
通过3个按键实现“设置-加-减”功能,短按“设置”键进入调时模式,依次切换调整时、分、秒;长按“加/减”键快速调整。
sbit KEY_SET = P3^3;
sbit KEY_ADD = P3^4;
sbit KEY_SUB = P3^5;
unsigned char adjust_mode = 0; // 0-正常显示,1-调时,2-调分,3-调秒
unsigned char hour, min, sec; // 当前时间
void KeyProcess() {
if(KEY_SET == 0) { // 设置键按下
_delay_ms(10); // 消抖
if(KEY_SET == 0) {
adjust_mode = (adjust_mode + 1) % 4; // 循环切换模式(0→1→2→3→0)
if(adjust_mode == 0) { // 退出调时模式,保存时间到DS1302
DS1302_WriteTime(hour, min, sec);
}
}
while(KEY_SET == 0); // 等待释放
}
if(adjust_mode > 0) { // 调时模式下
if(KEY_ADD == 0) { // 加键
_delay_ms(10);
if(KEY_ADD == 0) {
if(adjust_mode == 1) hour = (hour + 1) % 24; // 时(0-23)
if(adjust_mode == 2) min = (min + 1) % 60; // 分(0-59)
if(adjust_mode == 3) sec = (sec + 1) % 60; // 秒(0-59)
}
while(KEY_ADD == 0);
}
if(KEY_SUB == 0) { // 减键
_delay_ms(10);
if(KEY_SUB == 0) {
if(adjust_mode == 1) hour = (hour + 23) % 24; // 时减1
if(adjust_mode == 2) min = (min + 59) % 60; // 分减1
if(adjust_mode == 3) sec = (sec + 59) % 60; // 秒减1
}
while(KEY_SUB == 0);
}
}
}
参考代码 用DS1302与1602LCD设计的可调式电子日历与时钟 www.youwenfan.com/contentcst/135510.html
五、Proteus仿真
1. 仿真步骤
- 创建工程:Proteus中添加STC89C52、DS1302、6位共阳数码管、74HC595、按键、晶振、纽扣电池等元件;
- 连接电路:按原理图连接DS1302(SCLK-P3.1, I/O-P3.2, RST-P3.0)、数码管(段选-P1,位选-P2.2-P2.4)、按键(P3.3-P3.5);
- 加载程序:将编译好的HEX文件(Keil C51编译)加载到STC89C52;
- 运行仿真:观察数码管显示时间,按下按键测试调时功能,修改DS1302初始时间验证准确性。
2. 仿真截图
- 正常显示:数码管显示“12:34:56”;
- 调时模式:按下“设置”键,数码管闪烁提示当前调整位(如调时模式下时位闪烁);
- 时间调整:按“加/减”键,对应位数值变化,松开后更新显示。
六、制作与调试
1. 制作步骤
- 焊接电路:按原理图焊接元件,注意DS1302的晶振(32.768kHz)和纽扣电池(CR2032)正确连接;
- 烧录程序:用STC-ISP工具将HEX文件烧录到STC89C52;
- 校准时间:首次上电时,通过按键设置初始时间,DS1302将自动走时;
- 测试功能:检查数码管显示是否稳定,按键调时是否灵敏,掉电后时间是否保持。
2. 常见问题解决
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 数码管不亮 | 段选/位选接反、限流电阻过大 | 检查接线,减小限流电阻(220Ω) |
| 时间不走时 | DS1302晶振未起振、电池没电 | 更换32.768kHz晶振,检查纽扣电池电压 |
| 调时模式无反应 | 按键消抖不良、程序逻辑错误 | 增加按键消抖延时,检查adjust_mode变量 |
| 显示乱码 | BCD码转换错误、段码表错误 | 确认时间数据以BCD码写入DS1302,核对段码表 |
七、总结
本设计基于DS1302和数码管实现了可调电子表,具有以下特点:
- 低成本:核心元件(STC89C52、DS1302、数码管)价格低廉,适合DIY;
- 高精度:DS1302走时精度±2ppm(日误差<2秒),配合32.768kHz晶振;
- 易扩展:可添加日期显示(DS1302支持年/月/日)、闹钟功能(增加蜂鸣器)。
应用场景:家庭桌面时钟、实验室时间基准、教学演示(单片机+实时时钟应用)。