微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 求救! 51做智能温控风扇,怎么在风扇转时实时检测温度

求救! 51做智能温控风扇,怎么在风扇转时实时检测温度

时间:10-02 整理:3721RD 点击:
现在的问题是,运行时当超过预订的温度上限时,风扇一转一停,怎么改程序才能让风扇一直转,并且在风扇一直旋转的过程中实时检测温度,当温度低于预警温度,马上停转。一会贴出程序,大家帮帮看看!多谢!

/*******************************************************************************
* 实验名                 :温度显示实验
* 使用的IO             :
* 实验效果       :数码管显示温度
*        注意                                         :
*******************************************************************************/
#include<reg51.h>
sbit DSPORT=P3^7;         //ds18b20的数据通信端口的定义
sbit Beep = P1^5 ;
sbit PWM=P1^0;                  //PWM
void baojing();                  //报警函数
void Delay(unsigned int i);
void Delay1ms(unsigned int );        //延时函数
unsigned char Ds18b20Init();        //18b20初始化函数
void Ds18b20WriteByte(unsigned char com);//向18B20写入一个字节
unsigned char Ds18b20ReadByte();                 //从18b20读取一个字节
void  Ds18b20ChangeTemp();                             //让18b20开始转换温度
void  Ds18b20ReadTempCom();                                 //发送读取温度命令
int Ds18b20ReadTemp();                                     //读取温度
void SmgDisplay(int);
void Timer0Configuration();
void dianji(); //电机函数
#define smg        P0         //数码管IO定义
sbit LSA=P2^2;                //138译码器的输入端定义
sbit LSB=P2^3;
sbit LSC=P2^4;
unsigned char code smg_CODE[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
                               // 0,   1,   2,   3,   4,   5,   6,   7,   8,   9        段码
unsigned int disp[8]={0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f};
unsigned char Num=0;
unsigned char bjh=0,bjl=0;                //报警上限

/*******************************************************************************
* 函数名         : main
* 函数功能                   : 主函数
* 输入           : 无
* 输出                  : 无
*******************************************************************************/
void main()
{
        PWM=0;
    Timer0Configuration();          //定时器0进行初始化
        while(1)
        {  //        dianji();
                SmgDisplay(Ds18b20ReadTemp());
            baojing();
                 dianji();                  
        }
}
/*******************************************************************************
* 函数名         : SmgDisplay()
* 函数功能                   :数码管显示读取到的温度
* 输入           : 温度
* 输出                  : 无
*******************************************************************************/
void SmgDisplay(int temp)          //数码管显示
{
   
        float tp;                   // tp要定义为浮点型数据
        if(temp< 0)                                //当温度值为负数
          {
        disp[2] = 0x40;
                //因为读取的温度是实际温度的补码,所以减1,再取反求出原码
                temp=temp-1;
                temp=~temp;
                tp=temp;
                temp=tp*0.0625*100+0.5;       
                //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
                //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
                //算加上0.5,还是在小数点后面。

          }
        else
          {       
        disp[2] = 0;               
                tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
                //如果温度是正的那么,那么正数的原码就是补码它本身
                temp=tp*0.0625*100+0.5;       
                //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
                //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
                //算加上0.5,还是在小数点后面。
        }
    disp[0] = 0;
    disp[1] = 0;
    disp[3] = smg_CODE[temp / 10000];
        disp[4] = smg_CODE[temp % 10000 / 1000];        bjh= temp % 10000 / 1000;
        disp[5] = smg_CODE[temp % 1000 / 100] | 0x80; bjl=temp % 1000 / 100;    //0x80为小数点
        disp[6] = smg_CODE[temp % 100 / 10];
        disp[7] = smg_CODE[temp % 10];
       
       
         

}
/*******************************************************************************
* 函数名         : Timer0Configuration()
* 函数功能                   : 设置计时器
* 输入           : 无
* 输出                  : 无
*******************************************************************************/
void Timer0Configuration()
{
        TMOD=0X02;//选择为定时器模式,工作方式2,仅用TRX打开启动。
        TH0=0Xc4;        //给定时器赋初值,定时10us
        TL0=0Xc4;       
        ET0=1;      //打开定时器0中断允许
        EA=1;       //打开总中断
        TR0=1;      //打开定时器               
}
/*******************************************************************************
* 函数名         : smgDisplay() interrupt 1
* 函数功能                   : 中断数码管显示
* 输入           : 无
* 输出                  : 无
*******************************************************************************/
void smgdisplay() interrupt 1
{
    //定时器在工作方式二会自动重装初,所以不用在赋值。               
        smg=0; //消隐
        switch(Num)         //位选,选择点亮的数码管,
        {
                case(7):
                        LSA=0;LSB=0;LSC=0; break;
                case(6):
                        LSA=1;LSB=0;LSC=0; break;
                case(5):
                        LSA=0;LSB=1;LSC=0; break;
                case(4):
                        LSA=1;LSB=1;LSC=0; break;
                case(3):
                        LSA=0;LSB=0;LSC=1; break;
                case(2):                                                  
                        LSA=1;LSB=0;LSC=1; break;
                case(1):
                        LSA=0;LSB=1;LSC=1; break;
                case(0):
                        LSA=1;LSB=1;LSC=1; break;           //前两位为0
        }
        smg=disp[Num]; //段选,选择显示的数字。
        Num++;
        if(Num>7)Num=0;
       
}
         /*******************************************************************************
* 函数名         : baojing
* 函数功能                   : 报警函数
* 输入           : 无
* 输出                  : 无
*******************************************************************************/
void baojing()
{  
        if((bjh>=2)&&(bjl>=2))
  {
             
        int i;
    for(i=0;i<=10;i++)
   {
        Beep= 1;
        Delay(1);
        Beep= 0;
        Delay(1);
   }
}
  
}           /*******************************************************************************
* 函数名         : Delay()
* 函数功能                   : 延时函数
* 输入           : 无
* 输出                  : 无
*******************************************************************************/
void Delay(unsigned int i)
{
        char j;
        for(i; i > 0; i--)
                for(j =180; j > 0; j--);
}



           /*******************************************************************************
* 函 数 名       : dianji
* 函数功能                 : 主函数
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/
void dianji()
{
        if((bjh>=2)&&(bjl>=2))
        {
                PWM=1;
                Delay1ms(8);
                PWM=0;
        //        Delay1ms(1);
        }
       
}





/*******************************************************************************
* 函数名         : Delay1ms
* 函数功能                   : 延时函数
* 输入           : 无
* 输出                  : 无
*******************************************************************************/
void Delay1ms(unsigned int y)
{
        unsigned int x;
        for(y;y>0;y--)
                for(x=110;x>0;x--);
}
/*******************************************************************************
* 函数名         : Ds18b20Init
* 函数功能                   : 初始化
* 输入           : 无
* 输出                  : 初始化成功返回1,失败返回0
*******************************************************************************/
unsigned char Ds18b20Init()
{
        unsigned int i;
    EA = 0;
        TR0=0;
        DSPORT=0;                     //将总线拉低480us~960us
        i=70;       
        while(i--);         //延时642us
        DSPORT=1;                        //然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低
        i=0;
    EA = 1;
        while(DSPORT)           //等待DS18B20拉低总线
        {
                i++;
                if(i>1000)     //等待>5MS
                        return 0;  //初始化失败       
        }
        TR0=1;
        return 1;          //初始化成功
       
}
/*******************************************************************************
* 函数名         : Ds18b20WriteByte
* 函数功能                   : 向18B20写入一个字节
* 输入           : com
* 输出                  : 无
*******************************************************************************/
void Ds18b20WriteByte(unsigned char dat)
{
        unsigned int i,j;
    EA = 0;
        for(j=0;j<8;j++)
        {
                DSPORT=0;                 //每写入一位数据之前先把总线拉低1us
                i++;
                DSPORT=dat&0x01; //然后写入一个数据,从最低位开始
                i=6;
                while(i--);      //延时68us,持续时间最少60us
                DSPORT=1;             //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值
                dat>>=1;
        }
    EA = 1;       
}
/*******************************************************************************
* 函数名         : Ds18b20ReadByte
* 函数功能                   : 读取一个字节
* 输入           : com
* 输出                  : 无
*******************************************************************************/

unsigned char Ds18b20ReadByte()
{
        unsigned char byte,bi;
        unsigned int i,j;
    EA = 0;       
        for(j=8;j>0;j--)
        {
                DSPORT=0;//先将总线拉低1us
                i++;
                DSPORT=1;//然后释放总线
                i++;
                i++;     //延时6us等待数据稳定
                bi=DSPORT;         //读取数据,从最低位开始读取
                   /*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/
                byte=(byte>>1)|(bi<<7);                                                  
                i=4;                //读取完之后等待48us再接着读取下一个数
                while(i--);
        }
    EA = 1;                               
        return byte;
}
/*******************************************************************************
* 函数名         : Ds18b20ChangeTemp
* 函数功能                   : 让18b20开始转换温度
* 输入           : com
* 输出                  : 无
*******************************************************************************/
void  Ds18b20ChangeTemp()
{
        Ds18b20Init();
        Delay1ms(1);
        Ds18b20WriteByte(0xcc);                //跳过ROM操作命令                 
        Ds18b20WriteByte(0x44);            //温度转换命令
   
}
/*******************************************************************************
* 函数名         : Ds18b20ReadTempCom
* 函数功能                   : 发送读取温度命令
* 输入           : com
* 输出                  : 无
*******************************************************************************/
void  Ds18b20ReadTempCom()
{       
        Ds18b20Init();
        Delay1ms(1);
        Ds18b20WriteByte(0xcc);         //跳过ROM操作命令
        Ds18b20WriteByte(0xbe);         //发送读取温度命令
}
/*******************************************************************************
* 函数名         : Ds18b20ReadTemp
* 函数功能                   : 读取温度
* 输入           : com
* 输出                  : 无
*******************************************************************************/
int Ds18b20ReadTemp()
{
           int temp=0;
        unsigned char tmh,tml;
        Ds18b20ChangeTemp();                //先写入转换命令
        Ds18b20ReadTempCom();                //然后等待转换完后发送读取温度命令
        tml=Ds18b20ReadByte();                //读取温度值共16位,先读低字节
        tmh=Ds18b20ReadByte();                //再读高字节
        temp=tmh;
        temp<<=8;                                        //将数据左移8位,放在高八位上
        temp|=tml;                                        //位与上低八位的数据,便构成了一个完整的温度数据
        return temp;
}

大概一个时间段就去读取温度(这个时间段也不要太大也不要太小),至于你说设计风扇会一转一停,你这里是要保持温度吗?应该是快要接近理想温度才开风扇,温度一下子升上去,就关风扇了,一下子就降温了,就加热了,导致你说的一转一停
如果有什么不明白,欢迎加扣扣:2209931992  讨论

感谢分享                                 

用PWM控制就行了吧,我觉得。如果温度高于上限,就让它直接接电就行了。低于下限,就断开电。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top