51单片机+三极管驱动的温控小风扇代码与Proteus仿真原理图

[复制链接]
查看14 | 回复0 | 2021-6-14 02:55:11 | 显示全部楼层 |阅读模式
系统主要设计了一个基于单片机的风扇温控仪,以单片机和DS18B20传感器为核心,具有温度显示和控制风扇转速功能DS18B20传感器,将检测到的温度转化为数字信号,单片机对输入的数字信号进行分析处理,当温度高于上限值时,风扇全速旋转;当温度低于下限时,风扇停转;当温度处于上限值与下限之间时,风扇转速越慢,。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
1.png

原理图:
2.png

部分源码:完整源码请下载附件
  1. /***********************18b20初始化函数*****************************/
  2. void init_18b20()
  3. {
  4.         bit q;
  5.         dq = 1;                                //把总线拿高
  6.         delay_uint(1);            //15us
  7.         dq = 0;                                //给复位脉冲
  8.         delay_uint(80);                //750us
  9.         dq = 1;                                //把总线拿高 等待
  10.         delay_uint(10);                //110us
  11.         q = dq;                                //读取18b20初始化信号
  12.         delay_uint(20);                //200us
  13.         dq = 1;                                //把总线拿高 释放总线
  14. }

  15. /*************写18b20内的数据***************/
  16. void write_18b20(uchar dat)
  17. {
  18.         uchar i;
  19.         for(i=0;i<8;i++)
  20.         {                                         //写数据是低位开始
  21.                 dq = 0;                         //把总线拿低写时间隙开始
  22.                 dq = dat & 0x01; //向18b20总线写数据了
  23.                 delay_uint(5);         // 60us
  24.                 dq = 1;                         //释放总线
  25.                 dat >>= 1;
  26.         }        
  27. }

  28. /*************读取18b20内的数据***************/
  29. uchar read_18b20()
  30. {
  31.         uchar i,wendu;
  32.         for(i=0;i<8;i++)
  33.         {
  34.                 dq = 0;                         //把总线拿低读时间隙开始
  35.                 wendu >>= 1;         //读数据是低位开始
  36.                 dq = 1;                         //释放总线
  37.                 if(dq == 1)                 //开始读写数据
  38.                         wendu |= 0x80;
  39.                 delay_uint(5);         //60us        读一个时间隙最少要保持60us的时间
  40.         }
  41.         return wendu;                 //返回数据
  42. }

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

  52.         init_18b20();                   //初始化18b20
  53.         
  54.         write_18b20(0xcc);           //跳过64位ROM
  55.         write_18b20(0xbe);           //发出读取暂存器命令
  56.         
  57.         EA = 0;
  58.         low = read_18b20();           //读温度低字节
  59.         wendu = read_18b20();  //读温度高字节
  60.         EA = 1;
  61.         wendu <<= 8;                   //把温度的高位左移8位
  62.         wendu |= low;                   //把读出的温度低位放到value的低八位中
  63.         wendu *= 0.625;               //转换到温度值 小数
  64.         return wendu;                   //返回读出的温度 带小数
  65. }
  66. void display0()
  67. {
  68.         P0=0xff;//消隐
  69.         w1=0;                                //选通第一位数码管
  70.         if(speed>5)                        //如果speed的值>5则档位显示speed-5,比如speed=6,则显示1档
  71.         P0=table[speed-5];//显示档位
  72.         else                                //否则speed的值如果小于5,则显示0档
  73.         P0=table[0];//显示档位        
  74.         delay(2);//延迟一会
  75.         w1=1;//关闭第一位数码管
  76.                         
  77.         P0=0xff;//第二位数码管的显示原理及方法同上
  78.         w2=0;
  79.         P0=0xbf;//显示-
  80.         delay(2);
  81.         w2=1;
  82.         
  83.         P0=0xff;
  84.         w3=0;
  85.         P0=table[wendu/100];//显示温度十位

  86.         delay(2);
  87.         w3=1;
  88.         
  89.         P0=0xff;
  90.         w4=0;
  91.         P0=table[wendu%100/10];//显示温度各位
  92.         delay(2);
  93.         w4=1;        
  94. }
  95. void zi_dong()//自动温控模式
  96. {
  97. //        此函数的目的是将上限和下限的差值平均为5份,每一份对应一个速度值                14-25
  98.         if(wendu<t_max)                                                                                                                   //温度小于下限
  99.         speed=0;                                                                                                                           //速度0档
  100.         else if(wendu>=t_max&&(wendu<(uint)((t_max_1-t_max)/4+t_max)))                                           //温度大于下限并且小于(上限减去下限)除以4加下限
  101.         speed=6;                                                                                                                           //6档                14-16.75          14-15
  102.         else if((wendu>=(uint)((float)(t_max_1-t_max)/4+t_max))&&(wendu<(uint)((float)(t_max_1-t_max)/2+t_max)))           //温度大于 (上限减去下限)除以4加下限  并且小于(上限减去下限)除以2加下限
  103.         speed=7;                                                                                                                           //7档                16-19.5                  16-18
  104.         else if((wendu>=(uint)(t_max_1-t_max)/2+t_max)&&(wendu<(uint)((float)((float)(t_max_1-t_max)/4)*3+t_max)))   //温度大于 (上限减去下限)除以2加下限  并且小于(上限减去下限)除以4乘以3加下限
  105.         speed=8;                                                                                                                           //8档                19-22.25          19-21
  106.         else if((wendu>=(uint)((float)((float)(t_max_1-t_max)/4)*3+t_max))&&wendu<t_max_1)                                   //温度大于 (上限减去下限)除以4乘以3加下限  并且小于上限
  107.         speed=9;                                                                                                                           //9档                22-24                  22-24
  108.         else if(wendu>=t_max_1)                                                                                                   //大于上限
  109.         speed=10;                                                                                                                           //10档                >25
  110. }
  111. /***************************************/
  112. void fengshan()
  113. {
  114.                 uchar m;
  115.         if(m<speed)                          //m值小于speed
  116.         fs=0;                                  //打开风扇
  117.         else if(m>=speed)          //否则
  118.         fs=1;                                  //关闭风扇

  119.         m++;                                  //m加
  120.         if(m>=10)                          //m极爱到10,也就是2ms
  121.         m=0;
  122. }

  123. /**************************************/
  124. /**************************************/
  125. void display1()
  126. {
  127.         P0=0xff;//消隐
  128.         w1=0;//选通第一位数码管
  129.         P0=table1[0];//显示   L
  130.         delay(2);//延迟一会
  131.         w1=1;//关闭第一位数码管
  132.         
  133.         P0=0xff;//第二位数码管显示方法及原理同上
  134.         w2=0;
  135.         P0=0xbf;//显示  -
  136.         delay(2);
  137.         w2=1;
  138.         
  139.         P0=0xff;
  140.         w3=0;
  141.         P0=table[t_max/100];//显示设置下限值的十位

  142.         delay(2);
  143.         w3=1;
  144.         
  145.         P0=0xff;
  146.         w4=0;
  147.         P0=table[t_max%100/10];//显示设置下限值的个位
  148.         delay(2);
  149.         w4=1;               
  150. }
  151. /**************************************/
  152. void display2()
  153. {
  154.         P0=0xff;
  155.         w1=0;
  156.         P0=table1[1];//显示  H
  157.         delay(2);
  158.         w1=1;
  159.         
  160.         P0=0xff;
  161.         w2=0;
  162.         P0=0xbf;//显示  -
  163.         delay(2);
  164.         w2=1;
  165.         
  166.         P0=0xff;
  167.         w3=0;
  168.         P0=table[t_max_1/100];//显示设置上限值得十位

  169.         delay(2);
  170.         w3=1;
  171.         
  172.         P0=0xff;
  173.         w4=0;
  174.         P0=table[t_max_1%100/10];//显示设置上限值得个位
  175.         delay(2);
  176.         w4=1;               
  177. }

  178. /***************************************/
  179. void shezhi()
  180. {
  181.         if(flag_0==1)//flag_0==0时,为正常显示。等于1时,为设置下限位值。等2时为设置上限为置
  182.         {
  183.                 if(key_jia==0)//当设置下限位值时,按下加键
  184.                 {
  185.                         delay(10);//延迟消抖
  186.                         if(key_jia==0)//确认加键已按下
  187.                         {
  188.                                 t_max=t_max+10;//对下限位值每次加10
  189.                                 if(t_max>=t_max_1)                                //防止低温度高于高温度//如果下限位值设置时超过了上限位置
  190.                                         t_max=t_max_1-10;                                 //则让下限位值-10
  191.                                 while(!key_jia);//松手检测
  192.                         }
  193.                 }
  194.                 if(key_jian==0)//如果键键按下了,同上
  195.                 {
  196.                         delay(10);
  197.                         if(key_jian==0)
  198.                         {
  199.                                 t_max=t_max-10;
  200.                                 while(!key_jian);
  201.                         }
  202.                 }
  203.         }
  204.         if(flag_0==2)//对上限位设置时
  205.         {
  206.                 if(key_jia==0)
  207.                 {
  208.                         delay(10);
  209.                         if(key_jia==0)
  210.                         {
  211.                                 t_max_1=t_max_1+10;
  212.                                 while(!key_jia);
  213.                         }
  214.                 }
  215.                 if(key_jian==0)
  216.                 {
  217.                         delay(10);
  218.                         if(key_jian==0)
  219.                         {
  220.                                 t_max_1=t_max_1-10;
  221.                                 if(t_max_1<=t_max)                         //防止高温度小于低温度
  222.                                         t_max_1=t_max+10;
  223.                                 while(!key_jian);
  224.                         }
  225.                 }
  226.         }
  227. }
  228. void display()
  229. {
  230.                 if(flag_0==0)//flag_0==0时,为正常显示。等于1时,为设置下限位值。等2时为设置上限为置
  231.                         display0();//正常显示
  232.                 else if(flag_0==1)
  233.                         display1();//设置下限时的显示
  234.                 else if(flag_0==2)
  235.                         display2();        //设置上限时的显示
  236. }
  237. void main()
  238. {
  239.         while(1)
  240.         {

  241.         
  242.                 read_18b20();//读取温度传感器中的数据
  243.                
  244.                 t=read_temp();//把读出的数据赋给t
  245.                 if(t>=0&&t<=1250)  //温度合法范围,不在这个范围就是没有获取到合适的值
  246.                 {
  247.                         wendu=t;
  248.                 }
  249.                 pro();//按键处理
  250.                 display();//显示处理
  251.                 shezhi();//设置按键处理
  252.                 fengshan();//风扇处理
  253.                 zi_dong();//自动挡风扇处理
  254.         }
  255. }
复制代码
完整源码和proteus仿真文件: 小风扇.zip (209.04 KB, 售价: 5 工控币)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则