找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机温控风扇程序 DS18B20 Protuse仿真

[复制链接]
跳转到指定楼层
楼主
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)



仿真图的单片机代码和仿真图在附件里
  1. #include<reg51.h>
  2. #include<intrins.h>                         //包含头文件

  3. #define uchar unsigned char
  4. #define uint unsigned int                 //宏定义
  5. #include "eeprom52.h"

  6. //////////////////////////////按键定义/////////////////////////////////
  7. sbit dj=P1^0;//电机控制端接口
  8. sbit DQ=P1^6;//温度传感器接口
  9. sbit key1=P3^5;//设置温度
  10. sbit key2=P3^6;//温度加
  11. sbit key3=P3^7;//温度减
  12. sbit BEEP=P1^3;                            //定义蜂鸣器
  13. bit beep_st;                                     //蜂鸣器间隔标志
  14. sbit w1=P2^4;
  15. sbit w2=P2^5;
  16. sbit w3=P2^6;
  17. sbit w4=P2^7;                          //数码管的四个位

  18. uchar table[22]=
  19. {0x3F,0x06,0x5B,0x4F,0x66,
  20. 0x6D,0x7D,0x07,0x7F,0x6F,
  21. 0x77,0x7C,0x39,0x5E,0x79,0x71,
  22. 0x40,0x38,0x76,0x00,0xff,0x37};//'-',L,H,灭,全亮,n         16-21/////共阴数码管段选//////////
  23. unsigned int wen_du;                                                //温度变量  
  24. int shang,xia; //对比温度暂存变量
  25. uchar dang; //档位显示
  26. uchar flag;
  27. uchar d1,d2,d3;//显示数据暂存变量
  28. uchar m;
  29. uchar js;
  30. uchar cs=0;
  31. unsigned char s_t[];
  32. uchar stc[50]={"The current temperature is:"};
  33. //将数字转成字符串
  34. void convert_uint_to_uchar_array(unsigned int wen_du, unsigned char s_t[4]) {  
  35.     int i;
  36.                 for (i = 0; i < 4; i++) {  
  37.         s_t[i] = (wen_du >> i * 8) & 0xFF;  
  38.     }  
  39. }  

  40. void delay(unsigned int xms)//延时
  41. {
  42.         unsigned char i, j;
  43.         while(xms--)
  44.         {
  45.                 i = 2;
  46.                 j = 239;
  47.                 do
  48.                 {
  49.                         while (--j);
  50.                 } while (--i);
  51.         }
  52. }
  53. //发送
  54. void PutString(unsigned char *TXStr)  
  55. {   
  56.                 SCON=0x40;  //串行口方式1
  57.                 PCON=0x80;//增倍波特率
  58.                 TH1=0xf3; //4800波特率
  59.                 TL1=0xf3;
  60.                 TMOD=0x20;  //将T1定时器方式2
  61.                 TR1=1;  //启动T1
  62.     ES=0;     
  63.       while(*TXStr!=0)
  64.      {                     
  65.         SBUF=*TXStr;
  66.          while(TI==0);
  67.          TI=0;   
  68.         TXStr++;
  69.     }
  70.     ES=1;
  71. }

  72. /*写eeprom中*/
  73. void write_eeprom()
  74. {
  75.         SectorErase(0x2000);                //清除扇区
  76.         byte_write(0x2000, shang);        //写上限数值到扇区
  77.         byte_write(0x2001, xia);        //写下限数值到扇区
  78.         byte_write(0x2060, a_a);        //写初始变量到扇区指定位置
  79. }

  80. /*把数据从单片机内部eeprom中读出来*/
  81. void read_eeprom()
  82. {
  83.         shang   = byte_read(0x2000);                 //从扇区读取上限数据
  84.         xia = byte_read(0x2001);                         //从扇区读取下限数据
  85.         a_a      = byte_read(0x2060);                 //从扇区读取初始变量
  86. }

  87. /*开机自检传感器eeprom初始化*/
  88. void init_eeprom()
  89. {
  90.         read_eeprom();                //先读扇区的数据
  91.         if(a_a != 1)                //判断是否是新单片机(原理:新的单片机扇区里的数据都是0,这里判断是否不等于1。如果是不等于1,就是等于0,那就是新单片机了,就会执行下面的上下限值初始化数值的语句,并让a_a变成1,下次开机就会知道是用过的单片机了就会读取EEPROM里的上下限数据了)
  92.         {
  93.                 shang   = 30;        //上限数值初始为30
  94.                 xia = 20;                //下限数值初始为20
  95.                 a_a = 1;                //初始值变量赋值1,下次开机就会直接读取EEPROM内的上下限数据
  96.                 write_eeprom();           //将初始的数据保存进单片机的EEPROM
  97.         }        
  98. }


  99. /*ds18b20延迟子函数(晶振12MHz )*/
  100. void delay_18B20(uint i)
  101. {
  102.         while(i--);
  103. }
  104. /*ds18b20初始化函数*/
  105. void Init_DS18B20()
  106. {
  107.          uchar x=0;
  108.          DQ=1;          //DQ复位
  109.          delay_18B20(8);  //稍做延时
  110.          DQ=0;          //单片机将DQ拉低
  111.          delay_18B20(80); //精确延时 大于 480us
  112.          DQ=1;          //拉高总线
  113.          delay_18B20(14);
  114.          x=DQ;            //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
  115.          delay_18B20(20);
  116. }
  117. /*ds18b20读一个字节*/  
  118. uchar ReadOneChar()
  119. {
  120.         uchar i=0;
  121.         uchar dat=0;
  122.         for (i=8;i>0;i--)
  123.          {
  124.                   DQ=0; // 给脉冲信号
  125.                   dat>>=1;
  126.                   DQ=1; // 给脉冲信号
  127.                   if(DQ)
  128.                   dat|=0x80;
  129.                   delay_18B20(4);
  130.          }
  131.          return(dat);
  132. }
  133. /*ds18b20写一个字节*/  
  134. void WriteOneChar(uchar dat)
  135. {
  136.          uchar i=0;
  137.          for (i=8;i>0;i--)
  138.          {
  139.                   DQ=0;
  140.                  DQ=dat&0x01;
  141.             delay_18B20(5);
  142.                  DQ=1;
  143.             dat>>=1;
  144.         }
  145. }
  146. /*读取ds18b20当前温度*/
  147. void ReadTemperature()
  148. {
  149.         uchar a=0;
  150.         uchar b=0;
  151.         uchar t=0;
  152.         Init_DS18B20();
  153.         WriteOneChar(0xCC);            // 跳过读序号列号的操作
  154.         WriteOneChar(0x44);         // 启动温度转换
  155.         delay_18B20(100);       // this message is very important
  156.         Init_DS18B20();
  157.         WriteOneChar(0xCC);         //跳过读序号列号的操作
  158.         WriteOneChar(0xBE);         //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
  159.         delay_18B20(100);
  160.         a=ReadOneChar();            //读取温度值低位
  161.         b=ReadOneChar();                   //读取温度值高位
  162.         wen_du=((b*256+a)>>4);    //当前采集温度值除16得实际温度值
  163.         
  164.         
  165. }

  166. /*按键*/
  167. void zi_keyscan()//自动模式按键扫描函数
  168. {
  169.         if(key1==0)                                                          //设置键按下
  170.         {
  171.                 delay(300);                                                  //延时去抖
  172.                 if(key1==0)flag=1;                                  //再次判断按键,按下的话进入设置状态
  173.                 while(key1==0);//松手检测                  //按键释放
  174.         }
  175.         while(flag==1)                                                  //进入设置上限状态
  176.         {
  177.                 d1=18;d2=shang/10;d3=shang%10;          //显示字母H 和上限温度值
  178.                 if(key1==0)                                                  //判断设置键是否按下
  179.                 {
  180.                         delay(300);                                          //延时去抖
  181.                         if(key1==0)flag=2;                          //按键按下,进入设置下限模式
  182.                         while(key1==0);//松手检测
  183.                 }
  184.                 if(key2==0)                                                  //加键按下
  185.                 {
  186.                         delay(300);                                          //延时去抖
  187.                         if(key2==0)                                          //加键按下
  188.                         {
  189.                                 shang+=5;                                  //上限加5
  190.                                 if(shang>=100)shang=100;  //上限最大加到100
  191.                         }while(key2==0);//松手检测
  192.                         write_eeprom();                           //保存数据
  193.                 }
  194.                 if(key3==0)                                                  //减键按下
  195.                 {
  196.                         delay(300);                                          //延时去抖
  197.                         if(key3==0)                                          //减键按下
  198.                         {
  199.                                 shang-=1;                                  //上限减1
  200.                                 if(shang<=10)shang=10;          //上限最小减到10
  201.                         }while(key3==0);//松手检测
  202.                         write_eeprom();                           //保存数据
  203.                 }               
  204.         }
  205.         while(flag==2)                                                  //设置下限
  206.         {
  207.                 d1=17;d2=xia/10;d3=xia%10;                  //显示字母L 显示下限温度值
  208.                 if(key1==0)
  209.                 {
  210.                         delay(300);
  211.                         if(key1==0)flag=0;
  212.                         while(key1==0);//松手检测
  213.                 }
  214.                 if(key2==0)
  215.                 {
  216.                         delay(300);
  217.                         if(key2==0)
  218.                         {
  219.                                 xia+=5;
  220.                                 if(xia>=95)xia=95;        
  221.                         }while(key2==0);//松手检测
  222.                         write_eeprom();                           //保存数据
  223.                 }
  224.                 if(key3==0)
  225.                 {
  226.                         delay(300);
  227.                         if(key3==0)
  228.                         {
  229.                                 xia-=1;
  230.                                 if(xia<=0)xia=0;        
  231.                         }while(key3==0);//松手检测
  232.                         write_eeprom();                           //保存数据
  233.                 }               
  234.         }
  235. }
  236. void zi_dong()//自动温控模式
  237. {
  238.         d1=dang;d2=wen_du/10;d3=wen_du%10;                //显示档位,显示当前温度值
  239.         zi_keyscan();//按键扫描函数
  240.         if(wen_du<xia){dang=0;
  241.                 if(cs==0){
  242.                         BEEP=0;
  243.                         delay(500);
  244.                         BEEP=1;
  245.                         delay(500);
  246.                         
  247.                 }else{        BEEP=1;}
  248.                 cs=1;
  249.         }//低于下限  档位为0 电机停止
  250.         if((wen_du>=xia)&&(wen_du<=shang))//温度大于下限,小于上限  1挡
  251.         {dang=1;cs=0;}
  252.         if(wen_du>shang){dang=2;}//温度大于上限,2档
  253.         
  254. }

  255. void init()                   //定时器初始化函数
  256. {
  257.         TMOD=0x01;           //定时器0工作方式1
  258.         TH0=0xf8;
  259.         TL0=0x30;           //定时器初值5ms
  260.         ET0=1;                   //打开定时器0中断允许
  261.         TR0=1;                   //打开定时器0定时器开关
  262.         EA=1;                   //打开中断系统总开关
  263. }
  264. void main()                  //主函数
  265. {
  266.         uchar j;
  267.         dj=0;                  //电机开
  268.         init_eeprom();  //开始初始化保存的数据
  269.         for(j=0;j<80;j++)          //先读取温度值,防止开机显示85
  270.         ReadTemperature();
  271.         init();
  272.         while(1)                          //进入while循环
  273.         {
  274.                 if(js>=50)                        //当js在定时器里加到50次时(js加一次是20ms,加到50次就是1000ms,也就是1秒读取一次温度)
  275.                 {
  276.                         ReadTemperature();        //读取温度值
  277.                         js=0;                                //定时读取温度的变量js清零,重新计时下次读取温度
  278.                         
  279.                 }        
  280.                
  281.                 zi_dong();//判断当前需要哪一个档位
  282.                
  283.                
  284.         }
  285. }

  286. /*
  287. 控制占空比原理:
  288. 定时器每5ms控制变量m加一,当m加到4时,将m清零。
  289. 也就是占空比的一个周期是5ms*4=20ms,频率就是50Hz。
  290. 因为m是加四次是一个周期,也就是加一次占空比是加25%。
  291. 下面程序里if(m<=3)dj=1;else dj=0;就是让dj高电平的时间是m加3次的时间,而dj为低电平的时间就是加第四次的时间,所以占空比就是3/4就是75%
  292. */

  293. void T0_TIME() interrupt 1                  //定时器工作函数,用于PWM工作
  294. {
  295.         TH0=0xf8;
  296.         TL0=0x30;                                          //定时器赋初值5ms
  297.         m++;                                                  //5ms,m加一
  298.         switch(dang)                                  //判断档位
  299.         {
  300.                 case 0:dj=0;break;                  //0档,控制电机停止
  301.                 case 1:if(m<=3)dj=1;else dj=0;break;//控制电机以75%占空比转动
  302.                 case 2:dj=1;break;                  //2档,控制电机100%占空比转动
  303.                 default:;                                  //其他情况,直接跳出
  304.         }
  305.         switch(m)                                          //判断m的数值
  306.         {
  307.                 case 1:                                                                        //m为1时
  308.                                 w4=1;P0=table[d1];w1=0; break;        //关闭低四位数码管位选;P0口输出对应数字的段码;打开第一位数码管位选
  309.                 case 2:
  310.                                 w1=1;P0=table[16];w2=0; break;        //关闭低一位数码管位选;P0口输出对应数字的段码;打开第二位数码管位选
  311.                 case 3:
  312.                                 w2=1;P0=table[d2];w3=0;        break;        //关闭低二位数码管位选;P0口输出对应数字的段码;打开第三位数码管位选
  313.                 case 4:
  314.                                 w3=1;P0=table[d3];w4=0;m=0;if(js<50)js++;break; //关闭低三位数码管位选;P0口输出对应数字的段码;打开第四位数码管位选
  315.                                                                                                                                 //js变量小于50时,就让js加,加到50后,主函数里就会执行一次读取温度函数
  316.                 default:;                                                                //其他情况时跳出
  317.         }
  318. }
复制代码

仿真程序: 仿真程序.7z (124.42 KB, 下载次数: 47)

评分

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

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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