深入解析:【Proteus8.17仿真】 STM32仿真 0.96OLED 屏幕显示ds1302实时时间

news/2025/10/17 14:03:30/文章来源:https://www.cnblogs.com/lxjshuju/p/19147684

前言

在嵌入式架构开发中,实时时钟(RTC)和显示模块是常见的效果需求。今天我们来分享如何使用STM32F103C8T6(蓝桥杯常用芯片)驱动DS1302实时时钟芯片,并在OLED屏幕上显示时间信息。本文含有完整的代码实现和详细的原理讲解,适合嵌入式初学者和爱好者参考学习。

DS1302 概述

美国Dallas公司(后被Maxim Integrated,现为ADI公司一部分)推出的一款低成本、低功耗的实时时钟芯片。它能够提供秒、分、时、日、月、年等日历信息,并且具有闰年自动调整功能(奏效至2100年)。就是DS1302

由于其接口简便、成本低廉,在早期的电子设计、学习套件(如Arduino)、以及一些对时间精度要求不高的消费类产品中得到了非常广泛的应用。

ds1302实物图

主要特点

  1. 实时时钟特性

    • 提供秒、分、时、日、月、年和星期信息。
    • 月末日期自动调整,包括闰年补偿(管用至2100年)。
    • 可选择12小时制或24小时制。
  2. 低功耗

    • 在备用电源(如纽扣电池)模式下,功耗极低,典型值小于300nA,能保证在主电源断开后时钟长时间持续运行。
  3. 内置RAM

    • 提供31字节的额外静态RAM,可用于存储用户自定义的配置参数或资料。
  4. 串行接口

    • 采用简单的三线串行接口(CEI/OSCLK),与微控制器(如51单片机、AVR、Arduino等)连接非常方便,占用I/O口少。
  5. 双电源供电

    • 支持主电源和备用电源(如3V锂电池)双电源输入,具有电源切换和控制电路,在主电源失效时自动切换到备用电源。
  6. 宽电压工作

    • 主电源工作电压范围宽:2.0V 至 5.5V。

引脚定义与功能

DS1302通常有8引脚DIP或SOIC封装。

引脚编号引脚名称功能描述
1Vcc2主电源输入引脚。
2X132.768kHz晶振输入引脚1。
3X232.768kHz晶振输入引脚2。
4GND接地
5CE片选使能引脚(有时也标记为RST)。高电平有效,在开始读写数据前必须将其置为高电平。
6I/O双向数据线引脚,用于数据的串行输入和输出。
7SCLK串行时钟输入引脚。素材在时钟的上升沿或下降沿被读写。
8Vcc1备用电源输入引脚(如接3V纽扣电池)。

注意:Vcc1和Vcc2的供电关系是,当Vcc2 > Vcc1 + 0.2V时,芯片由Vcc2供电;当Vcc2 < Vcc1时,芯片自动切换到由Vcc1供电。


内部结构与核心部件

  1. 移位寄存器: 负责与微控制器进行串行通信。
  2. 控制逻辑: 解析微控制器发送的命令字节,决定是读操作还是写操作,以及目标是时钟寄存器还是RAM。
  3. 时钟/日历寄存器组: 存储秒、分、时等时间日期信息的BCD码。
  4. 静态RAM: 31字节的用户数据存储区。
  5. 振荡器与分频器: 外接32.768kHz晶振,经过内部分频链,产生1Hz的秒信号。
  6. 电源控制电路: 管理主电源和备用电源的自动切换。

通信协议(时序)

DS1302使用一种简单的同步串行协议,所有数据传输都发生在CE引脚为高电平期间。

在这里插入图片描述

应用领域

  • Arduino/Raspberry Pi/51/32等开发板的时钟模块
  • 数字万用表、数字温度计等仪器仪表
  • 电话、传真机等办公设备
  • 便携式设备、电池供电的平台
  • 智能电表
  • 汽车电子(如行车记录仪)

实现准备

proteus 仿真图一份(如下)
在这里插入图片描述

实现代码(基于stm32f103c8t6 标准库 代码)

在这里插入图片描述

代码实现细节:

#include "stm32f10x.h"                  // Device header
//#include "usart.h"
#include "delay.h"
#include "KEY.h"
#include "oled.h"
//#include "beep.h"
#include "bsp_dht11.h"
#include "adc0832.h" 
#include "stdio.h" 
//#include "ds1302.h"
char time[7]={25, 4, 25, 12, 30, 0, 5};
char readtime[7]={25, 4, 25, 12, 30, 0, 5};
u8 war[32];
u8 time1[32];
//温度湿度阈值
//u8 dht11_data[4] = {20, 70, 20, 40};
u8 Tmin=20;
u8 Tmax=40;
u8 Hmin=30;
u8 Hmax=70;
u16 count=0;
DHT11_Data_TypeDef DHT11_Data;
#define Delay_us delay_us
void Beep_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
}
void Beep_Run(unsigned char x)
{
if(x==1)
{
GPIO_SetBits(GPIOB,GPIO_Pin_5);
}else{
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
//GPIO_SetBits(GPIOB,GPIO_Pin_5);
}
}
#define DS1302_SCLK_PIN    GPIO_Pin_7
#define DS1302_IO_PIN      GPIO_Pin_6
#define DS1302_CE_PIN      GPIO_Pin_5
#define DS1302_GPIO        GPIOA
void DS1302_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// SCLK和CE配置为推挽输出
GPIO_InitStructure.GPIO_Pin = DS1302_SCLK_PIN | DS1302_CE_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DS1302_GPIO, &GPIO_InitStructure);
// IO配置为浮空输入(初始状态)
GPIO_InitStructure.GPIO_Pin = DS1302_IO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DS1302_GPIO, &GPIO_InitStructure);
// 初始状态
GPIO_ResetBits(DS1302_GPIO, DS1302_SCLK_PIN);
GPIO_ResetBits(DS1302_GPIO, DS1302_CE_PIN);
}
// 设置IO方向为输出
static void DS1302_IO_Output(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DS1302_IO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DS1302_GPIO, &GPIO_InitStructure);
}
// 设置IO方向为输入
static void DS1302_IO_Input(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DS1302_IO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DS1302_GPIO, &GPIO_InitStructure);
}
// 向DS1302写入一个字节
static void DS1302_WriteByte(uint8_t dat)
{
uint8_t i;
DS1302_IO_Output();
for(i=0; i<8; i++)
{
if(dat & 0x01)
GPIO_SetBits(DS1302_GPIO, DS1302_IO_PIN);
else
GPIO_ResetBits(DS1302_GPIO, DS1302_IO_PIN);
GPIO_SetBits(DS1302_GPIO, DS1302_SCLK_PIN);
Delay_us(5);
GPIO_ResetBits(DS1302_GPIO, DS1302_SCLK_PIN);
Delay_us(5);
dat >>= 1;
}
}
// 从DS1302读取一个字节
static uint8_t DS1302_ReadByte(void)
{
uint8_t i, dat = 0;
DS1302_IO_Input();
for(i=0; i<8; i++)
{
dat >>= 1;
if(GPIO_ReadInputDataBit(DS1302_GPIO, DS1302_IO_PIN))
dat |= 0x80;
GPIO_SetBits(DS1302_GPIO, DS1302_SCLK_PIN);
Delay_us(5);
GPIO_ResetBits(DS1302_GPIO, DS1302_SCLK_PIN);
Delay_us(5);
}
return dat;
}
// DS1302命令定义
#define DS1302_SECOND       0x80
#define DS1302_MINUTE       0x82
#define DS1302_HOUR         0x84
#define DS1302_DAY          0x86
#define DS1302_MONTH        0x88
#define DS1302_WEEK         0x8A
#define DS1302_YEAR         0x8C
#define DS1302_WP           0x8E    // 写保护
#define DS1302_BURST        0xBE
// 向DS1302寄存器写入数据
void DS1302_WriteReg(uint8_t reg, uint8_t dat)
{
GPIO_SetBits(DS1302_GPIO, DS1302_CE_PIN);
Delay_us(5);
DS1302_WriteByte(reg);      // 写入寄存器地址
DS1302_WriteByte(dat);      // 写入数据
GPIO_ResetBits(DS1302_GPIO, DS1302_CE_PIN);
Delay_us(5);
}
// 从DS1302寄存器读取数据
uint8_t DS1302_ReadReg(uint8_t reg)
{
uint8_t dat;
GPIO_SetBits(DS1302_GPIO, DS1302_CE_PIN);
Delay_us(5);
DS1302_WriteByte(reg | 0x01);  // 读命令需要将地址最低位置1
dat = DS1302_ReadByte();
GPIO_ResetBits(DS1302_GPIO, DS1302_CE_PIN);
Delay_us(5);
return dat;
}
// BCD码转十进制
static uint8_t BCD2DEC(uint8_t bcd)
{
return (bcd>>4)*10 + (bcd&0x0F);
}
// 十进制转BCD码
static uint8_t DEC2BCD(uint8_t dec)
{
return ((dec/10)<<4) + (dec%10);
}
// 设置时间
void DS1302_SetTime(uint8_t hour, uint8_t min, uint8_t sec)
{
// 关闭写保护
DS1302_WriteReg(DS1302_WP, 0x00);
// 写入时间
DS1302_WriteReg(DS1302_SECOND, DEC2BCD(sec));
DS1302_WriteReg(DS1302_MINUTE, DEC2BCD(min));
DS1302_WriteReg(DS1302_HOUR, DEC2BCD(hour));
// 开启写保护
DS1302_WriteReg(DS1302_WP, 0x80);
}
// 读取时间
void DS1302_GetTime(uint8_t *hour, uint8_t *min, uint8_t *sec)
{
*sec = BCD2DEC(DS1302_ReadReg(DS1302_SECOND) & 0x7F);
*min = BCD2DEC(DS1302_ReadReg(DS1302_MINUTE));
*hour = BCD2DEC(DS1302_ReadReg(DS1302_HOUR));
}
typedef struct {
uint8_t year;
uint8_t month;
uint8_t day;
uint8_t week;
uint8_t hour;
uint8_t minute;
uint8_t second;
} DS1302_DateTime;
// 设置完整日期时间
void DS1302_SetDateTime(DS1302_DateTime *dt)
{
// 关闭写保护
DS1302_WriteReg(DS1302_WP, 0x00);
// 写入时间日期
DS1302_WriteReg(DS1302_SECOND, DEC2BCD(dt->second)& 0x7F);
DS1302_WriteReg(DS1302_MINUTE, DEC2BCD(dt->minute));
DS1302_WriteReg(DS1302_HOUR, DEC2BCD(dt->hour));
DS1302_WriteReg(DS1302_DAY, DEC2BCD(dt->day));
DS1302_WriteReg(DS1302_MONTH, DEC2BCD(dt->month));
DS1302_WriteReg(DS1302_WEEK, DEC2BCD(dt->week));
DS1302_WriteReg(DS1302_YEAR, DEC2BCD(dt->year));
// 开启写保护
DS1302_WriteReg(DS1302_WP, 0x80);
}
// 读取完整日期时间
void DS1302_GetDateTime(DS1302_DateTime *dt)
{
dt->second = BCD2DEC(DS1302_ReadReg(DS1302_SECOND) & 0x7F);
dt->minute = BCD2DEC(DS1302_ReadReg(DS1302_MINUTE));
dt->hour = BCD2DEC(DS1302_ReadReg(DS1302_HOUR));
dt->day = BCD2DEC(DS1302_ReadReg(DS1302_DAY));
dt->month = BCD2DEC(DS1302_ReadReg(DS1302_MONTH));
dt->week = BCD2DEC(DS1302_ReadReg(DS1302_WEEK));
dt->year = BCD2DEC(DS1302_ReadReg(DS1302_YEAR));
}
int main(void)
{
unsigned char  getkey=0,keymode=0;
uint16_t tds=0;
delay_init();	     //延时初始化
//蜂鸣器初始化
Beep_Init();
//oled初始化
OLED_Init();
;
Key_Init();
DS1302_GPIO_Init();
DS1302_DateTime dt;
// 设置初始时间
dt.year = 23;
dt.month = 5;
dt.day = 15;
dt.week = 1;  // 周一
dt.hour = 12;
dt.minute = 0;
dt.second = 0;
OLED_Clear();
delay_ms(20);
OLED_ShowString(0, 0,"STM32-App time",16);
//设置时间
//DS1302_Init(); // 初始化DS1302
// 写入初始时间
//DS1302_WriteTime(time); // 2025年4月25日12点
//TIME_Set();
while(1)
{
DS1302_GetDateTime(&dt);
sprintf((char *)war, "%02d-%02d-%02d", dt.year,dt.month,dt.day);
OLED_ShowString(0, 3,war,8);
sprintf((char *)time1, "%02d-%02d-%02d",dt.hour,dt.minute,dt.second);
OLED_ShowString(0, 4,time1,8);
}//while line
}

实现效果

在这里插入图片描述
需要 源码工程的小伙伴在 评论区留言。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/938877.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年10月床垫品牌推荐榜:围绕环保认证与试睡政策的系统化评析

一、引言 对于每天需要7到8小时睡眠的消费者而言,床垫不仅决定休息质量,更与长期脊柱健康、过敏控制及居家环保直接相关。2025年三季度,全国主要电商平台床垫类目检索量环比增长18.6%,其中“环保材质”“可拆洗”“…

贪心策略总结

贪心 is so difficult!!! 国王游戏 Problem题意简介: 有 \(n\) 个大臣,国王左右手上的整数分别是 \(a_0,b_0\),第 \(i\) 个大臣左右手上的整数分别是 \(a_i,b_i\)。 现在国王和所有大臣将排成一排,国王在队伍最…

2025年10月上海装修公司推荐榜:极家家居设计标准与施工节点全维度对比

一、引言 在上海这样房价高、户型多元且老房比例高的城市,装修决策直接影响居住舒适度与资产保值。目标用户多为追求一次性整装落地、希望兼顾品质与效率的家庭业主,核心需求集中在三点:预算可控、工期可控、后期维…

完整教程:在鸿蒙NEXT中使用WebSocket实现实时网络通信

完整教程:在鸿蒙NEXT中使用WebSocket实现实时网络通信pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&q…

Atcoder Regular Contest 做题记录

Preface ARC C~F 选择性做题记录,难度大概在 $*2400\sim *3000$ 左右 (蓝至紫) 无特殊说明每个题的时空限制都是 $\text{2sec, 1GB}$。 难度记录方法: $x/_y$,其中 $x$ 为 kenkoooo 所述难度,$y$ 为个人认为的洛…

深入解析:Async++ 源码分析2---aligned_alloc.h

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Linux sas3ircu RAID 控制管理工具详解

Linux sas3ircu RAID 控制管理工具详解sas3ircu 是一款用于管理 LSI SAS3008 等系列 RAID 控制卡的强大命令行工具。它允许你在操作系统中直接配置RAID、查看磁盘信息、定位故障硬盘等,无需重启服务器进入BIOS设置。 …

Linux StorCLI RAID 控制管理工具详解

Linux StorCLI RAID 控制管理工具详解StorCLI 是管理 Broadcom(原LSI)MegaRAID 系列硬件 RAID 控制器的强大命令行工具,适合在缺乏图形界面的环境中进行精细的存储配置和监控 。 下面为您梳理其下载安装、核心用法和…

2025年浓缩机厂家权威推荐榜:高效浓缩机/尾矿浓缩机/污泥浓缩机/新型浓缩机/矿用浓缩机/浓密机/中心转动浓缩机/真空浓缩机/污泥脱水机

2025年浓缩机厂家权威推荐榜:高效浓缩机/尾矿浓缩机/污泥浓缩机/新型浓缩机/矿用浓缩机/浓密机/中心转动浓缩机/真空浓缩机/污泥脱水机行业背景与发展趋势在当今的工业处理领域,浓缩设备作为固液分离工艺中的关键环节…

新手学AI算法/嵌入式 “知其然不知其所以然”?华清远见虚拟仿真工具拆分算法组件 + 动态调参,过程感拉满

后台私信,备注“AI/嵌入式体验”,免费领取对应体验课试听及平台试用 前阵子看到俞敏洪讲AI的直播,他说 “AI 能写新疆旅行的文案,但写不出我骑在马背上看夕阳时的心跳”、“能整理课程大纲,却替代不了我和学生面对…

http1.0,http2.0,http3.0各个协议的特点和区别

好的,当然可以。以下是 HTTP/1.0、HTTP/2.0 和 HTTP/3.0 的详细中文说明,包括它们各自的特点和核心区别。 一张图看懂演进历程特性 HTTP/1.0 HTTP/2.0 HTTP/3.0核心模型 每个请求一个TCP连接 单一TCP连接,多路复用 …

Clip Studio Paint 4.0.3下载地址与安装教程

软件介绍 Clip Studio Paint 4.0.3是由CELSYS公司开发的专业数字绘画软件,分为PRO版与EX版,支持Windows、macOS、iOS及Android多平台运行。该版本搭载TRIGLAV绘画引擎,提供逼真的铅笔、画笔笔触模拟,并优化64位系统…

​​示波器探头的正确选择与使用指南​

本文系统介绍了示波器探头的选择、类型及使用规范,强调信号类型识别、探头匹配及安全操作的重要性。在电子电路测试中,示波器探头作为连接被测电路与示波器的关键部件,其正确选择和使用方法直接影响测量结果的准确性…

C# Avalonia 16- Animation- KeySplineAnimation

C# Avalonia 16- Animation- KeySplineAnimationKeySplineAnimation.axaml代码<Window xmlns="https://github.com/avaloniaui"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:…

2025年工厂维保服务厂家权威推荐榜:机电维修、应急维修、设备安装维修、运维服务全方位解析

2025年工厂维保服务厂家权威推荐榜:机电维修、应急维修、设备安装维修、运维服务全方位解析行业背景与发展趋势随着制造业数字化转型的深入推进,工厂维保服务行业正经历着深刻变革。现代工厂设备日益复杂,智能化程度…

SQL 多表查询实用技巧:ON 和 WHERE 的区别速览 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

windows 11 或 Windows 10 注册表修改企业版为专业版

Windows 11 或 Windows 10 版本标识修改指南( qwen 指导版) 本文档详细介绍了如何修改Windows 11/10 的版本标识信息,包括ProductName、EditionID和CompositionEditionID等注册表键值。 概述 此方法仅修改注册表中的…

低代码平台核心概念与设计理念

低代码平台核心概念与设计理念 1. 低代码平台概述 1.1 定义和特性 低代码平台(Low-Code Development Platform, LCDP)是一种通过可视化建模与配置,最小化手写代码量,从而快速构建和交付应用程序的软件开发平台。其…

PyTorch nn.Linear 终极详解:从零理解线性层的一切(含可视化+完整代码) - 指南

PyTorch nn.Linear 终极详解:从零理解线性层的一切(含可视化+完整代码) - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font…

C# Avalonia 16- Animation- ExpandElement2

C# Avalonia 16- Animation- ExpandElement2ExpandElement2.axaml代码<Window xmlns="https://github.com/avaloniaui"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="…