找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3841|回复: 0
打印 上一主题 下一主题
收起左侧

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

[复制链接]
跳转到指定楼层
#
系统主要设计了一个基于单片机的风扇温控仪,以单片机和DS18B20传感器为核心,具有温度显示和控制风扇转速功能DS18B20传感器,将检测到的温度转化为数字信号,单片机对输入的数字信号进行分析处理,当温度高于上限值时,风扇全速旋转;当温度低于下限时,风扇停转;当温度处于上限值与下限之间时,风扇转速越慢,。图1所示为系统设计结构框图。

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


电路原理图如下:


单片机源程序如下:
  1. #include <reg52.h>
  2. #include <stdio.h>
  3. #include<intrins.h>
  4. #define uchar unsigned char
  5. #define uint unsigned int
  6. sbit dq=P3^6;

  7. sbit w4=P2^6;
  8. sbit w3=P2^4;
  9. sbit w2=P2^2;
  10. sbit w1=P2^0;
  11. sbit dp=P0^7;
  12. sbit fs=P3^7;//风扇接口
  13. sbit key_shezhi=P1^5;
  14. sbit key_jia=P1^6;
  15. sbit key_jian=P1^7;
  16. uchar flag_0;
  17. uint t_max=250,t_max_1=300;
  18. uint count=0;
  19. int wendu,t;
  20. uchar speed;                        //速度变量
  21. void delay(uint z)                                                  //延时函数
  22. {
  23.         uint x,y;
  24.         for(x=z;x>0;x--)
  25.                 for(y=110;y>0;y--);
  26. }
  27. /********************************/
  28. void pro()//按键处理函数
  29. {
  30.         if(key_shezhi==0)
  31.         {
  32.                 delay(10);
  33.                 if(key_shezhi==0)
  34.                 {
  35.                         flag_0++;
  36.                         if(flag_0>=3)
  37.                                 flag_0=0;
  38.                         while(!key_shezhi)        ;
  39.                 }
  40.         }
  41. }
  42. /**********************************/
  43. uchar code table[]={
  44. 0xc0,0xf9,0xa4,0xb0, 0x99,0x92,0x82,0xf8, 0x80,0x90,0xbf//0  1  2  3......7  8  9 的字形码
  45. };
  46. uchar code table1[]={
  47. 0xc7,0x89                                                                //  L    H   的字形码
  48. };
  49. uint temp,mm;uchar i;float f_temp;


  50. /***********************小延时函数*****************************/
  51. void delay_uint(uint q)
  52. {
  53.         while(q--);
  54. }
  55. /*******************************************************

  56. /***********************18b20初始化函数*****************************/
  57. void init_18b20()
  58. {
  59.         bit q;
  60.         dq = 1;                                //把总线拿高
  61.         delay_uint(1);            //15us
  62.         dq = 0;                                //给复位脉冲
  63.         delay_uint(80);                //750us
  64.         dq = 1;                                //把总线拿高 等待
  65.         delay_uint(10);                //110us
  66.         q = dq;                                //读取18b20初始化信号
  67.         delay_uint(20);                //200us
  68.         dq = 1;                                //把总线拿高 释放总线
  69. }

  70. /*************写18b20内的数据***************/
  71. void write_18b20(uchar dat)
  72. {
  73.         uchar i;
  74.         for(i=0;i<8;i++)
  75.         {                                         //写数据是低位开始
  76.                 dq = 0;                         //把总线拿低写时间隙开始
  77.                 dq = dat & 0x01; //向18b20总线写数据了
  78.                 delay_uint(5);         // 60us
  79.                 dq = 1;                         //释放总线
  80.                 dat >>= 1;
  81.         }        
  82. }

  83. /*************读取18b20内的数据***************/
  84. uchar read_18b20()
  85. {
  86.         uchar i,wendu;
  87.         for(i=0;i<8;i++)
  88.         {
  89.                 dq = 0;                         //把总线拿低读时间隙开始
  90.                 wendu >>= 1;         //读数据是低位开始
  91.                 dq = 1;                         //释放总线
  92.                 if(dq == 1)                 //开始读写数据
  93.                         wendu |= 0x80;
  94.                 delay_uint(5);         //60us        读一个时间隙最少要保持60us的时间
  95.         }
  96.         return wendu;                 //返回数据
  97. }

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

  107.         init_18b20();                   //初始化18b20
  108.         
  109.         write_18b20(0xcc);           //跳过64位ROM
  110.         write_18b20(0xbe);           //发出读取暂存器命令
  111.         
  112.         EA = 0;
  113.         low = read_18b20();           //读温度低字节
  114.         wendu = read_18b20();  //读温度高字节
  115.         EA = 1;
  116.         wendu <<= 8;                   //把温度的高位左移8位
  117.         wendu |= low;                   //把读出的温度低位放到value的低八位中
  118.         wendu *= 0.625;               //转换到温度值 小数
  119.         return wendu;                   //返回读出的温度 带小数
  120. }
  121. void display0()
  122. {
  123.         P0=0xff;//消隐
  124.         w1=0;                                //选通第一位数码管
  125.         if(speed>5)                        //如果speed的值>5则档位显示speed-5,比如speed=6,则显示1档
  126.         P0=table[speed-5];//显示档位
  127.         else                                //否则speed的值如果小于5,则显示0档
  128.         P0=table[0];//显示档位        
  129.         delay(2);//延迟一会
  130.         w1=1;//关闭第一位数码管
  131.                         
  132.         P0=0xff;//第二位数码管的显示原理及方法同上
  133.         w2=0;
  134.         P0=0xbf;//显示-
  135.         delay(2);
  136.         w2=1;
  137.         
  138.         P0=0xff;
  139.         w3=0;
  140.         P0=table[wendu/100];//显示温度十位

  141.         delay(2);
  142.         w3=1;
  143.         
  144.         P0=0xff;
  145.         w4=0;
  146.         P0=table[wendu%100/10];//显示温度各位
  147.         delay(2);
  148.         w4=1;        
  149. }
  150. void zi_dong()//自动温控模式
  151. {
  152. //        此函数的目的是将上限和下限的差值平均为5份,每一份对应一个速度值                14-25
  153.         if(wendu<t_max)                                                                                                                   //温度小于下限
  154.         speed=0;                                                                                                                           //速度0档
  155.         else if(wendu>=t_max&&(wendu<(uint)((t_max_1-t_max)/4+t_max)))                                           //温度大于下限并且小于(上限减去下限)除以4加下限
  156.         speed=6;                                                                                                                           //6档                14-16.75          14-15
  157.         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加下限
  158.         speed=7;                                                                                                                           //7档                16-19.5                  16-18
  159.         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加下限
  160.         speed=8;                                                                                                                           //8档                19-22.25          19-21
  161.         else if((wendu>=(uint)((float)((float)(t_max_1-t_max)/4)*3+t_max))&&wendu<t_max_1)                                   //温度大于 (上限减去下限)除以4乘以3加下限  并且小于上限
  162.         speed=9;                                                                                                                           //9档                22-24                  22-24
  163.         else if(wendu>=t_max_1)                                                                                                   //大于上限
  164.         speed=10;                                                                                                                           //10档                >25
  165. }
  166. /***************************************/
  167. void fengshan()
  168. {
  169.                 uchar m;
  170.         if(m<speed)                          //m值小于speed
  171.         fs=0;                                  //打开风扇
  172.         else if(m>=speed)          //否则
  173.         fs=1;                                  //关闭风扇

  174.         m++;                                  //m加
  175.         if(m>=10)                          //m极爱到10,也就是2ms
  176.         m=0;
  177. }

  178. /**************************************/
  179. /**************************************/
  180. void display1()
  181. {
  182.         P0=0xff;//消隐
  183.         w1=0;//选通第一位数码管
  184.         P0=table1[0];//显示   L
  185.         delay(2);//延迟一会
  186.         w1=1;//关闭第一位数码管
  187.         
  188.         P0=0xff;//第二位数码管显示方法及原理同上
  189.         w2=0;
  190.         P0=0xbf;//显示  -
  191.         delay(2);
  192.         w2=1;
  193.         
  194.         P0=0xff;
  195.         w3=0;
  196.         P0=table[t_max/100];//显示设置下限值的十位

  197.         delay(2);
  198.         w3=1;
  199.         
  200.         P0=0xff;
  201.         w4=0;
  202.         P0=table[t_max%100/10];//显示设置下限值的个位
  203.         delay(2);
  204.         w4=1;               
  205. }
  206. /**************************************/
  207. void display2()
  208. {
  209.         P0=0xff;
  210.         w1=0;
  211.         P0=table1[1];//显示  H
  212.         delay(2);
  213.         w1=1;
  214.         
  215.         P0=0xff;
  216.         w2=0;
  217.         P0=0xbf;//显示  -
  218.         delay(2);
  219.         w2=1;
  220.         
  221.         P0=0xff;
  222.         w3=0;
  223.         P0=table[t_max_1/100];//显示设置上限值得十位

  224.         delay(2);
  225.         w3=1;
  226.         
  227.         P0=0xff;
  228.         w4=0;
  229.         P0=table[t_max_1%100/10];//显示设置上限值得个位
  230.         delay(2);
  231.         w4=1;               
  232. }

  233. /***************************************/
  234. void shezhi()
  235. {
  236.         if(flag_0==1)//flag_0==0时,为正常显示。等于1时,为设置下限位值。等2时为设置上限为置
  237.         {
  238.                 if(key_jia==0)//当设置下限位值时,按下加键
  239.                 {
  240.                         delay(10);//延迟消抖
  241.                         if(key_jia==0)//确认加键已按下
  242.                         {
  243.                                 t_max=t_max+10;//对下限位值每次加10
  244.                                 if(t_max>=t_max_1)                                //防止低温度高于高温度//如果下限位值设置时超过了上限位置
  245.                                         t_max=t_max_1-10;                                 //则让下限位值-10
  246.                                 while(!key_jia);//松手检测
  247.                         }
  248.                 }
  249.                 if(key_jian==0)//如果键键按下了,同上
  250.                 {
  251.                         delay(10);
  252.                         if(key_jian==0)
  253.                         {
  254.                                 t_max=t_max-10;
  255.                                 while(!key_jian);
  256.                         }
  257.                 }
  258.         }
  259.         if(flag_0==2)//对上限位设置时
  260.         {
  261.                 if(key_jia==0)
  262.                 {
  263.                         delay(10);
  264.                         if(key_jia==0)
  265.                         {
  266.                                 t_max_1=t_max_1+10;
  267.                                 while(!key_jia);
  268.                         }
  269.                 }
  270.                 if(key_jian==0)
  271.                 {
  272.                         delay(10);
  273.                         if(key_jian==0)
  274.                         {
  275.                                 t_max_1=t_max_1-10;
  276.                                 if(t_max_1<=t_max)                         //防止高温度小于低温度
  277.                                         t_max_1=t_max+10;
  278.                                 while(!key_jian);
  279.                         }
  280.                 }
  281.         }
  282. }
  283. void display()
  284. {
  285.                 if(flag_0==0)//flag_0==0时,为正常显示。等于1时,为设置下限位值。等2时为设置上限为置
  286.                         display0();//正常显示
  287.                 else if(flag_0==1)
  288.                         display1();//设置下限时的显示
  289.                 else if(flag_0==2)
  290.                         display2();        //设置上限时的显示
  291. }
  292. void main()
  293. {
  294.         while(1)
  295.         {

  296.         
  297.                 read_18b20();//读取温度传感器中的数据
  298.                
  299.                 t=read_temp();//把读出的数据赋给t
  300.                 if(t>=0&&t<=1250)  //温度合法范围,不在这个范围就是没有获取到合适的值
  301.                 {
  302.                         wendu=t;
  303.                 }
  304.                 pro();//按键处理
  305.                 display();//显示处理
  306.                 shezhi();//设置按键处理
  307.                 fengshan();//风扇处理
  308.                 zi_dong();//自动挡风扇处理
  309.         }
  310. }
复制代码

全部资料51hei下载地址:
小风扇.7z (269.68 KB, 下载次数: 35)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表