RTC芯片 DS1338 - stm32 HAL库代码实现

一、直接上代码
本人新手小白,写的很烂,代码可以运行,设置和读取时间正常。若有不足,恳请斧正。

RtcDs1338.c

/*
    RtcDs1338.c

    Implementation File for Ds1338 Module
*/

/*
    modification history
    --------------------
    01a, 20Mar24, Jasper Created
*/

/* Includes */
#include "include.h"
#include <cmsis_os.h>
#include "BspI2C.h"
#include "Rtc/RtcDs1338.h"

#if (RTC_ENABLE && RTC_DS1338_ENABLE)

/* Pragmas */
#pragma diag_suppress 177   /* warning: #177-D: function "FUNC" was set but never used */
#pragma diag_suppress 550   /* warning: #550-D: variable was set but never used */

/* Debug config */
#if RTC_DEBUG || 1
    #undef TRACE
    #define TRACE(...)  DebugPrintf(__VA_ARGS__)
#else
    #undef TRACE
    #define TRACE(...)
#endif /* RTC_DEBUG */
#if RTC_ASSERT
    #undef ASSERT
    #define ASSERT(a)   while(!(a)){DebugPrintf("ASSERT failed: %s %d\n", __FILE__, __LINE__);}
#else
    #undef ASSERT
    #define ASSERT(...)
#endif /* RTC_ASSERT */

/* Local defines */
/* Register definition */
#define DS1338_REG_SECONDS      (0x00)
#define DS1338_REG_MINUTES      (0x01)
#define DS1338_REG_HOURS        (0x02)
#define DS1338_REG_DAY          (0x03)
#define DS1338_REG_DATE         (0x04)
#define DS1338_REG_MONTH        (0x05)
#define DS1338_REG_YEAR         (0x06)
#define DS1338_REG_CONTROL      (0x07)
#define DS1338_REG_RAM_BEGIN    (0x08)
#define DS1338_REG_RAM_END      (0x3F)

/* Local types */
typedef struct {
    uint8_t ucYear;     /* Bcd: 0~99 */
    uint8_t ucMon;      /* Bcd: 1~12 */
    uint8_t ucDay;      /* Bcd: 1~31 */
    uint8_t ucWeek;     /* Bcd: 1~7 */
    uint8_t ucHour;     /* Bcd: 1~12 / 0~23 */
    uint8_t ucMin;      /* Bcd: 0~59 */
    uint8_t ucSec;      /* Bcd: 0~59 */
}DsTime_t;

/* Forward declaration */
static uint8_t      prvDs1338ReadTime(DsTime_t *time);
static uint8_t      prvDs1338WriteTime(DsTime_t *time);
static Time_t       prvDs1338ToStdCTime(DsTime_t* pxDsTm);
static DsTime_t     prvStdCToDs1338Time(Time_t* pxTm);
static uint8_t      prvBcdToDec(uint8_t ucBcd);
static uint8_t      prvDecToBcd(uint8_t ucDec);
static Status_t     prvPrintDs1338Time(DsTime_t *pxDsTm);
static Status_t     prvPrintStdCTime(Time_t *pxTm);


/* Local variables */
static Bool_t           s_bInit   = FALSE;
static Bool_t           s_bConfig = FALSE;
#if RTC_RTOS
static osMutexId        s_xMutex;
#endif /* RTC_RTOS */

/* Local defines */
#if RTC_RTOS
    #define DS1338_MUTEX_INIT()     do{ \
                                        osMutexDef(Ds1338Mutex); \
                                        s_xMutex = osMutexCreate(osMutex(Ds1338Mutex)); \
                                    }while(0)
    #define DS1338_LOCK()           osMutexWait(s_xMutex, osWaitForever)
    #define DS1338_UNLOCK()         osMutexRelease(s_xMutex)
#else
    #define DS1338_MUTEX_INIT()
    #define DS1338_LOCK()
    #define DS1338_UNLOCK()
#endif /* RTC_RTOS */
#define DS1338_RAM_SIZE             (31)

                                    /* Functions */
Status_t RtcDs1338Init(void)
{
    if (s_bInit == FALSE) {
        DS1338_MUTEX_INIT();
    #if RTC_RTOS
        if (NULL == s_xMutex) {
            TRACE("RtcDs1302Init create mutex failed\n");
            return STATUS_ERR;
        }
    #endif /* RTC_RTOS */
        s_bInit = TRUE;
        return STATUS_OK;
    }
    else {
        return STATUS_ERR;
    }
}

Time_t RtcDs1338ReadTime(void)
{   
    DsTime_t xDsTm;
    ASSERT((TRUE == s_bInit) && (TRUE == s_bConfig));
    DS1338_LOCK();
    prvDs1338ReadTime(&xDsTm);
    DS1338_UNLOCK();
    return prvDs1338ToStdCTime(&xDsTm);
}

Status_t RtcDs1338WriteTime(Time_t xTm)
{
    DsTime_t xDsTm;
    ASSERT((TRUE == s_bInit) && (TRUE == s_bConfig));
    DS1338_LOCK();
    xDsTm = prvStdCToDs1338Time(&xTm);
    prvDs1338WriteTime(&xDsTm);
    DS1338_UNLOCK();
    return STATUS_OK;
}

#if (RTC_STDC_TIME == 3)
time_t time(time_t * timer)
{
    Time_t tm;
    time_t t;
    tm = RtcDs1338ReadTime();
    t = mktime(&tm);
    if (NULL == timer) {
        return t;
    }
    else {
        *timer = t;
        return t;
    }
}

#endif /* (RTC_STDC_TIME == 3) */

static uint8_t prvDs1338ReadTime(DsTime_t *time)
{
	uint8_t buf[7];
    I2C_ReadData(DS1338_ADDR, DS1338_REG_SECONDS, &buf[0], 1);
    I2C_ReadData(DS1338_ADDR, DS1338_REG_MINUTES, &buf[1], 1);
    I2C_ReadData(DS1338_ADDR, DS1338_REG_HOURS,   &buf[2], 1);
    I2C_ReadData(DS1338_ADDR, DS1338_REG_DAY,     &buf[3], 1);
    I2C_ReadData(DS1338_ADDR, DS1338_REG_DATE,    &buf[4], 1);
    I2C_ReadData(DS1338_ADDR, DS1338_REG_MONTH,   &buf[5], 1);
    I2C_ReadData(DS1338_ADDR, DS1338_REG_YEAR,    &buf[6], 1);
    
	time->ucSec = prvBcdToDec(buf[0]);
	time->ucMin = prvBcdToDec(buf[1]);
	if (buf[2] & DS1338_HOUR_12)
	{
		time->ucHour = ((buf[2] >> 4) & 0x01) * 12 + ((buf[2] >> 5) & 0x01) * 12;
	}
	else
	{
		time->ucHour = prvBcdToDec(buf[2]);
	}
	time->ucDay = prvBcdToDec(buf[4]);
	time->ucMon = prvBcdToDec(buf[5] & 0x1F);
	time->ucYear = prvBcdToDec(buf[6]);

	return 0;
}

static uint8_t prvDs1338WriteTime(DsTime_t *time)
{
	uint8_t buf[7];
	buf[0] = prvDecToBcd(time->ucSec);
	buf[1] = prvDecToBcd(time->ucMin);
	buf[2] = prvDecToBcd(time->ucHour); // Time always stored in 24-hour format
	buf[3] = 1;						   // Not used
	buf[4] = prvDecToBcd(time->ucDay);
	buf[5] = prvDecToBcd(time->ucMon);
	buf[6] = prvDecToBcd(time->ucYear);

    I2C_WriteData(DS1338_ADDR, DS1338_REG_SECONDS, &buf[0], 1);
    I2C_WriteData(DS1338_ADDR, DS1338_REG_MINUTES, &buf[1], 1);
    I2C_WriteData(DS1338_ADDR, DS1338_REG_HOURS,   &buf[2], 1);
    I2C_WriteData(DS1338_ADDR, DS1338_REG_DAY,     &buf[3], 1);
    I2C_WriteData(DS1338_ADDR, DS1338_REG_DATE,    &buf[4], 1);
    I2C_WriteData(DS1338_ADDR, DS1338_REG_MONTH,   &buf[5], 1);
    I2C_WriteData(DS1338_ADDR, DS1338_REG_YEAR,    &buf[6], 1);

	return 0;
}

static Time_t prvDs1338ToStdCTime(DsTime_t* pxDsTm)
{
    Time_t cTm;
    cTm.tm_sec      = (pxDsTm->ucSec);       /* seconds after the minute, 0 to 60 (0 - 60 allows for the occasional leap second) */
    cTm.tm_min      = (pxDsTm->ucMin);       /* minutes after the hour, 0 to 59 */
    cTm.tm_hour     = (pxDsTm->ucHour);      /* hours since midnight, 0 to 23 */
    cTm.tm_mday     = (pxDsTm->ucDay);       /* day of the month, 1 to 31 */
    cTm.tm_mon      = (pxDsTm->ucMon)-1;     /* months since January, 0 to 11 */
    cTm.tm_year     = (pxDsTm->ucYear)+100;  /* years since 1900 */
    cTm.tm_wday     = (pxDsTm->ucWeek)-1;    /* days since Sunday, 0 to 6 */
    cTm.tm_yday     = (0);                   /* days since January 1, 0 to 365 */
    cTm.tm_isdst    = (0);                   /* Daylight Savings Time flag */

    return cTm;
}

static DsTime_t prvStdCToDs1338Time(Time_t* pxTm)
{
    DsTime_t xDsTm;
    xDsTm.ucYear    = (pxTm->tm_year-100);   /* 0~99 */
    xDsTm.ucMon     = (pxTm->tm_mon+1);      /* 1~12 */
    xDsTm.ucDay     = (pxTm->tm_mday);       /* 1~31 */
    xDsTm.ucWeek    = (pxTm->tm_wday+1);     /* 1~7 */
    xDsTm.ucHour    = (pxTm->tm_hour);       /* 1~12 / 0~23 */
    xDsTm.ucMin     = (pxTm->tm_min);        /* 0~59 */
    xDsTm.ucSec     = (pxTm->tm_sec);        /* 0~59 */
    
    return xDsTm;
}

static uint8_t prvBcdToDec(uint8_t ucBcd)
{ 
    return ((ucBcd >> 4) * 10 + (ucBcd & 0x0F));
}

static uint8_t prvDecToBcd(uint8_t ucDec)
{ 
    return ((((ucDec / 10) & 0x0F) << 4) + (ucDec % 10));
}

static Status_t prvPrintDs1338Time(DsTime_t *pxDsTm)
{
    TRACE("prvPrintDs1302Time:\n");
    TRACE("    ucYear:   %02X\n", pxDsTm->ucYear);
    TRACE("    ucMon:    %02X\n", pxDsTm->ucMon);
    TRACE("    ucDay:    %02X\n", pxDsTm->ucDay);
    TRACE("    ucWeek:   %02X\n", pxDsTm->ucWeek);
    TRACE("    ucHour:   %02X\n", pxDsTm->ucHour);
    TRACE("    ucMin:    %02X\n", pxDsTm->ucMin);
    TRACE("    ucSec:    %02X\n", pxDsTm->ucSec);
    return STATUS_OK;
}

static Status_t prvPrintStdCTime(Time_t *pxTm)
{
    TRACE("prvPrintStdCTime:\n");
    TRACE("    tm_year:   %d\n", pxTm->tm_year);
    TRACE("    tm_mon:    %d\n", pxTm->tm_mon);
    TRACE("    tm_mday:   %d\n", pxTm->tm_mday);
    TRACE("    tm_wday:   %d\n", pxTm->tm_wday);
    TRACE("    tm_yday:   %d\n", pxTm->tm_yday);
    TRACE("    tm_hour:   %d\n", pxTm->tm_hour);
    TRACE("    tm_min:    %d\n", pxTm->tm_min);
    TRACE("    tm_sec:    %d\n", pxTm->tm_sec);
    TRACE("    tm_isdst:  %d\n", pxTm->tm_isdst);
    return STATUS_OK;
}

#endif /* RTC_ENABLE && RTC_DS1338_ENABLE */

RtcDs1338.h

/*
    RtcDs1338.h

    Implementation File for Ds1338 Module
*/

/*
    modification history
    --------------------
    01a, 20Mar24, Jasper Created
*/

#ifndef __RTC_DS1338_H__
#define __RTC_DS1338_H__

#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus */

/* Includes */
#include <stdint.h>
#include <stm32f1xx_hal.h>
#include "Include/Include.h"
#include "Rtc/RtcConfig.h"


// Device address
#define DS1338_ADDR 0x68



/**
If set, in an hour register (DS1338_REG_HOURS, DS1338_REG_A1_HOUR,
DS1338_REG_A2_HOUR, the hour is between 0 and 12, and the
(!AM)/PM bit indicates AM or PM.

If not set, the hour is between 0 and 23.
*/
#define DS1338_HOUR_12          (0x01 << 6)

/**
If DS1338_HOUR_12 is set:
- If set, indicates PM
- If not set, indicates AM
*/
#define DS1338_PM_MASK          (0x01 << 5)

// If set, the oscillator has stopped since the last time
// this bit was cleared.
#define DS1338_OSC_STOP_FLAG    (0x01 << 5)

// Set to disable the oscillator
#define DS1338_OSC_DISABLE      (0x01 << 7)

/**
These options control the behavior of the SQW/(!INTB) pin. 
*/
#define DS1338_SQWE_FLAG        (0x01 << 4)
#define DS1338_SQW_MASK         (0x03)
#define DS1338_SQW_32768HZ      (0x03)
#define DS1338_SQW_8192HZ       (0x02)
#define DS1338_SQW_4096HZ       (0x01)
#define DS1338_SQW_1HZ          (0x00)

// Occurs when the number of I2C bytes available is less than the number requested.
#define READ_ERROR 5

#define decode_bcd(x) ((x >> 4) * 10 + (x & 0x0F))
#define encode_bcd(x) ((((x / 10) & 0x0F) << 4) + (x % 10))


/* Functions */
Time_t RtcDs1338ReadTime(void);
Status_t RtcDs1338WriteTime(Time_t xTm);
Status_t RtcDs1338Init(void);


#if (RTC_STDC_TIME == 2)
time_t time(time_t* timer); 
#endif /* (RTC_STDC_TIME == 2) */

#ifdef __cplusplus
}
#endif /*__cplusplus */

#endif /* __RTC_DS1302_H__ */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值