找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2195|回复: 5
收起左侧

用单片机开发板做温控风扇PWM调速 源程序

[复制链接]
yrx0203 发表于 2021-1-9 23:28 | 显示全部楼层 |阅读模式
能够利用PWM调速原理实现对系统的控制对象(直流电机)进行转速控制,当温度低于系统设置温度下限时直流电机停止工作,到达设置温度的下限和上限之间时以1档的速度工作,当温度高于系统设置温度上限时直流电机全速工作其中上下限温度可以在数码管上人工设置,数码管上能够显示当前的实时温度。

单片机源程序如下:
  1. #include<reg51.h>
  2. #include<intrins.h>                         //包含头文件
  3. typedef unsigned int u16;          //对数据类型进行声明定义 ,用u16表示 unsigned int
  4. typedef unsigned char u8;         //                用 u8表示  unsigned char

  5. /**定义各引脚**/
  6. sbit led=P2^0;//led
  7. sbit dj=P1^0;//电机
  8. sbit DQ=P3^7;//温度传感器
  9. //////////按键接口/////////////////////////////////
  10. sbit key1=P3^1;//设置温度
  11. sbit key2=P3^0;//温度加
  12. sbit key3=P3^2;//温度减
  13. ///////////数码管的四个位/////////////////////////////
  14. sbit LSA=P2^2;
  15. sbit LSB=P2^3;
  16. sbit LSC=P2^4;
  17.                           
  18. /*****共阴数码管段选*****/
  19. u8 table[22]=
  20. {0x3F,0x06,0x5B,0x4F,0x66,
  21. 0x6D,0x7D,0x07,0x7F,0x6F,
  22. 0x77,0x7C,0x39,0x5E,0x79,0x71,
  23. 0x40,0x38,0x76,0x00,0xff,0x37};//'-',L,H,灭,全亮,n         16-21

  24. /***定义各变量***/
  25. u16 wen_du;//温度变量  
  26. u16 shang,xia; //对比温度暂存变量
  27. u8 dang;//档位显示
  28. u8 flag;         //标志位
  29. u8 d1,d2,d3;//显示数据暂存变量
  30. u8 j        ;

  31. /***延时函数***/
  32. void delay(u16 ms)                //延时函数,大约延时25us
  33. {
  34.         u8 x;
  35.         for(ms;ms>0;ms--)
  36.                 for(x=10;x>0;x--);
  37. }


  38. /***********ds18b20延迟子函数(晶振12MHz )*******/
  39. void delay_18B20(u16 i)
  40. {
  41.         while(i--);
  42. }
  43. /**********ds18b20初始化函数**********************/
  44. void Init_DS18B20()
  45. {
  46.          u8 x=0;
  47.          DQ=1;          //DQ复位
  48.          delay_18B20(8);  //稍做延时
  49.          DQ=0;          //单片机将DQ拉低
  50.          delay_18B20(80); //精确延时 大于 480us
  51.          DQ=1;          //拉高总线
  52.          delay_18B20(14);
  53.          x=DQ;            //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
  54.          delay_18B20(20);
  55. }
  56. /***********ds18b20读一个字节**************/  
  57. u8 ReadOneChar()
  58. {
  59.         u8 i=0;
  60.         u8 dat=0;
  61.         for (i=8;i>0;i--)
  62.          {
  63.                   DQ=0; // 给脉冲信号
  64.                   dat>>=1;
  65.                   DQ=1; // 给脉冲信号
  66.                   if(DQ)
  67.                   dat|=0x80;
  68.                   delay_18B20(4);
  69.          }
  70.          return(dat);
  71. }
  72. /*************ds18b20写一个字节****************/  
  73. void WriteOneChar(u8 dat)
  74. {
  75.          u8 i=0;
  76.          for (i=8;i>0;i--)
  77.          {
  78.                   DQ=0;
  79.                  DQ=dat&0x01;
  80.             delay_18B20(5);
  81.                  DQ=1;
  82.             dat>>=1;
  83.         }
  84. }
  85. /**************读取ds18b20当前温度************/
  86. void ReadTemperature()
  87. {
  88.         u8 a=0;
  89.         u8 b=0;
  90.         u8 t=0;
  91.         Init_DS18B20();
  92.         WriteOneChar(0xCC);            // 跳过读序号列号的操作
  93.         WriteOneChar(0x44);         // 启动温度转换
  94.         delay_18B20(100);       // this message is wery important
  95.         Init_DS18B20();
  96.         WriteOneChar(0xCC);         //跳过读序号列号的操作
  97.         WriteOneChar(0xBE);         //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
  98.         delay_18B20(100);
  99.         a=ReadOneChar();            //读取温度值低位
  100.         b=ReadOneChar();                   //读取温度值高位
  101.         wen_du=((b*256+a)>>4);    //当前采集温度值除16得实际温度值
  102. }


  103. /***数码管显示函数***/
  104. void display()//显示温度
  105. {
  106.         LSA=1;LSB=1;LSC=0;P0=table[d1];delay(10); //第1位
  107.         P0=0x00;LSA=1;LSB=1;LSC=1;delay(1);
  108.          
  109.         LSA=0;LSB=1;LSC=0;P0=table[16];delay(10);//第2位
  110.         P0=0x00;LSA=1;LSB=1;LSC=1;delay(1);

  111.         LSA=1;LSB=0;LSC=0;P0=table[d2]; delay(10);//第3位
  112.         P0=0x00;LSA=1;LSB=1;LSC=1;delay(1);

  113.         LSA=0;LSB=0;LSC=0;P0=table[d3];delay(10);//第4位
  114.         P0=0x00;LSA=1;LSB=1;LSC=1;delay(1);
  115. }


  116. /***键盘自动扫描及消抖***/
  117. /***以及功能***/
  118. void zi_keyscan()//自动模式按键扫描函数
  119. {
  120.         if(key1==0)                                                          //设置键按下
  121.         {
  122.                 delay(30);                                                  //延时去抖
  123.                 if(key1==0)flag=1;                                  //再次判断按键,按下的话进入设置状态
  124.                 while(key1==0);//松手检测                  //按键释放
  125.         }
  126.         while(flag==1)                                                  //进入设置上限状态
  127.         {
  128.                 d1=18;d2=shang/10;d3=shang%10;          //显示字母H 和上限温度值
  129.                 display();                                                  //调用显示函数
  130.                 if(key1==0)                                                  //判断设置键是否按下
  131.                 {
  132.                         delay(30);                                          //延时去抖
  133.                         if(key1==0)flag=2;                          //按键按下,进入设置下限模式
  134.                         while(key1==0);//松手检测
  135.                 }
  136.                 if(key2==0)                                                  //加键按下
  137.                 {
  138.                         delay(30);                                          //延时去抖
  139.                         if(key2==0)                                          //加键按下
  140.                         {
  141.                                 shang+=5;                                  //上限加5
  142.                                 if(shang>=100)shang=100;  //上限最大加到100
  143.                         }while(key2==0);//松手检测
  144.                 }
  145.                 if(key3==0)                                                  //减键按下
  146.                 {
  147.                         delay(30);                                          //延时去抖
  148.                         if(key3==0)                                          //减键按下
  149.                         {
  150.                                 shang-=1;                                  //上限减1
  151.                                 if(shang<=10)shang=10;          //上限最小减到10
  152.                         }while(key3==0);//松手检测
  153.                 }               
  154.         }
  155.         while(flag==2)                                                  //设置下限
  156.         {
  157.                 d1=17;d2=xia/10;d3=xia%10;                  //显示字母L 显示下限温度值
  158.                 display();                                                  //注释同上
  159.                 if(key1==0)
  160.                 {
  161.                         delay(30);
  162.                         if(key1==0)flag=0;
  163.                         while(key1==0);//松手检测
  164.                 }
  165.                 if(key2==0)
  166.                 {
  167.                         delay(30);
  168.                         if(key2==0)
  169.                         {
  170.                                 xia+=5;
  171.                                 if(xia>=95)xia=95;        
  172.                         }while(key2==0);//松手检测
  173.                 }
  174.                 if(key3==0)
  175.                 {
  176.                         delay(30);
  177.                         if(key3==0)
  178.                         {
  179.                                 xia-=1;
  180.                                 if(xia<=0)xia=0;        
  181.                         }while(key3==0);//松手检测
  182.                 }               
  183.         }
  184. }


  185. /***数码管显示档位及温度***/
  186. /***键盘扫描***/
  187. /**根据按键显示档位及温度**/
  188. /*PWM*/
  189. void zi_dong()//自动温控模式
  190. {
  191.         u8 i;
  192.         d1=dang;d2=wen_du/10;d3=wen_du%10;                //显示档位,显示当前温度值
  193.         zi_keyscan();//按键扫描函数
  194.         display();         //调用显示函数
  195.         if(wen_du<xia){dj=0;dang=0;}//低于下限  档位为0 电机停止
  196.         if((wen_du>=xia)&&(wen_du<=shang))//温度大于下限,小于上限  1挡
  197.         {
  198.                 dang=1;                                                                                        //档位置1
  199.                 for(i=0;i<3;i++){dj=0;display();zi_keyscan();}        //PWM通过延时得到
  200.                 for(i=0;i<6;i++){dj=1;display();zi_keyscan();}               
  201.         }
  202.         if(wen_du>shang){dj=1;dang=2;}//高温全速
  203. }


  204. /***主函数***/
  205. void main()                  //主函数
  206. {
  207.         led=0;//点亮led判断单片机是否运行
  208.         
  209.         dj=0;                  //电机开
  210.         shang=22;
  211.         xia=19;                  //初始上下限值
  212.         for(j=0;j<80;j++)          //先读取温度值,防止开机显示85
  213.         ReadTemperature();
  214.         while(1)                          //进入while循环
  215.         {        
  216.                 ReadTemperature();        //读取温度值
  217.                 for(j=0;j<100;j++)zi_dong();//自动温控模式
  218.         }
  219. }
复制代码

Keil工程文件hex文件51hei提供下载(如果自己会编译就不必下载了):
普中板子,温控.zip (27.28 KB, 下载次数: 32)

评分

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

查看全部评分

回复

使用道具 举报

 楼主| yrx0203 发表于 2021-1-10 11:14 来自手机 | 显示全部楼层
用到的部分包括DS18B20,数码管,ULN2003放大电路模块,直流电机(小马达))
回复

使用道具 举报

 楼主| yrx0203 发表于 2021-1-10 11:16 来自手机 | 显示全部楼层
还有独立按键
回复

使用道具 举报

 楼主| yrx0203 发表于 2021-1-10 11:20 来自手机 | 显示全部楼层
想要修改的话,也很简单。数码管驱动模块用了138译码器,你们如果不用,就把数码管显示函数改一下。然后电机用了ULN2003。其他的你就响应地修改一下引脚就好了

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

人人学会单片机 发表于 2021-1-15 20:54 | 显示全部楼层
风扇调速器.jpg
我前段时间就做过类似这种的,也是DS18B20测温,控制电脑四线风扇。OLED显示。带蜂鸣器警报,莫尔斯代码的那种。

你的这个DS18B20的初始化有死等,建议使用计数方式延迟。释放CPU效率。
回复

使用道具 举报

 楼主| yrx0203 发表于 2021-1-17 23:47 来自手机 | 显示全部楼层
人人学会单片机 发表于 2021-1-15 20:54
我前段时间就做过类似这种的,也是DS18B20测温,控制电脑四线风扇。OLED显示。带蜂鸣器警报,莫尔斯代码 ...

好的,谢谢
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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