基于51单片机的温控系统
生活随笔
收集整理的這篇文章主要介紹了
基于51单片机的温控系统
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
基于51單片機的溫控系統
本文是基于STC89C52單片機的溫度控制系統,主要由主控模塊、顯示模塊及外圍電路幾個部分組成。
通過DS18B20檢測外部溫度,通過LCD1602顯示,按鍵可調節上下限。當溫度超過上限或低于下限,蜂鳴器均會報警。當溫度超過上限時,電機會開始工作,模擬風扇,起到降溫作用。LED燈電路模擬家用電燈,由兩個開關對其進行控制。
刪除線格式 該溫控系統可以模擬簡易智能家居系統。
系統硬件設計
整體電路原理圖設計
該系統由51單片機作為主控模塊,通過DS18B20檢測溫度,由LCD1602顯示,并加外圍電路組成。
測溫顯示模塊
蜂鳴器報警及電機模塊
系統軟件設計
單片機IO口定義
sbit beep = P1^7; //定義蜂鳴器IO口sbit LED1 = P1^0; //定義燈IO口 sbit LED2 = P1^1; sbit k1 = P1^2; //定義燈開關IO口 sbit k2 = P1^3;sbit MOTOR = P1^4; //定義電機 sbit BUTTON_RUN = P1^5; //定義電機啟動按鈕 sbit BUTTON_STOP = P1^6; //定義電機關閉按鈕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數據端LCD1602初始化及讀/寫數據
void lcd_init() {uint8 i;RW = 0;lcd_order(0x38); //設置顯示光標功能delay(100);lcd_order(0x0e); //顯示開及光標設置delay(100);lcd_order(0x06); //顯示光標移動設置delay(100);lcd_order(0x01); //顯示清屏delay(100);lcd_order(0x80);for(i=0;i<16;i++)lcd_data(hodometer[i]); }void write_1602(uint8 add,uint8 daa) {lcd_order(0x80+add);lcd_data(0x30+daa/10);lcd_data(0x30+daa%10); }void lcd_order(uint8 date) //LCD1602寫指令 {RS = 0; //選擇寫指令RW = 0; //使能初始化P0 = date; //發送指令EN = 1; //開使能delay(100); //延時EN = 0; //關使能 }void lcd_data(uint8 date) //LCD1602寫數據 {RS = 1; //選擇寫數據RW = 0; //使能初始化P0 = date; //發送指令EN = 1; //開使能delay(100); //延時EN = 0; //關使能 }DS18B20初始化及讀/寫數據
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;elsereturn 0; }void DS18B20_write(uint8 date) {uint8 i;DQ = 1;delay(1);for(i=0;i<8;i++) //根據時序將數據從低到高一位一位發送出來{DQ = 0;if(date&0x01) //從低到高取出數據的每位DQ = 1;elseDQ = 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++) //根據時序將數據從低到高一位一位接收{DQ = 0;date >>= 1;DQ = 1;if(DQ)date |= 0x80; //將data的一位置1delay(8);DQ = 1;delay(1);}return date; //返回讀出的數 }void DS18B20_check() {uint8 date1,date2;float ta;if(DS18B20_init()){DS18B20_write(0xcc); //跳過序列號DS18B20_write(0x44); //啟動溫度轉換DS18B20_init(); //復位DS18B20_write(0xcc); //跳過序列號DS18B20_write(0xbe); //啟動讀取溫度date1 = DS18B20_read(); //讀取兩個溫度字節date2 = DS18B20_read();tmp = date2;tmp <<= 8;tmp = tmp|date1;ta = tmp*0.0625;tmp = ta*1000;} }溫度上下限調節函數
void KEY() {uint8 jj;uint8 i = 0;beep = 1;if(K1==0){while(!K1);while(1){lcd_order(0x0f); //開啟光標顯示lcd_order(0x80+5); //光標顯示位置if(K2==0) //判斷加按鍵按下{while(K2==0); //等待按鍵釋放t_h++; //溫度上限加1write_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; }完整程序展示
#include<reg52.h> #include"stdio.h"#define uint unsigned int #define uchar unsigned chartypedef 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; //定義燈開關IO口 sbit k2 = P1^3;sbit MOTOR = P1^4; //定義電機 sbit BUTTON_RUN = P1^5; //定義電機啟動按鈕 sbit BUTTON_STOP = P1^6; //定義電機關閉按鈕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數據端//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寫一個指令 void lcd_data(uint8 date); //向LCD1602寫一個指令 void write_1602(uint8 add,uint8 daa); //寫數據void display(); //顯示溫度uint8 DS18B20_init(); //DS18B20初始化 void DS18B20_write(uint8 date); //向DS18B20中寫入一個數據 uint8 DS18B20_read(); //從DS18B20中讀一個數據并返回 void DS18B20_check(); //啟動DS18B20進行溫度采集,并返回當前溫度void KEY(); //修改報警范圍long tmp = 0; //存儲溫度值 long t_h = 37,t_l = 10; //溫度上限 溫度下限bit tmp_hb = 0; tmp_lb = 0; //溫度上下限調節指示變量void judge(); //判斷報警uint8 hodometer[] = " H:00 L:00 "; uint8 temp[]= " wendu:00.00 "; uint16 ji = 0; uint8 ku = 0; //標志位void main() {init();lcd_init(); //LCD1602初始化DS18B20_init(); //DS18B20初始化DS18B20_write(0xcc); //跳過序列號DS18B20_write(0x44); //啟動溫度轉換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() //判斷是否在報警范圍 {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); //開啟光標顯示lcd_order(0x80+5); //光標顯示位置if(K2==0) //判斷加按鍵按下{while(K2==0); //等待按鍵釋放t_h++; //溫度上限加1write_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) //延時 //{ // 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); //設置顯示光標功能delay(100);lcd_order(0x0e); //顯示開及光標設置delay(100);lcd_order(0x06); //顯示光標移動設置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; //發送指令EN = 1; //開使能delay(100); //延時EN = 0; //關使能 }void lcd_data(uint8 date) //LCD1602寫數據 {RS = 1; //選擇寫數據RW = 0; //使能初始化P0 = date; //發送指令EN = 1; //開使能delay(100); //延時EN = 0; //關使能 }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;elsereturn 0; }void DS18B20_write(uint8 date) {uint8 i;DQ = 1;delay(1);for(i=0;i<8;i++) //根據時序將數據從低到高一位一位發送出來{DQ = 0;if(date&0x01) //從低到高取出數據的每位DQ = 1;elseDQ = 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++) //根據時序將數據從低到高一位一位接收{DQ = 0;date >>= 1;DQ = 1;if(DQ)date |= 0x80; //將data的一位置1delay(8);DQ = 1;delay(1);}return date; //返回讀出的數 }void DS18B20_check() {uint8 date1,date2;float ta;if(DS18B20_init()){DS18B20_write(0xcc); //跳過序列號DS18B20_write(0x44); //啟動溫度轉換DS18B20_init(); //復位DS18B20_write(0xcc); //跳過序列號DS18B20_write(0xbe); //啟動讀取溫度date1 = DS18B20_read(); //讀取兩個溫度字節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() //初始化函數 {BUTTON_RUN = 1; BUTTON_STOP = 1;MOTOR = 0;beep = 0;delay(50); }void motor_run() //打開電機 {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() //關閉電機 {if(BUTTON_STOP==0){delay(10);if(BUTTON_STOP==0){MOTOR = 0;}} }void LED1_SWITCH() //LED1開關 {if(k1==0)LED1 = 0;else if(k1==1)LED1 = 1; }void LED2_SWITCH() //LED2開關 {if(k2==0)LED2 = 0;else if(k2==1)LED2 = 1; }使用Proteus仿真
整體電路PCB設計
51單片機溫控系統程序(電機模擬風扇 可調上下限)Proteus仿真 DS18B20+LCD1602顯示
原理圖+程序+仿真圖
HappyFrankie的公眾號
總結
以上是生活随笔為你收集整理的基于51单片机的温控系统的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NB物联网之天翼物联(2)——profi
- 下一篇: 【NVIDIA Xavier NX入坑记