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 小时前
《计算机操作系统》第六章-输入输出系统
java·开发语言·c++·人工智能·嵌入式硬件·os·计算机操作系统
国科安芯3 小时前
商业卫星轴角转换器的抗辐照MCU尺寸约束研究
单片机·嵌入式硬件·架构·安全性测试
沪漂的码农3 小时前
FlexCAN寄存器完全解读
stm32·单片机·嵌入式硬件·can
钰珠AIOT3 小时前
τ = R × C 这个公式是如何推导出来的?
单片机·嵌入式硬件·物联网
代码游侠3 小时前
学习笔记——I2C(Inter-Intergrated Circuit)总线详解
arm开发·笔记·嵌入式硬件·学习·架构
程序员_小兵3 小时前
GPIO分析
c语言·单片机·嵌入式硬件·mcu
weixin_669545205 小时前
持续2.7A峰值5A有刷直流马达正反转驱动芯片TC1305E
人工智能·嵌入式硬件·硬件工程·信息与通信
国科安芯14 小时前
商业航天高可靠PCBA制造:抗辐射CAN收发器SMT贴装关键技术及系统级挑战
单片机·嵌入式硬件·制造·pcb工艺·安全性测试
申克Lab15 小时前
STM32 FreeRTOS 消息队列
java·stm32·嵌入式硬件