基于18B20的多點(diǎn)溫度顯示系統(tǒng)
范例二 環(huán)境溫度監(jiān)測(cè)系統(tǒng)
一、設(shè)計(jì)要求
環(huán)境溫度監(jiān)測(cè)系統(tǒng)廣泛地用于住宅小區(qū)、樓宇建筑和設(shè)備內(nèi)部等。其主要功能和指標(biāo)如下:
1、可以監(jiān)測(cè)8點(diǎn)環(huán)境溫度信號(hào),可以擴(kuò)充;
2、測(cè)量范圍為0.00℃~99.9℃,可以擴(kuò)充到-55℃~+125℃,精度為±0.5℃;
3、用4位數(shù)碼管進(jìn)行循環(huán)顯示,其中最高位顯示通道提示符A~H,低3位顯示實(shí)際溫度值,每秒切換一個(gè)通道進(jìn)行輪流顯示;
4、 可以隨時(shí)查看指定通道的溫度值(擴(kuò)充功能)。
二、設(shè)計(jì)指導(dǎo)
1、方案選擇
該系統(tǒng)主要由溫度檢測(cè)和數(shù)據(jù)采集兩部分組成。下面列舉兩種實(shí)現(xiàn)方案:
方案一:溫度檢測(cè)可以使用低溫?zé)崤蓟蜚K電阻,數(shù)據(jù)采集部分則使用帶有A/D通道的單片機(jī)。考慮到一般的A/D輸入通道都只能接收大信號(hào),所以還應(yīng)設(shè)計(jì)相應(yīng)的放大電路。此方案的軟件簡(jiǎn)單,但硬件復(fù)雜,且檢測(cè)點(diǎn)數(shù)追加時(shí),成本會(huì)有較大增長(zhǎng)幅度。
方案二:使用單片機(jī)和單總線溫度傳感器構(gòu)成。單總線溫度傳感器可以采用DALLAS公司生產(chǎn)的DS18B20系列,這類溫度傳感器直接輸出數(shù)字信號(hào),且多路溫度傳感器可以掛在1條總線上,共同占用單片機(jī)的1條I/O線即可實(shí)現(xiàn)接口。在提升單片機(jī)I/O線驅(qū)動(dòng)能力的前提下,理論上可以任意擴(kuò)充檢測(cè)的溫度點(diǎn)數(shù)。
比較兩個(gè)方案后可以發(fā)現(xiàn),方案二更適合于用作本系統(tǒng)的實(shí)施方案。盡管方案二不需要A/D,但考慮到系統(tǒng)擴(kuò)充等因素,單片機(jī)可以選用ADuc812,以便于在需要的時(shí)候擴(kuò)充參數(shù)存儲(chǔ)、 D/A輸出、溫度控制等功能。
2、 硬件設(shè)計(jì)
采用方案二的硬件設(shè)計(jì)比較簡(jiǎn)單,系統(tǒng)構(gòu)成如圖1所示,原理圖如圖5所示。單片機(jī)的P0口用作4位數(shù)碼管的段碼線,P3.4~P3.7用作4位數(shù)碼管的位選線(ADuc812的P3有允許8mA的灌電流,可以不加驅(qū)動(dòng))。P2.4用作DS18B20的數(shù)據(jù)輸入/輸出線。
DS18B20的引腳定義和封裝形式之一如圖2所示。DQ為數(shù)字信號(hào)輸入/輸出端;GND為電源地;VDD為外接電源
。
DS18B20的光刻ROM中存有64位序列號(hào),它可以看作是該DS18B20的地址序列碼。64位光刻ROM的排列是:開始8位(28H)是產(chǎn)品類型標(biāo)號(hào),接著的48位是該DS18B20自身的序列號(hào),最后8位是前面56位的循環(huán)冗余校驗(yàn)碼(CRC=X8+X5+X4+1)。光刻ROM的作用是使每一個(gè)DS18B20擁有惟一的地址序列碼,以確保在一根總線上掛接多個(gè)DS18B20。
DS18B20內(nèi)部集成了暫存寄存器(或稱為暫存RAM)和EEPROM兩類存儲(chǔ)器。暫存RAM為9個(gè)字節(jié),其地址分配及其相關(guān)說(shuō)明如表1所示。
單片機(jī)通過(guò)命令實(shí)現(xiàn)對(duì)DS18B20的控制,其支持的主要命令如表2所示。DS18B20的復(fù)位操作、讀寫操作都必須遵從嚴(yán)格的時(shí)序,其復(fù)位時(shí)序、讀寫時(shí)序分別如圖3和圖4所示。關(guān)于DS18B20的詳細(xì)介紹和使用方法可以參考其數(shù)據(jù)手冊(cè)。
表1 DS18B20暫存RAM地址分配及其說(shuō)明
寄存器名稱 地址 說(shuō) 明
溫度低字節(jié) 0 溫度測(cè)量值的低8位,即b7 b6 b5 b4 b3 b2 b1 b0
溫度高字節(jié) 1 溫度測(cè)量值的高3位及符號(hào)位,即S S S S S b10 b9 b8
溫度高限 2 溫度報(bào)警上限,也可以用作自定義字節(jié)
溫度高限 3 溫度報(bào)警下限,也可以用作自定義字節(jié)
配置寄存器 4 格式為0 R1 R0 1 1 1 1 1,R1和R0為00、01、10、11對(duì)應(yīng)的分辨率分別為9、10、11和12位(包括符號(hào)位)
保留 5 未定義
保留 6 未定義
保留 7 未定義
校驗(yàn)碼 8 按X8+X5+X4+1對(duì)前8個(gè)字節(jié)進(jìn)行CRC校驗(yàn)
表2 DS18B20主要命令及其功能說(shuō)明
命令碼 功能說(shuō)明 命令碼 功能說(shuō)明
33H 讀ROM中的64位地址序列碼 BEH 讀9字節(jié)暫存寄存器
55H 只有地址碼匹配的DS18B2才能接受后續(xù)的命令 4EH 寫入溫度上/下限,緊隨其后是2字節(jié)數(shù)據(jù),對(duì)應(yīng)上限和下限值
F0H 鎖定總線上DS18B20的個(gè)數(shù)和識(shí)別其ROM中的64位地址序列碼 48H 將9字節(jié)暫存寄存器的第3和4字節(jié)復(fù)制到EEPROM中
ECH 只有溫度超過(guò)上限或下限的DS18B20才做出響應(yīng) B8H 將EEPROM的內(nèi)容恢復(fù)到暫存寄存器的第3和4字節(jié)
44H 啟動(dòng)DS18B20進(jìn)行溫度轉(zhuǎn)換,結(jié)果存入9字節(jié)的暫存寄存器 B4H 讀供電模式,寄生供電時(shí)DS18B20發(fā)送0,外接電源時(shí)DS18B20發(fā)送1
CCH 忽略地址序列碼,適合單片DS18B20
圖5 系統(tǒng)原理圖
3、 軟件設(shè)計(jì)
1、 軟件模塊的劃分
該系統(tǒng)的控制軟件可以分為單片機(jī)初始化程序、定時(shí)中斷服務(wù)程序和DS18B20接口程序等模塊。單片機(jī)初始化程序由主函數(shù)實(shí)現(xiàn),主要完成定時(shí)器T0、T1的初始化、中斷系統(tǒng)的初始化等功能。定時(shí)器T0中斷函數(shù)每隔5ms執(zhí)行1次,動(dòng)態(tài)顯示1位數(shù)碼管;定時(shí)器T1中斷函數(shù)每隔50ms中斷1次,每中斷20次(1秒)即讀取1路DS18B20的溫度代碼,轉(zhuǎn)換為溫度值,再拆分成單個(gè)數(shù)碼后送入顯示緩沖區(qū)。DS18B20接口程序主要由復(fù)位函數(shù)、讀位函數(shù)、讀字節(jié)函數(shù)、寫位函數(shù)、寫字節(jié)函數(shù)、讀溫度函數(shù)等組成。
2、 參考程序
#include <aduc812.h>
#include <intrins.h>
sbit led0=P3^4; //P3.4~P3.7用作4位LED的位選線
sbit led1=P3^5;
sbit led2=P3^6;
sbit led3=P3^7;
sbit DQ = P2^4; //P2.4用作DS18B20的數(shù)據(jù)線DQ
float data TMP[2]={0,0}; //讀取后的2個(gè)溫度值,將其除以2即可得出實(shí)際溫度;
unsigned char data f[2]={0,0}; //結(jié)果是否為負(fù)溫,0為正溫,1為負(fù)溫。
unsigned char data disp_buf[4]={0,0,0,0}; //4位數(shù)碼管對(duì)應(yīng)的值放入該緩沖區(qū)
unsigned char data dot_position=0;
unsigned char data chno=0; //對(duì)應(yīng)某路DS18B20
//存各路DS18B20的地址序列號(hào),為便于調(diào)試,只設(shè)計(jì)了2路,可以擴(kuò)充到8路或更多
unsigned char code SN[2][8]={ {16, 62,148,60,0,0,0, 247},{16,229,146,60,0,0,0, 87} };
//數(shù)字0~9和通道提示符A~H的段碼
unsigned char code seg_table[ ]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71,0x6f,0x76};
unsigned char code CH[ ]={10,11,12,13,14,15,16,17}; //通道提示符的段碼偏移量
//將0.00~999之間的浮點(diǎn)數(shù)轉(zhuǎn)為單個(gè)數(shù)碼,并送顯示緩沖區(qū)和返回小數(shù)點(diǎn)的位置
void ftochar(float valp)
{
if(valp<10.0)
{
dot_position=1;
valp *=100.0;
}
else if((valp>=10.0)&&(valp<100.0))
{
dot_position=2;
valp *=10.0;
}
else if((valp>=100.0)&&(valp<1000.0)) dot_position=3;
disp_buf[1]=(int)valp/100;
disp_buf[2]=((int)valp%100)/10;
disp_buf[3]=((int)valp%100)%10;
}
//延時(shí)15微妙的函數(shù)
void delay(unsigned char n)
{
do {
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); //_nop_()的頭文件為intrins.h
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
n--;
}while(n);
}
//DS18B20復(fù)位函數(shù),按復(fù)位時(shí)序進(jìn)行設(shè)計(jì)
void ow_reset(void)
{
DQ = 0; // DQ置為低電平
delay(36); // 保持480μs
DQ = 1; // DQ置為高電平
delay(24); // 延時(shí),等DS18B20輸出低電平
}
//DS18B20讀位函數(shù),按讀位時(shí)序進(jìn)行設(shè)計(jì)
unsigned char read_bit(void)
{
unsigned char i;
DQ = 0; // DQ置為低電平
DQ = 1; // DQ置為高電平
for (i=0; i<5; i++); // 延時(shí) 15μs
return(DQ); // 返回DQ 線的電平狀態(tài)
}
// DS18B20寫位函數(shù),按寫位時(shí)序進(jìn)行設(shè)計(jì)
void write_bit(char bitval)
{
DQ = 0; // DQ置為低電平
if(bitval==1) DQ =1; // 如果寫1則DQ置為高電平
delay(6); // 延時(shí)以維持電平狀態(tài)
DQ = 1; // DQ置為高電平
}
// 從DS18B20讀取字節(jié)的函數(shù)
unsigned char read_byte(void)
{
unsigned char i;
unsigned char value = 0;
for (i=0;i<8;i++)
{
if(read_bit()) value|=0x01<<i; //調(diào)用讀位函數(shù),讀出的8個(gè)位移位成1個(gè)字節(jié)
delay(11); //延時(shí)以讀余下的位
}
return(value);
}
//寫字節(jié)到DS18B20的函數(shù)
void write_byte(char val)
{
unsigned char i;
unsigned char temp;
for (i=0; i<8; i++) //每次寫1位,1個(gè)字節(jié)分8次完成
{
temp = val>>i;
temp &= 0x01;
write_bit(temp); //調(diào)用寫位函數(shù)
}
delay(10); //延時(shí)
}
// 從DS18B20讀物溫度代碼
void read_temp ()
{
unsigned char i,j;
unsigned char a,b;
int mr;
for(j=0;j<2;j++) //為便于調(diào)試,僅以2路為例,改循環(huán)次數(shù)即可擴(kuò)充到8路或更多,
{
ow_reset(); //調(diào)用復(fù)位函數(shù)
delay(20);
write_byte (0x55); //發(fā)送ROM匹配命令
for(i=0;i<8;i++)
{
write_byte(SN[j][i]); //發(fā)送64位序列號(hào)
}
write_byte (0xbe); //發(fā)送讀取暫存寄存器的命令
a = read_byte(); //連續(xù)讀取兩位溫度,余下數(shù)據(jù)沒(méi)有讀,實(shí)際使用時(shí)應(yīng)讀出所有數(shù)
b = read_byte(); //據(jù),并進(jìn)行校驗(yàn),以提高可靠性
mr=b*256+a;
if((mr&0xf800)!=0) mr=-mr+1;
TMP[j]=mr*0.5;
}
}
//定時(shí)器T0中斷函數(shù),每中斷1次,顯示1位數(shù)碼管
void Time_disp(void) interrupt 1
{
static unsigned char dispno=0; //數(shù)碼管位號(hào)
TH0=0xee; //主頻為11.0592,定時(shí)5ms的時(shí)間常數(shù)為EE00H
TL0=0x00;
P3|=0xf0;
P0=seg_table[disp_buf[dispno]]; //查當(dāng)前數(shù)碼管的顯示數(shù)字對(duì)應(yīng)的段碼
if(dispno==dot_position) P0|=0x80; //當(dāng)前位有小數(shù)點(diǎn),則段碼最高位置1
switch(dispno) //根據(jù)當(dāng)前顯示的數(shù)碼管,接通位選線
{
case 0 : led0=0; break;
case 1 : led1=0; break;
case 2 : led2=0; break;
case 3 : led3=0; break;
}
dispno++;
if(dispno==4) dispno=0;
}
//定時(shí)器T1中斷服務(wù)函數(shù),每50ms中斷1次
void Timer1(void) interrupt 3
{
static unsigned int count;
TH1=0x4c; //50ms對(duì)應(yīng)的時(shí)間常數(shù)為4C00H
TL1=0x00;
count++;
if(count>=20) //中斷20次即為1秒
{
count=0;
ftochar(TMP[chno]); //當(dāng)前通道對(duì)應(yīng)的溫度值轉(zhuǎn)換為單個(gè)數(shù)碼送顯示緩沖區(qū)
disp_buf[0]=CH[chno]; //當(dāng)前通道的提示符的段碼偏移量送顯示緩沖區(qū)首地址
chno++;
if(chno= =2) chno=0; //修改此判斷對(duì)應(yīng)的數(shù)值,即可擴(kuò)充到8路或更多
}
}
//主函數(shù)
main( )
{
TMOD=0x11; //定時(shí)器T0和T1按方式1工作
EA=1;
ET0=1;
ET1=1;
TH0=0xee; //5ms對(duì)應(yīng)的時(shí)間常數(shù)
TL0=0x00;
TH1=0x4c; //50ms對(duì)應(yīng)的時(shí)間常數(shù)
TL1=0x00;
TR0=1;
TR1=1;
do {
ow_reset( ); //復(fù)位DS18B20
write_byte(0xcc);
write_byte(0x44); //啟動(dòng)1820
read_temp( ); //調(diào)用讀取溫度的函數(shù),結(jié)果存于TMP[ ]數(shù)組中
}while(1);
}
本網(wǎng)站文章僅供交流學(xué)習(xí) ,不作為商用, 版權(quán)歸屬原作者,部分文章推送時(shí)未能及時(shí)與原作者取得聯(lián)系,若來(lái)源標(biāo)注錯(cuò)誤或侵犯到您的權(quán)益煩請(qǐng)告知,我們將立即刪除.