找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机数字温度控制器Proteus仿真设计带源码

[复制链接]
跳转到指定楼层
楼主
用DS18B20进行温度转换,用AT89C51单片机读取温度,并根据温度值,控制1602显示和直流电机转动,采用占空比调速,带有ISIS仿真文件,可直接使用。

proteus仿真原理图如下:


单片机源程序如下:
  1. /******************************/
  2. /*       数字温度控制器       */
  3. /******************************/
  4. #include <reg51.h>
  5. //引脚定义
  6. sbit RS=P2^0;//1602LCD RS
  7. sbit RW=P2^1;//1602LCD RW
  8. sbit E=P2^2;//1602LCD E
  9. sbit Moto1=P2^3;//直流电机控制端
  10. sbit Moto2=P2^4;//直流电机控制端
  11. sbit DQ=P2^5;//DS18B20 DQ

  12. #define uchar unsigned char   
  13. #define uint unsigned int           //宏定义
  14. #define LcdData P0                   //1602的D0~D7
  15. #define CWD Moto1=1;Moto2=0           //正转
  16. #define CCWD Moto1=0;Moto2=1   //反转
  17. #define Stop Moto1=1; Moto2=1  //停止

  18. //全局变量定义
  19. uchar HPulseNum;//高电平数(PWM波高电平持续长度)
  20. uchar LPulseNum;//低电平数(PWM波低电平持续长度)
  21. uint NumChange;        //周期
  22. bit TempFlag;//正负温度标志:温度为正Temp_Flag=0,否则为1
  23. uint Temp;//温度值
  24. //直流电机转向状态 0为CWD(顺时针方向) 1为CCWD(逆时针方向)
  25. uchar MotoStatus;  //电机状态
  26. bit PulseStatus;//PWM波状态,0高电平 1低电平

  27. //函数申明(共11个函数)
  28. /*****************************************************/
  29. void Delayms(uint xms);//ms级延时函数
  30. void WriteLcd(uchar Dat,bit x);//写1602LCD指令、数据函数
  31. void InitLcd(void);//初始化1602LCD函数
  32. void StatusLCD(void);//1602LCD显示状态函数
  33. void InitT0(void);//初始化定时器T0函数
  34. void Delayus(uchar xus);//us级延时函数
  35. bit Init_DS18B20(void);//初始化DS18B20函数
  36. uchar Read_DS18B20(void);//读DS18B20函数
  37. void Write_DS18B20(uchar Dat);//写DS18B20函数
  38. void GetTemp();//取温度函数
  39. void MotoControl();
  40. /*****************************************************/
  41. uchar FirstLine[16]={"       C STOP"};        //用于1602LCD第一行显示的数组
  42. uchar SecondLine[16]={"TG! H/L:  0%"};        //用于1602LCD第二行显示的数组



  43. //ms级延时函数
  44. void Delayms(uint xms)//1ms左右延时
  45. {
  46.         uint i,j;
  47.         for(i=xms; i>0; i--)
  48.                 for(j=110; j>0; j--);
  49. }

  50. //写1602LCD指令、数据函数
  51. void WriteLcd(uchar Dat,bit x)
  52. {
  53.         E=0;
  54.         LcdData=Dat;
  55.         RS=x;//写指令时x=0,写数据时x=1
  56.         RW=0;
  57.         E=1;
  58.         Delayms(1);
  59.         E=0;
  60. }

  61. //初始化1602LCD函数
  62. void InitLcd(void)
  63. {
  64.         WriteLcd(0x38,0);//功能设定(38H)
  65.         WriteLcd(0x0C,0);//显示开、关设定(0CH)
  66.         WriteLcd(0x06,0);//输入模式设定(06H)
  67.         WriteLcd(0x01,0);//清除显示(01H)
  68. }

  69. //1602LCD显示状态函数
  70. void StatusLCD(void)
  71. {
  72.         if(TempFlag) FirstLine[0]='-';//如果温度值为负,显示负符号
  73.         else FirstLine[0]=' ';//否则不显示温度符号

  74.         if(Temp<1000) FirstLine[1]=' ';//如果温度值小于100,百位显示空白(不显示0)
  75.         else FirstLine[1]=Temp/1000+0x30;//取温度百位并转换成ASCII码

  76.         if(Temp<100) FirstLine[2]=' ';//如果温度值小于10,十位显示空白(不显示0)
  77.         else FirstLine[2]=Temp%1000/100+0x30;//取温度十位并转换成ASCII码

  78.         FirstLine[3]=Temp%100/10+0x30;//取温度个位并转换成ASCII码
  79.         FirstLine[4]='.';//显示小数点
  80.         FirstLine[5]=Temp%10+0x30;//取温度十分位并转换成ASCII码
  81.         FirstLine[6]=0xDF;//显示℃中C前面的小圆

  82.         if(NumChange!=0)
  83.         {
  84.                 if(MotoStatus==1)//顺时针时显示CWD
  85.                 {
  86.                         FirstLine[9]=' ';
  87.                         FirstLine[10]='C';
  88.                         FirstLine[11]='W';
  89.                         FirstLine[12]='D';
  90.                 }
  91.                 if(MotoStatus==2)//逆时针时显示CCWD
  92.                 {
  93.                         FirstLine[9]='C';
  94.                         FirstLine[10]='C';
  95.                         FirstLine[11]='W';
  96.                         FirstLine[12]='D';                               
  97.                 }
  98.         }
  99.         else
  100.         {
  101.                 FirstLine[9]='S';
  102.                 FirstLine[10]='T';
  103.                 FirstLine[11]='O';
  104.                 FirstLine[12]='P';               
  105.         }

  106.         if((TempFlag)|(Temp<250))//如果温度为负或小于25度,温度过低
  107.                 SecondLine[1]='L';//改写1602LCD第二行显示内容

  108.         if((!TempFlag)&(Temp>=250)&(Temp<=300))//如果温度为正且在25℃~30℃之间,温度正常
  109.                 SecondLine[1]='G';//改写1602LCD第二行显示内容

  110.         if((!TempFlag)&(Temp>300))//如果温度为正且大于30度,温度过高
  111.                 SecondLine[1]='H';//改写1602LCD第二行显示内容

  112.         //占空比小于100%时,不显示百位
  113.         if(NumChange<100)
  114.                 SecondLine[8]=' ';
  115.         else
  116.         //取占空比百位并转换成ASCII码
  117.                 SecondLine[8]=NumChange/100+0x30;
  118.        
  119.         //占空比小于10%时,不显示十位
  120.         if(NumChange<10)
  121.                 SecondLine[9]=' ';
  122.         else
  123.         //取占空比十位并转换成ASCII码
  124.                 SecondLine[9]=NumChange%100/10+0x30;
  125.        
  126.         //取占空比个位并转换成ASCII码
  127.         SecondLine[10]=NumChange%10+0x30;
  128. }





  129. //us级延时函数
  130. void Delayus(uchar xus)//晶振为12MHz,延时时间为2i+5 us
  131. {
  132.         while(--xus);
  133. }

  134. //初始化DS18B20函数
  135. bit Init_DS18B20(void)
  136. {
  137.         bit x;
  138.         DQ=1;
  139.         DQ=0;
  140.         Delayus(250);
  141.         DQ=1;
  142.         Delayus(27);
  143.         if(!DQ) x=0;
  144.         else x=1;
  145.         Delayus(250);
  146.         DQ=1;
  147.         return x;
  148. }

  149. //读DS18B20函数
  150. uchar Read_DS18B20(void)
  151. {
  152.         uchar i=0,Dat=0;
  153.         for(i=0;i<8;i++)
  154.         {
  155.                 DQ=1;
  156.                 DQ=0;
  157.                 Dat>>=1;
  158.                 DQ=1;
  159.                 if(DQ) Dat |= 0x80;
  160.                 DQ=1;
  161.                 Delayus(30);
  162.         }
  163.         return Dat;
  164. }

  165. //写DS18B20函数
  166. void Write_DS18B20(uchar Dat)
  167. {
  168.         uchar i=0;
  169.         for(i=0;i<8;i++)//循环8次,写入一个字节
  170.         {
  171.                 DQ=1;//未发送前的状态
  172.                 Dat >>= 1;//将要传送的最低位放入CY
  173.                 DQ=0;//将总线拉低,产生写时序
  174.                 DQ=CY;//将要传送的位状态送到总线上
  175.                 Delayus(30);//延时50us,即保持总线状态,待DS18B20采样
  176.                 DQ=1;//恢复期,总线置1
  177.         }
  178. }

  179. //取温度函数
  180. void GetTemp(void)//获取温度函数
  181. {
  182.         uchar a=0,b=0;
  183.         TR0=0;
  184.         Init_DS18B20();
  185.         Write_DS18B20(0xcc);//跳过ROM
  186.         Write_DS18B20(0x44);//开启温度转换
  187.         Init_DS18B20();
  188.         Write_DS18B20(0xcc);//跳过ROM
  189.         Write_DS18B20(0xbe);//读暂存器
  190.         a=Read_DS18B20();//读取高速暂存字节0,温度低8位
  191.         b=Read_DS18B20();//读取高速暂存字节1,温度高8位
  192.         Temp=b;
  193.         Temp<<=8;
  194.         Temp=Temp|a;//将高、低位温度编码合在一起
  195.         if(b>=8)//判断温度值是否为负,如果温度高字节大于等于8说明温度值为负
  196.         {
  197.                 Temp=~Temp+1;//将补码转换成原码
  198.                 TempFlag=1;//温度标志为1,表示温度为负
  199.         }
  200.         else
  201.         {
  202.                 TempFlag=0;//温度标志为0,表示温度为正
  203.         }
  204.         Temp=Temp*0.0625*10+0.5;//将温度编码转换成温度值  放大10倍  加0.5是为了四舍五入
  205.         TR0=1;
  206. }

  207. //初始化外部中断INT0和定时器T0
  208. void InitT0(void)
  209. {
  210.         EA=1;
  211.         ET0=1;
  212.         TMOD=0x02;//T0工作于定时、方式2
  213.         TH0=256-250;//250us定时
  214.         TL0=256-250;
  215.         TR0=1;//启动定时器
  216. }

  217. //T0定时器中断服务函数
  218. void T0Serv() interrupt 1
  219. {
  220.         if(!PulseStatus)//如果当前处于PWM波高电平段         PulseStatus:PWM波状态,0高电平 1低电平
  221.         {
  222.                 if(HPulseNum--!=0)//如果高电平段延时计数不为0
  223.                 {
  224.                         if(MotoStatus!=0)//如果MotoStatus!=0(为0是停止状态)
  225.                         {
  226.                                 if(MotoStatus==1)
  227.                                         {
  228.                                                 CWD;//顺时针驱动直流电机
  229.                                         }
  230.                                         else//MotoStatus=1(逆时针)
  231.                                         {
  232.                                                 CCWD;//逆时针驱动直流电机
  233.                                         }
  234.                         }
  235.                 }
  236.                 else//高电平段延时计数为0
  237.                 {                               
  238.                         PulseStatus=!PulseStatus;//取反PWM波电平状态
  239.                         LPulseNum=100-NumChange; //装载低电平段延时计数,为低电平段延时做准备
  240.                 }
  241.         }
  242.         else//当前处于PWM波低电平段
  243.         {
  244.                 //如果低电平段延时计数不为0
  245.                 if(LPulseNum--!=0)
  246.                 {
  247.                         Stop;//停止驱动直流电机
  248.                 }
  249.                 //低电平段延时计数为0
  250.                 else
  251.                 {       
  252.                         PulseStatus=!PulseStatus;         //取反PWM波电平状态
  253.                         HPulseNum=NumChange;                //装载高电平段延时计数,为高电平段延时做准备
  254.                 }
  255.         }
  256. }

  257. void MotoControl()
  258. {
  259.         if((!TempFlag)&(Temp>300)) //正的温度且大于30℃
  260.         {
  261.                 MotoStatus=1;
  262.                 NumChange=Temp-300;
  263.                 if(NumChange>=100) NumChange=100;//控制上限
  264.         }

  265.         if((!TempFlag)&(Temp<=300)&(Temp>=250))
  266.         {
  267.                 MotoStatus=0;
  268.                 NumChange=0;
  269.         }
  270.         if((Temp<250)|(TempFlag))
  271.         {
  272. ……………………

  273. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
任务5 数字温度控制器.rar (71.55 KB, 下载次数: 66)



评分

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

查看全部评分

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

使用道具 举报

沙发
ID:414264 发表于 2018-10-30 16:35 | 只看该作者
为什么仿真不对 有错误?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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