找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8968|回复: 4
收起左侧

基于单片机的可控硅智能调速风扇控制系统

[复制链接]
ID:297879 发表于 2018-3-27 19:29 | 显示全部楼层 |阅读模式
设计内容:

1、单片机分析采集到的数字温度信号,再通过可控硅对风扇电机进行调速。
2、用户可以在一定范围内设置电风扇的最低工作温度和最高工作温度。当温度低于所设置温度时,电风扇将自动关闭,当高于此温度时电风扇又将重新启动。
3、温度显示在LED数码管上
4、设计硬件电路,并制作实物。

ALIM1063.JPG ALIM1064.JPG

全部资料:
QQ截图20180327192634.png

主要程序代码
主要程序代码及说明(见注释语句)如下:
数字温度传感器模块和显示子模块程序:
  1. #include <reg52.h>        //调用单片机头文件
  2. #define uchar unsigned char //无符号字符型 宏定义  变量范围0~255
  3. #define uint unsigned int //无符号整型 宏定义    变量范围0~65535
  4. #include "eeprom52.h"
  5. //数码管段选定义   0    1   2 3   4   5 6   7   8  9   
  6. Ucharcodesmg_du[]={0x28,0xee,0x42,0x52,0xe5,0xa8,0x41,0xe7,0x20,0xa0,
  7. 0x60,0x25,0x39,0x26,0x31,0x71,0xff};   //断码
  8. //数码管位选定义
  9. uchar code smg_we[]={0xef,0xdf,0xbf,0x7f};
  10. uchar dis_smg[8] = {0x28,0xee,0x32,0xa2,0xe4,0x92,0x82,0xf8};  
  11. uchar smg_i = 3;    //显示数码管的个位数
  12. sbit dq   = P2^4;    //18b20 IO口的定义
  13. bit flag_lj_en;       //按键连加使能
  14. bit flag_lj_3_en;     //按键连3次连加后使能  加的数就越大了
  15. uchar key_time,key_value;     //用做连加的中间变量
  16. bit key_500ms  ;
  17. sbit pwm = P2^3;  
  18. uchar f_pwm_l ;    //越小越暗
  19. uint temperature ;  //
  20. bit flag_300ms ;
  21. uchar menu_1;       //菜单设计的变量
  22. uint t_high = 300,t_low = 100;    //温度上下限报警值
  23. /********************1ms延时函数*************************/
  24. void delay_1ms(uint q)
  25. {
  26.    uint i,j;
  27.    for(i=0;i<q;i++)
  28.        for(j=0;j<120;j++);
  29. }
  30. /***********************小延时函数*************************/
  31. void delay_uint(uint q)
  32. {
  33.    while(q--);
  34. }
  35. /***********************数码显示函数**********************/
  36. void display()
  37. {
  38.    static uchar i;   
  39.    i++;
  40.    if(i >= smg_i)
  41.        i = 0;
  42.    P1 = 0xff;          //消隐
  43.    P3 = smg_we;            //位选
  44.    P1 = dis_smg;       //段选           
  45. }
  46. /***************把数据保存到单片机内部eepom中***************/
  47. void write_eeprom()
  48. {
  49.    SectorErase(0x2000);
  50.    byte_write(0x2000,t_high % 256);
  51.    byte_write(0x2001,t_high / 256);
  52.    byte_write(0x2002,t_low % 256);
  53.    byte_write(0x2003,t_low / 256);
  54.    byte_write(0x2055,a_a);
  55. }
  56. /*************把数据从单片机内部eeprom中读出来**************/
  57. void read_eeprom()
  58. {
  59.    t_high  = byte_read(0x2001);
  60.    t_high <<= 8;
  61.    t_high  |= byte_read(0x2000);
  62.    t_low   = byte_read(0x2003);
  63.    t_low <<= 8;
  64.    t_low   |= byte_read(0x2002);
  65.    a_a      = byte_read(0x2055);
  66. }
  67. /**************开机初始化保存的数据*****************/
  68. void init_eeprom()
  69. {
  70.    read_eeprom();        //先读
  71.    if(a_a != 22)     //新的单片机初始单片机内问eeprom
  72.    {
  73.        t_high = 320;
  74.        t_low  = 280;
  75.        a_a = 22;
  76.        write_eeprom();      //保存数据
  77.    }   
  78. }
  79. /*******************18b20初始化函数*************************/
  80. void init_18b20()
  81. {
  82.    bit q;
  83.    dq = 1;                //把总线拿高
  84.    delay_uint(1);       //15us
  85.    dq = 0;                //给复位脉冲
  86.    delay_uint(80);       //750us
  87.    dq = 1;                //把总线拿高 等待
  88.    delay_uint(10);       //110us
  89.    q = dq;                //读取18b20初始化信号
  90.    delay_uint(20);       //200us
  91.    dq = 1;                //把总线拿高 释放总线
  92. }
  93. /*************写18b20内的数据***************/
  94. void write_18b20(uchar dat)
  95. {
  96.    uchar i;
  97.    for(i=0;i<8;i++)
  98.    {                    //写数据是低位开始
  99.        dq = 0;             //把总线拿低写时间隙开始
  100.        dq = dat & 0x01; //向18b20总线写数据了
  101.        delay_uint(5);     // 60us
  102.        dq = 1;             //释放总线
  103.        dat >>= 1;
  104.    }   
  105. }
  106. /*************读取18b20内的数据***************/
  107. uchar read_18b20()
  108. {
  109.    uchar i,value;
  110.    for(i=0;i<8;i++)
  111.    {
  112.        dq = 0;             //把总线拿低读时间隙开始
  113.        value >>= 1;   //读数据是低位开始
  114.        dq = 1;             //释放总线
  115.        if(dq == 1)        //开始读写数据
  116.            value |= 0x80;
  117.        delay_uint(5);     //60us    读一个时间隙最少要保持60us的时间
  118.    }
  119.    return value;      //返回数据
  120. }
  121. /*************读取温度的值 读出来的是小数***************/
  122. uint read_temp()
  123. {
  124.    uint value;
  125.    uchar low;            //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序
  126.    init_18b20();        //初始化18b20
  127.    EA = 0;
  128.    write_18b20(0xcc);      //跳过64位ROM
  129.    write_18b20(0x44);      //启动一次温度转换命令
  130.    EA = 1;
  131.    delay_uint(50);          //500us
  132.    init_18b20();        //初始化18b20
  133.    
  134.    EA = 0;
  135.    write_18b20(0xcc);      //跳过64位ROM
  136.    write_18b20(0xbe);      //发出读取暂存器命令
  137.    
  138.    low = read_18b20();     //读温度低字节
  139.    value =read_18b20();  //读温度高字节
  140.    EA = 1;
  141.    value <<= 8;         //把温度的高位左移8位
  142.    value |= low;        //把读出的温度低位放到value的低八位中
  143.    value *= 0.625;          //转换到温度值 小数
  144.    return value;        //返回读出的温度 带小数
  145. }
  146. /*************定时器0初始化程序***************/
  147. void time_init()   
  148. {
  149.    EA   = 1;        //开总中断
  150.    TMOD = 0X11;    //定时器0、定时器1工作方式1
  151.    ET0  = 1;        //开定时器0中断
  152.    TR0  = 1;        //允许定时器0定时
  153.    ET1  = 1;        //开定时器0中断
  154.    TR1  = 0;        //允许定时器0定时
  155. }
  156. /********************独立按键程序*****************/
  157. uchar key_can;    //按键值
  158. void key()     //独立按键程序
  159. {
  160.    static uchar key_new;
  161.    key_can = 20;                   //按键值还原
  162.    P2 |= 0x07;
  163.    if((P2 & 0x07) !=0x07)      //按键按下
  164.    {
  165.        if(key_500ms == 1)   //连加
  166.        {
  167.            key_500ms = 0;
  168.            key_new = 1;
  169.        }
  170.        delay_1ms(1);        //按键消抖动
  171.        if(((P2 & 0x07) != 0x07) && (key_new == 1))
  172.        {                       //确认是按键按下
  173.            key_new = 0;
  174.            switch(P2 & 0x07)
  175.            {
  176.                case 0x06: key_can = 3; break;     //得到k2键值
  177.                case 0x05: key_can = 2; break;     //得到k3键值
  178.                case 0x03: key_can = 1; break;     //得到k4键值
  179.            }
  180.            flag_lj_en = 1;    //连加使能
  181.        }           
  182.    }
  183.    else
  184.    {
  185.        if(key_new == 0)
  186.        {
  187.            key_new = 1;
  188.            write_eeprom();       //保存数据
  189.            flag_lj_en = 0;       //关闭连加使能
  190.            flag_lj_3_en = 0; //关闭3秒后使能
  191.            key_value = 0;        //清零
  192.            key_time = 0;
  193.            key_500ms = 0;
  194.        }
  195.    }   
  196. }
  197. /****************按键处理数码管显示函数***************/
  198. void key_with()
  199. {
  200.    if(key_can == 1)    //设置键
  201.    {
  202.        f_pwm_l = 30;
  203.        menu_1 ++;
  204.        if(menu_1 >= 3)
  205.        {
  206.            menu_1 = 0;
  207.            smg_i = 3;       //数码管显示3位
  208.        }
  209.    }
  210.    if(menu_1 == 1)           //设置高温报警
  211.    {
  212.        smg_i = 4;       //数码管显示4位
  213.        if(key_can == 2)
  214.        {
  215.            if(flag_lj_3_en == 0)
  216.                t_high ++ ;       //按键按下未松开自动加三次  
  217.            else
  218.                t_high += 10; //按键按下未松开自动加三次之后每次自动加10
  219.            if(t_high > 990)
  220.                t_high = 990;
  221.        }
  222.        if(key_can == 3)
  223.        {
  224.            if(flag_lj_3_en == 0)
  225.                t_high -- ;       //按键按下未松开自动减三次  
  226.            else
  227.                t_high -= 10; //按键按下未松开自动减三次之后每次自动减10
  228.            if(t_high <= t_low)
  229.                t_high = t_low + 1;
  230.        }
  231.        dis_smg[0] = smg_du[t_high % 10];             //取小数显示
  232.        dis_smg[1] = smg_du[t_high / 10 % 10] & 0xdf;  //取个位显示
  233.        dis_smg[2] = smg_du[t_high / 100 % 10] ;     //取十位显示
  234.        dis_smg[3] = 0x64;    //H
  235.    }   
  236.    if(menu_1 == 2)           //设置低温报警
  237.    {
  238.        smg_i = 4;       //数码管显示4位
  239.        if(key_can == 2)
  240.        {
  241.            if(flag_lj_3_en == 0)
  242.                t_low ++ ;         //按键按下未松开自动加三次  
  243.            else
  244.                t_low += 10;      //按键按下未松开自动加三次之后每次自动加10
  245.            if(t_low >= t_high)
  246.                t_low = t_high - 1;
  247.        }
  248.        if(key_can == 3)
  249.        {
  250.            if(flag_lj_3_en == 0)
  251.                t_low -- ;         //按键按下未松开自动减三次  
  252.            else
  253.                t_low -= 10;      //按键按下未松开自动加三次之后每次自动加10
  254.            if(t_low <= 10)
  255.                t_low = 10;
  256.        }
  257.        dis_smg[0] = smg_du[t_low % 10];              //取小数显示
  258.        dis_smg[1] = smg_du[t_low / 10 % 10] & 0xdf;   //取个位显示
  259.        dis_smg[2] = smg_du[t_low / 100 % 10] ;          //取十位显示
  260.        dis_smg[3] = 0x3D;     //L
  261.    }   
  262. }  
  263. /****************风扇控制函数***************/
  264. void fengshan_kz()
  265. {
  266. // static uchar value;
  267.    if(temperature >=t_high)    //风扇全开
  268.    {   
  269.        TR1 = 1;
  270.        pwm = 0;
  271.    }
  272.    else if((temperature< t_high)  && (temperature>= t_low))         //风扇缓慢
  273.    {
  274.        f_pwm_l = 60;     
  275.        TR1 = 1;
  276.    }
  277.    else if(temperature< t_low)     //关闭风扇
  278.    {
  279.        TR1 = 0;
  280.        pwm = 1;
  281.    }           
  282. }
  283. /****************主函数***************/
  284. void main()
  285. {
  286.    time_init();                    //初始化定时器
  287.    temperature =read_temp();      //先读出温度的值  
  288.    init_eeprom();  //开始初始化保存的数据
  289.    delay_1ms(650);               
  290.    temperature =read_temp();               //先读出温度的值
  291.    dis_smg[0] =smg_du[temperature % 10];  //取温度的小数显示
  292.    dis_smg[1] =smg_du[temperature / 10 % 10] & 0xdf; //取温度的个位显示
  293.    dis_smg[2] =smg_du[temperature / 100 % 10] ;    //取温度的十位显示
  294.    f_pwm_l = 50;
  295.    while(1)
  296.    {      
  297.        key();                 //按键程序
  298.        if(key_can < 10)
  299.        {
  300.            key_with();           //设置报警温度   
  301.        }
  302.        if(flag_300ms == 1)      //300ms 处理一次温度程序
  303.        {      
  304.            flag_300ms = 0;   
  305.            temperature =read_temp();  //先读出温度的值
  306.            if(menu_1 == 0)
  307.            {   
  308.                smg_i = 3;
  309.        dis_smg[0] = smg_du[temperature % 10];  //取温度的小数显示
  310.            dis_smg[1] =smg_du[temperature / 10 % 10] & 0xdf; //取温度的个位显示
  311.    dis_smg[2] =smg_du[temperature / 100 % 10] ;    //取温度的十位显示
  312.            }
  313.        }
  314.        fengshan_kz();        //风扇控制函数
  315.    }
  316. }
  317. /*************定时器0中断服务程序***************/
  318. void time0_int() interrupt 1
  319. {  
  320.    static uchar value;           //定时2ms中断一次
  321.    TH0 = 0xf8;
  322.    TL0 = 0x30;     //2ms
  323.    display();     //数码管显示函数
  324.    value++;     
  325.    if(value >= 150)
  326.    {
  327.        value = 0;   
  328.        flag_300ms = 1;
  329.    }
  330.    if(flag_lj_en == 1)     //按下按键使能
  331.    {
  332.        key_time ++;
  333.        if(key_time >= 250) //500ms
  334.        {
  335.            key_time = 0;
  336.            key_500ms = 1; //500ms
  337.            key_value ++;
  338.            if(key_value > 3)
  339.            {
  340.                key_value = 10;
  341.                flag_lj_3_en = 1; //3次后1.5秒连加大些
  342.            }   
  343.        }
  344.    }
  345. }
  346. /************定时器1用做单片机模拟PWM 调节***********************/
  347. void Timer1() interrupt 3 //调用定时器1
  348. {
  349.    static uchar value_l;
  350.    TH1=0xfe;    //   定时10ms中断一次
  351.    TL1=0x0c;   //500us
  352.    if(pwm==1)
  353.    {
  354.        value_l+=3;
  355.        if(value_l > f_pwm_l)  //高电平
  356.        {
  357.            value_l=0;
  358.            if(f_pwm_l != 0)   
  359.                pwm=0;
  360.        }
  361.    }
  362.    else               
  363.    {
  364.        value_l+=3;
  365.        if(value_l  > 100 -f_pwm_l)          //低电平
  366.        {
  367.            value_l=0;
  368.            pwm=1;
  369.        }
  370.     }
  371. }
复制代码

QQ截图20180327192726.png

基于单片机的智能调速风扇控制系统.rar

3.28 MB, 下载次数: 202, 下载积分: 黑币 -5

评分

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

查看全部评分

回复

使用道具 举报

ID:346921 发表于 2018-7-11 16:11 | 显示全部楼层
看了半天就是没见可控硅在哪,能指点下吗?
回复

使用道具 举报

ID:226801 发表于 2018-8-18 20:35 | 显示全部楼层
对啊,楼主,没见可控硅在哪?实物板上没有啊,只有7805稳压块。
回复

使用道具 举报

ID:95703 发表于 2019-1-9 21:24 | 显示全部楼层
用可控硅来控制220V 来调速??
回复

使用道具 举报

ID:376283 发表于 2020-5-24 22:20 | 显示全部楼层
电路没可控硅部分,没啥用呀
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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