一、項(xiàng)目背景
數(shù)字溫度計(jì)是一種用于測(cè)量和顯示環(huán)境溫度的設(shè)備。本文章介紹基于STC89C52主控芯片的數(shù)字溫度計(jì)的設(shè)計(jì)過程和實(shí)現(xiàn)原理。該設(shè)計(jì)采用DS18B20溫度傳感器進(jìn)行溫度采集,使用LCD1602顯示屏進(jìn)行溫度顯示,通過按鍵設(shè)置溫度的上限和下限閥值,并通過蜂鳴器進(jìn)行報(bào)警。
二、系統(tǒng)架構(gòu)
數(shù)字溫度計(jì)的系統(tǒng)架構(gòu)如下所示:
(1)硬件部分:主控芯片STC89C52、DS18B20溫度傳感器、LCD1602顯示屏、按鍵、蜂鳴器;
(2)軟件部分:嵌入式C語言程序。
三、系統(tǒng)功能設(shè)計(jì)
【1】溫度采集:通過DS18B20溫度傳感器采集環(huán)境溫度;
【2】溫度顯示:使用LCD1602顯示屏顯示當(dāng)前環(huán)境溫度;
【3】閾值設(shè)置:通過按鍵設(shè)置溫度的上限和下限閥值;
【4】報(bào)警功能:當(dāng)溫度超出閥值時(shí),蜂鳴器發(fā)出報(bào)警信號(hào)。
四、整體設(shè)計(jì)
4.1 硬件設(shè)計(jì)
【1】主控芯片選擇:STC89C52,具有較好的性能和豐富的外設(shè)資源,適合作為數(shù)字溫度計(jì)的核心處理器;
【2】溫度傳感器:采用DS18B20溫度傳感器,利用其一線通信功能實(shí)現(xiàn)溫度采集;
【3】顯示屏:使用LCD1602顯示屏,通過并口連接到主控芯片,實(shí)時(shí)顯示溫度信息;
【4】按鍵:通過按鍵設(shè)置溫度閥值,包括上限和下限;
【5】蜂鳴器:當(dāng)溫度超出閥值時(shí),蜂鳴器發(fā)出報(bào)警信號(hào)。
4.2 軟件設(shè)計(jì)
【1】GPIO配置:配置主控芯片的GPIO引腳,包括DS18B20溫度傳感器的引腳、LCD1602顯示屏的引腳、按鍵的引腳和蜂鳴器的引腳;
【2】DS18B20通信:利用主控芯片的IO口實(shí)現(xiàn)與DS18B20溫度傳感器的一線通信,獲取溫度數(shù)據(jù);
【3】LCD顯示:通過并口通信協(xié)議,將溫度數(shù)據(jù)發(fā)送給LCD1602顯示屏進(jìn)行顯示;
【4】按鍵檢測(cè):使用外部中斷方式監(jiān)聽按鍵引腳的狀態(tài)變化,當(dāng)按鍵被按下時(shí),進(jìn)入設(shè)置模式,并根據(jù)按鍵次數(shù)調(diào)整溫度閥值;
【5】溫度比較和報(bào)警:在主循環(huán)中,不斷比較當(dāng)前溫度與設(shè)置的閥值,當(dāng)溫度超出閾值時(shí),觸發(fā)蜂鳴器報(bào)警。
五、源代碼
#include <reg52.h>
// 定義IO口
sbit DQ = P2^0;
sbit RS = P2^1;
sbit RW = P2^2;
sbit E = P2^3;
sbit K1 = P2^4;
sbit K2 = P2^5;
sbit Buzzer = P2^6;
// 定義全局變量
unsigned int highTemp = 30; // 溫度上限
unsigned int lowTemp = 20; // 溫度下限
unsigned int currentTemp = 0; // 當(dāng)前溫度
// 延時(shí)函數(shù)
void delay(unsigned int ms) {
unsigned int i, j;
for (i = ms; i > 0; i--)
for (j = 110; j > 0; j--);
}
// DS18B20初始化
bit Init_DS18B20() {
bit presence;
DQ = 1; // 設(shè)置DQ為輸出
delay(1);
DQ = 0; // 主機(jī)拉低DQ線
delay(75);
DQ = 1; // 主機(jī)釋放DQ線
delay(4);
presence = DQ; // 從機(jī)檢測(cè)到的應(yīng)答信號(hào)
delay(20);
return presence;
}
// DS18B20寫字節(jié)
void Write_DS18B20(unsigned char dat) {
unsigned char i;
for (i = 0; i < 8; i++) {
DQ = 0; // 主機(jī)拉低DQ線
_nop_();
DQ = dat & 0x01; // 寫數(shù)據(jù)位
delay(5);
DQ = 1; // 主機(jī)釋放DQ線
dat >>= 1;
}
}
// DS18B20讀字節(jié)
unsigned char Read_DS18B20() {
unsigned char i, dat;
for (i = 0; i < 8; i++) {
DQ = 0; // 主機(jī)拉低DQ線
_nop_();
DQ = 1; // 主機(jī)釋放DQ線
_nop_();
dat >>= 1;
if (DQ)
dat |= 0x80; // 讀數(shù)據(jù)位
delay(5);
}
return dat;
}
// 讀取溫度
unsigned char ReadTemperature() {
unsigned char temp_h, temp_l;
Init_DS18B20();
Write_DS18B20(0xCC); // 跳過ROM指令
Write_DS18B20(0xBE); // 發(fā)送讀溫度命令
temp_l = Read_DS18B20(); // 讀低字節(jié)
temp_h = Read_DS18B20(); // 讀高字節(jié)
currentTemp = temp_h;
return temp_l;
}
// LCD初始化
void LCD_Init() {
delay(15);
Write_Command(0x38); // 設(shè)置8位數(shù)據(jù)總線,2行顯示,5x7點(diǎn)陣
Write_Command(0x0C); // 顯示器打開,光標(biāo)關(guān)閉
Write_Command(0x06); // 光標(biāo)右移,顯示器不移動(dòng)
Write_Command(0x01); // 顯示清屏
}
// LCD寫命令
void Write_Command(unsigned char com) {
RS = 0;
RW = 0;
E = 1;
P0 = com;
delay(1);
E = 0;
}
// LCD寫數(shù)據(jù)
void Write_Data(unsigned char dat) {
RS = 1;
RW = 0;
E = 1;
P0 = dat;
delay(1);
E = 0;
}
// LCD顯示溫度
void Display_Temperature(unsigned char temp) {
unsigned char temp_str[5];
temp_str[0] = temp / 10 + '0';
temp_str[1] = temp % 10 + '0';
temp_str[2] = '.';
temp_str[3] = ReadTemperature() / 10 + '0';
temp_str[4] = ReadTemperature() % 10 + '0';
Write_Command(0x80); // 第一行第一個(gè)字符位置
Write_String("Temp: ");
Write_Command(0x86); // 第一行第七個(gè)字符位置
Write_String(temp_str);
Write_Command(0xC0); // 第二行第一個(gè)字符位置
Write_String("High: ");
Write_Command(0xC6); // 第二行第七個(gè)字符位置
Write_Char(highTemp / 10 + '0');
Write_Char(highTemp % 10 + '0');
Write_Command(0xCB); // 第二行第十個(gè)字符位置
Write_String("Low: ");
Write_Command(0xCF); // 第二行第十四個(gè)字符位置
Write_Char(lowTemp / 10 + '0');
Write_Char(lowTemp % 10 + '0');
}
// LCD寫字符串
void Write_String(unsigned char *str) {
while (*str != '?') {
Write_Data(*str);
str++;
}
}
// LCD寫字符
void Write_Char(unsigned char dat) {
Write_Data(dat);
}
// 蜂鳴器報(bào)警
void Alarm() {
Buzzer = 0;
delay(500);
Buzzer = 1;
delay(500);
}
// 按鍵掃描
void Key_Scan() {
if (K1 == 0) { // K1按下,設(shè)置高溫
delay(5);
if (K1 == 0) {
highTemp++;
Write_Command(0xCB); // 第二行第十個(gè)字符位置
Write_Char(highTemp / 10 + '0');
Write_Char(highTemp % 10 + '0');
while (!K1);
}
}
if (K2 == 0) { // K2按下,設(shè)置低溫
delay(5);
if (K2 == 0) {
lowTemp--;
Write_Command(0xCF); // 第二行第十四個(gè)字符位置
Write_Char(lowTemp / 10 + '0');
Write_Char(lowTemp % 10 + '0');
while (!K2);
}
}
}
// 主函數(shù)
void main() {
LCD_Init();
while (1) {
ReadTemperature(); // 讀取溫度
Display_Temperature(currentTemp); // 顯示溫度
if (currentTemp > highTemp || currentTemp < lowTemp) { // 溫度超出閾值,觸發(fā)報(bào)警
Alarm();
}
Key_Scan(); // 按鍵掃描
}
}
代碼最開始定義了一些用于控制硬件的IO口,如DQ用于連接溫度傳感器、RS、RW、E用于連接LCD顯示屏、K1、K2用于連接按鍵、Buzzer用于連接蜂鳴器。接下來定義了一些全局變量,包括高溫上限、低溫下限以及當(dāng)前溫度。然后是一些函數(shù)的定義和實(shí)現(xiàn),包括延時(shí)函數(shù)、DS18B20溫度傳感器初始化函數(shù)、寫字節(jié)函數(shù)、讀字節(jié)函數(shù)等。
ReadTemperature() 函數(shù)用于讀取溫度傳感器的溫度值,并將其保存到 currentTemp 變量中。
LCD_Init() 函數(shù)用于初始化LCD顯示屏。
Write_Command() 和 Write_Data() 函數(shù)用于向LCD顯示屏寫入命令和數(shù)據(jù)。
Display_Temperature() 函數(shù)用于在LCD顯示屏上顯示當(dāng)前溫度、高溫上限和低溫下限。
Alarm() 函數(shù)用于觸發(fā)蜂鳴器報(bào)警。
Key_Scan() 函數(shù)用于掃描按鍵狀態(tài),根據(jù)按鍵狀態(tài)來修改高溫上限和低溫下限。
主函數(shù) main() 中的邏輯:
- 調(diào)用 LCD_Init() 初始化LCD顯示屏。
- 進(jìn)入一個(gè)無限循環(huán),不斷讀取當(dāng)前溫度并顯示在LCD上。
- 如果當(dāng)前溫度超過設(shè)定的高溫上限或低于設(shè)定的低溫下限,就觸發(fā)報(bào)警。
- 通過按鍵掃描函數(shù)來修改高溫上限和低溫下限。
六、總結(jié)
本文章詳細(xì)介紹了基于STC89C52主控芯片的數(shù)字溫度計(jì)的設(shè)計(jì)過程和實(shí)現(xiàn)原理。通過集成DS18B20溫度傳感器、LCD1602顯示屏、按鍵和蜂鳴器等功能,實(shí)現(xiàn)了溫度的采集、顯示和報(bào)警功能。通過按鍵設(shè)置溫度的上限和下限閥值,用戶可以根據(jù)需要進(jìn)行調(diào)整,并在超出閥值時(shí)觸發(fā)報(bào)警,提醒用戶注意環(huán)境溫度的變化。該設(shè)計(jì)可以廣泛應(yīng)用于家庭、辦公室和實(shí)驗(yàn)室等場(chǎng)景,為用戶提供了方便、準(zhǔn)確和實(shí)用的溫度監(jiān)測(cè)工具。