|
本文是基于STC89C52單片機(jī)的溫度控制系統(tǒng),主要由主控模塊、顯示模塊及外圍電路幾個(gè)部分組成。
通過DS18B20檢測(cè)外部溫度,通過LCD1602顯示,按鍵可調(diào)節(jié)上下限。當(dāng)溫度超過上限或低于下限,蜂鳴器均會(huì)報(bào)警。當(dāng)溫度超過上限時(shí),電機(jī)會(huì)開始工作,模擬風(fēng)扇,起到降溫作用。LED燈電路模擬家用電燈,由兩個(gè)開關(guān)對(duì)其進(jìn)行控制。
該溫控系統(tǒng)可以模擬簡(jiǎn)易智能家居系統(tǒng),希望可以給各位有所幫助,本人能力有限,做的較為簡(jiǎn)單,如果做的不好,或者存在錯(cuò)誤,還請(qǐng)指出,謝謝啦。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
整體電路仿真
溫度未超上下限,電機(jī)不工作,蜂鳴器不報(bào)警
Altium Designer畫的原理圖和PCB圖如下:(51hei附件中可下載工程文件)
溫度超過上限,電機(jī)工作,蜂鳴器報(bào)警(視頻無法上傳,見諒)
單片機(jī)代碼如下:
- #include<reg52.h>
- #include"stdio.h"
- #define uint unsigned int
- #define uchar unsigned char
- typedef unsigned char uint8;
- typedef unsigned int uint16;
- sbit beep = P1^7; //定義蜂鳴器IO口
- sbit LED1 = P1^0; //定義燈IO口
- sbit LED2 = P1^1;
- sbit k1 = P1^2; //定義燈開關(guān)IO口
- sbit k2 = P1^3;
- sbit MOTOR = P1^4; //定義電機(jī)
- sbit BUTTON_RUN = P1^5; //定義電機(jī)啟動(dòng)按鈕
- sbit BUTTON_STOP = P1^6; //定義電機(jī)關(guān)閉按鈕
- sbit RS = P2^7;
- sbit RW = P2^6;
- sbit EN = P2^5;
- sbit K1 = P2^0;
- sbit K2 = P2^1; //加
- sbit K3 = P2^2; //減
- sbit DQ = P2^3; //DS18B20數(shù)據(jù)端
- //void delay(uint xms);
- void motor_run();
- void motor_stop();
- void LED1_SWITCH();
- void LED2_SWITCH();
- void init();
- void delay(uint16 time);
- void lcd_init(); //LCD1602初始化
- void lcd_order(uint8 date); //向LCD1602寫一個(gè)指令
- void lcd_data(uint8 date); //向LCD1602寫一個(gè)指令
- void write_1602(uint8 add,uint8 daa); //寫數(shù)據(jù)
- void display(); //顯示溫度
- uint8 DS18B20_init(); //DS18B20初始化
- void DS18B20_write(uint8 date); //向DS18B20中寫入一個(gè)數(shù)據(jù)
- uint8 DS18B20_read(); //從DS18B20中讀一個(gè)數(shù)據(jù)并返回
- void DS18B20_check(); //啟動(dòng)DS18B20進(jìn)行溫度采集,并返回當(dāng)前溫度
- void KEY(); //修改報(bào)警范圍
- long tmp = 0; //存儲(chǔ)溫度值
- long t_h = 37,t_l = 10; //溫度上限 溫度下限
- bit tmp_hb = 0; tmp_lb = 0; //溫度上下限調(diào)節(jié)指示變量
- void judge(); //判斷報(bào)警
- uint8 hodometer[] = " H:00 L:00 ";
- uint8 temp[]= " wendu:00.00 ";
- uint16 ji = 0;
- uint8 ku = 0; //標(biāo)志位
- void main()
- {
- init();
- lcd_init(); //LCD1602初始化
- DS18B20_init(); //DS18B20初始化
- DS18B20_write(0xcc); //跳過序列號(hào)
- DS18B20_write(0x44); //啟動(dòng)溫度轉(zhuǎn)換
- write_1602(4,t_h);
- write_1602(12,t_l);
- while(1)
- {
- LED1_SWITCH();
- LED2_SWITCH();
- motor_run();
- motor_stop();
- DS18B20_check(); //從DS18B20中讀取溫度
- display();
- KEY();
- judge();
- }
- }
- void write_1602(uint8 add,uint8 daa)
- {
- lcd_order(0x80+add);
- lcd_data(0x30+daa/10);
- lcd_data(0x30+daa%10);
- }
- void judge() //判斷是否在報(bào)警范圍
- {
- if(tmp<(t_l*1000)||tmp>(t_h*1000)&&t_l>=0)
- {
- beep = 0;
- delay(10);
- MOTOR = 1;
- }
- else if(t_l<0&&tmp>(t_h*1000))
- {
- beep = 1;
- MOTOR = 0;
- }
- else
- {
- beep = 1;
- MOTOR = 0;
- }
- }
- void KEY()
- {
- uint8 jj;
- uint8 i = 0;
- beep = 1;
- if(K1==0)
- {
- while(!K1);
- while(1)
- {
- lcd_order(0x0f); //開啟光標(biāo)顯示
- lcd_order(0x80+5); //光標(biāo)顯示位置
- if(K2==0) //判斷加按鍵按下
- {
- while(K2==0); //等待按鍵釋放
- t_h++; //溫度上限加1
- write_1602(4,t_h); //顯示溫度上限
- }
- if(K3==0) //判斷減按鍵按下
- {
- while(K3==0); //等待按鍵釋放
- if(t_h>t_l) //判斷溫度上限大于溫度下限
- t_h--;
- write_1602(4,t_h); //顯示溫度上限
- }
- if(K1==0)
- {
- while(K1==0);
- while(1)
- {
- lcd_order(0x0f);
- lcd_order(0x80+13);
- if(K2==0)
- {
- while(K2==0);
- if(t_l<t_h&&t_l>=0)
- {
- lcd_order(0x80+11);
- lcd_data(' ');
- t_l++;
- write_1602(12,t_l);
- }
- else
- {
- t_l++;
- jj =~ t_l;
- write_1602(12,jj);
- }
- }
- if(K3==0)
- {
- while(K3==0);
- if(t_l>(-50))
- {
- t_l--;
- if(t_l<0)
- jj =~ t_l;
- }
- if(t_l>=0)
- {
- lcd_order(0x80+11);
- lcd_data(' ');
- write_1602(12,t_l);
- }
- if(t_l<0)
- {
- write_1602(12,jj);
- lcd_order(0x80+11);
- lcd_data('-');
- }
- }
- if(K1==0)
- {
- while(K1==0);
- goto loop;
- }
- }
- }
- }
- }
- loop:beep = 1;
- }
- //void delay(uint xms) //延時(shí)
- //{
- // uint i,j;
- // for(i=xms;i>0;i--)
- // for(j=110;j>0;j--) ;
- //}
- void delay(uint16 time)
- {
- while(time--);
- }
- void lcd_init()
- {
- uint8 i;
- RW = 0;
- lcd_order(0x38); //設(shè)置顯示光標(biāo)功能
- delay(100);
- lcd_order(0x0e); //顯示開及光標(biāo)設(shè)置
- delay(100);
- lcd_order(0x06); //顯示光標(biāo)移動(dòng)設(shè)置
- delay(100);
- lcd_order(0x01); //顯示清屏
- delay(100);
- lcd_order(0x80);
- for(i=0;i<16;i++)
- lcd_data(hodometer[i]);
- }
- void lcd_order(uint8 date) //LCD1602寫指令
- {
- RS = 0; //選擇寫指令
- RW = 0; //使能初始化
- P0 = date; //發(fā)送指令
- EN = 1; //開使能
- delay(100); //延時(shí)
- EN = 0; //關(guān)使能
- }
- void lcd_data(uint8 date) //LCD1602寫數(shù)據(jù)
- {
- RS = 1; //選擇寫數(shù)據(jù)
- RW = 0; //使能初始化
- P0 = date; //發(fā)送指令
- EN = 1; //開使能
- delay(100); //延時(shí)
- EN = 0; //關(guān)使能
- }
- uint8 DS18B20_init()
- {
- uint8 ans;
- DQ = 1;
- delay(1);
- DQ = 0;
- delay(100);
- DQ = 1;
- delay(6);
- ans = DQ;
- delay(100);
- if(!ans)
- return 1;
- else
- return 0;
- }
- void DS18B20_write(uint8 date)
- {
- uint8 i;
- DQ = 1;
- delay(1);
- for(i=0;i<8;i++) //根據(jù)時(shí)序?qū)?shù)據(jù)從低到高一位一位發(fā)送出來
- {
- DQ = 0;
- if(date&0x01) //從低到高取出數(shù)據(jù)的每位
- DQ = 1;
- else
- DQ = 0;
- delay(10);
- DQ = 1;
- date >>= 1;
- delay(1);
- }
- }
- uint8 DS18B20_read()
- {
- uint8 i,date = 0;
- DQ = 1; //釋放總線
- delay(1);
- for(i=0;i<8;i++) //根據(jù)時(shí)序?qū)?shù)據(jù)從低到高一位一位接收
- {
- DQ = 0;
- date >>= 1;
- DQ = 1;
- if(DQ)
- date |= 0x80; //將data的一位置1
- delay(8);
- DQ = 1;
- delay(1);
- }
- return date; //返回讀出的數(shù)
- }
- void DS18B20_check()
- {
- uint8 date1,date2;
- float ta;
- if(DS18B20_init())
- {
- DS18B20_write(0xcc); //跳過序列號(hào)
- DS18B20_write(0x44); //啟動(dòng)溫度轉(zhuǎn)換
- DS18B20_init(); //復(fù)位
- DS18B20_write(0xcc); //跳過序列號(hào)
- DS18B20_write(0xbe); //啟動(dòng)讀取溫度
- date1 = DS18B20_read(); //讀取兩個(gè)溫度字節(jié)
- date2 = DS18B20_read();
- tmp = date2;
- tmp <<= 8;
- tmp = tmp|date1;
- ta = tmp*0.0625;
- tmp = ta*1000;
- }
- }
- void display()
- {
- uint8 i;
- temp[8] = 0x30+tmp/10000;
- temp[9] = 0x30+tmp/1000%10;
- temp[11] = 0x30+tmp/100%10;
- temp[12] = 0x30+tmp/10%10;
- temp[13] = 0x30+tmp%10;
- lcd_order(0x80+0x40);
- for(i=0;i<16;i++)
- lcd_data(temp[i]) ;
- }
- void init() //初始化函數(shù)
- {
- BUTTON_RUN = 1;
- BUTTON_STOP = 1;
- MOTOR = 0;
- beep = 0;
- delay(50);
- }
- void motor_run() //打開電機(jī)
- {
- if(BUTTON_RUN==0)
- {
- delay(10);
- if(BUTTON_RUN==0)
- {
- while(1)
- {
- MOTOR = 1;
- if(BUTTON_STOP==0)
- {
- delay(5);
- if(BUTTON_STOP==0)
- {
- break;
- }
- }
- }
- }
- }
- }
- void motor_stop() //關(guān)閉電機(jī)
- {
- if(BUTTON_STOP==0)
- {
- delay(10);
- if(BUTTON_STOP==0)
- {
- MOTOR = 0;
- }
- }
- }
- void LED1_SWITCH() //LED1開關(guān)
- {
- if(k1==0)
- LED1 = 0;
- else if(k1==1)
- LED1 = 1;
- }
- void LED2_SWITCH() //LED2開關(guān)
- {
- if(k2==0)
- LED2 = 0;
- else if(k2==1)
- LED2 = 1;
- }
復(fù)制代碼
如果寫的不好,還請(qǐng)見諒
文件里的原理圖可能并不完全適配,還請(qǐng)各位仔細(xì)檢查,謝謝啦
我的公眾號(hào):HFrankie
我同樣會(huì)在上面發(fā)布單片機(jī)相關(guān)內(nèi)容,還請(qǐng)各位朋友、大佬,可以關(guān)注關(guān)注,如果我寫的有問題,或者有什么建議都可以提醒我,謝謝啦
Keil代碼+原理圖PCB+Proteus仿真下載:
TemperatureControl.7z
(1009.76 KB, 下載次數(shù): 688)
2021-12-22 20:25 上傳
點(diǎn)擊文件名下載附件
|
評(píng)分
-
查看全部評(píng)分
|