总体设计
本设计是使用AT89C51单片机为核心制作的一个模拟温控电扇的系统。通过DS18B20温度传感器来实现温度的调节,使用四位一体数码管来显示电扇的挡位以及当前温度,通过proteus中的直流电机(motor)来模拟风扇的转动,然后通过按键来实现挡位温度区间的调节,当DS18B20温度传感器显示数值在这一挡位温度区间数码管便显示这一挡位,同时直流点击的转速与挡位有关,这个系统我设置了三个挡位,第一个挡位是停止运行,第二个是一档转速,第二个是二档转速,但如果温度超过某一温度值都将会产生报警,这时led灯闪烁且蜂鸣器工作,当温度降下去后,将自动取消报警。
按键电路模块
通过按键实现挡位温度区间的设置,点击key1按键可以设置最高的温度值(hight),点击key2按键温度值加5,点击key3按键温度值减5;如果再次点击key1按键可以设置最低的温度值(low),点击key2按键温度值加5,点击key3按键温度值减5;若温度低于low的值风扇则停止运行,若温度在low~hight值之间则为一档,若温度高于hight的值则为二档,当高于某一温度值后进触发报警系统。
数码管显示模块
使用的是4个八段共阴极数码管,该数码管是将八段发光二极管封装在一起且二极管的阴极连接在一起
报警电路模块
通过led闪烁以及蜂鸣器来模拟报警系统,例如当温度高于45°时,led便会不停闪烁蜂鸣器报警,但当温度低于45°后便会自动取消报警。
源程序:
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit led=P1^0;
sbit beep=P1^1;
sbit dj=P3^0;//电机控制接口
sbit DQ=P3^1;//温度传感器接口sbit key1=P3^2;//设置温度
sbit key2=P3^3;//温度加
sbit key3=P3^4;//温度减
sbit w1=P2^0;
sbit w2=P2^1;
sbit w3=P2^2;
sbit w4=P2^3; //数码管的四个位
//共阴数码管段选
uchar table[22]=
{0x3F,0x06,0x5B,0x4F,0x66,
0x6D,0x7D,0x07,0x7F,0x6F,
0x77,0x7C,0x39,0x5E,0x79,0x71,
0x40,0x38,0x76,0x00,0xff,0x37};//'-',L,H,灭,全亮,n 16-21
uint wen_du; //温度变量
uint hight,low; //对比温度暂存变量
uchar dangwei;//档位显示
uchar flag;
uchar d1,d2,d3;//显示数据暂存变量
void delay(uint ms) //延时函数,大约延时25us
{uchar x;for(ms;ms>0;ms--){for(x=10;x>0;x--);}
}
//ds18b20延迟子函数
void delay_18B20(uint i)
{while(i--);
}
//ds18b20初始化
void Init_DS18B20()
{uchar x=0;DQ=1; //DQ复位delay_18B20(8); //稍做延时DQ=0; //单片机将DQ拉低delay_18B20(80); //精确延时 大于 480usDQ=1; //拉高总线delay_18B20(14);x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败delay_18B20(20);
}uchar Read()
{uchar i=0;uchar dat=0;for (i=8;i>0;i--){DQ=0; // 给脉冲信号dat>>=1;DQ=1; // 给脉冲信号if(DQ)dat|=0x80;delay_18B20(4);}return(dat);
}void Write(uchar dat)
{uchar i=0;for (i=8;i>0;i--){DQ=0;DQ=dat&0x01;delay_18B20(5);DQ=1;dat>>=1;}
}
//读取ds18b20当前温度
void ReadTemperature()
{uchar a=0;uchar b=0;uchar t=0;Init_DS18B20();Write(0xCC); // 跳过读序号列号的操作Write(0x44); // 启动温度转换delay_18B20(100); Init_DS18B20();Write(0xCC); //跳过读序号列号的操作Write(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度delay_18B20(100);a=Read(); //读取温度值低位b=Read(); //读取温度值高位wen_du=((b*256+a)>>4); //当前采集温度值除16得实际温度值}
void display()//显示温度
{w1=0;P0=table[d1];delay(10); //第1位P0=0x00;w1=1;delay(1);w2=0;P0=table[16];delay(10);//第2位P0=0x00;w2=1;delay(1);w3=0;P0=table[d2]; delay(10);//第3位P0=0x00;w3=1;delay(1);w4=0;P0=table[d3];delay(10);//第4位P0=0x00;w4=1;delay(1);
}
void zi_keyscan()//按键扫描函数
{if(key1==0) {delay(30); if(key1==0)flag=1; while(key1==0);//松手检测 }while(flag==1) {d1=18;d2=hight/10;d3=hight%10; display(); if(key1==0) {delay(30); if(key1==0)flag=2; while(key1==0);}if(key2==0) {delay(30); if(key2==0) {hight+=5; if(hight>=100)hight=100; }while(key2==0);}if(key3==0) {delay(30); if(key3==0) {hight-=5; if(hight<=10)hight=10; }while(key3==0);} }while(flag==2) {d1=17;d2=low/10;d3=low%10; display(); if(key1==0){delay(30);if(key1==0)flag=0;while(key1==0);}if(key2==0){delay(30);if(key2==0){low+=5;if(low>=95)low=95; }while(key2==0);}if(key3==0){delay(30);if(key3==0){low-=5;if(low<=0)low=0; }while(key3==0);} }
}
void zi_dong()//自动温控模式
{uchar i;d1=dangwei;d2=wen_du/10;d3=wen_du%10; zi_keyscan();display(); if(wen_du<low){dj=0;dangwei=0;}if((wen_du>=low)&&(wen_du<=hight)){dangwei=1; for(i=0;i<3;i++){dj=0;display();zi_keyscan();} for(i=0;i<6;i++){dj=1;display();zi_keyscan();} }if(wen_du>hight){ dj=1;dangwei=2; }}
void main() //主函数
{uchar j;dj=0; hight=30;low=20; for(j=0;j<80;j++) ReadTemperature();while(1) { ReadTemperature(); zi_dong();if(wen_du>=45){led=~led;beep=~beep;} else{led=0;beep=0;}}
}
Proteus仿真图
总结:这个设计借鉴了不少大佬的代码,由于对于直流电机运转的不理解,所以去看了许多大佬的案例才理解,对于这个设计期间想过增加更多的功能,想到用8255扩展端口来实现更多的功能,但是8255好像端口不可以定义,所以许多想法都没法添加,但虽然这个设计不太复杂,但是DS18B20这个温度传感器还是比较难理解的,对于大佬来说可能这个很简单,对于刚接触单片机的我们还是可以借鉴学习下的。🙄🙄🙄🙄🙄🙄