STM32 HAL DS1302时钟模块

标准库教程https://blog.csdn.net/qq_43270506/article/details/104952746

ds1302.h

复制代码
#ifndef __DS1302_H 
#define __DS1302_H  

#include "main.h" 

// 引脚重新定义:PB3=DATA, PB4=CE, PB5=SCLK
#define DATA_PIN    GPIO_PIN_3
#define CE_PIN      GPIO_PIN_4
#define SCLK_PIN    GPIO_PIN_5
#define DS1302_PORT GPIOB

// HAL库电平操作宏
#define CE_L        HAL_GPIO_WritePin(DS1302_PORT, CE_PIN, GPIO_PIN_RESET)
#define CE_H        HAL_GPIO_WritePin(DS1302_PORT, CE_PIN, GPIO_PIN_SET)
#define SCLK_L      HAL_GPIO_WritePin(DS1302_PORT, SCLK_PIN, GPIO_PIN_RESET)
#define SCLK_H      HAL_GPIO_WritePin(DS1302_PORT, SCLK_PIN, GPIO_PIN_SET)
#define DATA_L      HAL_GPIO_WritePin(DS1302_PORT, DATA_PIN, GPIO_PIN_RESET)
#define DATA_H      HAL_GPIO_WritePin(DS1302_PORT, DATA_PIN, GPIO_PIN_SET)

// 类型定义兼容
#define u16 uint16_t
#define u8  uint8_t

// 时间结构体
struct TIMEData
{
	u16 year;
	u8  month;
	u8  day;
	u8  hour;
	u8  minute;
	u8  second;
	u8  week;
};

extern struct TIMEData TimeData;//全局变量

// 函数声明
void ds1302_gpio_init(void);          // ds1302端口初始化
void ds1302_DATAOUT_init(void);       // IO端口配置为输出
void ds1302_DATAINPUT_init(void);     // IO端口配置为输入
void ds1302_write_onebyte(u8 data);   // 向ds1302发送一字节数据
void ds1302_write_reg(u8 address,u8 data); // 向指定寄存器写一字节数据
u8 ds1302_read_reg(u8 address);       // 从指定寄存器读一字节数据
void ds1302_init(void);               // ds1302初始化函数
void ds1302_read_time(void);          // 从ds1302读取实时时间(BCD码)
void ds1302_read_realTime(void);      // 将BCD码转化为十进制数据

#endif

ds1302.c

复制代码
#include "ds1302.h"
#include "main.h"
#include "gpio.h"
#include "delay.h"

struct TIMEData TimeData;
u8 read_time[7];
 
// CE、SCLK端口初始化(HAL库版本 + PB4/PB5)
void ds1302_gpio_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // 使能GPIOB时钟
    __HAL_RCC_GPIOB_CLK_ENABLE();

    // 配置CE引脚(PB4) 推挽输出
    GPIO_InitStruct.Pin = CE_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(DS1302_PORT, &GPIO_InitStruct);
    CE_L; // 初始拉低

    // 配置SCLK引脚(PB5) 推挽输出
    GPIO_InitStruct.Pin = SCLK_PIN;
    HAL_GPIO_Init(DS1302_PORT, &GPIO_InitStruct);
    SCLK_L; // 初始拉低
}
 
// 配置DATA引脚(PB3)为输出态(HAL库版本)
void ds1302_DATAOUT_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitStruct.Pin = DATA_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(DS1302_PORT, &GPIO_InitStruct);
    DATA_L; // 初始拉低
}
 
// 配置DATA引脚(PB3)为输入态(HAL库版本)
void ds1302_DATAINPUT_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOB_CLK_ENABLE();
    GPIO_InitStruct.Pin = DATA_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL; // 浮空输入
    HAL_GPIO_Init(DS1302_PORT, &GPIO_InitStruct);
}
 
// 向DS1302发送一字节数据
void ds1302_write_onebyte(u8 data)
{
    ds1302_DATAOUT_init();
    u8 count=0;
    SCLK_L;
    for(count=0;count<8;count++)
    {   
        SCLK_L;
        if(data&0x01)
        {
            DATA_H;
        }
        else
        {
            DATA_L;
        }//先准备好数据再发送
        SCLK_H;//拉高时钟线,发送数据
        data>>=1;
    }
}
 
// 向指定寄存器地址发送数据(修正原函数名笔误:wirte_rig -> write_reg)
void ds1302_write_reg(u8 address,u8 data)
{
    u8 temp1=address;
    u8 temp2=data;
    CE_L;SCLK_L;delay_us(1);
    CE_H;delay_us(2);
    ds1302_write_onebyte(temp1);
    ds1302_write_onebyte(temp2);
    CE_L;SCLK_L;delay_us(2);
}
 
// 从指定地址读取一字节数据(修正原函数名笔误:read_rig -> read_reg)
u8 ds1302_read_reg(u8 address)
{
    u8 temp3=address;
    u8 count=0;
    u8 return_data=0x00;
    CE_L;SCLK_L;delay_us(3);
    CE_H;delay_us(3);
    ds1302_write_onebyte(temp3);
    ds1302_DATAINPUT_init();//配置I/O口为输入(修正原函数名笔误)
    delay_us(2);
    for(count=0;count<8;count++)
    {
        delay_us(2);//使电平持续一段时间
        return_data>>=1;
        SCLK_H;delay_us(4);//使高电平持续一段时间
        SCLK_L;delay_us(14);//延时14us后再去读取电压,更加准确
        // HAL库读取PB3引脚电平(替换原标准库函数)
        if(HAL_GPIO_ReadPin(DS1302_PORT, DATA_PIN) == GPIO_PIN_SET)
        {
            return_data=return_data|0x80;
        }
    }
    delay_us(2);
    CE_L;DATA_L;
    return return_data;
}
 
// ds1302初始化函数
void ds1302_init(void)
{
    ds1302_write_reg(0x8e,0x00);//关闭写保护
    ds1302_write_reg(0x80,0x00);//seconds37秒
    ds1302_write_reg(0x82,0x13);//minutes58分
    ds1302_write_reg(0x84,0x12);//hours23时
    ds1302_write_reg(0x86,0x24);//date30日
    ds1302_write_reg(0x88,0x01);//months9月
    ds1302_write_reg(0x8a,0x06);//days星期日
    ds1302_write_reg(0x8c,0x26);//year2020年
    ds1302_write_reg(0x8e,0x80);//开启写保护
}

// 读取实时时间(BCD码)(修正原函数名笔误:ds1032_read_time -> ds1302_read_time)
void ds1302_read_time(void)
{
    read_time[0]=ds1302_read_reg(0x81);//读秒
    read_time[1]=ds1302_read_reg(0x83);//读分
    read_time[2]=ds1302_read_reg(0x85);//读时
    read_time[3]=ds1302_read_reg(0x87);//读日
    read_time[4]=ds1302_read_reg(0x89);//读月
    read_time[5]=ds1302_read_reg(0x8B);//读星期
    read_time[6]=ds1302_read_reg(0x8D);//读年
}
 
// BCD码转十进制(修正原函数名笔误:ds1032_read_realTime -> ds1302_read_realTime)
void ds1302_read_realTime(void)
{
    ds1302_read_time();  //BCD码转换为10进制
    TimeData.second=(read_time[0]>>4)*10+(read_time[0]&0x0f);
    TimeData.minute=((read_time[1]>>4)&(0x07))*10+(read_time[1]&0x0f);
    TimeData.hour=(read_time[2]>>4)*10+(read_time[2]&0x0f);
    TimeData.day=(read_time[3]>>4)*10+(read_time[3]&0x0f);
    TimeData.month=(read_time[4]>>4)*10+(read_time[4]&0x0f);
    TimeData.week=read_time[5];
    TimeData.year=(read_time[6]>>4)*10+(read_time[6]&0x0f)+2000;
}

调用示例:

ds1302_gpio_init();

//ds1302_init(); //初始时间只需要在设定时间使用

ds1302_read_realTime();

调用TimeData全局变量时间

使用sprintf格式化后显示即可

sprintf(time_str1, "%04d-%02d-%02d", TimeData.year, TimeData.month, http://TimeData.day);

sprintf(time_str2, "%02d:%02d:%02d", TimeData.hour, TimeData.minute, TimeData.second);

sprintf(time_str3, "Week:%d", TimeData.week);

相关推荐
碧海银沙音频科技研究院3 小时前
炬芯ATS3089X手表的HFP通话不自动路由到设备BT的问题解决
网络·人工智能·嵌入式硬件·算法
youcans_8 小时前
【STM32C5教程】(3)GPIO 按键输入实验
stm32·单片机·嵌入式硬件
俊基科技9 小时前
回音消不掉、底噪压不住、主板还对不上口?——A-59P 多功能语音处理模组技术解析
嵌入式硬件·回音消除·ai降噪模块
北京盛世宏博10 小时前
通信异常深度排查:以太网温湿度设备 TCP 粘包、UDP 丢包根治方案
单片机·网络协议·tcp/ip·udp·以太网·传感器·温湿度
蓝天居士10 小时前
PY32F系列MCU在串口接收时跑飞的根因分析(2)
单片机·嵌入式硬件
wuyk55513 小时前
嵌入式驱动开发:量产级工程化实战(第9篇)——低功耗下的通信可靠性
c语言·驱动开发·stm32·单片机·嵌入式硬件
创界工坊工作室14 小时前
24-基于单片机的仓鼠养殖环境监控系统设计
stm32·单片机·嵌入式硬件·proteus
碧海银沙音频科技研究院14 小时前
基于炬芯ATS录音卡BLE控制协议
人工智能·嵌入式硬件·算法·语音识别
comyccccc15 小时前
PCB走线设计秘籍:从载流到3D预览全解析学习笔记
单片机·嵌入式硬件
俊基科技15 小时前
A-59 工业级 AI 语音处理模组:100 dB 消回音 + 神经网络降噪的工程实践
嵌入式硬件·神经网络·硬件开发·语音模块·回音消除·拾音降噪