找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6252|回復: 5
收起左側(cè)

一起來搞定 ds1302

[復制鏈接]
ID:70481 發(fā)表于 2014-12-16 17:46 | 顯示全部樓層 |閱讀模式
   最近在論壇看到很多同仁在研究ds1302這款時鐘芯片,正巧公司項目上也用到這個,因為學習過程中遇到些問題,略有所悟。突然萌生一個想法,召集老鳥們過來一起吃透這款芯片,然后記錄下來,留給后來的同學,希望他們能夠獲益,避免走一些彎路...以后也不會有那么多帖子來問ds1302問題。。。。
    也希望高手們過來一起補充,一起討論遇到的問題...更希望曾經(jīng)研究過這款芯片的同學來分享學習ds1302遇到的 問題以及解決方法....總之,謹以綿薄之力為 后來要用的這款芯片的同學,提供參考。。。不勝感激!!

DS1302編程注意事項:

通信:
1、單片機通過三線與ds1302芯片進行數(shù)據(jù)通信:reset, data, sclk,但并非I2C通信方式。
2、reset其實質(zhì)相當于片選CE,兩個作用:
   a、選中芯片,開啟ds1302移位寄存器,以進行數(shù)據(jù)傳輸,且整個數(shù)據(jù)傳輸過程中,需要保持為 高電平;
   b、突發(fā)訪問(多字節(jié)傳輸)模式下,通過拉低reset來結(jié)束本次突發(fā)訪問模式。
   需要注意必須保證在sclk拉低的前提前才能拉高reset(換言之,每次開始數(shù)據(jù)通信之前,必須sclk必須為低電平,那么sclk第一個邊緣則一定為上升沿)。
3、data引腳應(yīng)配置成可以雙向通信的模式(例如:開漏輸出,外接上拉電阻),在程序中應(yīng)注意在單片機從接收ds1302數(shù)據(jù)之前,應(yīng)拉高data,避免影響ds1302輸出數(shù)據(jù);
4、sclk 與 reset引腳,配置為普通輸出模式即可。
5、ds1302時序:ds1302在sclk上升沿讀取data數(shù)據(jù),下降沿發(fā)布數(shù)據(jù)到data上。應(yīng)注意在ds1302有數(shù)據(jù)輸出時,輸出數(shù)據(jù)開始位是緊接著命令發(fā)送字節(jié)的末尾的下降沿輸出的。

操作:
1、任何寫操作之前應(yīng)先清除寫保護bit(特別重要)。
2、ds1302應(yīng)外接32768Hz晶振,但并非直接就能起振的 ,需要軟件清除 秒寄存器的bit7 即CH Bit,晶振才能正常工作,從而驅(qū)動ds1302內(nèi)部計數(shù)器,達到準確計時 的目的,若正常起振,則此時可以用示波器在晶振引腳處測出波形。
3、對于突發(fā)訪問模式:即是在sclk的驅(qū)動下,可以一次對多個寄存器進行讀寫,但是均是從(ram或者時間/日歷寄存器)地址0開始訪問的。應(yīng)注意若是突發(fā)模式下寫 時鐘/日歷寄存器 ,則必須要求傳輸8字節(jié)數(shù)據(jù),若是突發(fā)訪問ram數(shù)據(jù),則不需要限定字節(jié)數(shù),可以通過拉低reset來結(jié)束本次突發(fā)訪問。
4、ds1302的ram區(qū)域,掉電丟失,可以利用這種特性來檢測ds1302是否為第一次上電,從而確定是否需要配置ds1302。

回復

使用道具 舉報

ID:70481 發(fā)表于 2014-12-16 17:46 | 顯示全部樓層
以下是我編寫的DS1302芯片驅(qū)動代碼,已測試,可以正常操作芯片,但是我用到的是stm32單片機,估計會有同學不習慣使用庫的風格,但是不重要,感興趣的同學可以參考程序的步驟就可以了,比如要看時序,就只看那一個 函數(shù)就可以了。。。。。

更希望用51單片機開發(fā)的同學要是方便的話,能上傳你寶貴的代碼,讓更多的人簡單清楚的明白驅(qū)動步驟,更好的幫助他們...........謝謝!

  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.         //接收數(shù)據(jù),數(shù)據(jù)是緊接著控制字最后一位輸出的
  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.         //發(fā)送數(shù)據(jù)
  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);//連續(xù)寫 日歷/時鐘寄存器
  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);//連續(xù)讀 日歷/時鐘寄存器
  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 數(shù)據(jù)
  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);//設(shè)置秒
  135.         DS1302WriteRegister(0x82,0x18);//設(shè)置分
  136.         DS1302WriteRegister(0x84,0x17);//設(shè)置時
  137.         DS1302WriteRegister(0x86,0x29);//設(shè)置日
  138.         DS1302WriteRegister(0x88,0x11);//設(shè)置月
  139.         DS1302WriteRegister(0x8a,0x04);//設(shè)置星期
  140.         DS1302WriteRegister(0x8c,0x12);//設(shè)置年
  141.         */
  142.     }
  143. }

  144. void DS1302TimeUpdate(unsigned char *data)
  145. {
  146.     //data 數(shù)據(jù)應(yīng)為壓縮bcd碼
  147.     DS1302WriteRegister(0x8e, 0x00);//允許寫操作
  148.     DS1302WriteRegister(0xc0, 0xaa);//置標志位
  149.         
  150.     DS1302WriteTime(data);//連續(xù)寫入 時鐘/日歷 寄存器數(shù)據(jù)
  151.     DS1302WriteRegister(0x8e, 0x80);//禁止寫操作
  152. }
復制代碼
回復

使用道具 舉報

ID:67796 發(fā)表于 2014-12-16 22:31 | 顯示全部樓層
樓主真要吃透ds1302可別拉下那31個ram,參考下這篇文章 “DS1302在溫室CO2增施控制器中的應(yīng)用” 。
回復

使用道具 舉報

ID:70012 發(fā)表于 2014-12-17 06:34 | 顯示全部樓層
頂一下   不過DS1302好像還需要 BCD轉(zhuǎn)碼的吧
回復

使用道具 舉報

ID:114742 發(fā)表于 2016-5-9 11:13 | 顯示全部樓層
樓主教下我stm32的軟件安裝相關(guān)細節(jié)可好我的qq3263065307
回復

使用道具 舉報

ID:391591 發(fā)表于 2018-11-26 16:59 | 顯示全部樓層
STC芯片需要接上拉電阻,我試了幾天,才想起。
現(xiàn)象:不接外部供電,一讀數(shù)據(jù)就丟失
估計電池那點電不夠引腳底電平吸的吧。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表