由温度决定风扇转速

温度控制风扇转速

代码中LCD和18B20完全是照搬的百度上网友的代码,但不记得具体搬的是哪里了。…对不起原作者。

DIY的2.1音响,由于作的功放箱子体积有限,芯片温度较高,底噪时能到60度,须要加风扇,心太大,买的风扇转速太高,太吵,为了使温度受控而风扇不要太吵,百度到处找,终于搞出这个小程序;

使用芯片: STC89C52RC
显示硬件: LCD1602;
温度硬件:18B20
风扇硬件: 台达,12V0.4A 4线的,即±两线,方波输出线,PWM转速控制线;

运行效果:PWM频率81Hz,PWM Duty 宽度可调,风扇转速随便温度上升而上升,当然风扇噪声也跟着变大,全速的时候,即Duty为10的时候,占空比用示波器看是90%样子。应选用不那么暴力的风扇。12V0.4A左右即可。电流越大,噪声越大。

程序代码如下,可直接使用。

#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long uint32;

sfr P4 = 0xe8;
sbit led1 = P4^0;
sbit led2 = P3^7;
sbit rs=P2^4;
sbit rw=P2^5;
sbit e=P2^6;
sbit dq=P1^0;
sbit pwm=P1^2;

uint8 d[16]=" Internal Temp  ";
uint8 num[10]="0123456789";
uint8 a,c,temp;

char time,RDD,speed;

void delay(uint16 i)
{
	while(i--);
}
void wrc(uint8 c)
{
	delay(1000);
	rs=0;
	rw=0;
	e=0;
	P0=c;
	e=1;
	delay(10);
	e=0;
}
void wrd(uint8 dat)
{
	delay(1000);
	rs=1;
	rw=0;
	e=0;
	P0=dat;
	e=1;
	delay(10);
	e=0;
	rs=0;
}
void lcdinit()
{
	delay(10);
	wrc(0x38);
	wrc(0x38);
	wrc(0x38);
	wrc(0x06);
	wrc(0x0c);
	wrc(0x01);
}
void ds18b20init()		//18b20的初始化
{
	dq=1;
	delay(1);
	dq=0;
	delay(80);
	dq=1;
	delay(5);
	dq=0;
	delay(20);
	dq=1;
	delay(35);
}
void ds18b20wr(uint8 dat)	  //18b20写数据
{
	uint8 i;
	for(i=0;i<8;i++)
	{
		dq=0;
		dq=dat&0x01;
		dat>>=1;
		delay(8);//在时序上只有这一块对时序要求最准确,他的时间必须大于15us
		dq=1;
		delay(1);
	}	
}
uint8 ds18b20rd()		  //18b20读数据
{
	uint8 value,i;
	for(i=0;i<8;i++)	
	{
		dq=0;
		value>>=1;
		dq=1;
		if(dq==1)value|=0x80;
		delay(8);//在这一块也对时间要求特别准确,整段程序必须大于60us		
	}
	return value;
}
uint8 readtemp()			  //读取温度内需要复位的
{
	uint8 b;
	ds18b20init();		//初始化
	ds18b20wr(0xcc);   //发送忽略ROM指令
	ds18b20wr(0x44);   //发送温度转换指令
	delay(100);
	ds18b20init();	   //初始化
	ds18b20wr(0xcc);   //发送忽略ROM指令
	ds18b20wr(0xbe);   //发读暂存器指令
	a=ds18b20rd();	 //温度的低八位
	b=ds18b20rd();	 //温度的高八位
	b<<=4;			 //ssss s***;s为标志位s=0表示温度值为正数,s=1温度值为负数
	c=b&0x80;		//温度正负标志位确认
	b+=(a&0xf0)>>4;
	a=a&0x0f;	  //温度的小数部分
	return b;
}
void display()
{
	uint16 i,k;
	float dio;
	dio=a*0.0625;
	k=dio*10000;//取小数点后两位有效数字
	wrc(0x80);//+0x00);
	for(i=0;i<16;i++)
	{
		wrd(d[i]);
	}
	wrc(0x80+0x43);
	if(c==0x80)	//读取到负温度即为补码,要将其转换成源码
	{
		wrd('-');
		temp=temp-1;
		temp=(~temp)|0x80;//负数的补码即为反码+1;而负数的反码为其源码取反,除了符号位;正数的补码等于正数的反码等于正数的源码
	}	
	else
	{
		wrd('+');
		temp=(temp);
	}			
	wrd(num[temp/100]);
	wrd(num[temp%100/10]);
	wrd(num[temp%100%10]);
	wrd('.');
	wrd(num[k/1000]);
	wrd(num[k%1000/100]);
	wrd(0xdf);
	wrd('C');
}

void time0init()  //定时器0初始化
{
	TMOD=0x02;
	TH0=0xFC;
	TL0=0x18;  //1ms
	TR0=1;
	EA=1;
	ET0=1;
}

void time1init()  //定时器0初始化
{
	TMOD=0x01;
	TH1=0xFB;
	TL1=0xAE;  //1ms
	TR1=1;
	EA=1;
	ET1=1;
}

void TempSpeed()		//根据温度,设定风扇转速;
{
	if(28>temp && temp>=20){speed=1;}				//比如:当温度大于等于20度,同时,小于28度时,风扇仅10%全速;
	else if(30>temp && temp>=28){speed=2;}
	else if(31>temp && temp>=30){speed=4;}
	else if(32>temp && temp>=31){speed=6;}
	else if(50>temp && temp>=32){speed=8;}
	else if(temp>=50){speed=10;}
}

void main()
{
	time0init();
	time1init();
	lcdinit();
	PT0 = 1;
	speed=1;
	while(1);
}

void time0()interrupt 1
{
	EA = 0;//关闭定时器0;
	TR1 = 1;//开启定时器1;
	TH0 = 0xFC;
	TL0 = 0x18;
	TR1 = 0;//关闭定时器1;
	EA = 1;//开启定时器0;
	
	time++;
	
	if(time>10){time = 0;}
	if(time<(speed)){pwm = 1;led1 = 1;led2 = 1;}
	else{pwm = 0;led1 = 0;led2 = 0;}
}

void time1()interrupt 3
{
		EA = 0;
		TH1 = 0Xfb;
		TL1 = 0Xae;
		EA = 1;
	
		RDD++;
	
		if(RDD>=10){RDD=0;}
		if(RDD<5)
			{
				temp=readtemp();
			}
		else
			{
				display();
				TempSpeed();
			}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值