PIC单片机驱动时钟芯片DS1302(附代码)

在工业控制、家电等产品中经常会用到实时时钟,DS1302是比较常用的一款时钟芯片。今天,就以PIC16F877为例,阐述一下DS1302的驱动方法。

一、DS1302简介

DS1302工作电压为2.0V~5.5V。采用三线接口与CPU进行同步通信,支持双电源供电,具有低至300nA的待机功耗。正常工作时由系统电源供电,掉电后自动切换到备份电池,确保时钟持续运行。这个特性在工业现场极为重要,能有效避免更换电池时时间重置的尴尬。

二、硬件连接:PIC单片机与DS1302

PIC单片机与DS1302的典型电路:

设计中的三个关键细节:

  1. 晶振选择:须使用6pF负载电容的32.768kHz晶振,普通12.5pF的晶振会导致走时不准。
  2. 备用电池VCC1端串联1N5819二极管(图中未画出)可以防止系统电源对电池充电。对于CR2032这类不可充电电池,这是必须的保护措施。
  3. 上拉电阻:三线接口建议在靠近MCU侧加5.1kΩ上拉电阻,提高抗干扰能力,特别是当连接线较长时。

三、软件实现:

以下代码基于PIC16F877,可以通过串口来设置DS1302的初值

例程如下:

#include <pic16f87x.h>

#define i_o   RC3                      //定义DS1302的数据口

#define sclk  RC4                      //定义DS1302的时钟口

#define rst   RC2                      //定义DS1302的复位口

void ds1302_init();                    //申明DS1302初始化函数

void set_time();                       //申明设置时间函数

void get_time();                       //申明读取时间函数

void time_write (unsigned char time_tx);    //申明写一个字节函数

unsigned char  time_read ();          //申明读一个字节函数

//定义待设置的时间: 秒、 分、 时、 日、月、星期、年、控制字

unsigned char table[8];

//定义读取时间和日期存放表格

unsigned char table1[7];

void ds1302_init()

  {

   sclk=0;                            //拉低时钟信号

   rst =0;                            //复位DS1302

   rst=1;                             //使能DS1302

   time_write_2(0x8e);                //发控制命令

   time_write_2(0);                   //允许写DS1302

   rst=0;                             //复位

  }

//---------------------------------------------

//设置时间函数

void set_time()

  {

   int i;                             //定义循环变量

   rst=1;                             //使能DS1302

   time_write_1(0xbe);                //时钟多字节写命令

   for(i=0;i<8;i++)                   //连续写8个字节数据

     {

       time_write_1(table[i]);        //调用写一个字节函数

     }

   rst=0;                             //复位

   }

//---------------------------------------------

//读取时间函数

void get_time()

 {

   int i;                             //设置循环变量

   rst=1;                             //使能DS1302

   time_write_1(0xbf);                //发送多字节读取命令

   for(i=0;i<7;i++)                   //连续读取7个字节数据

     {

        table1[i]=time_read_1();      //调用读取1个字节数据的函数

     }

    rst=0;                            //复位DS1302

 }

//写一个字节数据函数

void time_write(unsigned char time_tx)

 {

    int j;                            //设置循环变量

    for(j=0;j<8;j++)                  //连续写8bit

      {

        i_o=0;                        //先设置数据为0

        sclk=0;                       //时钟信号拉低

        if(time_tx&0x01)              //判断待发送的数据位是0或1

          {

            i_o=1;                    //待发送数据位是1

          }

        time_tx=time_tx>>1;           //待发送的数据右移1位

        sclk=1;                       //拉高时钟信号

       }

      sclk=0;                         //写完一个字节,拉低时钟信号

  }

//读一个字节函数

unsigned char time_read()

 {

   int j;                            //设置循环变量

   TRISC3=1;                         //设置数据口方向为输入

   for(j=0;j<8;j++)                  //连续读取8bit

      {

        sclk=0;                      //拉低时钟信号

        time_rx=time_rx>>1;          //接收寄存器右移1位

        time_rx7=i_o;                //把接收到的数据放到接收寄存器的最高位

       sclk=1;                       //拉高时钟信号

      }

    TRISC3=0;                        //恢复数据口方向为输出

    sclk=0;                          //拉低时钟信号

    return(time_rx);                 //返回读取到的数据

  }

四、BCD码转换

DS1302内部所有时间数据均以BCD格式存储。

例如:

  • 十进制 23 → BCD = 0x23 (二进制 0010 0011
  • 十进制 59 → BCD = 0x59 (二进制 0101 1001

如果不做转换,直接用二进制读写,会出现时间错乱的情况。

下面是转换函数

// 二进制转BCD码(0-99
unsigned char bin2bcd(unsigned char bin)
{
    return ((bin / 10) << 4) | (bin % 10);
}

// BCD码转二进制
unsigned char bcd2bin(unsigned char bcd)
{
    return (bcd >> 4) * 10 + (bcd & 0x0F);
}

附:《PIC单片机入门实战》共8篇文章与《PIC单片机进阶实战》共6篇文章内容来源于我自己画的电路原理图及程序,有对PIC单片机感兴趣想学习的朋友可以关注我,免费赠送资料(包括原理图、数据手册、各种例程等)。

有需要这两款控制板的朋友也可以关注联系我。

后续干货不断,咱们一起在单片机的世界里,共同进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值