单片机与智能风扇_51单片机智能温控风扇 - CSDN
  • 51单片机智能温控风扇

    千次阅读 多人点赞 2017-03-03 16:37:27
    大三上学期写的一个课程设计,还要应付各种考试

    大三上学期写的一个课程设计,完成的功能就是读取当前环境温度,在数码管上显示,并根据其驱动风扇转动的快慢,另用键盘扫描实现了总开关,超过一定阈值蜂鸣器响起。用51单片机由于芯片问题,使用两个定时器,很容易得到脏数据,程序当时写完,反复检查各种模块,和老师讨论,得出不是代码的问题,就进行了一次数据过滤
    主要难点:步进电机的控制,使用占空比。

    回头看,段锁存和位锁存都弄不清楚了,位锁存就是第几个数码管,段锁存就是数码管上的第几段,锁存器的锁存端为1是,数据直通,为0时就无论输入什么,输出保持前一次的输入值。

    主程序:

    
    #include<reg52.h> 
    #include "18b20.h"
    #include "delay.h"
    
    sbit LATCH1=P2^6;//定义锁存使能端口 段锁存
    sbit LATCH2=P2^7;//                 位锁存
    sbit A1=P1^0; //定义步进电机连接端口
    sbit B1=P1^1;
    sbit C1=P1^2;
    sbit D1=P1^3;
    sbit SPK1=P1^4;    //定义喇叭端口
    bit ReadTempFlag;//定义读时间标志
    
    #define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0 替换
    #define Coil_A1 {A1=1;B1=0;C1=0;D1=0;}//A相通电,其他相断电
    #define Coil_OFF {A1=0;B1=0;C1=0;D1=0;}//全部断电
    #define KeyPort P3
    
    
    
    
    
    unsigned char code dofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0~9
    unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码
    unsigned char code special_DuanMa[10]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};// 带小数点的段码0~9
    unsigned char TempData[8]; //存储显示值的全局变量
    unsigned int CYCLE=100,PWM_ON=0;//定义周期并赋值
    unsigned char key = 0;              //键盘扫描
    unsigned int flag=0;            //电机转动开关
    unsigned int lin=0;
    unsigned int tp=0;
    
    
    void Init_Timer0(void);//定时器初始化
    void Init_Timer1(void);
    void Display(unsigned char FirstBit,unsigned char Num);//数码管显示函数
    
    unsigned char KeyScan(void);//键盘扫描
    unsigned char KeyPro(void);
    
    /*------------------------------------------------
                        主函数
    ------------------------------------------------*/
    void main (void)
    {                  
        unsigned int TempH,TempL;
        unsigned int temp=0;
        unsigned int hig,low;
        Init_Timer0();
        Init_Timer1();
    
        while (1)         //主循环
          {
    
          if(ReadTempFlag==1)
          {
              ReadTempFlag=0;
              temp=ReadTemperature();
    
                 TempData[0]=0;
    
                 TempH=temp>>4;
                 TempL=temp&0x0F;        
                 TempL=TempL*6/10;//小数近似处理
                 hig=(TempH%100)/10;
                 low=((TempH%100)%10);
                 lin=hig*10+low;        //数据存储 
                 if(lin<30)
                  {
                     tp=lin;
                     TempData[1]=dofly_DuanMa[(TempH%100)/10]; //十位温度
                     TempData[2]=special_DuanMa[(TempH%100)%10]; //个位温度,特殊段码
                     TempData[3]=dofly_DuanMa[TempL];
                     TempData[4]=0x39;         //显示C符号
                  }
    
          } 
    
          if(flag==1)
                {
                    Coil_A1                 
                    DelayMs(PWM_ON);
                    Coil_OFF
                    DelayMs(CYCLE-PWM_ON);
                    TempData[7]=dofly_DuanMa[(PWM_ON/20)];
                }
    
                else
                {                
    
                    Coil_OFF            
                    DelayMs(CYCLE-PWM_ON);
                    TempData[7]=0;
                }
    
         }
    }
    
    /*------------------------------------------------
     显示函数,用于动态扫描数码管
     输入参数 FirstBit 表示需要显示的第一位,如赋值2表示从第三个数码管开始显示
     Num表示需要显示的位数,如需要显示99两位数值则该值输入2
    ------------------------------------------------*/
    void Display(unsigned char FirstBit,unsigned char Num)
    {
          static unsigned char i=0;
    
    
           DataPort=0;   //清空数据,防止有交替重影
           LATCH1=1;     //段锁存
           LATCH1=0;
    
           DataPort=dofly_WeiMa[i+FirstBit]; //取位码 
           LATCH2=1;     //位锁存
           LATCH2=0;
    
           DataPort=TempData[i]; //取显示数据,段码
    
           LATCH1=1;     //段锁存
           LATCH1=0;
    
           i++;
           if(i==Num)
              i=0;
    
    
    }
    /*------------------------------------------------
                        定时器初始化子程序
    ------------------------------------------------*/
    void Init_Timer0(void)
    {
         TMOD |= 0x01;    //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响          
         //TH0=0x00;          //给定初值
         //TL0=0x00;
         EA=1;            //总中断打开
         ET0=1;           //定时器中断打开
         TR0=1;           //定时器开关打开
    }
    void Init_Timer1(void)
    {
         TMOD |= 0x10;    //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响 
         TH1=0x00;        //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出
         TL1=0x00;
         EA=1;            //总中断打开
         ET1=1;           //定时器中断打开
         TR1=1;           //定时器开关打开
    }
    
    /*------------------------------------------------
                     定时器中断子程序
    ------------------------------------------------*/
    void Timer0_isr(void) interrupt 1 
    {
     static unsigned int num;
        TH0 = 0x0F8;
        TL0 = 0x30;
            key=KeyPro();    //按键扫描
        if(key==1)      //开
        {
            flag=1;
        }
        if(key==2)      //关
        {
            flag=0;
    
        }
        Display(0,8);       // 调用数码管扫描
        num++;
        if(num==100)        //读取比扫描时间更长一点
        {
            num=0;
            ReadTempFlag=1; //读标志位置1
        }          
    }
    
    void Timer1_isr(void) interrupt 3 using 1
    {
        unsigned int tep=0;
        TH1 = 0x0D8;
        TL1 = 0x0F0;    //10ms
    
        if(flag==1)     //进入电机转动
        {
            if(tp>27)
            {
                PWM_ON=100;
                SPK1=!SPK1;
    
            }
            else if(tp>25)
            {
    
                PWM_ON=80;
    
            }
    
            else if(tp>22)
            {
    
                PWM_ON=60;
    
            }
    
            else if(tp>20)
            {
    
                PWM_ON=40;
    
            }
    
            else
            {
                PWM_ON=20;
    
            }
        }
    
    }
    
    
    unsigned char KeyScan(void)  //键盘扫描函数,使用行列逐级扫描法
    {
         unsigned char Val;
         KeyPort=0xf0;//高四位置高(列),低四位拉低(行)
         if(KeyPort!=0xf0)//表示有按键按下
         {
            DelayMs(10);  //去抖
            if(KeyPort!=0xf0)
            {           //表示有按键按下
                KeyPort=0xfe; //检测第一行
                if(KeyPort!=0xfe)       //去抖
                    {
                        Val=KeyPort&0xf0;   //取列码
                      Val+=0x0e;
                      //while(KeyPort!=0xfe);                                 
                      //DelayMs(10); //去抖
                      //while(KeyPort!=0xfe);
                      return Val;
                    }
                KeyPort=0xfd; //检测第二行
                if(KeyPort!=0xfd)
                    {
                      Val=KeyPort&0xf0;
                      Val+=0x0d;
                      //while(KeyPort!=0xfd);
                      //DelayMs(10); //去抖
                      //while(KeyPort!=0xfd);
                      return Val;
                    }
                KeyPort=0xfb; //检测第三行
                if(KeyPort!=0xfb)
                    {
                      Val=KeyPort&0xf0;
                      Val+=0x0b;
                      //while(KeyPort!=0xfb);
                      //DelayMs(10); //去抖
                      //while(KeyPort!=0xfb);
                      return Val;
                    }
                KeyPort=0xf7; //检测第四行
                if(KeyPort!=0xf7)
                    {
                      Val=KeyPort&0xf0;
                      Val+=0x07;
                      //while(KeyPort!=0xf7);
                      //DelayMs(10); //去抖
                      //while(KeyPort!=0xf7);
                      return Val;
                    }
             }
           }
          return 0xff;
    }
    
    
    
    unsigned char KeyPro(void)
    {
         switch(KeyScan())
         {
          case 0xee:return 0;break;//0 按下相应的键显示相对应的码值
          case 0xde:return 1;break;//1
          case 0xbe:return 2;break;//2
          case 0x7e:return 3;break;//3
          case 0xed:return 4;break;//4
          case 0xdd:return 5;break;//5
          case 0xbd:return 6;break;//6
          case 0x7d:return 7;break;//7
          case 0xeb:return 8;break;//8
          case 0xdb:return 9;break;//9
          case 0xbb:return 10;break;//+
          case 0x7b:return 11;break;//-
          case 0xe7:return 12;break;//c
          case 0xd7:return 13;break;//d
          case 0xb7:return 14;break;//*
          case 0x77:return 15;break;//=
          //case 0xff:return 9;break;
          default:return 0xff;break;
         }
    }
    

    延时模块

    #include "delay.h"
    /*------------------------------------------------
     uS延时函数,含有输入参数 unsigned char t,无返回值
     unsigned char 是定义无符号字符变量,其值的范围是
     0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
     长度如下 T=tx2+5 uS 
    ------------------------------------------------*/
    void DelayUs2x(unsigned char t)
    {   
     while(--t);
    }
    /*------------------------------------------------
     mS延时函数,含有输入参数 unsigned char t,无返回值
     unsigned char 是定义无符号字符变量,其值的范围是
     0~255 这里使用晶振12M,精确延时请使用汇编
    ------------------------------------------------*/
    void DelayMs(unsigned char t)
    {
    
     while(t--)
     {
         //大致延时1mS
         DelayUs2x(245);
         DelayUs2x(245);
     }
    }
    

    温度传感器模块18b20

    这里写图片描述
    GND为接地端口,DQ为数据传输端口,VD为电源端口,关于I2C通信可以参考:介绍及格式

    #include"delay.h"
    #include"18b20.h"
    /*------------------------------------------------
                        18b20初始化
    ------------------------------------------------*/
    bit Init_DS18B20(void)
    {
         bit dat=0;
         DQ = 1;    //DQ复位
         DelayUs2x(5);   //稍做延时
         DQ = 0;         //单片机将DQ拉低
         DelayUs2x(200); //精确延时 大于 480us 小于960us
         DelayUs2x(200);
         DQ = 1;        //拉高总线
         DelayUs2x(50); //15~60us 后 接收60-240us的存在脉冲
         dat=DQ;        //如果x=0则初始化成功, x=1则初始化失败
         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);
    }
    

    最后放效果张图:
    这里写图片描述

    展开全文
  • 基于51单片机智能温控风扇

    万次阅读 多人点赞 2019-01-20 20:29:56
    本设计为一种温控风扇系统,具有灵敏的温度感测和显示功能,系统选用STC89C52单片机作为控制平台对风扇转速进行控制。可在测得温度值在高低温度之间时打开风扇弱风档,当温度升高超过所设定的温度时自动切换到大风档...

    1.功能
    本设计为一种温控风扇系统,具有灵敏的温度感测和显示功能,系统选用STC89C52单片机作为控制平台对风扇转速进行控制。可在测得温度值在高低温度之间时打开风扇弱风档,当温度升高超过所设定的温度时自动切换到大风档,当温度小于所设定的温度时自动关闭风扇,控制状态随外界温度而定。

    2.硬件设计
    在这里插入图片描述
    硬件电路主要由:

    1. 单片机最小系统
    2. 风扇驱动电路
    3. LCD1602显示屏电路
    4. DS18B20温度采集电路

    3.程序设计

    (1)LCD1602驱动程序

    #define LCD1602_DB  P0
    sbit LCD1602_RS = P2^0;
    sbit LCD1602_RW = P2^1;
    sbit LCD1602_E  = P2^2;
    
    /* 等待液晶准备好 */
    void LcdWaitReady()
    {
        unsigned char sta;
        
        LCD1602_DB = 0xFF;
        LCD1602_RS = 0;
        LCD1602_RW = 1;
        do {
            LCD1602_E = 1;
            sta = LCD1602_DB; //读取状态字
            LCD1602_E = 0;
        } while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止
    }
    /* 向LCD1602液晶写入一字节命令,cmd-待写入命令值 */
    void LcdWriteCmd(unsigned char cmd)
    {
        LcdWaitReady();
        LCD1602_RS = 0;
        LCD1602_RW = 0;
        LCD1602_DB = cmd;
        LCD1602_E  = 1;
        LCD1602_E  = 0;
    }
    /* 向LCD1602液晶写入一字节数据,dat-待写入数据值 */
    void LcdWriteDat(unsigned char dat)
    {
        LcdWaitReady();
        LCD1602_RS = 1;
        LCD1602_RW = 0;
        LCD1602_DB = dat;
        LCD1602_E  = 1;
        LCD1602_E  = 0;
    }
    /* 设置显示RAM起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */
    void LcdSetCursor(unsigned char x, unsigned char y)
    {
        unsigned char addr;
        
        if (y == 0)  //由输入的屏幕坐标计算显示RAM的地址
            addr = 0x00 + x;  //第一行字符地址从0x00起始
        else
            addr = 0x40 + x;  //第二行字符地址从0x40起始
        LcdWriteCmd(addr | 0x80);  //设置RAM地址
    }
    /* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针 */
    void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
    {
        LcdSetCursor(x, y);   //设置起始地址
        while (*str != '\0')  //连续写入字符串数据,直到检测到结束符
        {
            LcdWriteDat(*str++);
        }
    }
    /* 初始化1602液晶 */
    void InitLcd1602()
    {
        LcdWriteCmd(0x38);  //16*2显示,5*7点阵,8位数据接口
        LcdWriteCmd(0x0C);  //显示器开,光标关闭
        LcdWriteCmd(0x06);  //文字不动,地址自动+1
        LcdWriteCmd(0x01);  //清屏
    }
    

    (2)DS18B20驱动程序

    sbit IO_18B20=P3^2;
    
    /*软件延时函数,延时时间(t*10)us*/
    void DelayX10us(unsigned char t)
    {
    	do{
    		_nop_();
    		_nop_();
    		_nop_();
    		_nop_();
    		_nop_();
    		_nop_();
    		_nop_();
    		_nop_();
    	}while(--t);
    }
    /*复位总线,获取存在脉冲,以启动一次读写操作*/
    bit Get18B20Ack()
    {
    	bit ack;
    	
    	EA=0;	   			//禁止总中断
    	IO_18B20=0;			//产生500us复位脉冲
    	DelayX10us(50);
    	IO_18B20=1;
    	DelayX10us(6);		//延时60us
    	ack=IO_18B20;		//读取存在脉冲
    	while(!IO_18B20);   //等待存在脉冲结束
    	EA=1;				//重新使能总中断
    	return ack;
    }
    /*向DS18B20写入一个字节,dat-待写入字节*/
    void Write18B20(unsigned char dat)
    {
    	unsigned char mask;
    	EA=0;
    	for(mask=0x01;mask!=0;mask<<=1)//低位在先,依次移出8个bit
    	{
    		IO_18B20=0;//产生2us低电平脉冲
    		_nop_();
    		_nop_();
    		if((mask&dat)==0)//输出该bit值
    			IO_18B20=0;
    		else
    			IO_18B20=1;
    		DelayX10us(6);//延时60us
    		IO_18B20=1;//拉高通信引脚
    	}
    	EA=1;
    }
    /*从DS18B20读取一个字节,返回值-读到的字节*/
    unsigned char Read18B20()
    {
    	unsigned char dat;
    	unsigned char mask;
    
    	EA=0;
    	for(mask=0x01;mask!=0;mask<<=1)//低位在先,依次采集8个bit
    	{
    		IO_18B20=0;//产生2us低电平脉冲
    		_nop_();
    		_nop_();
    		IO_18B20=1;//结束低电平脉冲,等待18B20输出数据
    		_nop_(); //延时2us
    		_nop_();
    		if(!IO_18B20)//读取通信引脚上的值
    			dat &= ~mask;
    		else
    			dat |= mask;
    		DelayX10us(6);//再延时60us
    	}
    	EA=1;
    	return dat;
    }
    /*启动一次18B20温度转换,返回值-表示是否启动成功*/
    bit Start18B20()
    {
    	bit ack;
    	ack=Get18B20Ack();//执行总线复位,并获取18B20应答
    	if(ack==0)
    	{
    		Write18B20(0xCC);
    		Write18B20(0x44);
    	}
    	return ~ack;
    }
    /*读取DS18B20转换的温度值,返回值-表示是否读取成功*/
    bit Get18B20Temp(int *temp)
    {
    	bit ack;
    	unsigned char LSB,MSB;//16bit温度值的低字节和高字节
    
    	ack=Get18B20Ack();//执行总线复位,并获取18B20应答
    	if(ack==0)
    	{
    		Write18B20(0xCC);//跳过ROM操作
    		Write18B20(0xBE);//发送读命令
    		LSB=Read18B20();//读温度值的低字节
    		MSB=Read18B20();//读温度值的高字节
    		*temp=((int)MSB<<8)+LSB;//合成为16bit整型数
    	}
    	return ~ack;
    }
    

    (3)主程序

    sbit IN1=P2^7;
    sbit IN2=P2^6;
    sbit ENA=P2^5;
    
    bit flag1s=0;//1s定时标志
    unsigned char T0RH=0;
    unsigned char T0RL=0;
    
    int temp;//读取到的当前温度值
    unsigned char len;
    int intT,decT;//温度值的整数和小数部分
    unsigned char str[12];
    
    void Compare();
    void GetTemp();
    void ConfigTimer0(unsigned int ms);
    unsigned char IntToString(unsigned char *str,int dat);
    extern bit Start18B20();
    extern bit Get18B20Temp(int *temp);
    extern void InitLcd1602();
    extern void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str);
    
    void main()
    {
    	bit res;
    
    	EA=1;
    	ConfigTimer0(10);//T0定时10ms
    	Start18B20();//启动DS18B20
    	InitLcd1602();//初始化液晶
    
    	while(1)
    	{		
    		if(flag1s)//每秒更新一次温度
    		{
    			flag1s=0;
    			res=Get18B20Temp(&temp);//读取当前温度
    			if(res)//读取成功时,刷新当前温度显示
    			{
    				GetTemp();
    			
    				LcdShowStr(0,0,"Welcome to use");//显示字符及温度值
    				LcdShowStr(0,1,"Current T:");
    				LcdShowStr(10,1,str);
    					Compare();
    			}
    			else //读取失败时,提示错误信息
    			{
    				LcdShowStr(0,0,"error!");
    
    			}
    			Start18B20();//重新启动下一次转换					 
    		}
    	}
    }
    /*温度获取函数,获取当前环境温度值并保存在str数组中*/
    void GetTemp()
    {
    
    	intT=temp>>4;//分离出温度值整数部分
    	decT=temp &0x0F;//分离出温度值小数部分
    			
    	len=IntToString(str,intT);//整数部分转换成字符串
    			
    	str[len++]='.';
    	decT=(decT*10)/16;//二进制的小数部分转换为1位十进制位
    	str[len++]=decT+'0';//十进制小数位再转换为ASCII字符
    	while(len<6)//用空格补齐到6个字符长度
    	{
    		str[len++]=' ';
    	}
    	str[len++]='\0';
    }
    /*延时函数,用于PWM控制*/
    void delay(unsigned int z)
    {
    	unsigned int x,y;
    	for(x=z;x>0;x--)
    		for(y=110;y>0;y--);
    } 
    /*比较函数,通过温度值的比较设置电机的转速*/
    void Compare()
    {
    	unsigned int i=0;
    	unsigned char j;
    
    	if((intT>= 24) && (intT<26))   //以两度为一个温差范围,并设温度范围索引
    	{
    		j=0;	
    	}
    	else if((intT>=26) &&(intT<28))
    	{
    		j=1;
    	}
    	else if((intT>=28) &&(intT<30))
    	{
    		j=2;
    	}
    	else if(intT>=30)
    	{
    		j=3;
    	}
    	switch(j)		  //根据温度索引设置电机转速
    	{
    		case 0:	IN1=1;
    				IN2=0;
    		  		for(i=0;i<200;i++)
    	      		{
    					ENA=1;
    	     			delay(20);
    	      		    ENA=0;
    					delay(30);
    				}
    				break;
    	
    		case 1:	IN1=1;
    				IN2=0;
    		  		for(i=0;i<200;i++)
    	      		{
    					ENA=1;
    	     			delay(30);
    	      		    ENA=0;
    					delay(30);
    				}
    				break;	 
    	
    		case 2:	IN1=1;
    				IN2=0;
    		  		for(i=0;i<200;i++)
    	      		{
    					ENA=1;
    	     			delay(55);			 
    	      		    ENA=0;
    					delay(30);
    				}
    				break;	 
    							
    		case 3:	IN1=1;
    				IN2=0;
    		  	    ENA=1;
    				break;
    
    		default:break;	 	 
    	}
    }  
    
    /*整型数转换为字符串,str-字符串指针,dat-待转换数,返回值-字符串长度*/
    unsigned char IntToString(unsigned char *str,int dat)
    {
    	signed char i=0;
    	unsigned char len=0;
    	unsigned char buf[6];
    
    	if(dat<0)//如果为负数,首先取绝对值,并在指针上添加负号
    	{
    	 	dat=-dat;
    		*str++='-';
    		len++;
    	}
    	do{	   //先转换为低位在前的十进制数组
    		buf[i++]=dat%10;
    		dat /=10;
    	}while(dat>0);
    	len += i;//i最后的值就是有效字符的个数
    	while(i-->0)//将数组值转换为ASCII码反向拷贝到接收指针上
    	{
    		*str++=buf[i]+'0';
    	}
    	*str='\0';
    	return len;
    }
    void ConfigTimer0(unsigned int ms)
    {
    	unsigned long tmp;
    
    	tmp=11059200/12;
    	tmp=(tmp*ms)/1000;
    	tmp=65536-tmp;
    	tmp=tmp+12;
    	T0RH=(unsigned char)(tmp>>8);
    	T0RL=(unsigned char)tmp;
    	TMOD &= 0xF0;
    	TMOD |= 0x01;
    	TH0=T0RH;
    	TL0=T0RL;
    	ET0=1;
    	TR0=1;
    }
    void InterruptTimer0() interrupt 1
    {
    	static unsigned char tmr1s=0;
    
    	TH0=T0RH;
    	TL0=T0RL;
    	tmr1s++;
    	if(tmr1s>=100)
    	{
    		tmr1s=0;
    		flag1s=1;
    	}		 
    
    }
    

    源码+电路图 下载:关注公众号,首页回复“温控风扇”获取资料
    在这里插入图片描述

    展开全文
  • 基于51单片机智能风扇控制程序 看了你就知道了 有12864 18b20 1302
  • 本设计为一种温控风扇系统,具有灵敏的温度感测和显示功能,系统选用STC89C52单片机作为控制平台对风扇转速进行控制。可在测得温度值在高低温度之间时打开风扇弱风档,当温度升高超过所设定的温度时自动切换到大风档...
  • 基于单片机风扇
  • 基于单片机的电风扇智能控制论文(设计)外文文献综述.d
  • 使用单片机设计的智能温控风扇论文资料: 传统电风扇具有以下缺点:风扇不能遥控控制风扇调速,必须手动调速,给人们生活带来极大的不方便。传统电风机械的定时方式常常会伴随着机械运动的声音,特别是夜间影响人们...

    使用单片机设计的智能温控风扇论文资料:
      传统电风扇具有以下缺点:风扇不能遥控控制风扇调速,必须手动调速,给人们生活带来极大的不方便。传统电风机械的定时方式常常会伴随着机械运动的声音,特别是夜间影响人们的睡眠,而且定时范围有限,不能满足人们的需求。鉴于这些缺点,我们需要设计一款智能的电风扇控制系统来解决,技术交流:787059199。
      本文以STC89C52单片机为核心,通过数字温度传感器对外界环境温度进行数据采集,从而建立一个控制系统,使电风扇随温度的变化而自动调节档位,实现“温度高、风力大、温度低、风力弱”的性能。另外,通过红外发射和接收装置及按键实现各种功能的启动与关闭,并且可对各种功能实现遥控,用户可以在一定范围内设置电风扇的最低工作温度,当温度低于所设置温度时,电风扇将自动关闭,当高于此温度时电风扇又将重新启动。



    本设计主要内容如下:
      (1)风速设为从低到高共2个档位,可由用户通过键盘设定。
      (2)每当温度低于下限值时,则电风扇风速关闭。
      (3)每当温度在下限和上限之间时,则电风扇转速缓慢。
      (4)每当温度高于上限值时,则电风扇风速全速运转。
      本设计的整体思路是:利用温度传感器DSI8B20检测环境温度并直接输出数字温度信号给单片机STC89C52进行处理,在LED数码管上显示当前环境温度值以及预设温度值。其中预设温度值只能为整数形式,检测到的当前环境温度可精确到小数点后一位。同时采用PWM脉宽调制方式来改变直流风扇电机的转速。并通过两个按键改变预设温度值,一个提高预设温度,另一个降低预设温度值。系统结构框图,如图所示。

     

    完整资料链接:https://bbs.usoftchina.com/thread-209974-1-3.html

     

     

    展开全文
  • 智能风扇散热控制系统的设计: 设计内容:硬件部分:单片机模块、温度检测模块、按键模块、辅助电路模块、显示模块、电机驱动模块,电路中所用元器件的参数要有计算,所有硬件电路的电路原理图及PCB板图要完整。软件...
  • 基于单片机的温控风扇的设计 摘 要 温控风扇在现代社会中的生产以及人们的日常生活中都有广泛的应用,如工业生产中大型机械散热系统中的风扇、现在笔记本电脑上的广泛应用的智能CPU风扇等。本文设计了基于单片机...
  • 51单片机做的温空风扇 数码管显示 带人体感应模块,实现智能调速,功能非常强大,这是一个本科的毕业设计,毕业论文 开题...智能风扇仿真截图: 温空风扇的DXP格式 protel99格式 温控风扇原理图: DXP格式用 Alti...

    51单片机做的温空风扇 数码管显示 带人体感应模块,实现智能调速,功能非常强大,这是一个本科的毕业设计,毕业论文 开题报告 源码 原理图 还有proteus仿真等等都是一应俱全. 还有答辩常见问题解答,焊接注意事项和调试讲解,以及详细的制作过程.

    温空风扇实物图:

    在这里插入图片描述
    在这里插入图片描述
    智能风扇仿真截图:
    在这里插入图片描述
    温空风扇的DXP格式 protel99格式 温控风扇原理图:
    在这里插入图片描述
    DXP格式用 Altium designer Summer 软件打开
    protel99格式用 protel99SE 软件打开
    PDF格式用 PDF 软件打开
    Word格式用 Word 或用WPS 软件打开

    4种格式的原理图都内容是一样的 只是打开方式不同

    相关论文参考
    在这里插入图片描述
    在这里插入图片描述
    温空风扇程序:
    如果没有装KEIL软件
    找到 .c .h结尾的文件即为程序。打开方式选择记事本打开
    或者到开发资料里安装KEIL软件

    C语言参考源代码:

    #include <reg52.h> //调用单片机头文件
    #define uchar unsigned char //无符号字符型 宏定义 变量范围0~255
    #define uint unsigned int //无符号整型 宏定义 变量范围0~65535

    //数码管段选定义 0 1 2 3 4 5 6 7 8 9
    uchar code smg_du[]={0x28,0xe4,0x42,0x72,0xe5,0xa8,0x41,0x77,0x20,0xa0,
    0x60,0x25,0x39,0x26,0x31,0x71,0xff}; //断码
    //数码管位选定义
    uchar code smg_we[]={0xef,0xdf,0xbf,0x7f};
    uchar dis_smg[8] = {0};
    uchar smg_i = 3; //显示数码管的个位数
    sbit dq = P2^4; //18b20 IO口的定义
    sbit hw = P2^5;
    uchar miao = 30;
    uchar flag_en;

    bit flag_lj_en; //按键连加使能
    bit flag_lj_3_en; //按键连3次连加后使能 加的数就越大了
    uchar key_time,key_value; //用做连加的中间变量
    bit key_500ms ;
    sbit pwm = P2^3;
    uchar f_pwm_l ; //越小越慢

    uint temperature ; //
    bit flag_200ms ;
    uchar menu_1; //菜单设计的变量
    uint t_high = 200,t_low = 100; //温度上下限报警值

    /1ms延时函数******/
    void delay_1ms(uint q)
    {
    uint i,j;
    for(i=0;i<q;i++)
    for(j=0;j<120;j++);
    }

    /小延时函数******/
    void delay_uint(uint q)
    {
    while(q–);
    }

    /数码显示函数******/
    void display()
    {
    static uchar i;
    i++;
    if(i >= smg_i)
    i = 0;
    P1 = 0xff; //消隐
    P3 = smg_we[i]; //位选
    P1 = dis_smg[i]; //段选

    }

    /18b20初始化函数******/
    void init_18b20()
    {
    bit q;
    dq = 1; //把总线拿高
    delay_uint(1); //15us
    dq = 0; //给复位脉冲
    delay_uint(80); //750us
    dq = 1; //把总线拿高 等待
    delay_uint(10); //110us
    q = dq; //读取18b20初始化信号
    delay_uint(20); //200us
    dq = 1; //把总线拿高 释放总线
    }

    /写18b20内的数据**/
    void write_18b20(uchar dat)
    {
    uchar i;
    for(i=0;i<8;i++)
    { //写数据是低位开始
    dq = 0; //把总线拿低写时间隙开始
    dq = dat & 0x01; //向18b20总线写数据了
    delay_uint(5); // 60us
    dq = 1; //释放总线
    dat >>= 1;
    }
    }

    /读取18b20内的数据**/
    uchar read_18b20()
    {
    uchar i,value;
    for(i=0;i<8;i++)
    {
    dq = 0; //把总线拿低读时间隙开始
    value >>= 1; //读数据是低位开始
    dq = 1; //释放总线
    if(dq == 1) //开始读写数据
    value |= 0x80;
    delay_uint(5); //60us 读一个时间隙最少要保持60us的时间
    }
    return value; //返回数据
    }

    /读取温度的值 读出来的是小数**/
    uint read_temp()
    {
    uint value;
    uchar low; //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序
    init_18b20(); //初始化18b20
    write_18b20(0xcc); //跳过64位ROM
    write_18b20(0x44); //启动一次温度转换命令
    delay_uint(50); //500us

    init_18b20(); //初始化18b20

    write_18b20(0xcc); //跳过64位ROM
    write_18b20(0xbe); //发出读取暂存器命令

    low = read_18b20(); //读温度低字节
    value = read_18b20(); //读温度高字节
    value <<= 8; //把温度的高位左移8位
    value |= low; //把读出的温度低位放到value的低八位中
    value *= 0.625; //转换到温度值 小数
    return value; //返回读出的温度 带小数
    }

    /定时器0初始化程序**/
    void time_init()
    {
    EA = 1; //开总中断
    TMOD = 0X21; //定时器0、定时器1工作方式1
    ET0 = 1; //开定时器0中断
    TR0 = 1; //允许定时器0定时

    ET1 = 1; //开定时器0中断
    TR1 = 1; //允许定时器0定时
    }

    /***独立按键程序/
    uchar key_can; //按键值

    void key() //独立按键程序
    {
    static uchar key_new;
    key_can = 20; //按键值还原
    P2 |= 0x07;
    if((P2 & 0x07) != 0x07) //按键按下
    {
    if(key_500ms == 1) //连加
    {
    key_500ms = 0;
    key_new = 1;
    }
    delay_1ms(1); //按键消抖动
    if(((P2 & 0x07) != 0x07) && (key_new == 1))
    { //确认是按键按下
    key_new = 0;
    switch(P2 & 0x07)
    {
    case 0x06: key_can = 1; break; //得到k2键值
    case 0x04: key_can = 2; break; //得到k3键值
    case 0x02: key_can = 3; break; //得到k4键值
    }
    flag_lj_en = 1; //连加使能
    }
    }
    else
    {
    if(key_new == 0)
    {
    key_new = 1;
    flag_lj_en = 0; //关闭连加使能
    flag_lj_3_en = 0; //关闭3秒后使能
    key_value = 0; //清零
    key_time = 0;
    key_500ms = 0;
    }
    }
    }

    /*按键处理数码管显示函数/
    void key_with()
    {
    if(key_can == 1) //设置键
    {
    f_pwm_l = 30;
    menu_1 ++;
    if(menu_1 >= 3)
    {
    menu_1 = 0;
    smg_i = 3; //数码管显示3位
    }
    }
    if(menu_1 == 1) //设置高温报警
    {
    smg_i = 4; //数码管显示4位
    if(key_can == 2)
    {
    if(flag_lj_3_en == 0)
    t_high ++ ; //按键按下未松开自动加三次
    else
    t_high += 10; //按键按下未松开自动加三次之后每次自动加10
    if(t_high > 990)
    t_high = 990;
    }
    if(key_can == 3)
    {
    if(flag_lj_3_en == 0)
    t_high – ; //按键按下未松开自动减三次
    else
    t_high -= 10; //按键按下未松开自动减三次之后每次自动减10
    if(t_high <= t_low)
    t_high = t_low + 1;
    }
    dis_smg[0] = smg_du[t_high % 10]; //取小数显示
    dis_smg[1] = smg_du[t_high / 10 % 10] & 0xdf; //取个位显示
    dis_smg[2] = smg_du[t_high / 100 % 10] ; //取十位显示
    dis_smg[3] = 0x64; //H
    }
    if(menu_1 == 2) //设置低温报警
    {
    smg_i = 4; //数码管显示4位
    if(key_can == 2)
    {
    if(flag_lj_3_en == 0)
    t_low ++ ; //按键按下未松开自动加三次
    else
    t_low += 10; //按键按下未松开自动加三次之后每次自动加10
    if(t_low >= t_high)
    t_low = t_high - 1;
    }
    if(key_can == 3)
    {
    if(flag_lj_3_en == 0)
    t_low – ; //按键按下未松开自动减三次
    else
    t_low -= 10; //按键按下未松开自动加三次之后每次自动加10
    if(t_low <= 10)
    t_low = 10;
    }
    dis_smg[0] = smg_du[t_low % 10]; //取小数显示
    dis_smg[1] = smg_du[t_low / 10 % 10] & 0xdf; //取个位显示
    dis_smg[2] = smg_du[t_low / 100 % 10] ; //取十位显示
    dis_smg[3] = 0x3D; //L
    }
    }

    /*风扇控制函数/
    void fengshan_kz()
    {
    if(flag_en == 1)
    {
    if(temperature >= t_high) //风扇全开
    {
    TR1 = 1;
    pwm = 0;
    }
    else if((temperature < t_high) && (temperature >= t_low)) //风扇缓慢
    {
    f_pwm_l = 60;
    TR1 = 1;
    }
    else if(temperature < t_low) //关闭风扇
    {
    TR1 = 0;
    pwm = 1;
    }
    }
    }

    /*主函数/
    void main()
    {
    static uchar value;
    time_init(); //初始化定时器
    temperature = read_temp(); //先读出温度的值
    delay_1ms(650);
    temperature = read_temp(); //先读出温度的值
    dis_smg[0] = smg_du[temperature % 10]; //取温度的小数显示
    dis_smg[1] = smg_du[temperature / 10 % 10] & 0xdf; //取温度的个位显示
    dis_smg[2] = smg_du[temperature / 100 % 10] ; //取温度的十位显示
    while(1)
    {
    key(); //按键程序
    if(key_can < 10)
    {
    key_with(); //设置报警温度
    }
    if(flag_200ms == 1) //200ms 处理一次温度程序
    {
    flag_200ms = 0;
    temperature = read_temp(); //先读出温度的值
    if(menu_1 == 0)
    {
    smg_i = 3;
    dis_smg[0] = smg_du[temperature % 10]; //取温度的小数显示
    dis_smg[1] = smg_du[temperature / 10 % 10] & 0xdf; //取温度的个位显示
    dis_smg[2] = smg_du[temperature / 100 % 10] ; //取温度的十位显示
    }
    fengshan_kz(); //风扇控制函数
    value ++;
    if(value >= 4)
    {
    value = 0;
    if(miao != 0)
    {
    miao --; //时间减1
    }
    if(miao == 0)
    flag_en = 0;
    // dis_smg[3] = smg_du[miao % 10] ;
    }
    if(hw == 1) //感应到人
    {
    miao = 30;
    flag_en = 1;
    }
    }

    display(); //数码管显示函数
    }
    }

    /定时器0中断服务程序**/
    void time0_int() interrupt 1
    {
    static uchar value; //定时2ms中断一次
    TH0 = 0xf8;
    TL0 = 0x30; //2ms
    value++;
    if(value >= 150)
    {
    value = 0;
    flag_200ms = 1;
    }
    if(flag_lj_en == 1) //按下按键使能
    {
    key_time ++;
    if(key_time >= 250) //500ms
    {
    key_time = 0;
    key_500ms = 1; //500ms
    key_value ++;
    if(key_value > 3)
    {
    key_value = 10;
    flag_lj_3_en = 1; //3次后1.5秒连加大些
    }
    }
    }
    }

    /定时器1用做单片机模拟PWM 调节****/
    void Timer1() interrupt 3 //调用定时器1
    {
    static uchar value_l;
    TH1=0xff; // 定时中断一次
    TL1=0xec; //

    最后,如果有什么意见或者建议欢迎您留言给我,让我们共同学习一起进步,
    如果需要 程序完整源代码和 设计文件,请在下方留言或者私信我,看到后会第一时间回复。

    谢谢!

    展开全文
  • 基于单片机智能风扇的设计pdf,基于单片机智能风扇的设计
  • 系统电路设计总体设计方框图所示,控制器采用单片机AT89S52,温度传感器采用DS18B20,用2位LED数码管以串口传送数据实现温度显示。 主控制器 单片机AT89S52具有低电压供电和体积小等特点,四个端就能满足电路系统的...
  • AT89C51单片机:AT89C51是一种带4K字节闪烁可编程可擦除只读存储器(FPEROM—Falsh Programmable and Erasable Read Only Memory)的低电压,高性能CMOS8位微处理器,俗称单片机。该器件采用ATMEL高密度非易失...
  • 文档中包括温度传感器18b20控制直流风扇转速,并在液晶显示屏上显示出来,可以检测风扇转速,文档为开题报告
  • 基于51单片机智能红外温控风扇设计

    千次阅读 2020-05-02 22:03:48
    本产品采用单片机+最小系统+数码管显示模块+数码管驱动模块+温度采集模块+人体感应模块+风扇模块+按键模块等构成。
  • 该系统以STC89C51RC单片机最小系统为核心,利用DS18B20温度采集模块,LCD 1602显示屏、L298N电机驱动模块、HC-SR501人体感应模块、舵机控制模块、ESP8266 WIFI控制模块组成智能风扇控制系统。当有人进入室内,HC-SR...
  • 本设计包括四个按键,单片机复位按键,设置按键,加键,减键。 开机运行后读取温度值,根据默认设置上下限决定电机运行档位。没有按键按下情况下会一直运行。 按下设置键后进入设置模式,第一次按下设置温度底限,第...
  • 单片机智能温控风扇的设计(Proteus 仿真,原理图,程序,论文全套设计 数码管显示)
  • 智能温控风扇控制设计(51单片机)(原理;论文;仿真;C源代码;制作过程)
  • 此文档详细的介绍了智能风扇是如何设计,以及程序是如何编写的
1 2 3 4 5 ... 20
收藏数 446
精华内容 178
关键字:

单片机与智能风扇