基于SLH89F5162
单片机的智能电风扇控制系统 第1节 引 言 电风扇曾一度被认为是空调产品冲击下的淘汰品,其实并非如此,市场人士称,家用电风扇并没有随着空调的普及而淡出市场,近两年反而出现了市场销售复苏的态势。其主要原因:一是风扇和空调的降温效果不同——空调有强大的制冷功能,可以快速有效地降低环境温度,但电风扇的风更温和,更加适合老人儿童和体质较弱的人使用;二是电风扇有价格优势,价格低廉而且相对省电,安装和使用都非常简单。尽管电风扇有其市场优势,但传统电风扇还是有许多应当进行改良的地方
.对于夜间温差大的地区,人们在夏夜使用电风扇时可能遇到这样的问题:当凌晨降温的时候电风扇依然在工作,可是人们因为熟睡而无法察觉,既浪费电资源又容易引起感冒,传统的机械定时器虽然能够控制电风扇在工作一定后关闭,但定时范围有限,且无法对温度变化灵活处理。鉴于以上方面的考虑,我们需要设计一种智能电风扇控制系统来解决这些问题。1.1 智能电风扇控制系统概述 传统电风扇是220V交流电供电,电机转速分为几个档位,通过人为调整电机转速达到改变风力大小的目的,亦即,每次风力改变,必然有人参与操作,这样势必带来诸多不便。本设计中的智能电风扇控制系统,是指将电风扇的电机转速作为被控制量,由单片机分析采集到的数字温度信号,再通过可控硅对风扇电机进行调速。从而达到无须人为控制便可自动调整风力大小的效果。1.2 设计任务和主要内容本设计以单片机为核心,通过温度传感器对环境温度进行数据采集实现当温度低于所设置温度时,电风扇将自动关闭,当高于此温度时电风扇又将重新启动。本设计主要内容如下:1、 可由用户通过键盘手动设定阀值。2
、 可以实时监测温度 3、 用户可设定电风扇最低工作温度,当低于该温度时,电风扇自动停转系统主要硬件
威廉希尔官方网站
设计 2.1 总体硬件设计系统总体设计框图如图2-1所示 图
2-1
系统原理框图2.1数字温度传感器模块设计 我采用更为优秀的DS18B20数字温度传感器,它可以直接将模拟温度信号转化为数字信号,降低了威廉希尔官方网站
的复杂程度,提高了威廉希尔官方网站
的运行质量。2.2.1 温度传感器模块组成本模块以DS18B20作为温度传感器,SLH89F5162作为处理器,配以温度显示作为温度控制输出单元。整个系统力求结构简单,功能完善。威廉希尔官方网站
图如图2-2所示。系统工作原理如下:DS18B20进行现场温度测量 2.2.2 DS18B20的温度处理方法DS18B20直接将测量温度值转化为数字量提交给单片机,工作时必须严格遵守单总线器件的工作时序。2.2 电机调速与控制模块设计 图2-3 电机控制原理图 2.3 温度显示与控制模块设计 其原理图如图2-4所示。 2.4
按键控制模块 2.5蜂鸣器模块 第三节 系统软件设计3.1 数字温度传感器模块程序设计
本系统的运行程序采用C语言编写,采用模块化设计,整体程序由主程序和子程序构成。图3-1 数字温度传感器模块程序流程图如图3-1所示,主机控制DS18B20完成温度转换工作必须经过三个步骤:初始化、ROM操作指令、存储器操作指令。单片机所用的系统频率为12MHz。根据DS18B20初始化时序、读时序和写时序分别可编写4个子程序:初始化子程序、写子程序、读子程序、显示子程序。程序内容如下:/*-----------------------------------------------#include"delay.h"#include"18b20.h"/*------------------------------------------------ 18b20初始化------------------------------------------------*/ ***it DQ=P1^1; bit Init_DS18B20(void){ bit dat=0; DQ = 1; DelayUs2x(5); DQ = 0; DelayUs2x(200); DelayUs2x(200); DQ = 1; DelayUs2x(50); dat=DQ; DelayUs2x(25); return dat;} /*------------------------------------------------ 读取一个字节------------------------------------------------*/unsigned char ReadOneChar(void){unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--) { DQ = 0; // 给脉冲信号 dat>>=1; DQ = 1; // 给脉冲信号 if(DQ) dat|=0x80; DelayUs2x(25); } return(dat);}/*------------------------------------------------ 写入一个字节------------------------------------------------*/void WriteOneChar(unsigned char dat){ unsigned char i=0; for (i=8; i>0; i--) { DQ = 0; DQ = dat&0x01; DelayUs2x(25); DQ = 1; dat>>=1; }DelayUs2x(25);} /*------------------------------------------------ 读取温度------------------------------------------------*/unsigned int ReadTemperature(void){unsigned char a=0;unsigned int b=0;unsigned int t=0;Init_DS18B20();WriteOneChar(0xCC); // 跳过读序号列号的操作WriteOneChar(0x44); // 启动温度转换DelayMs(10);Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作 WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度a=ReadOneChar(); //低位b=ReadOneChar(); //高位 b<<=8;t=a+b; return(t);}3.2 按键控制模块程序流程程序设计原理#include " SLH89F5162.h "#include "extern.h"#include "SaveTempreture.h"#include "delay.h" #define LED_ON 1#define LED_OFF 0#define BEEP_ON 0#define BEEP_OFF 1 ***it FuncButton = P2^0;//功能键***it PlusButton = P2^1;//增加+***it MinusButton= P2^2;//减少-***it BEEP = P3^4; void BeepWarn(void){// sta
tic flag=0; // if(flag==0) { // flag = 1; BEEP = !BEEP; DelayMs(70); } }void AdjustIndex(char x){ switch(FuncIndex) { case 1://调报警温度 上 if(x==1) Al
ARMHigh += 16; if(x==-1)AlarmHigh -=16; break; case 2://调报警温度 下 if(x==1) AlarmLow += 16; if(x==-1)AlarmLow -=16; break; }}void KeyScan(void){ if(FuncButton==0)//功能键 { DelayMs(10);//消除抖动 if(FuncButton==0) { while(FuncButton==0); FuncIndex++; if(FuncIndex>2) FuncIndex = 0; } } if(PlusButton==0)//增加+ { DelayMs(10);//消除抖动 if(PlusButton==0) { while(PlusButton==0); AdjustIndex(1); } } if(MinusButton==0)//减少- { DelayMs(10);//消除抖动 if(MinusButton==0) { while(MinusButton==0); AdjustIndex(-1); } } } 3.3显示模块#include
//包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义 #include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义#include "extern.h"#include "delay.h" //#define USE_proteus #define SMG_DATA_PORT P0//ABCDEFGDP#define SMG_DATA_COM P2//COM1 COM2 COM3 COM4#define SMG_NUMBER 4#define SMG_FORM_NUMBER 4 //共阳 // 0 1 2 3 4 5 6 7 8 9 A B C D E F NULL - H Lunsigned char const DisplayCode[] ={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0xBF,0x89,0XC7}; #ifdef USE_PROTEUS unsigned char const DisplayBitCode[]={ 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//unsigned char const DisplayBitCode[]={ 0x01,0x02,0x04,0x08}; #else //实际应用是用PNP管驱动,三极管的B极为0时候,对应位为1 unsigned char const DisplayBitCode[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; #endif ***it D1 = P2^4;//功能键***it D2 = P2^5;//增加+***it D3 = P2^6;//减少-***it D4 = P2^7; void Display(void){ #ifdef USE_PROTEUS SMG_DATA_COM &= 0X0F;//关所有数码管#else SMG_DATA_COM |= 0XF0;//D1=1;D2=1;D3=1;D4=1;//关所有数码管 实际应用是用PNP管驱动,三极管的B极为1时候,对应位为0,对应的那位的段码均熄灭#endif SMG_DATA_PORT=DisplayCode[DisplayBuf[DisplayBitCount]];#ifdef USE_PROTEUS SMG_DATA_COM |=DisplayBitCode[DisplayBitCount];//亮对应的数码管#else SMG_DATA_COM &=DisplayBitCode[DisplayBitCount];//亮对应的数码管 /*if (DisplayBitCount==4){D1=0;D2=1;D3=1;D4=1;} else if(DisplayBitCount==5){D1=1;D2=0;D3=1;D4=1;} else if(DisplayBitCount==6){D1=1;D2=1;D3=0;D4=1;} else if(DisplayBitCount==7){D1=1;D2=1;D3=1;D4=0;}*/#endif DisplayBitCount++; if (DisplayBitCount==(SMG_NUMBER+SMG_FORM_NUMBER)) { DisplayBitCount=0+SMG_FORM_NUMBER; } } void DisplayTempreture(int value){ float temp; unsigned int val; unsigned char ch; ch = 0; val = value; if(val>0x0fff) // { val=~val+1; ch = 0xff;/// } temp=(float)val*0.0625;//如果是*0.625 ,就是放大10倍,保留一位小数 DisplayBuf[3+SMG_FORM_NUMBER] = (int)temp%10; DisplayBuf[2+SMG_FORM_NUMBER] = (int)temp/10%10; DisplayBuf[1+SMG_FORM_NUMBER] = 16;//(int)temp/100; DisplayBuf[0+SMG_FORM_NUMBER] = 16;//不显示 if(ch==0xff) DisplayBuf[1+SMG_FORM_NUMBER] = 17;//'-' if(FuncIndex==1) DisplayBuf[0+SMG_FORM_NUMBER] = 18;//'H' else if(FuncIndex==2) DisplayBuf[0+SMG_FORM_NUMBER] = 19;//'L'} 主程序如下 #include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义#include #include "Init_Time0.h"#include "SMG_Display.h"#include "KeyScan.h"#include "18b20.h" #define LED_ON 0#define LED_OFF 1#define RELAY_OPEN 0#define RELAY_CLOSE 1#define BEEP_ON 0#define BEEP_OFF 1 #define T_HIGH 35 //35度#define T_LOW 10 //10度 ***it UpLed = P3^7;//超过上限温度显示灯***it DownLed = P3^6;//超过下限温度显示灯***it RELAYOUT = P2^3;//继电器输出***it BEEP = P3^4; bit bWarn=0;int AlarmHigh;int AlarmLow;int CurrentTemp;int PreTemp;unsigned char FuncIndex;bit OneSecondArrive; /*------------------------------------------------ 主函数------------------------------------------------*/ void main (void){ FuncIndex = 0; AlarmHigh = T_HIGH*16;//高温报警温度 AlarmLow = T_LOW*16; //低温报警温度 CurrentTemp = 0; Init_Timer0(); //Init_Timer1(); //UART_Init(); CurrentTemp = ReadTemperature(); while(OneSecondArrive==0); OneSecondArrive = 0; CurrentTemp = ReadTemperature(); while(OneSecondArrive==0); OneSecondArrive = 0; PreTemp = CurrentTemp; while (1) //主循环 { if(OneSecondArrive==1)//更新温度显示并处理 { OneSecondArrive=0; CurrentTemp = ReadTemperature(); if((PreTemp-CurrentTemp>=80)||(CurrentTemp-PreTemp>=80))//如果两次温度相差5度,取消此次数据,防止温度数据检测错误 CurrentTemp = PreTemp ; else PreTemp =CurrentTemp; if(CurrentTemp >= AlarmHigh)//上下限报警比较 { DownLed = LED_OFF; UpLed = LED_ON; //高温报警灯亮 RELAYOUT = RELAY_OPEN; bWarn = 1; } else if(CurrentTemp <= AlarmLow) { UpLed = LED_OFF; DownLed = LED_ON; RELAYOUT = RELAY_CLOSE; bWarn = 1; } else { UpLed = LED_OFF; DownLed = LED_OFF; RELAYOUT = RELAY_CLOSE; bWarn = 0; } } KeyScan(); if(FuncIndex==0) DisplayTempreture(CurrentTemp);//显示当前温度 else if(FuncIndex==1) DisplayTempreture(AlarmHigh); //设置温度上限 else if(FuncIndex==2) DisplayTempreture(AlarmLow); //设置温度下限 if(bWarn==1)//超出温度上下限,声音报警 BeepWarn(); else BEEP = BEEP_OFF; }}