一、介绍

        DS1302是一款实时时钟(RTC)芯片,它能够为微控制器提供年、月、日、星期、时、分、秒的时间信息,并且可以通过简单的串行接口进行通信。DS1302 具有低功耗、备用电池接口和 RAM 存储等功能,广泛应用于需要时间记录的电子设备中。

        以上是我们要使用的模块,芯片的详细介绍看一看之前在蓝桥杯里面的介绍。

二、程序

采用STM32F407来驱动,下列是引脚接口:

DS1302_RST

PC12

DS1302_DAT

PC11

DS1302_CLK

PC10

1、CubeMX配置

        将三个GPIO都初始化为推挽上拉输出,输出速度不必太高。

2、编写一个微秒延时函数(这个并不准确,如果需要更准确的延时,建议采用定时器)

// 添加微秒级延时函数
void Delay_us(uint32_t us)
{
    uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us);
    while (delay--)
    {
        __NOP();
    }
}

3、DS1302.c文件

uint8_t DS1302_Time[3] = {23, 59, 50}; //初始时间 23:59:50
uint8_t RTC_Write_Addr[3] = {0x84, 0x82, 0x80};
uint8_t RTC_Read_Addr[3] = {0x85, 0x83, 0x81};
void DS1302_DataPin_Input(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.Pin = DS1302_DAT_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(DS1302_DAT_GPIO_Port, &GPIO_InitStruct);
}

void DS1302_DataPin_Output(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.Pin = DS1302_DAT_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(DS1302_DAT_GPIO_Port, &GPIO_InitStruct);
}
/*RST*/
#define CE_L HAL_GPIO_WritePin(DS1302_RST_GPIO_Port, DS1302_RST_Pin, GPIO_PIN_RESET)
#define CE_H HAL_GPIO_WritePin(DS1302_RST_GPIO_Port, DS1302_RST_Pin, GPIO_PIN_SET)
/*SCLK*/
#define SCLK_L HAL_GPIO_WritePin(DS1302_CLK_GPIO_Port, DS1302_CLK_Pin, GPIO_PIN_RESET)
#define SCLK_H HAL_GPIO_WritePin(DS1302_CLK_GPIO_Port, DS1302_CLK_Pin, GPIO_PIN_SET)
/*IO*/
#define IO_L HAL_GPIO_WritePin(DS1302_DAT_GPIO_Port, DS1302_DAT_Pin, GPIO_PIN_RESET)
#define IO_H HAL_GPIO_WritePin(DS1302_DAT_GPIO_Port, DS1302_DAT_Pin, GPIO_PIN_SET)

void Write_DS1302(uint8_t dat)
{
    DS1302_DataPin_Output();
    for(uint8_t i=0; i<8; i++)
    {  
		SCLK_L;
        if(dat & 0x01) IO_H;
        else IO_L;
		Delay_us(2);
        SCLK_H;
        Delay_us(2);
        
        dat >>= 1;
    }
}

void Write_DS1302_Byte(uint8_t addr, uint8_t dat)
{
    CE_L; 	
    SCLK_L; Delay_us(5);
    CE_H;   Delay_us(5);
    Write_DS1302(addr);
    Write_DS1302(dat);
    CE_L;
    SCLK_L; 
}

uint8_t Read_DS1302_Byte(uint8_t addr)
{
    uint8_t dat = 0;
    CE_L;	
    SCLK_L; Delay_us(5);
    CE_H;  	Delay_us(5);
    Write_DS1302(addr);
    DS1302_DataPin_Input();
    for(uint8_t i=0; i<8; i++)
    {
		SCLK_L; 
		Delay_us(2);
		dat >>= 1;
		if(HAL_GPIO_ReadPin(DS1302_DAT_GPIO_Port, DS1302_DAT_Pin) == GPIO_PIN_SET)
            dat |= 0x80;
        SCLK_H;     
		Delay_us(2);
		
		
    }
	CE_L;	Delay_us(2);
	SCLK_L;	Delay_us(2);
    
    return dat;
}

void DS1302_SetTime(void)
{
    uint8_t i=0;
    Write_DS1302_Byte(0x8E, 0x00); // Disable write protection
    for(i=0; i<3; i++)
    {
        Write_DS1302_Byte(RTC_Write_Addr[i], (DS1302_Time[i] / 10 * 16 + DS1302_Time[i] % 10));
    }
    Write_DS1302_Byte(0x8E, 0x80); // Enable write protection
}

void DS1302_GetTime(void)
{
    uint8_t i=0, temp=0;
    for(i=0; i<3; i++)
    {
        temp = Read_DS1302_Byte(RTC_Read_Addr[i]);
        DS1302_Time[i] = (temp / 16 * 10 + temp % 16);
    }
}

4、DS1302.h文件

#ifndef __DS1302_H
#define __DS1302_H

#include "main.h"
#include "gpio.h"
#include "oled.h"

extern uint8_t DS1302_Time[3];

void DS1302_SetTime(void);
void DS1302_GetTime(void);

#endif

5、可以调用自己的OLED函数显示数组中存储的时分秒时间,年月日也是同样道理,在数组中添加相应地址即可(注意先后与顺序)。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐