打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033

LiSun

打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一、简介

DS1339串行实时时钟(RTC)是低功耗的时钟/日历芯片,具有两个可编程日历闹钟与一路可编程方波输出。地址与数据通过I²C总线串行传送。时钟/日历可以提供秒、分、时、日、月、年信息。对于少于31天的月份,到每月的最后一天会自动进行调节,包括闰年修正。该时钟可以通过AM/PM指示器工作在24小时模式或12小时模式。DS1339具有一个内部电源感应电路,可以检测到电源失效,并自动转换到备用电源。

二、特性

  1. 实时时钟(RTC)记录秒、分、时、星期、日、月、年信息,具有有效至2100年的闰年补偿
  2. 内置晶振(DS1339C),采用表面贴封装
  3. I²C串行接口
  4. 2个日历闹钟
  5. 可编程方波输出
  6. 振荡器停止标志
  7. 自动电源失效检测与转换电路
  8. 提供涓流充电

三、笔记

1、P17-特性:如果之前有发送命令地址,则读数据命令,会从上个地址顺延,并读取数据。
直到发送了新的命令地址。
2、P17-器件读写操作流程

说明:

☆ 时间寄存器的B6选择12或24小时模式,1=12小时模式,0=24小时模式;

☆ 12小时模式时,AM/PM位=1是PM,0=AM;

☆ 24小时模式时,小时寄存器的B5是10小时位(20到23时);

☆ 当12/24模式改变时,所有的小时值(包括报警)都必须重新输入;

☆ 当从99年到00年时,就触发月寄存器的B7(世纪);

☆ 星期寄存器在午夜递增,和星期对应的值是可以自定义的,但必须是顺序的(如1对应星期天,则2就对应星期一,等等);

☆ 控制寄存器的INTCN位使能报警;

☆ 控制寄存器0EH

EOSC:晶振使能0=启动晶振,1=停止晶振,缺省=0;

BBSQI:1=当没有VCC使用VBACKUP时输出方波或中断,0=当VCC低于VPF时SQW/INT脚变成高阻态。缺省是0;

RS2:RS1:控制方波输出频率,如下表所示,缺省是11;

四、示例代码

#include "ds1339.h"

/*************笔记****[DS1339数据手册.pdf]************

*******************************************************/

/*声明内部函数*/
uint8_t ConvertDataToSet(const T_DS1339TIME *time, uint8_t regType);
void ConvertDataToGet(uint8_t rData, T_DS1339TIME *time, uint8_t regType);


/*********************************************
函数名:DS1339Init
功  能:初始化器件的IIC引脚
形  参:PIN     --IIC信息结构体
**********************************************/
void DS1339Init(const IIC_PIN *PIN)
{
    IIC_Init(PIN);
}

/******************************
函数名:DS1339GetTime
功  能:设置器件时间
形  参:PIN     --IIC信息结构体
        time    --存放器件时间的信息结构体
返回值:
备  注:特性,器件寄存器地址,每次写入1byte,就会自动递增到下一个地址。
*******************************/
IIC_STATUS DS1339SetTime(const IIC_PIN *PIN, const T_DS1339TIME *time)
{
    IIC_STATUS status;
    uint8_t i, sendData;

    osDelay(100);
    IIC_Start(PIN);
    IIC_WriteByte(PIN, PIN->ADDR);
    status = IIC_Wait_ACK(PIN);
    IIC_WriteByte(PIN, REGADDR_SECONDS);
    status |= IIC_Wait_ACK(PIN);
    for(i = 0; i < 7; i++)
    {
        sendData = ConvertDataToSet(time, REGADDR_SECONDS + i); //时间格式转换
        IIC_WriteByte(PIN, sendData);
        status |= IIC_Wait_ACK(PIN);
    }
    IIC_Stop(PIN);
    if(status)
        return(IIC_WRITE_ERR);
    else
        return(IIC_OK);
}

/******************************
函数名:DS1339GetTime
功  能:从器件读取时间
形  参:PIN     --IIC信息结构体  
        time    --存放器件时间的信息结构体
*******************************/
IIC_STATUS DS1339GetTime(const IIC_PIN *PIN, T_DS1339TIME *time)
{
    T_DS1339TIME rTime;
    uint8_t i, rData[7];
    IIC_STATUS status;

    IIC_Start(PIN);
    IIC_WriteByte(PIN, PIN->ADDR);
    status = IIC_Wait_ACK(PIN);
    IIC_WriteByte(PIN, REGADDR_SECONDS);
    status |= IIC_Wait_ACK(PIN);

    IIC_Start(PIN);
    IIC_WriteByte(PIN, PIN->ADDR | 0x01);
    status |= IIC_Wait_ACK(PIN);
    for(i = 0; i < 7; i++) //从器件寄存器中按顺序读取 秒,分,时,天(0-7),日,月,年
    {
        if(i != 0 )
            IIC_ACK(PIN);
        IIC_ReadByte(PIN, &rData[i]);
    }
    IIC_NACK(PIN);
    IIC_Stop(PIN);

    /*时间转换*/
    for(i = 0; i < 7; i++)
    {
        ConvertDataToGet(rData[i], &rTime, REGADDR_SECONDS + i);
    }
    if(status)
    {
        return (IIC_READ_ERR);
    }
    else
    {
        *time = rTime;
        return (IIC_OK);
    }
}

/******************************************************************
函数名:ConvertDataToSet
功  能:设置器件时间,因为器件寄存器对时间格式有要求,
        所以需要对时间进行转换,具体看手册。
形  参:
        time    --向器件设置时间的信息结构体
        regType --时间类型
返回值:
备  注:DS1339数据手册.pdf --10页--寄存器说明
*******************************************************************/
uint8_t ConvertDataToSet(const T_DS1339TIME *time, uint8_t regType)
{
    uint8_t sendData = 0;

    switch(regType)
    {
        case REGADDR_SECONDS:
            if(time->second > 10)
            {
                sendData = ((time->second / 10) << 4) & 0x7F;
                sendData |= time->second % 10;
            }
            else
            {
                sendData = time->second;
            }
            break;

        case REGADDR_MINUTES:
            if(time->minute > 10)
            {
                sendData = ((time->minute / 10) << 4) & 0x7F;
                sendData |= time->minute % 10;
            }
            else
            {
                sendData = time->minute;
            }
            break;

        case REGADDR_HOURS:
            if(time->hour > 10)
            {
                sendData = ((time->hour / 10) << 4) & 0x1F;
                sendData |= time->hour % 10;
            }
            else
            {
                sendData = time->hour;
            }
            break;

        case REGADDR_DAY:
            sendData = time->weekday & 0x0E;
            break;

        case REGADDR_DATA:
            if(time->day > 10)
            {
                sendData = ((time->day / 10) << 4) & 0x3F;
                sendData |= time->day % 10;
            }
            else
            {
                sendData = time->day;
            }
            break;

        case REGADDR_MONTH_CENTURY:
            if(time->month > 10)
            {
                sendData = ((time->month / 10) << 4) & 0x1F;
                sendData |= time->month % 10;
            }
            else
            {
                sendData = time->month;
            }
            break;
        case REGADDR_YEAR:
            if(time->year > 10)
            {
                sendData = ((time->year / 10) << 4) & 0xF0;
                sendData |= time->year % 10;
            }
            else
            {
                sendData = time->year;
            }
            break;
        default:
            ;
    }
    return sendData;
}

/******************************************************************
函数名:ConvertDataToGet
功  能:从器件获取时间的需要转换,因为器件寄存器对时间格式有要求,
        所以需要对时间进行转换,具体看手册。
形  参:
        time    --存放器件时间的信息结构体
        regType --时间类型
返回值:
备  注:DS1339数据手册.pdf --10页--寄存器说明
*******************************************************************/
void ConvertDataToGet(uint8_t rData, T_DS1339TIME *time, uint8_t regType)
{
    switch(regType)
    {
        case REGADDR_SECONDS:
            time->second = (rData >> 4 & 0x07) * 10 + (rData & 0x0F);
            break;

        case REGADDR_MINUTES:
            time->minute = (rData >> 4 & 0x07) * 10 + (rData & 0x0F);
            break;

        case REGADDR_HOURS:
            time->hour = (rData >> 4 & 0x01) * 10 + (rData & 0x0F);
            break;

        case REGADDR_DAY:
            time->weekday = rData & 0x07;
            break;

        case REGADDR_DATA:
            time->day = (rData >> 4 & 0x03) * 10 + (rData & 0x0F);
            break;

        case REGADDR_MONTH_CENTURY:
            time->month = (rData >> 4 & 0x01) * 10 + (rData & 0x0F);
            break;

        case REGADDR_YEAR:
            time->year = (rData >> 4 & 0x0F) * 10 + (rData & 0x0F);
            break;

        default:
            ;
    }
}

#ifndef _DS1339_HEAD_
#define _DS1339_HEAD_

#include "stdio.h"
#include "stdint.h"
#include "stdlib.h"
#include "cmsis_os.h"
#include "hal_iic.h"

/*************笔记****************
1、S1339数据手册.pdf --10页--寄存器说明
***********************************/
/*需要首次初始化时,配置以下寄存器*/
#define     REGADDR_SECONDS                         0x00   //秒   寄存器
#define     REGADDR_MINUTES                         0x01   //分   寄存器
#define     REGADDR_HOURS                           0x02   //时   寄存器
#define     REGADDR_DAY                             0x03   //周日 寄存器
#define     REGADDR_DATA                            0x04   //日   寄存器
#define     REGADDR_MONTH_CENTURY                   0x05   //月   寄存器
#define     REGADDR_YEAR                            0x06   //年   寄存器
/*需要设置闹钟,可以配置以下寄存器,否则默认即可*/
#define     REGADDR_ALARM1SECONDS                   0x07   //闹钟1-秒   寄存器
#define     REGADDR_ALARM1MINUTES                   0x08   //闹钟1-分   寄存器
#define     REGADDR_ALARM1HOURS                     0x09   //闹钟1-时   寄存器
#define     REGADDR_ALARM1DAY_ALARM1DATE            0x0A   //闹钟1-周日-日 寄存器

#define     REGADDR_ALARM2MINUTES                   0x0B   //闹钟2-分   寄存器
#define     REGADDR_ALARM2HOURS                     0x0C   //闹钟2-时   寄存器
#define     REGADDR_ALARM2DAY_ALARM2DATE            0x0D   //闹钟2-周日-日 寄存器
/*以下寄存器默认即可*/
#define     REGADDR_CONTROL                         0x0E   //控制寄存器,用于设置晶振频率
#define     REGADDR_STATUS                          0x0F   //状态
#define     REGADDR_TRICKLECHARGER                  0x10

/*DS1339时间信息结构体*/
typedef struct           //24小时制
{
    uint8_t second;
    uint8_t minute;
    uint8_t hour;
    uint8_t weekday;
    uint8_t day;
    uint8_t month;
    uint8_t year;        //00-99
} T_DS1339TIME;

void DS1339Init(const IIC_PIN *PIN);
IIC_STATUS DS1339SetTime(const IIC_PIN *PIN, const T_DS1339TIME *time);
IIC_STATUS DS1339GetTime(const IIC_PIN *PIN, T_DS1339TIME *time);

#endif

posted on 2020-04-12 19:00  xuejianqiang  阅读(35)  评论(0编辑  收藏  举报  来源
打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033