久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 7121|回復: 15
打印 上一主題 下一主題
收起左側

玩轉DS1302和DS18B20

  [復制鏈接]
跳轉到指定樓層
樓主
對于市面上的大多數51單片機開發板來說。ds1302和ds18b20應該是比較常見的兩種外圍芯片。ds1302是具有SPI總線接口的時鐘芯片。ds18b20則是具有單總線接口的數字溫度傳感器。下面讓我們分別來認識并學會應用這兩種芯片。
首先依舊是看DS1302的datasheet中的相關介紹。

上面是它的一些基本的應用介紹。
下面是它的引腳的描述。

下面是DS1302的時鐘寄存器。我們要讀取的時間數據就是從下面這些數據寄存器中讀取出來的。當我們要想調整時間時,可以把時間數據寫入到相應的寄存器中就可以了。

這是DS1302內部的31個RAM寄存器。在某些應用場合我們可以應用到。如我們想要做一個帶定時功能的鬧鐘。則可以把鬧鐘的時間寫入到31個RAM寄存器中的任意幾個。當單片機掉電時,只要我們的DS1302的備用電池還能工作,那么保存在其中的鬧鐘數據就不會丟失~~

由于對于這些器件的操作基本上按照數據手冊上面提供的時序圖和相關命令字來進行操作就可以了。因此在我們應用這些器件的時候一定要對照著手冊上面的要求來進行操作。如果覺得還不夠放心的話。可以到網上下載一些參考程序。對著手冊看別人的程序,看別人的思路是怎么樣的。
     DS1302和單片機的連接很簡單。只需一根復位線,一根時鐘線,一根數據線即可。同時它本身還需要接一個32.768KHz的晶振來提供時鐘源。對于晶振的兩端可以分別接一個6PF左右的電容以提高晶振的精確度。同時可以在第8腳接上一個3.6V的可充電的電池。當系統正常工作時可以對電池進行涓流充電。當系統掉電時,DS1302由這個電池提供的能量繼續工作。
     下面讓我們來驅動它。
     sbit io_DS1302_RST  = P2^0 ;
     sbit io_DS1302_IO     = P2^1 ;
     sbit io_DS1302_SCLK = P2^2 ;
     
     //-------------------------------------常數宏---------------------------------//
    #define DS1302_SECOND_WRITE        0x80          //寫時鐘芯片的寄存器位置
    #define DS1302_MINUTE_WRITE        0x82
    #define DS1302_HOUR_WRITE        0x84
    #define DS1302_WEEK_WRITE        0x8A
    #define DS1302_DAY_WRITE        0x86
    #define DS1302_MONTH_WRITE        0x88
    #define DS1302_YEAR_WRITE        0x8C

    #define DS1302_SECOND_READ        0x81          //讀時鐘芯片的寄存器位置
    #define DS1302_MINUTE_READ        0x83
    #define DS1302_HOUR_READ        0x85
    #define DS1302_WEEK_READ        0x8B
    #define DS1302_DAY_READ        0x87
    #define DS1302_MONTH_READ        0x89
    #define DS1302_YEAR_READ        0x8D
//-----------------------------------操作宏----------------------------------//
    #define DS1302_SCLK_HIGH         io_DS1302_SCLK = 1 ;
    #define    DS1302_SCLK_LOW             io_DS1302_SCLK = 0 ;
     
    #define DS1302_IO_HIGH             io_DS1302_IO   = 1 ;
    #define DS1302_IO_LOW             io_DS1302_IO   = 0 ;
    #define DS1302_IO_READ           io_DS1302_IO

    #define DS1302_RST_HIGH             io_DS1302_RST  = 1 ;
    #define DS1302_RST_LOW           io_DS1302_RST  = 0 ;




/******************************************************
* 保存時間數據的結構體         *
******************************************************/
struct
{
    uint8 Second ;
    uint8 Minute ;
    uint8 Hour ;
    uint8 Day ;
    uint8 Week ;
    uint8 Month ;
    uint8 Year ;
}CurrentTime ;



/******************************************************************************
* Function:    static void v_DS1302Write_f( uint8 Content )        *
* Description:向DS1302寫一個字節的內容            *
* Parameter:uint8 Content :    要寫的字節            *
*                        *
******************************************************************************/

static void v_DS1302Write_f( uint8 Content )
{
    uint8 i ;
    for( i = 8 ; i > 0 ; i-- )
    {
        if( Content & 0x01 )
        {
            DS1302_IO_HIGH
        }
        else
        {
            DS1302_IO_LOW
        }
        Content >>= 1 ;

        DS1302_SCLK_HIGH   
        DS1302_SCLK_LOW
    }
}


/******************************************************************************
* Function:    static uint8 v_DS1302Read_f( void )          *
* Description: 從DS1302當前設定的地址讀取一個字節的內容    *
* Parameter:                    *
* Return:    返回讀出來的值(uint8)                 *
******************************************************************************/
static uint8 v_DS1302Read_f( void )
{
    uint8 i, ReadValue ;
    DS1302_IO_HIGH
    for( i = 8 ; i > 0 ; i-- )
    {
         ReadValue >>= 1 ;
          if( DS1302_IO_READ )
         {
             ReadValue |= 0x80 ;
         }
         else
         {
             ReadValue &= 0x7f ;
         }

         DS1302_SCLK_HIGH
         DS1302_SCLK_LOW
         
    }
    return ReadValue ;
}

/******************************************************************************
* Function:    void v_DS1302WriteByte_f( uint8 Address,  uint8 Content )     *
* Description:  從DS1302指定的地址寫入一個字節的內容               *
* Parameter:  Address:    要寫入數據的地址            *
*    Content:    寫入數據的具體值            *
* Return:                                                                                                                *
******************************************************************************/
void v_DS1302WriteByte_f( uint8 Address,  uint8 Content )
{
    DS1302_RST_LOW
    DS1302_SCLK_LOW
    DS1302_RST_HIGH     

    v_DS1302Write_f( Address ) ;
    v_DS1302Write_f( Content ) ;

    DS1302_RST_LOW
    DS1302_SCLK_HIGH
}

/******************************************************************************
* Function:    uint8 v_DS1302ReadByte_f( uint8 Address )                          *
* Description:從DS1302指定的地址讀出一個字節的內容        *
* Parameter:Address:    要讀出數據的地址            *
*                         *
* Return:        指定地址讀出的值(uint8)         *
******************************************************************************/
uint8 v_DS1302ReadByte_f( uint8 Address )
{
    uint8 ReadValue ;
    DS1302_RST_LOW
    DS1302_SCLK_LOW
    DS1302_RST_HIGH     

    v_DS1302Write_f( Address ) ;
    ReadValue = v_DS1302Read_f() ;

    DS1302_RST_LOW
    DS1302_SCLK_HIGH
    return ReadValue ;
}
/******************************************************************************
* Function:    void v_ClockInit_f( void )             *
* Description:初始化寫入DS1302時鐘寄存器的值(主程序中只需調用一次即可) *
* Parameter:                                                                                                                                        *
*                                               *
* Return:                            *
******************************************************************************/
void v_ClockInit_f( void )
{
    if( v_DS1302ReadByte_f( 0xc1) != 0xf0 )
    {
        v_DS1302WriteByte_f( 0x8e, 0x00 ) ;     //允許寫操作
        v_DS1302WriteByte_f( DS1302_YEAR_WRITE, 0x08 ) ;     //年
        v_DS1302WriteByte_f( DS1302_WEEK_WRITE, 0x04 ) ;     //星期
        v_DS1302WriteByte_f( DS1302_MONTH_WRITE, 0x12 ) ;     //月
        v_DS1302WriteByte_f( DS1302_DAY_WRITE, 0x11 ) ;          //日
        v_DS1302WriteByte_f( DS1302_HOUR_WRITE, 0x13 ) ;     //小時
        v_DS1302WriteByte_f( DS1302_MINUTE_WRITE, 0x06 ) ;     //分鐘
        v_DS1302WriteByte_f( DS1302_SECOND_WRITE, 0x40 ) ;     //秒
        v_DS1302WriteByte_f( 0x90, 0xa5 ) ;                      //充電
    v_DS1302WriteByte_f( 0xc0, 0xf0 ) ;             //判斷是否初始化一次標識寫入
        v_DS1302WriteByte_f( 0x8e, 0x80 ) ;                      //禁止寫操作
    }
}
/******************************************************************************
* Function:    void v_ClockUpdata_f( void )             *
* Description:讀取時間數據,并保存在結構體CurrentTime中         *
* Parameter:                                                                                                                                                       *
*                        *
* Return:                                                                                                                                          *
******************************************************************************/
void v_ClockUpdata_f( void )
{
    CurrentTime.Second = v_DS1302ReadByte_f( DS1302_SECOND_READ ) ;
    CurrentTime.Minute = v_DS1302ReadByte_f( DS1302_MINUTE_READ ) ;
    CurrentTime.Hour   = v_DS1302ReadByte_f( DS1302_HOUR_READ ) ;
    CurrentTime.Day    = v_DS1302ReadByte_f( DS1302_DAY_READ ) ;
    CurrentTime.Month  = v_DS1302ReadByte_f( DS1302_MONTH_READ ) ;
    CurrentTime.Week   = v_DS1302ReadByte_f( DS1302_WEEK_READ ) ;
    CurrentTime.Year   = v_DS1302ReadByte_f( DS1302_YEAR_READ ) ;
}

有了上面的這些函數我們就可以對DS1302進行操作了。當我們想要獲取當前時間時,只需要調用v_ClockUpdata_f( void )這個函數即可。讀取到的時間數據保存在CurrentTime這個結構體中。至于如何把時間數據在數碼管或者是液晶屏上顯示出來我相信大家應該都會了吧^_^.

看看顯示效果如何~~


下面再讓我們看看DS18B20吧。
DS18B20是單總線的數字溫度傳感器。其與單片機的接口只需要一根數據線即可。當然連線簡單意味著軟件處理上可能要麻煩一點。下面來看看它的優點:

看看它的靚照。外形和我們常用的三極管沒有什么兩樣哦。
   
DS18B20的內部存儲器分為以下幾部分
ROM:存放該器件的編碼。前8位為單線系列的編碼(DS18B20的編碼是19H)后面48位為芯片的唯一序列號。在出場的時候就已經設置好,用戶無法更改。最后8位是以上56位的CRC碼。
RAM:DS18B20的內部暫存器共9個字節。其中第一個和第二個字節存放轉換后的溫度值。第二個和第三個字節分別存放高溫和低溫告警值。(可以用RAM指令將其拷貝到EEPROM中)第四個字節為配置寄存器。第5~7個字節保留。第9個字節為前8個字節的CRC碼。
  
DS18B20的溫度存放如上圖所示。其中S位符號位。當溫度值為負值時,S = 1 ,反之則S = 0 。我們把得到的溫度數據乘上對應的分辨率即可以得到轉換后的溫度值。
DS18B20的通訊協議:
    在對DS18B20進行讀寫編程時,必須嚴格保證讀寫的時序。否則將無法讀取測溫結果。根據DS18B20的通訊協議,主機控制DS18B20完成溫度轉換必須經過3個步驟:每一次讀寫之前都要對DS18B20進行復位,復位成功后發送一條ROM指令,最后發送RAM指令。這樣才能對DS18B20進行預定的操作。
復位要求主機將數據線下拉500us,然后釋放,DS18B20收到信號后等待16~160us然后發出60~240us的存在低脈沖,主機收到此信號表示復位成功。

上圖即DS18B20的復位時序圖。
下面是讀操作的時序圖
  
這是寫操作的時序圖

下面讓我們來看看它的驅動程序如何寫吧。

sbit io_DS18B20_DQ  = P2^3 ;
#define DS18B20_DQ_HIGH  io_DS18B20_DQ = 1 ;
#define DS18B20_DQ_LOW   io_DS18B20_DQ = 0 ;
#define DS18B20_DQ_READ  io_DS18B20_DQ

/*******************************************************************
* 保存溫度值的數組.依次存放正負標志,溫度值十位,個位,和小數位        *
*******************************************************************/
uint8 Temperature[ 4 ] ;

void v_Delay10Us_f( uint16 Count )
{
    while( --Count )
    {
        _nop_();
    }
}

/**************************************************************************
* Function:        uint8 v_Ds18b20Init_f( void )                                 *
* Description:    初始化DS18B20                                                 *
* Parameter:                                                                  *
*                                                                          *
* Return:        返回初始化的結果(0:復位成功   1:復位失敗)                         *
**************************************************************************/
uint8 v_Ds18b20Init_f( void )
{
    uint8 Flag ;
    DS18B20_DQ_HIGH          //稍作延時
    v_Delay10Us_f( 3 ) ;
    DS18B20_DQ_LOW           //總線拉低

    v_Delay10Us_f( 80 ) ; //延時大于480us

    DS18B20_DQ_HIGH       //總線釋放

    v_Delay10Us_f( 15 ) ;

    Flag = DS18B20_DQ_READ ;   //如果Flag為0,則復位成功,否則復位失敗
    return Flag ;
}
/******************************************************************************
* Function:        void v_Ds18b20Write_f( uint8 Cmd )                                 *
* Description:    向DS18B20寫命令                                                 *
* Parameter:    Cmd:    所要寫的命令                                              *
*                                                                              *
* Return:                                                                         *
******************************************************************************/
void v_Ds18b20Write_f( uint8 Cmd )
{
    uint8 i ;
    for( i = 8 ; i > 0 ; i-- )
    {
        DS18B20_DQ_LOW             //拉低總線,開始寫時序
        DS18B20_DQ_READ = Cmd & 0x01  ;     //控制字的最低位先送到總線
        v_Delay10Us_f( 5 ) ;             //稍作延時,讓DS18B20讀取總線上的數據
        DS18B20_DQ_HIGH             //拉高總線,1bit寫周期結束
        Cmd >>= 1 ;
    }
}



/******************************************************************************
* Function:        uint8 v_Ds18b20Read_f( void )                                      *
* Description:    向DS18B20讀取一個字節的內容                                     *
* Parameter:                                                                       *
*                                                                              *
* Return:        讀取到的數據                                                     *
******************************************************************************/
uint8 v_Ds18b20Read_f( void )
{
    uint8 ReadValue, i ;
    for( i = 8 ; i > 0 ; i-- )
    {
        DS18B20_DQ_LOW     
        ReadValue >>= 1 ;
        DS18B20_DQ_HIGH
        if( DS18B20_DQ_READ == 1 )
        ReadValue |= 0x80 ;
        v_Delay10Us_f( 3 ) ;
    }
    return ReadValue ;
}

/******************************************************************************
* Function:        uint16 v_Ds18b20ReadTemp_f( void )                                  *
* Description:    讀取當前的溫度數據(只保留了一位小數)                                 *
* Parameter:                                                                        *
*                                                                                 *
* Return:        讀取到的溫度值                                                     *
******************************************************************************/
uint16 v_Ds18b20ReadTemp_f( void )
{
    uint8 TempH, TempL ;
    uint16 ReturnTemp ;
     
/*    if( v_Ds18b20Init_() ) return ;  //復位失敗,在這里添加錯誤處理的代碼      */
    v_Ds18b20Init_f() ;            /復位DS18B20
    v_Ds18b20Write_f( 0xcc ) ;    //跳過ROM
    v_Ds18b20Write_f( 0x44 ) ;         //啟動溫度轉換
    v_Ds18b20Init_f() ;            
    v_Ds18b20Write_f( 0xcc ) ;    //跳過ROM
    v_Ds18b20Write_f( 0xbe ) ;    //讀取DS18B20內部的寄存器內容
    TempL = v_Ds18b20Read_f() ;     //讀溫度值低位(內部RAM的第0個字節)
    TempH = v_Ds18b20Read_f() ;     //讀溫度值高位(內部RAM的第1個字節)
    ReturnTemp = TempH ;
    ReturnTemp <<= 8 ;
    ReturnTemp |= TempL ;     //溫度值放在變量ReturnTemp中
    return ReturnTemp ;
}
/******************************************************************************
* Function:    void v_TemperatureUpdate_f( void )        *
* Description:讀取當前的溫度數據并轉化存放在數組Temperature(只保留了一位小數) *
* Parameter:                                                                                                                                           *
*                            *
* Return:                                                                                                                                             *
******************************************************************************/
void v_TemperatureUpdate_f( void )
{
    uint8 Tflag = 0 ;
    uint16 TempDat ;
    float Temp ;
    TempDat = v_Ds18b20ReadTemp_f() ;
    if( TempDat & 0xf000 )
    {
        Tflag = 1 ;                           
        TempDat = ~TempDat + 1 ;
    }
    Temp = TempDat * 0.0625    ;           
    TempDat = Temp * 10          ;         
    Temperature[ 0 ] = Tflag ;          //溫度正負標志
    Temperature[ 1 ] = TempDat / 100  + '0' ;       //溫度十位值
    Temperature[ 2 ] = TempDat % 100 / 10 + '0' ;  //溫度個位值
    Temperature[ 3 ] = TempDat % 10         + '0' ;//溫度小數位
}
如果想獲取當前的溫度數據,在主函數中調用v_TemperatureUpdate_f( void )就可以了。溫度數據就保存到Temperature中去了。至于如何顯示,就不用多說了吧~@_@~
   
時間和溫度一起顯示出來看看

OK,至此ds18b20和ds1302的應用告一段落。如果有不懂的,記得多看datasheet,多交流。

評分

參與人數 2黑幣 +20 收起 理由
bh4djj + 12 贊一個!
wrty0 + 8 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏9 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發
ID:262 發表于 2013-9-6 14:47 | 只看該作者
好東東我頂,51hei(51黑)單片機論壇有你更精彩.
回復

使用道具 舉報

板凳
ID:53421 發表于 2013-10-4 01:41 | 只看該作者
學習了,慢慢消化。感謝!
回復

使用道具 舉報

地板
ID:55611 發表于 2013-10-5 12:51 | 只看該作者
玩轉DS1302和DS18B20
回復

使用道具 舉報

5#
ID:55611 發表于 2013-10-5 12:51 | 只看該作者
好好學習,天天向上
回復

使用道具 舉報

6#
ID:55613 發表于 2013-10-6 15:08 | 只看該作者
樓主,我是剛剛接觸單片機什么多不懂。能否講了詳細點。溫度顯示如何寫在1602時間后面謝謝
回復

使用道具 舉報

7#
ID:52286 發表于 2013-10-13 23:46 | 只看該作者
支持支持!!
回復

使用道具 舉報

8#
ID:57793 發表于 2013-12-17 21:52 | 只看該作者
謝謝分享
回復

使用道具 舉報

9#
ID:55219 發表于 2013-12-21 20:49 | 只看該作者
頂一下。。。。。
回復

使用道具 舉報

10#
ID:58213 發表于 2014-2-11 14:46 | 只看該作者
謝謝分享
回復

使用道具 舉報

11#
ID:58936 發表于 2014-2-17 11:28 | 只看該作者
樓主厲害,我也想學習這個。
回復

使用道具 舉報

12#
ID:56665 發表于 2014-2-17 23:17 | 只看該作者
在網上買了幾片DS1302做時鐘,誤差比用定時器中斷做的時鐘誤差還大,不知道是IC問題還是晶振問題。
回復

使用道具 舉報

13#
ID:69408 發表于 2015-10-18 11:01 | 只看該作者
學習不同的方法使用DS1302,不錯,謝謝樓主分享!
回復

使用道具 舉報

14#
ID:103999 發表于 2016-1-24 22:06 | 只看該作者
有木有匯編的程序
回復

使用道具 舉報

15#
ID:158995 發表于 2017-1-5 10:43 | 只看該作者
不錯,能不能講講多點測溫系統呢
回復

使用道具 舉報

16#
ID:225059 發表于 2017-11-8 16:29 | 只看該作者
寫入后,其他功能正常使用,但是分鐘不論是寫入還是讀取 都是顯示為0, 年月日星期顯示的都是正確的
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 特一级毛片 | 国产一区免费 | 成人不卡视频 | 亚洲人a | 欧美激情一区二区三区 | 中文字幕在线视频一区二区三区 | 激情网站在线 | 欧美在线视频网 | 国产精品中文在线 | 国产中文字幕网 | 在线久草 | 色又黄又爽网站www久久 | 久久综合久久久 | 四虎影院在线观看av | 999久久久久久久久 国产欧美在线观看 | 九九热最新地址 | 欧美福利 | 久久在线看 | 日韩成人精品一区二区三区 | 毛片一级片 | 国产成人免费 | 国产成人精品一区二区 | 亚洲综合色视频在线观看 | 成人免费在线观看 | 日韩二区 | 中文字幕在线观看 | h在线观看 | 九九久久99 | 欧美极品视频 | 91偷拍精品一区二区三区 | 在线一区 | 亚洲精品福利视频 | 亚洲高清视频一区二区 | 欧美激情亚洲激情 | 久久久久久综合 | 日日射影院 | 久久久久久精 | 青青草国产在线观看 | 一级毛片视频 | 精品国产鲁一鲁一区二区张丽 | 天天操欧美 |