|
對(duì)于市面上的大多數(shù)51單片機(jī)開發(fā)板來(lái)說(shuō)。ds1302和ds18b20應(yīng)該是比較常見的兩種外圍芯片。ds1302是具有SPI總線接口的時(shí)鐘芯片。ds18b20則是具有單總線接口的數(shù)字溫度傳感器。下面讓我們分別來(lái)認(rèn)識(shí)并學(xué)會(huì)應(yīng)用這兩種芯片。
首先依舊是看DS1302的datasheet中的相關(guān)介紹。
1.JPG (74.38 KB, 下載次數(shù): 127)
下載附件
2013-8-7 03:13 上傳
上面是它的一些基本的應(yīng)用介紹。
下面是它的引腳的描述。
2.JPG (19.42 KB, 下載次數(shù): 130)
下載附件
2013-8-7 03:13 上傳
下面是DS1302的時(shí)鐘寄存器。我們要讀取的時(shí)間數(shù)據(jù)就是從下面這些數(shù)據(jù)寄存器中讀取出來(lái)的。當(dāng)我們要想調(diào)整時(shí)間時(shí),可以把時(shí)間數(shù)據(jù)寫入到相應(yīng)的寄存器中就可以了。
3.JPG (65.24 KB, 下載次數(shù): 128)
下載附件
2013-8-7 03:13 上傳
這是DS1302內(nèi)部的31個(gè)RAM寄存器。在某些應(yīng)用場(chǎng)合我們可以應(yīng)用到。如我們想要做一個(gè)帶定時(shí)功能的鬧鐘。則可以把鬧鐘的時(shí)間寫入到31個(gè)RAM寄存器中的任意幾個(gè)。當(dāng)單片機(jī)掉電時(shí),只要我們的DS1302的備用電池還能工作,那么保存在其中的鬧鐘數(shù)據(jù)就不會(huì)丟失~~
由于對(duì)于這些器件的操作基本上按照數(shù)據(jù)手冊(cè)上面提供的時(shí)序圖和相關(guān)命令字來(lái)進(jìn)行操作就可以了。因此在我們應(yīng)用這些器件的時(shí)候一定要對(duì)照著手冊(cè)上面的要求來(lái)進(jìn)行操作。如果覺得還不夠放心的話?梢缘骄W(wǎng)上下載一些參考程序。對(duì)著手冊(cè)看別人的程序,看別人的思路是怎么樣的。
DS1302和單片機(jī)的連接很簡(jiǎn)單。只需一根復(fù)位線,一根時(shí)鐘線,一根數(shù)據(jù)線即可。同時(shí)它本身還需要接一個(gè)32.768KHz的晶振來(lái)提供時(shí)鐘源。對(duì)于晶振的兩端可以分別接一個(gè)6PF左右的電容以提高晶振的精確度。同時(shí)可以在第8腳接上一個(gè)3.6V的可充電的電池。當(dāng)系統(tǒng)正常工作時(shí)可以對(duì)電池進(jìn)行涓流充電。當(dāng)系統(tǒng)掉電時(shí),DS1302由這個(gè)電池提供的能量繼續(xù)工作。
下面讓我們來(lái)驅(qū)動(dòng)它。
sbit io_DS1302_RST = P2^0 ;
sbit io_DS1302_IO = P2^1 ;
sbit io_DS1302_SCLK = P2^2 ;
//-------------------------------------常數(shù)宏---------------------------------//
#define DS1302_SECOND_WRITE 0x80 //寫時(shí)鐘芯片的寄存器位置
#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 //讀時(shí)鐘芯片的寄存器位置
#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 ;
/******************************************************
* 保存時(shí)間數(shù)據(jù)的結(jié)構(gòu)體 *
******************************************************/
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寫一個(gè)字節(jié)的內(nèi)容 *
* Parameter:uint8 Content : 要寫的字節(jié) *
* *
******************************************************************************/
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當(dāng)前設(shè)定的地址讀取一個(gè)字節(jié)的內(nèi)容 *
* Parameter: *
* Return: 返回讀出來(lái)的值(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指定的地址寫入一個(gè)字節(jié)的內(nèi)容 *
* Parameter: Address: 要寫入數(shù)據(jù)的地址 *
* Content: 寫入數(shù)據(jù)的具體值 *
* 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指定的地址讀出一個(gè)字節(jié)的內(nèi)容 *
* Parameter:Address: 要讀出數(shù)據(jù)的地址 *
* *
* 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時(shí)鐘寄存器的值(主程序中只需調(diào)用一次即可) *
* 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 ) ; //小時(shí)
v_DS1302WriteByte_f( DS1302_MINUTE_WRITE, 0x06 ) ; //分鐘
v_DS1302WriteByte_f( DS1302_SECOND_WRITE, 0x40 ) ; //秒
v_DS1302WriteByte_f( 0x90, 0xa5 ) ; //充電
v_DS1302WriteByte_f( 0xc0, 0xf0 ) ; //判斷是否初始化一次標(biāo)識(shí)寫入
v_DS1302WriteByte_f( 0x8e, 0x80 ) ; //禁止寫操作
}
}
/******************************************************************************
* Function: void v_ClockUpdata_f( void ) *
* Description:讀取時(shí)間數(shù)據(jù),并保存在結(jié)構(gòu)體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 ) ;
}
有了上面的這些函數(shù)我們就可以對(duì)DS1302進(jìn)行操作了。當(dāng)我們想要獲取當(dāng)前時(shí)間時(shí),只需要調(diào)用v_ClockUpdata_f( void )這個(gè)函數(shù)即可。讀取到的時(shí)間數(shù)據(jù)保存在CurrentTime這個(gè)結(jié)構(gòu)體中。至于如何把時(shí)間數(shù)據(jù)在數(shù)碼管或者是液晶屏上顯示出來(lái)我相信大家應(yīng)該都會(huì)了吧^_^.
看看顯示效果如何~~
4.JPG (15.59 KB, 下載次數(shù): 127)
下載附件
2013-8-7 03:13 上傳
下面再讓我們看看DS18B20吧。
DS18B20是單總線的數(shù)字溫度傳感器。其與單片機(jī)的接口只需要一根數(shù)據(jù)線即可。當(dāng)然連線簡(jiǎn)單意味著軟件處理上可能要麻煩一點(diǎn)。下面來(lái)看看它的優(yōu)點(diǎn):
5.JPG (51.83 KB, 下載次數(shù): 129)
下載附件
2013-8-7 03:13 上傳
看看它的靚照。外形和我們常用的三極管沒有什么兩樣哦。
6.JPG (12.88 KB, 下載次數(shù): 117)
下載附件
2013-8-7 03:13 上傳
DS18B20的內(nèi)部存儲(chǔ)器分為以下幾部分
ROM:存放該器件的編碼。前8位為單線系列的編碼(DS18B20的編碼是19H)后面48位為芯片的唯一序列號(hào)。在出場(chǎng)的時(shí)候就已經(jīng)設(shè)置好,用戶無(wú)法更改。最后8位是以上56位的CRC碼。
RAM:DS18B20的內(nèi)部暫存器共9個(gè)字節(jié)。其中第一個(gè)和第二個(gè)字節(jié)存放轉(zhuǎn)換后的溫度值。第二個(gè)和第三個(gè)字節(jié)分別存放高溫和低溫告警值。(可以用RAM指令將其拷貝到EEPROM中)第四個(gè)字節(jié)為配置寄存器。第5~7個(gè)字節(jié)保留。第9個(gè)字節(jié)為前8個(gè)字節(jié)的CRC碼。
7.JPG (18.97 KB, 下載次數(shù): 130)
下載附件
2013-8-7 03:15 上傳
DS18B20的溫度存放如上圖所示。其中S位符號(hào)位。當(dāng)溫度值為負(fù)值時(shí),S = 1 ,反之則S = 0 。我們把得到的溫度數(shù)據(jù)乘上對(duì)應(yīng)的分辨率即可以得到轉(zhuǎn)換后的溫度值。
DS18B20的通訊協(xié)議:
在對(duì)DS18B20進(jìn)行讀寫編程時(shí),必須嚴(yán)格保證讀寫的時(shí)序。否則將無(wú)法讀取測(cè)溫結(jié)果。根據(jù)DS18B20的通訊協(xié)議,主機(jī)控制DS18B20完成溫度轉(zhuǎn)換必須經(jīng)過(guò)3個(gè)步驟:每一次讀寫之前都要對(duì)DS18B20進(jìn)行復(fù)位,復(fù)位成功后發(fā)送一條ROM指令,最后發(fā)送RAM指令。這樣才能對(duì)DS18B20進(jìn)行預(yù)定的操作。
復(fù)位要求主機(jī)將數(shù)據(jù)線下拉500us,然后釋放,DS18B20收到信號(hào)后等待16~160us然后發(fā)出60~240us的存在低脈沖,主機(jī)收到此信號(hào)表示復(fù)位成功。
8.JPG (28.08 KB, 下載次數(shù): 134)
下載附件
2013-8-7 03:15 上傳
上圖即DS18B20的復(fù)位時(shí)序圖。
下面是讀操作的時(shí)序圖
9.JPG (27.14 KB, 下載次數(shù): 116)
下載附件
2013-8-7 03:15 上傳
這是寫操作的時(shí)序圖
10.JPG (25.32 KB, 下載次數(shù): 116)
下載附件
2013-8-7 03:15 上傳
下面讓我們來(lái)看看它的驅(qū)動(dòng)程序如何寫吧。
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
/*******************************************************************
* 保存溫度值的數(shù)組.依次存放正負(fù)標(biāo)志,溫度值十位,個(gè)位,和小數(shù)位 *
*******************************************************************/
uint8 Temperature[ 4 ] ;
void v_Delay10Us_f( uint16 Count )
{
while( --Count )
{
_nop_();
}
}
/**************************************************************************
* Function: uint8 v_Ds18b20Init_f( void ) *
* Description: 初始化DS18B20 *
* Parameter: *
* *
* Return: 返回初始化的結(jié)果(0:復(fù)位成功 1:復(fù)位失敗) *
**************************************************************************/
uint8 v_Ds18b20Init_f( void )
{
uint8 Flag ;
DS18B20_DQ_HIGH //稍作延時(shí)
v_Delay10Us_f( 3 ) ;
DS18B20_DQ_LOW //總線拉低
v_Delay10Us_f( 80 ) ; //延時(shí)大于480us
DS18B20_DQ_HIGH //總線釋放
v_Delay10Us_f( 15 ) ;
Flag = DS18B20_DQ_READ ; //如果Flag為0,則復(fù)位成功,否則復(fù)位失敗
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 //拉低總線,開始寫時(shí)序
DS18B20_DQ_READ = Cmd & 0x01 ; //控制字的最低位先送到總線
v_Delay10Us_f( 5 ) ; //稍作延時(shí),讓DS18B20讀取總線上的數(shù)據(jù)
DS18B20_DQ_HIGH //拉高總線,1bit寫周期結(jié)束
Cmd >>= 1 ;
}
}
/******************************************************************************
* Function: uint8 v_Ds18b20Read_f( void ) *
* Description: 向DS18B20讀取一個(gè)字節(jié)的內(nèi)容 *
* Parameter: *
* *
* Return: 讀取到的數(shù)據(jù) *
******************************************************************************/
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: 讀取當(dāng)前的溫度數(shù)據(jù)(只保留了一位小數(shù)) *
* Parameter: *
* *
* Return: 讀取到的溫度值 *
******************************************************************************/
uint16 v_Ds18b20ReadTemp_f( void )
{
uint8 TempH, TempL ;
uint16 ReturnTemp ;
/* if( v_Ds18b20Init_() ) return ; //復(fù)位失敗,在這里添加錯(cuò)誤處理的代碼 */
v_Ds18b20Init_f() ; /復(fù)位DS18B20
v_Ds18b20Write_f( 0xcc ) ; //跳過(guò)ROM
v_Ds18b20Write_f( 0x44 ) ; //啟動(dòng)溫度轉(zhuǎn)換
v_Ds18b20Init_f() ;
v_Ds18b20Write_f( 0xcc ) ; //跳過(guò)ROM
v_Ds18b20Write_f( 0xbe ) ; //讀取DS18B20內(nèi)部的寄存器內(nèi)容
TempL = v_Ds18b20Read_f() ; //讀溫度值低位(內(nèi)部RAM的第0個(gè)字節(jié))
TempH = v_Ds18b20Read_f() ; //讀溫度值高位(內(nèi)部RAM的第1個(gè)字節(jié))
ReturnTemp = TempH ;
ReturnTemp <<= 8 ;
ReturnTemp |= TempL ; //溫度值放在變量ReturnTemp中
return ReturnTemp ;
}
/******************************************************************************
* Function: void v_TemperatureUpdate_f( void ) *
* Description:讀取當(dāng)前的溫度數(shù)據(jù)并轉(zhuǎn)化存放在數(shù)組Temperature(只保留了一位小數(shù)) *
* 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 ; //溫度正負(fù)標(biāo)志
Temperature[ 1 ] = TempDat / 100 + '0' ; //溫度十位值
Temperature[ 2 ] = TempDat % 100 / 10 + '0' ; //溫度個(gè)位值
Temperature[ 3 ] = TempDat % 10 + '0' ;//溫度小數(shù)位
}
如果想獲取當(dāng)前的溫度數(shù)據(jù),在主函數(shù)中調(diào)用v_TemperatureUpdate_f( void )就可以了。溫度數(shù)據(jù)就保存到Temperature中去了。至于如何顯示,就不用多說(shuō)了吧~@_@~
11.JPG (12.23 KB, 下載次數(shù): 124)
下載附件
2013-8-7 03:15 上傳
時(shí)間和溫度一起顯示出來(lái)看看
12.JPG (13.14 KB, 下載次數(shù): 119)
下載附件
2013-8-7 03:15 上傳
OK,至此ds18b20和ds1302的應(yīng)用告一段落。如果有不懂的,記得多看datasheet,多交流。
|
評(píng)分
-
查看全部評(píng)分
|