打印
[DemoCode下载]

使用I2C操作DS3231

[复制链接]
2811|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
a_ziliu|  楼主 | 2016-12-26 10:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
使用I2C操作DS3231
EC_NUC230_240_I2C_DS3231.zip (958.13 KB)
沙发
643757107| | 2016-12-26 15:01 | 只看该作者
DS3231是低成本、高精度I2C实时时钟(RTC),具有集成的温补晶振(TCXO)和晶体。该器件包含电池输入端,断开主电源时仍可保持精确的计时。集成晶振提高了器件的长期精确度,并减少了生产线的元件数量。DS3231提供商用级和工业级温度范围,采用16引脚300mil的SO封装。
RTC保存秒、分、时、星期、日期、月和年信息。少于31天的月份,将自动调整月末的日期,包括闰年的修正。时钟的工作格式可以是24小时或带/AM/PM指示的12小时格式。提供两个可设置的日历闹钟和一个可设置的方波输出。地址与数据通过I2C双向总线串行传输。
精密的、经过温度补偿的电压基准和比较器电路用来监视VCC状态,检测电源故障,提供复位输出,并在必要时自动切换到备份电源。另外,/RST监视引脚可以作为产生μP复位的手动输入。
  
  除计时精度高之外,DS3231还具有一些其它功能,这些功能扩展了系统主机的附加功能和选择范围。该器件内部集成了一个非常精确的数字温度传感器,可通过I2C*接口对其进行访问(如同时间一样)。这个温度传感器的精度为±3°C。片上控制电路可实现自动电源检测,并管理主电源和备用电源(即低压电池)之间的电源切换。如果主电源掉电,该器件仍可继续提供精确的计时和温度,性能不受影响。当主电源重新加电或电压值返回到容许范围内时,片上复位功能可用来重新启动系统微处理器。

使用特权

评论回复
板凳
nobleliom| | 2016-12-30 20:07 | 只看该作者
DS3231没用过,我用的一般都是DS1302,不过这个假货确实比较多点。

使用特权

评论回复
地板
yiyigirl2014| | 2016-12-31 10:02 | 只看该作者
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url]     main.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V3.00
* $Revision: 4 $
* $Date: 15/05/18 4:22p $
* [url=home.php?mod=space&uid=247401]@brief[/url]    NUC230_240 Series I2C Driver Sample Code for EEPROM 24LC64
*
* @note
* Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include "NUC230_240.h"

#define PLLCON_SETTING      CLK_PLLCON_72MHz_HXT
#define PLL_CLOCK           72000000


/*---------------------------------------------------------------------------------------------------------*/
/* Global variables                                                                                        */
/*---------------------------------------------------------------------------------------------------------*/
volatile uint8_t g_u8DeviceAddr;
volatile uint8_t g_au8TxData[3];
volatile uint8_t g_u8RxData;
volatile uint8_t temp;
volatile uint8_t g_u8DataLen;
volatile uint8_t g_u8EndFlag = 0;

typedef void (*I2C_FUNC)(uint32_t u32Status);

static I2C_FUNC s_I2C0HandlerFn = NULL;

/*---------------------------------------------------------------------------------------------------------*/
/*  I2C0 IRQ Handler                                                                                       */
/*---------------------------------------------------------------------------------------------------------*/
void I2C0_IRQHandler(void)
{
    uint32_t u32Status;

    u32Status = I2C_GET_STATUS(I2C0);
    if(I2C_GET_TIMEOUT_FLAG(I2C0))
    {
        /* Clear I2C0 Timeout Flag */
        I2C_ClearTimeoutFlag(I2C0);
    }
    else
    {
        if(s_I2C0HandlerFn != NULL)
            s_I2C0HandlerFn(u32Status);
    }
}

/*---------------------------------------------------------------------------------------------------------*/
/*  I2C Rx Callback Function                                                                               */
/*---------------------------------------------------------------------------------------------------------*/
void I2C_MasterRx(uint32_t u32Status)
{
    if(u32Status == 0x08)                       /* START has been transmitted and prepare SLA+W */
    {
        I2C_SET_DATA(I2C0, (g_u8DeviceAddr << 1));    /* Write SLA+W to Register I2CDAT */
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
    }
    else if(u32Status == 0x18)                  /* SLA+W has been transmitted and ACK has been received */
    {
        I2C_SET_DATA(I2C0, g_au8TxData[g_u8DataLen++]);
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
    }
    else if(u32Status == 0x20)                  /* SLA+W has been transmitted and NACK has been received */
    {
        I2C_STOP(I2C0);
        I2C_START(I2C0);
    }
    else if(u32Status == 0x28)                  /* DATA has been transmitted and ACK has been received */
    {
        if(g_u8DataLen != 1)
        {
            I2C_SET_DATA(I2C0, g_au8TxData[g_u8DataLen++]);
            I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
        }
        else
        {
            I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STA_SI);
        }
    }
    else if(u32Status == 0x10)                  /* Repeat START has been transmitted and prepare SLA+R */
    {
        I2C_SET_DATA(I2C0, ((g_u8DeviceAddr << 1) | 0x01));   /* Write SLA+R to Register I2CDAT */
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
    }
    else if(u32Status == 0x40)                  /* SLA+R has been transmitted and ACK has been received */
    {
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
    }
    else if(u32Status == 0x58)                  /* DATA has been received and NACK has been returned */
    {
        g_u8RxData = (unsigned char) I2C_GET_DATA(I2C0);
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STO_SI);
        g_u8EndFlag = 1;
    }
    else
    {
        /* TO DO */
        printf("Status 0x%x is NOT processed\n", u32Status);
    }
}

/*---------------------------------------------------------------------------------------------------------*/
/*  I2C Tx Callback Function                                                                               */
/*---------------------------------------------------------------------------------------------------------*/
void I2C_MasterTx(uint32_t u32Status)
{
    if(u32Status == 0x08)                       /* START has been transmitted */
    {
        I2C_SET_DATA(I2C0, g_u8DeviceAddr << 1);    /* Write SLA+W to Register I2CDAT */
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
    }
    else if(u32Status == 0x18)                  /* SLA+W has been transmitted and ACK has been received */
    {
        I2C_SET_DATA(I2C0, g_au8TxData[g_u8DataLen++]);
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
    }
    else if(u32Status == 0x20)                  /* SLA+W has been transmitted and NACK has been received */
    {
        I2C_STOP(I2C0);
        I2C_START(I2C0);
    }
    else if(u32Status == 0x28)                  /* DATA has been transmitted and ACK has been received */
    {
        if(g_u8DataLen != 2)
        {
            I2C_SET_DATA(I2C0, g_au8TxData[g_u8DataLen++]);
            I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI);
        }
        else
        {
            I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STO_SI);
            g_u8EndFlag = 1;
        }
    }
    else
    {
        /* TO DO */
        printf("Status 0x%x is NOT processed\n", u32Status);
    }
}



void SYS_Init(void)
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init System Clock                                                                                       */
    /*---------------------------------------------------------------------------------------------------------*/

    /* Enable Internal RC 22.1184MHz clock */
    CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);

    /* Waiting for Internal RC clock ready */
    CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);

    /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
    CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));

    /* Enable external XTAL 12MHz clock */
    CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);

    /* Waiting for external XTAL clock ready */
    CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);

    /* Set core clock as PLL_CLOCK from PLL */
    CLK_SetCoreClock(PLL_CLOCK);

    /* Enable UART module clock */
    CLK_EnableModuleClock(UART0_MODULE);

    /* Enable I2C0 module clock */
    CLK_EnableModuleClock(I2C0_MODULE);

    /* Select UART module clock source */
    CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1));


    /*---------------------------------------------------------------------------------------------------------*/
    /* Init I/O Multi-function                                                                                 */
    /*---------------------------------------------------------------------------------------------------------*/

    /* Set GPB multi-function pins for UART0 RXD and TXD */
    SYS->GPB_MFP = SYS_GPB_MFP_PB0_UART0_RXD | SYS_GPB_MFP_PB1_UART0_TXD;

    /* Set GPA multi-function pins for I2C0 SDA and SCL */
    SYS->GPA_MFP = SYS_GPA_MFP_PA8_I2C0_SDA | SYS_GPA_MFP_PA9_I2C0_SCL;
}

void UART0_Init()
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init UART                                                                                               */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Reset IP */
    SYS_ResetModule(UART0_RST);

    /* Configure UART0 and set UART0 Baudrate */
    UART_Open(UART0, 115200);
}

void I2C0_Close(void)
{
    /* Disable I2C0 interrupt and clear corresponding NVIC bit */
    I2C_DisableInt(I2C0);
    NVIC_DisableIRQ(I2C0_IRQn);

    /* Disable I2C0 and close I2C0 clock */
    I2C_Close(I2C0);
    CLK_DisableModuleClock(I2C0_MODULE);

}

void I2C0_Init(void)
{
    /* Open I2C module and set bus clock */
    I2C_Open(I2C0, 100000);

    /* Get I2C0 Bus Clock */
    printf("I2C clock %d Hz\n", I2C_GetBusClockFreq(I2C0));


    /* Enable I2C interrupt */
    I2C_EnableInt(I2C0);
    NVIC_EnableIRQ(I2C0_IRQn);
}

uint8_t dec_to_bcd(int dec)
{
        uint8_t bcd=((dec / 10) << 4) | (dec % 10);
  return bcd;
}

int bcd_to_dec(uint8_t hex)
{
    int dec = ((hex & 0xF0) >> 4) * 10 + (hex & 0x0F);
    return dec;
}   


unsigned char DS3231_RTC_Read(unsigned char reg)
{
       
g_u8DeviceAddr = 0x68;

g_au8TxData[0] = reg; //register                               

g_u8DataLen = 0;  
        g_u8EndFlag = 0;

        /* I2C function to write data to slave */
        s_I2C0HandlerFn = (I2C_FUNC)I2C_MasterRx;

        /* I2C as master sends START signal */
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STA);

        /* Wait I2C Tx Finish */
        while(g_u8EndFlag == 0);
        g_u8EndFlag = 0;

return bcd_to_dec(g_u8RxData);
}

void DS3231_RTC_Write(unsigned char reg,unsigned char value)
{
       
g_u8DeviceAddr = 0x68;

g_au8TxData[0] = reg; //register                               
g_au8TxData[1] = dec_to_bcd(value); //value
g_u8DataLen = 0;  
        g_u8EndFlag = 0;

        /* I2C function to write data to slave */
        s_I2C0HandlerFn = (I2C_FUNC)I2C_MasterTx;

        /* I2C as master sends START signal */
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STA);

        /* Wait I2C Tx Finish */
        while(g_u8EndFlag == 0);
        g_u8EndFlag = 0;


}
#define Seconds 0x00
#define Miutes 0x01
#define Hours   0x02
#define Day     0x03
#define Date     0x04
#define Month     0x05
#define Year     0x06
/*---------------------------------------------------------------------------------------------------------*/
/*  Main Function                                                                                          */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main(void)
{

unsigned char Seconds_temp;
    /* Unlock protected registers */
    SYS_UnlockReg();

    /* Init System, IP clock and multi-function I/O */
    SYS_Init();

    /* Lock protected registers */
    SYS_LockReg();

    /* Init UART0 for printf */
    UART0_Init();

    /*
        This sample code sets I2C bus clock to 100kHz. Then, accesses EEPROM 24LC64 with Byte Write
        and Byte Read operations, and check if the read data is equal to the programmed data.
    */

    printf("+------------------------------------------------------------+\n");
    printf("|    NUC230_240 I2C Driver Sample Code with DS3231    |\n");
    printf("+------------------------------------------------------------+\n");

    /* Init I2C0 to access EEPROM */
    I2C0_Init();

   

       DS3231_RTC_Write(Hours,01);
                         DS3231_RTC_Write(Miutes,01);
                         DS3231_RTC_Write(Seconds,01);
                               


while(1)
{
       
  if(Seconds_temp!=DS3231_RTC_Read(Seconds))   
        {
                Seconds_temp=DS3231_RTC_Read(Seconds);
                printf("%d: ",DS3231_RTC_Read(Hours));
          printf("%d: ",DS3231_RTC_Read(Miutes));
    printf("%d\n\r",Seconds_temp);
        }
   
}


}


使用特权

评论回复
5
huangcunxiake| | 2016-12-31 10:24 | 只看该作者
DS1302是SPI接口的,还有个并口的时钟芯片,比较大的,里面据说还封装了锂电池。

使用特权

评论回复
6
天灵灵地灵灵| | 2017-1-14 20:56 | 只看该作者
中断后都是用回调函数实现

使用特权

评论回复
7
734774645| | 2017-1-15 22:47 | 只看该作者
DS系列还有什么DS18B20,不知道有没有一线的收发器。

使用特权

评论回复
8
shaoziyang| | 2017-1-15 23:16 | 只看该作者
734774645 发表于 2017-1-15 22:47
DS系列还有什么DS18B20,不知道有没有一线的收发器。

有UART转单总线的。

使用特权

评论回复
9
nuc240入门| | 2017-1-16 09:34 | 只看该作者
shaoziyang 发表于 2017-1-15 23:16
有UART转单总线的。

请问,UART转单总线的型号?谢谢!

使用特权

评论回复
10
shaoziyang| | 2017-1-16 18:39 | 只看该作者

使用特权

评论回复
11
734774645| | 2017-1-25 21:42 | 只看该作者
有一个内置锂电池的时钟芯片,谁还记得

使用特权

评论回复
12
mintspring| | 2017-1-25 22:34 | 只看该作者
还没用过这个外设,收藏了学习学习。

使用特权

评论回复
13
643757107| | 2017-1-26 10:42 | 只看该作者
DS3231还具有一些其它功能,这些功能扩展了系统主机的附加功能和选择范围

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

100

主题

295

帖子

6

粉丝