打印
[STM32]

DS3231SN 方案开发以及供应

[复制链接]
289|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
michaelleng8888|  楼主 | 2020-10-9 14:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

  http://blog.sina.com.cn/s/blog_152dddb6f0102yqn1.html  Maxim Integrated新型实时时钟(RTC) DS3231,内部集成了TCXO、RTC和32.768kHz晶体,并采用低成本、标准型、16引脚SOIC封装DS3231是低成本、高精度I²C实时时钟(RTC),具有集成的温补晶振(TCXO)和晶体。该器件包含电池输入端,断开主电源时仍可保持精确的计时。集成晶振提高了器件的长期精确度,并减少了生产线的元件数量。DS3231提供商用级和工业级温度范围,采用16引脚300mil的SO封装。

RTC保存秒、分、时、星期、日期、月和年信息。少于31天的月份,将自动调整月末的日期,包括闰年的修正。时钟的工作格式可以是24小时或带/AM/PM指示的12小时格式。提供两个可设置的日历闹钟和一个可设置的方波输出。地址与数据通过I²C双向总线串行传输。

精密的、经过温度补偿的电压基准和比较器电路用来监视VCC状态,检测电源故障,提供复位输出,并在必要时自动切换到备份电源。另外,/RST监视引脚可以作为产生µP复位的手动输入。

关键特性

  • 0°C至+40°C范围内精度为±2ppm
  • -40°C至+85°C范围内精度为±3.5ppm
  • 为连续计时提供电池备份输入
  • 工作温度范围
    • 商用级:0°C至+70°C
    • 工业级:-40°C至+85°C
  • 低功耗
  • 实时时钟产生秒、分、时、星期、日期、月和年计时,并提供有效期到2100年的闰年补偿
  • 两个日历闹钟
  • 可编程方波输出
  • 高速(400kHz) I²C接口
  • 工作在3.3V
  • 数字温度传感器输出:精度为±3°C
  • 老化修正寄存器
  • /RST输出/按钮复位去抖输入
  • 做了块板子,用ds3231sn时钟芯片,板子其它部分都做好了,昨天网上找了一个stm32驱动ds3231的程序,我用的430单片机,按照程序修改了一下,却死活读取不到正确时间。貌似通讯不对,可是时序延时是完全按照网上的程序的。为什么会这样?附原理图。
    补充:在仿真时,时间读取函数里面,仿真看到年月日时分秒都是0。/****************************************************/
    把代码贴出来吧:

    ///
    /*
    DS3231.C文件
    */

    #include"ds3231sn.h"
    #define SETIIC_SCL P1OUT |= BIT7
    #define CLRIIC_SCL P1OUT &=~BIT7

    #define SETIIC_SDA P1OUT |= BIT6
    #define CLRIIC_SDA P1OUT &=~BIT6

    #define IIC_SDA (P1IN&BIT6)
    _calendar_obj calendar;
    #define DS3231_WriteAddress 0xD0   
    #define DS3231_ReadAddress  0xD1
    //-------------------------------------------------------------------
    unsigned char BCD2HEX(unsigned char val)
    {
        unsigned char i;
        i= val&0x0f;
        val >>= 4;
        val &= 0x0f;
        val *= 10;
        i += val;
        return i;
    }

    unsigned short B_BCD(unsigned char val)
    {
      unsigned char i,j,k;
      i=val/10;
      j=val%10;
      k=j+(i<<4);
      return k;
    }
    //-------------------------------------------------------------------
    void IIC_Init(void)
    {//IIC总线初始化函数
        P1DIR |= BIT7;P1DIR |= BIT6;
        SETIIC_SDA;//释放IIC总线的数据线。
        SETIIC_SCL;//释放IIC总线的时钟线。
    }
    //-------------------------------------------------------------------
    void IIC_start(void)
    {//IIC总线产生起始信号函数
         P1DIR |= BIT6;
         SETIIC_SDA;//拉高数据线
         delay_us(1);
         SETIIC_SCL;//拉高时钟线
         delay_us(5);
         CLRIIC_SDA;//在时钟线为高电平时,拉低数据线,产生起始信号。
         delay_us(5);
         CLRIIC_SCL;//拉低时钟线
         delay_us(2);
    }
    //-------------------------------------------------------------------
    void IIC_stop(void)
    {//IIC总线产生停止信号函数
        P1DIR |= BIT6;
        CLRIIC_SCL;//拉低时钟线
        CLRIIC_SDA;//拉低数据线
        delay_us(4);
        SETIIC_SCL;//拉高时钟线。
        delay_us(5);
        SETIIC_SDA;//时钟时线为高电平时,拉高数据线,产生停止信号。
        delay_us(4);
    }
    //-------------------------------------------------------------------
    unsigned char IIC_Tack(void)
    {//接收应答信号函数
        unsigned char timnu=0;//定义一个位变量,来暂存应答状态。
        P1DIR &=~ BIT6;
        SETIIC_SDA;//释放数据总线,准备接收应答信号。
        delay_us(1);
        SETIIC_SCL;//拉高时钟线。
        delay_us(1);
        while(IIC_SDA==1)//读取应答信号的状态。
        {
          timnu++;
          if(timnu>250)
          {
            IIC_stop();
            return 1;//返回应答信号的状态,0表示应答,1表示非应答。
          }
        }
        CLRIIC_SCL;//拉低时钟线。
        return 0;//返回应答信号的状态,0表示应答,1表示非应答。
    }
    //产生ACK应答
    void IIC_Ack(void)
    {
            P1DIR |= BIT6;
            CLRIIC_SCL;
            CLRIIC_SDA;
            delay_us(2);
            SETIIC_SCL;
            delay_us(2);
            CLRIIC_SCL;
    }
    //不产生ACK应答                    
    void IIC_NAck(void)
    {
            P1DIR |= BIT6;
            CLRIIC_SCL;
            SETIIC_SDA;
            delay_us(2);
            SETIIC_SCL;
            delay_us(2);
            CLRIIC_SCL;
    }               
    //-------------------------------------------------------------------
    void IIC_write_byte(unsigned char Data)
    {//向IIC总线写入一个字节的数据函数
        unsigned char i;
        P1DIR |= BIT6;
        CLRIIC_SCL;//拉低时钟线,允许改变数据线的状态
        for(i=0;i<8;i++)
        {              
                    if((Data&0x80)>>7)
                       SETIIC_SDA;
                    else
                       CLRIIC_SDA;
                    Data<<=1;           
                    delay_us(2);   //对TEA5767这三个延时都是必须的
                    SETIIC_SCL;//拉高时钟线。
                    delay_us(2);
                    CLRIIC_SCL;//拉低时钟线,允许改变数据线的状态
                    delay_us(2);
        }
    }
    //-------------------------------------------------------------------
    unsigned char IIC_read_byte(unsigned char ack)
    {//从IIC总线读取一个字节的数据函数
        unsigned char i;
        unsigned char Data=0;       //定义一个缓冲寄存器。
        P1DIR &=~ BIT6;
        for(i=0;i<8;i++)//有8位数据
        {
            CLRIIC_SCL;//拉低时钟线,为读取下一位数据做准备。
            delay_us(2);
            SETIIC_SCL;//拉高时钟线,为读取下一位数据做准备。
            Data=Data<<1;//将缓冲字节的数据左移一位,准备读取数据。

            if(IIC_SDA==1)//如果数据线为高平电平。
                Data++;delay_us(1);
        }
         if (!ack)
            IIC_NAck();//发送nACK
        else
            IIC_Ack(); //发送ACK   
        return Data;//返回读取的一个字节数据。
    }
    //-------------------------------------------------------------------
    void IIC_single_byte_write(unsigned char Waddr,unsigned char Data)
    {//向任意地址写入一个字节数据函数
        IIC_start();//产生起始信号
        delay_us(5);
        IIC_write_byte(DS3231_WriteAddress);//写入设备地址(写)
        IIC_Tack();//等待设备的应答.
        delay_us(5);
        IIC_write_byte(Waddr);//写入要操作的单元地址。
        IIC_Tack();//等待设备的应答。
        delay_us(5);
        IIC_write_byte(Data);//写入数据。
        IIC_Tack();//等待设备的应答。
        delay_us(5);
        IIC_stop();//产生停止符号。
    }
    //-------------------------------------------------------------------
    unsigned char IIC_single_byte_read(unsigned char Waddr)
    {//从任意地址读取一个字节数据函数
        unsigned char Data;//定义一个缓冲寄存器。
        IIC_start();//产生起始信号
        IIC_write_byte(DS3231_WriteAddress);//写入设备地址(写)
        IIC_Tack();//等待设备的应答
        delay_us(5);
        IIC_write_byte(Waddr);//写入要操作的单元地址。
        IIC_Tack();//等待设备的应答。
        delay_us(5);
        IIC_start();//产生起始信号
        IIC_write_byte(DS3231_ReadAddress);//写入设备地址(写)
        IIC_Tack();//等待设备的应答
        delay_us(5);
        Data=IIC_read_byte(1);//写入数据。
        IIC_stop();//产生停止符号。
        //-------------------返回读取的数据--------------------
        return Data;//返回读取的一个字节数据。
    }
    void Read_RTC(void)
    {
      calendar.w_year=IIC_single_byte_read(0x06);  
      calendar.w_month=IIC_single_byte_read(0x05);  
      calendar.w_date=IIC_single_byte_read(0x04);
      calendar.hour=IIC_single_byte_read(0x02);  
      calendar.min=IIC_single_byte_read(0x01);
      calendar.sec=IIC_single_byte_read(0x00);  
    }
    void Set_RTC(unsigned char yea,unsigned char mon,unsigned char da,unsigned char hou,unsigned char min,unsigned char sec)
    {
      unsigned char temp=0;

      temp=B_BCD(yea);
      IIC_single_byte_write(0x06,temp);

      temp=B_BCD(mon);
      IIC_single_byte_write(0x05,temp);

      temp=B_BCD(da);
      IIC_single_byte_write(0x04,temp);

      temp=B_BCD(hou);
      IIC_single_byte_write(0x02,temp);

      temp=B_BCD(min);
      IIC_single_byte_write(0x01,temp);

      temp=B_BCD(sec);
      IIC_single_byte_write(0x00,temp);
    }
    void get_show_time(void)
    {
      calendar.w_year=IIC_single_byte_read(0x06);  
      calendar.w_year=BCD2HEX(calendar.w_year);


      calendar.w_month=IIC_single_byte_read(0x05);
      calendar.w_month=BCD2HEX(calendar.w_month);


      calendar.w_date=IIC_single_byte_read(0x04);  
      calendar.w_date=BCD2HEX(calendar.w_date);


      calendar.hour=IIC_single_byte_read(0x02);
      calendar.hour&=0x3f;                  
      calendar.hour=BCD2HEX(calendar.hour);


      calendar.min=IIC_single_byte_read(0x01);
      calendar.min=BCD2HEX(calendar.min);


      calendar.sec=IIC_single_byte_read(0x00);
      calendar.sec=BCD2HEX(calendar.sec);
    }
    void DS3231_Initial()
    {
        IIC_Init();
        IIC_single_byte_write(0x0e,0);
        delay_ms(2);
        IIC_single_byte_write(0x0f,0);
        delay_ms(2);
    }


使用特权

评论回复

相关帖子

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

本版积分规则

9

主题

33

帖子

0

粉丝