当前位置: 首页 > news >正文

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

前言

在嵌入式架构开发中,实时时钟(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.hskmm.com/?act=detail&tid=32966

相关文章:

  • 2025年10月床垫品牌推荐榜:围绕环保认证与试睡政策的系统化评析
  • 贪心策略总结
  • 2025年10月上海装修公司推荐榜:极家家居设计标准与施工节点全维度对比
  • 完整教程:在鸿蒙NEXT中使用WebSocket实现实时网络通信
  • Atcoder Regular Contest 做题记录
  • Linux sas3ircu RAID 控制管理工具详解
  • Linux StorCLI RAID 控制管理工具详解
  • 2025年浓缩机厂家权威推荐榜:高效浓缩机/尾矿浓缩机/污泥浓缩机/新型浓缩机/矿用浓缩机/浓密机/中心转动浓缩机/真空浓缩机/污泥脱水机
  • 新手学AI算法/嵌入式 “知其然不知其所以然”?华清远见虚拟仿真工具拆分算法组件 + 动态调参,过程感拉满
  • http1.0,http2.0,http3.0各个协议的特点和区别
  • Clip Studio Paint 4.0.3下载地址与安装教程
  • ​​示波器探头的正确选择与使用指南​
  • C# Avalonia 16- Animation- KeySplineAnimation
  • 2025年工厂维保服务厂家权威推荐榜:机电维修、应急维修、设备安装维修、运维服务全方位解析
  • windows 11 或 Windows 10 注册表修改企业版为专业版
  • 低代码平台核心概念与设计理念
  • C# Avalonia 16- Animation- ExpandElement2
  • 2025年10月洗碗机品牌榜单推荐:五强性能全解析
  • PolarDB Supabase 助力 Qoder、Cursor、Bolt.diy 完成 VibeCoding 最后一公里
  • 问题一
  • 2025年陶瓷过滤机厂家权威推荐榜:盘式/矿用/全自动陶瓷真空过滤机,真空脱水机,尾矿干排设备,圆盘过滤机源头企业深度解析
  • 00-第一个C语言程序-Hello,world
  • 提取ai字幕
  • 乙二醇
  • 图论初步 - L
  • CSP-S2 历年真题 - L
  • 2025 集装箱吊机厂家推荐:乳山华江以智能技术+硬核质量破局,解决选机难题!
  • springboot结合阿里巴巴easyexcel,实现一键导出数据到Excel中
  • 深入解析:PX4 无人机地面调试全攻略:从机械到参数的系统优化
  • 2025年陶瓷过滤板厂家推荐排行榜,白刚玉陶瓷过滤板,棕刚玉陶瓷过滤板,扇形陶瓷板,真空陶瓷过滤板,陶瓷滤膜,陶瓷过滤机配件公司推荐