找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5596|回复: 5
打印 上一主题 下一主题
收起左侧

一起来搞定 ds1302

[复制链接]
跳转到指定楼层
楼主
ID:70481 发表于 2014-12-16 17:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
   最近在论坛看到很多同仁在研究ds1302这款时钟芯片,正巧公司项目上也用到这个,因为学习过程中遇到些问题,略有所悟。突然萌生一个想法,召集老鸟们过来一起吃透这款芯片,然后记录下来,留给后来的同学,希望他们能够获益,避免走一些弯路...以后也不会有那么多帖子来问ds1302问题。。。。
    也希望高手们过来一起补充,一起讨论遇到的问题...更希望曾经研究过这款芯片的同学来分享学习ds1302遇到的 问题以及解决方法....总之,谨以绵薄之力为 后来要用的这款芯片的同学,提供参考。。。不胜感激!!

DS1302编程注意事项:

通信:
1、单片机通过三线与ds1302芯片进行数据通信:reset, data, sclk,但并非I2C通信方式。
2、reset其实质相当于片选CE,两个作用:
   a、选中芯片,开启ds1302移位寄存器,以进行数据传输,且整个数据传输过程中,需要保持为 高电平;
   b、突发访问(多字节传输)模式下,通过拉低reset来结束本次突发访问模式。
   需要注意必须保证在sclk拉低的前提前才能拉高reset(换言之,每次开始数据通信之前,必须sclk必须为低电平,那么sclk第一个边缘则一定为上升沿)。
3、data引脚应配置成可以双向通信的模式(例如:开漏输出,外接上拉电阻),在程序中应注意在单片机从接收ds1302数据之前,应拉高data,避免影响ds1302输出数据;
4、sclk 与 reset引脚,配置为普通输出模式即可。
5、ds1302时序:ds1302在sclk上升沿读取data数据,下降沿发布数据到data上。应注意在ds1302有数据输出时,输出数据开始位是紧接着命令发送字节的末尾的下降沿输出的。

操作:
1、任何写操作之前应先清除写保护bit(特别重要)。
2、ds1302应外接32768Hz晶振,但并非直接就能起振的 ,需要软件清除 秒寄存器的bit7 即CH Bit,晶振才能正常工作,从而驱动ds1302内部计数器,达到准确计时 的目的,若正常起振,则此时可以用示波器在晶振引脚处测出波形。
3、对于突发访问模式:即是在sclk的驱动下,可以一次对多个寄存器进行读写,但是均是从(ram或者时间/日历寄存器)地址0开始访问的。应注意若是突发模式下写 时钟/日历寄存器 ,则必须要求传输8字节数据,若是突发访问ram数据,则不需要限定字节数,可以通过拉低reset来结束本次突发访问。
4、ds1302的ram区域,掉电丢失,可以利用这种特性来检测ds1302是否为第一次上电,从而确定是否需要配置ds1302。

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:70481 发表于 2014-12-16 17:46 | 只看该作者
以下是我编写的DS1302芯片驱动代码,已测试,可以正常操作芯片,但是我用到的是stm32单片机,估计会有同学不习惯使用库的风格,但是不重要,感兴趣的同学可以参考程序的步骤就可以了,比如要看时序,就只看那一个 函数就可以了。。。。。

更希望用51单片机开发的同学要是方便的话,能上传你宝贵的代码,让更多的人简单清楚的明白驱动步骤,更好的帮助他们...........谢谢!

  1. #include "stm32f10x_gpio.h"
  2. #include "stm32f10x_rcc.h"

  3. #include "ds1302.h"

  4. #define DS1302_RESET_PORT            GPIOC
  5. #define DS1302_RESET_BIT             GPIO_Pin_10
  6. #define DS1302_SCLK_PORT             GPIOC
  7. #define DS1302_SCLK_BIT              GPIO_Pin_11
  8. #define DS1302_DATA_PORT             GPIOC
  9. #define DS1302_DATA_BIT              GPIO_Pin_12


  10. void DS1302Init(void)
  11. {
  12.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//打开时钟模块
  13.     GPIO_InitTypeDef GPIO_InitStructure;
  14.     GPIO_InitStructure.GPIO_Pin = DS1302_RESET_BIT;//reset
  15.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  16.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  17.     GPIO_Init(DS1302_RESET_PORT, &GPIO_InitStructure);//复位引脚
  18.    
  19.     GPIO_InitStructure.GPIO_Pin = DS1302_SCLK_BIT;
  20.     GPIO_Init(DS1302_SCLK_PORT, &GPIO_InitStructure);//SCLK
  21.     GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_RESET);
  22.    
  23.     GPIO_InitStructure.GPIO_Pin = DS1302_DATA_BIT;//data
  24.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//开漏输出,通过外接上拉电阻,达到双向通信
  25.     GPIO_Init(DS1302_DATA_PORT, &GPIO_InitStructure);
  26.    
  27.     DS1302TimeConfig();
  28. }

  29. unsigned char CommunicationByte(unsigned char value)
  30. {
  31.     unsigned char i, temp;
  32.    
  33.     GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_RESET);//sclk = 0;
  34.     temp = 0;
  35.     i = 0;
  36.     for(i = 0; i < 8; i++)
  37.     {
  38.         //接收数据,数据是紧接着控制字最后一位输出的
  39.         asm("NOP");asm("NOP");asm("NOP");asm("NOP");
  40.         temp >>= 1;//低位在前
  41.         if (GPIO_ReadInputDataBit(DS1302_DATA_PORT, DS1302_DATA_BIT) == 1)
  42.         {
  43.             temp |= 0x80;
  44.         }
  45.       
  46.         //发送数据
  47.         if ((value & 0x01) != 0)
  48.         {
  49.             GPIO_WriteBit(DS1302_DATA_PORT, DS1302_DATA_BIT, Bit_SET);
  50.         }
  51.         else
  52.         {
  53.             GPIO_WriteBit(DS1302_DATA_PORT, DS1302_DATA_BIT, Bit_RESET);
  54.         }
  55.         GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_SET);//sclk = 1, 上升沿
  56.         value >>= 1;//低位在前
  57.         asm("NOP");asm("NOP");asm("NOP");asm("NOP");
  58.         GPIO_WriteBit(DS1302_DATA_PORT, DS1302_DATA_BIT, Bit_SET);//拉高DATA IO,避免影响芯片输出
  59.         
  60.         GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_RESET);//sclk = 0,下降沿
  61.     }
  62.    
  63.     return temp;
  64. }

  65. void DS1302WriteRegister(unsigned char reg, unsigned char value)
  66. {
  67.     GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_RESET);//sclk = 0;
  68.     GPIO_WriteBit(DS1302_RESET_PORT, DS1302_RESET_BIT, Bit_SET);//只有在SCLK为低电平时候,才允许将rst置位高电平
  69.    
  70.     CommunicationByte(reg);
  71.     CommunicationByte(value);
  72.    
  73.     GPIO_WriteBit(DS1302_RESET_PORT, DS1302_RESET_BIT, Bit_RESET);//reset = 0;
  74. }

  75. unsigned char DS1302ReadRegister(unsigned char reg)
  76. {
  77.     unsigned char temp;
  78.    
  79.     GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_RESET);//sclk = 0;
  80.     GPIO_WriteBit(DS1302_RESET_PORT, DS1302_RESET_BIT, Bit_SET);//只有在SCLK为低电平时候,才允许将rst置位高电平
  81.    
  82.     CommunicationByte(reg);
  83.     temp = CommunicationByte(0xff);
  84.    
  85.     GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_SET);//sclk = 0;
  86.     GPIO_WriteBit(DS1302_RESET_PORT, DS1302_RESET_BIT, Bit_RESET);//reset = 0;
  87.    
  88.     return temp;
  89. }

  90. void DS1302WriteTime(unsigned char *data)
  91. {
  92.     unsigned char i;

  93.     GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_RESET);//sclk = 0;
  94.     GPIO_WriteBit(DS1302_RESET_PORT, DS1302_RESET_BIT, Bit_SET);//reset = 1;

  95.     CommunicationByte(0xbe);//连续写 日历/时钟寄存器
  96.    
  97.     for (i = 0; i < 8; i++)
  98.     {
  99.         CommunicationByte(data[i]);
  100.     }
  101.    
  102.     GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_RESET);//sclk = 0;
  103.     GPIO_WriteBit(DS1302_RESET_PORT, DS1302_RESET_BIT, Bit_RESET);//reset = 0;
  104. }

  105. void DS1302ReadTime(unsigned char *buffer)
  106. {
  107.     unsigned char i;

  108.     GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_RESET);//sclk = 0;
  109.     GPIO_WriteBit(DS1302_RESET_PORT, DS1302_RESET_BIT, Bit_SET);//reset = 1;
  110.     CommunicationByte(0xbf);//连续读 日历/时钟寄存器
  111.    
  112.     for (i = 0; i < 8; i++)
  113.     {
  114.         buffer[i] = CommunicationByte(0xff);
  115.     }
  116.    
  117.     GPIO_WriteBit(DS1302_SCLK_PORT, DS1302_SCLK_BIT, Bit_SET);//sclk = 0;
  118.     GPIO_WriteBit(DS1302_RESET_PORT, DS1302_RESET_BIT, Bit_RESET);//reset = 0;   
  119. }

  120. void DS1302TimeConfig(void)
  121. {
  122.     unsigned char temp;
  123.     unsigned char data[8] = {0x01,0x10,0x11,0x30,0x11,0x05,0x12};//for test
  124.    
  125.     temp = DS1302ReadRegister(0xc1);//读取ds1302ram 数据
  126.     if (temp != 0xaa)//第一次上电
  127.     {
  128.         DS1302WriteRegister(0x8e, 0x00);//允许写操作
  129.         DS1302WriteRegister(0xc0, 0xaa);//置标志位
  130.         
  131.         DS1302WriteTime(data);
  132.         DS1302WriteRegister(0x8e, 0x80);//禁止写操作
  133.         /*
  134.         DS1302WriteRegister(0x80,0x01);//设置秒
  135.         DS1302WriteRegister(0x82,0x18);//设置分
  136.         DS1302WriteRegister(0x84,0x17);//设置时
  137.         DS1302WriteRegister(0x86,0x29);//设置日
  138.         DS1302WriteRegister(0x88,0x11);//设置月
  139.         DS1302WriteRegister(0x8a,0x04);//设置星期
  140.         DS1302WriteRegister(0x8c,0x12);//设置年
  141.         */
  142.     }
  143. }

  144. void DS1302TimeUpdate(unsigned char *data)
  145. {
  146.     //data 数据应为压缩bcd码
  147.     DS1302WriteRegister(0x8e, 0x00);//允许写操作
  148.     DS1302WriteRegister(0xc0, 0xaa);//置标志位
  149.         
  150.     DS1302WriteTime(data);//连续写入 时钟/日历 寄存器数据
  151.     DS1302WriteRegister(0x8e, 0x80);//禁止写操作
  152. }
复制代码
回复

使用道具 举报

板凳
ID:67796 发表于 2014-12-16 22:31 | 只看该作者
楼主真要吃透ds1302可别拉下那31个ram,参考下这篇文章 “DS1302在温室CO2增施控制器中的应用” 。
回复

使用道具 举报

地板
ID:70012 发表于 2014-12-17 06:34 | 只看该作者
顶一下   不过DS1302好像还需要 BCD转码的吧
回复

使用道具 举报

5#
ID:114742 发表于 2016-5-9 11:13 | 只看该作者
楼主教下我stm32的软件安装相关细节可好我的qq3263065307
回复

使用道具 举报

6#
ID:391591 发表于 2018-11-26 16:59 | 只看该作者
STC芯片需要接上拉电阻,我试了几天,才想起。
现象:不接外部供电,一读数据就丢失
估计电池那点电不够引脚底电平吸的吧。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表