×
单片机 > 单片机程序设计 > 详情

51单片机风扇和测温程序

发布时间:2021-08-17 发布时间:
|

使用的模块有:直流电机,舵机,蜂鸣器,红外,温度传感器,lcd1602, ,


舵机,这种舵机它的频率是50HZ,一个周期为20ms,是通过一个周期中高低电平的占比来控制角度的角度的,本程序舵机是来回摆动,不是停在五个角度(0,45,90,135,180)的某个角度,可通过红外遥控来实现停在某个角度,电扇的开关,也由红外来控制。


为了方便起见,将过温自动报警,和使用舵机的功能,分成两种模式,可通过红外遥控来切换,因为我之前遇到过,使用了舵机后(需要用到定时器),温度就不能正常显示,

通过DS18b20来测温度,在lcd1602上显示温度和时间,当温度超过26度时(可在代码中修改),直流电机打开,蜂鸣器报警,低于26关闭。也可遥控打开或关闭电机,没有使用舵机,此时直流电机不能改变方向。


当遥控器按下时,lcd1602显示turn off,无法显示温度,定时器1初始化,舵机可以使用,利用舵机对直流电机来控制方向,将ds18b20和舵机分开使用的原因,ds18b20对时序的要求很高,如果用舵机的话就会使温度无法正常显示。


红外遥控的优先级始终大于超过温度。


单片机源程序如下:

#include "reg52.h"

#include"temp.h"

#include"1302.h"

sbit IRIN=P3^2; //红外

sbit duoji=P3^5;


uchar IrValue[6];//温度数组

uchar zxc,count=0,flag1=1,flag2,k,m;

uchar Disp[16]="trun off ";

uchar push_val_left=14,pwm_val_left;

uint timer=0,flex;


uchar DisplayData[14]={'t'-0x30,'e'-0x30,'m'-0x30,'p'-0x30,':'-0x30,' '-0x30};

uchar code smgduan[10]={0,1,2,3,4,5,6,7,8,9};

void pwm_Servomoto_angle(unsigned int angle,unsigned int Servo_time)

{

push_val_left=5+angle*20/180; //舵机向左转90度

// timer=0;

while(timer<=Servo_time); //延时400MS让舵机转到其位置 4000

delay(flex);

}

void pwm_Servomoto(void)

{


if(pwm_val_left<=push_val_left)

duoji=1;

else

duoji=0;

if(pwm_val_left>=200)

pwm_val_left=0;


}


void datapros(int temp)

{

float tp; uint h=4000;

if(temp< 0) //当温度值为负数

{

DisplayData[0] = 0x40; // -

//因为读取的温度是实际温度的补码,所以减1,再取反求出原码

temp=temp-1;

temp=~temp;

tp=temp;

temp=tp*0.0625*100+0.5;


}

else

{

DisplayData[6] = 0x00;

tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量

//如果温度是正的那么,那么正数的原码就是补码它本身

temp=tp*0.0625*100+0.5;

}

if(flag2==0)

if(temp>2600)

{dj=1;

while(h)

{beep=~beep;

delay(10);

h--;

}

}

else

dj=0;

DisplayData[7] = smgduan[temp / 10000];

DisplayData[8] = smgduan[temp % 10000 / 1000];

DisplayData[9] = smgduan[temp % 1000 / 100] ;

DisplayData[10] = -2;

DisplayData[11] = smgduan[temp % 100 / 10];

DisplayData[12] = smgduan[temp % 10];

DisplayData[13] =51;

}

void test_servo(void)

{

int pos;

for(pos=0;pos<180;pos+=3)

{


pwm_Servomoto_angle(pos,100) ;

delay(300);

}

for(pos = 180; pos>=0; pos-=3) // goes from 180 degrees to 0 degrees

{

pwm_Servomoto_angle(pos,100) ;

delay(300);

}

}

void LcdDisplay()

{

lcdwrc(0x80+0X40);

lcdwrd('t');

lcdwrd('i');

lcdwrd('m');

lcdwrd('e');

lcdwrd(':');

lcdwrd(' ');

lcdwrd('0'+hsp[2]/16); //时

lcdwrd('0'+(hsp[2]&0x0f));

lcdwrd('-');

lcdwrd('0'+hsp[1]/16); //分

lcdwrd('0'+(hsp[1]&0x0f));

lcdwrd('-');

lcdwrd('0'+hsp[0]/16); //秒

lcdwrd('0'+(hsp[0]&0x0f));

}


//外部中断0初始化

void IrInit()

{

IT0=1;//下降沿触发

EX0=1;//打开中断0允许

EA=1; //打开总中断


IRIN=1;//初始化端口

}

//定时器1初始化

void timeinit()

{TMOD=0X10;

TH1=(65536-100)/256; //100US定时

TL1=(65536-100)%256;

TR1= 1;

ET1= 1;

EA = 1;

}


//main函数

void main()

{uchar i,n=0;

IrInit(); //红外初始化

lcdinit();

Ds1302Init();


dj=0;

while(1)

{

if(flag1==1) //关闭定时器,实现功能为超过设定温度打开电机

{

Ds1302ReadTime();

datapros(Ds18b20ReadTemp()); //数据处理函数

for(i=0;i<14;i++)

{

lcdwrd(DisplayData[i]+0x30);

}

LcdDisplay();



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
51单片机中断源的扩展方法