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);

相关推荐
宵时待雨1 小时前
STM32笔记归纳9:定时器
笔记·stm32·单片机·嵌入式硬件
逐步前行1 小时前
STM32_新建工程(寄存器版)
stm32·单片机·嵌入式硬件
bai5459361 小时前
STM32 CubeIDE 通过PWM占空比控制舵机角度
stm32·单片机·嵌入式硬件
松涛和鸣3 小时前
72、IMX6ULL驱动实战:设备树(DTS/DTB)+ GPIO子系统+Platform总线
linux·服务器·arm开发·数据库·单片机
简单中的复杂3 小时前
【避坑指南】RK3576 Linux SDK 编译:解决 Buildroot 卡死在 host-gcc-final 的终极方案
linux·嵌入式硬件
上海合宙LuatOS4 小时前
LuatOS核心库API——【audio 】
java·网络·单片机·嵌入式硬件·物联网·音视频·硬件工程
Hhh __灏4 小时前
stm32的SRAM内存不足如何分析和优化?堆栈空间如何优化?
单片机
LS_learner4 小时前
Snapd和Apt—Linux 上两种完全不同的软件包管理系统
嵌入式硬件
点灯小铭4 小时前
基于51单片机的双档交流电压表设计与实现
单片机·嵌入式硬件·毕业设计·51单片机·课程设计·期末大作业