一、項目介紹
當(dāng)前文章介紹基于51單片機(jī)的熱敏電阻測溫系統(tǒng)的設(shè)計過程,用于實時監(jiān)測環(huán)境溫度,并在溫度超過預(yù)設(shè)閾值時進(jìn)行報警。由于采用的是熱敏電阻測溫技術(shù),無需外置溫度傳感器,使得系統(tǒng)具有結(jié)構(gòu)簡單、成本較低等優(yōu)點。
主控芯片采用STC89C52,具有良好的穩(wěn)定性和可靠性,適應(yīng)于工業(yè)控制等領(lǐng)域的應(yīng)用需要。ADC采集模塊采用PCF8591模塊,可方便地實現(xiàn)對熱敏電阻溫度數(shù)據(jù)的轉(zhuǎn)換和采集,提高了系統(tǒng)的準(zhǔn)確度和實用性。
系統(tǒng)通過4位數(shù)碼管顯示出溫度值,同時通過按鍵設(shè)置溫度上限閥值,當(dāng)溫度超過閥值時,會通過蜂鳴器報警,提醒用戶注意環(huán)境溫度的變化情況。
在項目中主要是用到了熱敏電阻和PCF8591模塊。
(1)熱敏電阻介紹
熱敏電阻(Thermistor)是一種基于材料的電阻元件,其電阻值隨溫度的變化而發(fā)生相應(yīng)的變化。通常情況下,熱敏電阻的電阻值隨溫度升高而降低,反之則隨溫度降低而升高,這種特性被稱為負(fù)溫度系數(shù)(NTC)或正溫度系數(shù)(PTC)。
熱敏電阻的工作原理是基于材料的溫度敏感性質(zhì)。在熱敏電阻中,存在許多導(dǎo)電粒子,當(dāng)溫度升高時,導(dǎo)電粒子與材料中的離子激發(fā)程度增強(qiáng),導(dǎo)致導(dǎo)電粒子的數(shù)量變多,因此電阻值降低;反之,當(dāng)溫度降低時,導(dǎo)電粒子的數(shù)量變少,電阻值增加。
(2)PCF8591
PCF8591是一款4通道、8位模數(shù)轉(zhuǎn)換器(ADC)和1通道、8位數(shù)模轉(zhuǎn)換器(DAC)的集成電路芯片。可以通過I2C總線與微控制器進(jìn)行通信,實現(xiàn)模擬信號的輸入和輸出。
PCF8591的輸入電壓范圍為0V~VCC(通常為5V),可以通過外部電阻進(jìn)行放大或縮小。它還有一個內(nèi)部參考電壓源,可以通過軟件控制選擇使用。
PCF8591的輸出電壓范圍也是0V~VCC,可以用于控制模擬信號的輸出,比如控制電機(jī)的轉(zhuǎn)速、LED的亮度等。
在熱敏電阻測溫系統(tǒng)中,使用PCF8591模塊來采集熱敏電阻的電壓信號,并將其轉(zhuǎn)換為數(shù)字信號,進(jìn)而計算出溫度值。
二、設(shè)計思路
2.1 系統(tǒng)結(jié)構(gòu)
系統(tǒng)采用單片機(jī)作為主控芯片,熱敏電阻用于測量環(huán)境溫度,PCF8591模塊采集熱敏電阻的溫度數(shù)據(jù)并將其轉(zhuǎn)換為正常溫度值,通過數(shù)碼管進(jìn)行顯示。同時,系統(tǒng)設(shè)置上限閥值,當(dāng)溫度超過該值時,系統(tǒng)會通過蜂鳴器報警。
2.2 硬件設(shè)計
(1)主控芯片
本系統(tǒng)采用STC89C52單片機(jī)作為主控芯片,具有強(qiáng)大的計算能力、穩(wěn)定的性能和較低的功耗,支持多種外設(shè)接口,適合于工業(yè)控制等領(lǐng)域的應(yīng)用需求。
(2)溫度傳感器
本系統(tǒng)采用熱敏電阻作為溫度傳感器,其結(jié)構(gòu)簡單、價格便宜,且無需額外的電源供應(yīng),可直接通過PC8591模塊的輸入端口進(jìn)行檢測。
(3)ADC采集模塊
系統(tǒng)采用PCF8591模塊進(jìn)行ADC采集,具有4路模擬輸入通道和一個模擬輸出通道,采樣精度高達(dá)8位,能夠滿足本系統(tǒng)對溫度信號的準(zhǔn)確采集需求。
(4)數(shù)碼管顯示模塊
系統(tǒng)采用4位共陽數(shù)碼管進(jìn)行數(shù)據(jù)顯示,其顯示范圍為-999~+9999,可滿足本系統(tǒng)對溫度數(shù)據(jù)的實時顯示需求。
(5)蜂鳴器報警模塊
系統(tǒng)采用蜂鳴器進(jìn)行報警提示,當(dāng)溫度超過預(yù)設(shè)閾值時,蜂鳴器會發(fā)出持續(xù)聲響,提醒用戶注意環(huán)境溫度的變化情況。
(6)按鍵模塊
按鍵模塊,方便用戶進(jìn)行閥值的設(shè)置和調(diào)整操作。
2.3 軟件設(shè)計
(1)溫度采集與轉(zhuǎn)換
系統(tǒng)使用ADC采集熱敏電阻的溫度信號,并將采集到的數(shù)字信號轉(zhuǎn)換成溫度值進(jìn)行顯示。轉(zhuǎn)換公式為: T=(adc_value/255.0)*330,其中adc_value為AD轉(zhuǎn)換器輸出的數(shù)字值,330是熱敏電阻的參考電阻值。
(2)溫度上限閥值設(shè)置
系統(tǒng)通過按鍵實現(xiàn)溫度上限閥值的設(shè)置和調(diào)整操作,用戶可以根據(jù)自己的需求進(jìn)行設(shè)定。
(3)報警功能設(shè)計
系統(tǒng)在采集到溫度超過預(yù)設(shè)閾值時,蜂鳴器會發(fā)出聲響進(jìn)行提醒,并且LED指示燈會亮起。
2.4 總體流程
(1)初始化各個模塊,包括單片機(jī)、PCF8591、數(shù)碼管、蜂鳴器和按鍵等。
(2)采集熱敏電阻的溫度信號,并將數(shù)字信號轉(zhuǎn)換為溫度值。
(3)將溫度值通過數(shù)碼管進(jìn)行顯示。
(4)檢測當(dāng)前溫度是否超過預(yù)設(shè)閾值,若超過,則觸發(fā)報警并點亮LED指示燈。
(5)用戶可以通過按鍵設(shè)置溫度上限閥值,系統(tǒng)會保存設(shè)置的閾值并進(jìn)行下一次溫度比較。
三、代碼實現(xiàn)
以下是基于51單片機(jī)設(shè)計的熱敏電阻測溫系統(tǒng)的實現(xiàn)代碼。
#include < reg52.h >
#include < intrins.h >
?
typedef unsigned char u8;
typedef unsigned int u16;
?
#define PCF8591_address_write 0x90
#define PCF8591_address_read 0x91
?
sbit SCLK = P1^0; //PCF8591模塊時鐘線
sbit DOUT = P1^1; //PCF8591模塊數(shù)據(jù)線
sbit DIN = P1^2; //PCF8591模塊數(shù)據(jù)線
sbit CS = P1^3; //PCF8591模塊片選線
?
sbit LATCH1 = P3^4; //鎖存器1
sbit LATCH2 = P3^5; //鎖存器2
?
sbit KEY1 = P2^0; //按鍵1
sbit KEY2 = P2^1; //按鍵2
?
sbit BUZZ = P2^3; //蜂鳴器
?
u16 ADC_value; //采集到的ADC值
float temperature; //計算得到的溫度值
?
u8 table[] = { //共陽數(shù)碼管段碼表
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0xbf, //-
};
?
void delay(u16 i){
while(i--);
}
?
void delay_ms(u16 ms){
u16 i, j;
for(i=0; i< ms; i++){
for(j=0; j< 110; j++);
}
}
?
void write_PCF8591(u8 data){
u8 i;
DIN = 1;
SCLK = 0;
CS = 0;
for(i=0; i< 8; i++){
DOUT = (data & 0x80) > > 7;
data < <= 1;
SCLK = 1;
SCLK = 0;
}
CS = 1;
}
?
u16 read_ADC(){
u16 value;
CS = 0;
DIN = 1;
SCLK = 0;
DIN = 0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCLK = 1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
value = P1;
SCLK = 0;
value < <= 8;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCLK = 1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
value |= P1;
CS = 1;
return value;
}
?
void display(u8 addr, u8 dat){
LATCH1 = 0;
LATCH2 = 0;
P0 = addr;
LATCH1 = 1;
LATCH1 = 0;
P0 = table[dat];
LATCH2 = 1;
LATCH2 = 0;
}
?
void main(){
u8 set_value = 40; //溫度上限閥值
u8 temp;
write_PCF8591(0x40);
while(1){
ADC_value = read_ADC