標(biāo)題: 單片機(jī)數(shù)字溫度控制器Proteus仿真設(shè)計(jì)帶源碼 [打印本頁(yè)]

作者: 我不是我    時(shí)間: 2017-7-17 21:37
標(biāo)題: 單片機(jī)數(shù)字溫度控制器Proteus仿真設(shè)計(jì)帶源碼
用DS18B20進(jìn)行溫度轉(zhuǎn)換,用AT89C51單片機(jī)讀取溫度,并根據(jù)溫度值,控制1602顯示和直流電機(jī)轉(zhuǎn)動(dòng),采用占空比調(diào)速,帶有ISIS仿真文件,可直接使用。

proteus仿真原理圖如下:


單片機(jī)源程序如下:
  1. /******************************/
  2. /*       數(shù)字溫度控制器       */
  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;//直流電機(jī)控制端
  10. sbit Moto2=P2^4;//直流電機(jī)控制端
  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           //正轉(zhuǎn)
  16. #define CCWD Moto1=0;Moto2=1   //反轉(zhuǎn)
  17. #define Stop Moto1=1; Moto2=1  //停止

  18. //全局變量定義
  19. uchar HPulseNum;//高電平數(shù)(PWM波高電平持續(xù)長(zhǎng)度)
  20. uchar LPulseNum;//低電平數(shù)(PWM波低電平持續(xù)長(zhǎng)度)
  21. uint NumChange;        //周期
  22. bit TempFlag;//正負(fù)溫度標(biāo)志:溫度為正Temp_Flag=0,否則為1
  23. uint Temp;//溫度值
  24. //直流電機(jī)轉(zhuǎn)向狀態(tài) 0為CWD(順時(shí)針?lè)较颍?1為CCWD(逆時(shí)針?lè)较颍?br />
  25. uchar MotoStatus;  //電機(jī)狀態(tài)
  26. bit PulseStatus;//PWM波狀態(tài),0高電平 1低電平

  27. //函數(shù)申明(共11個(gè)函數(shù))
  28. /*****************************************************/
  29. void Delayms(uint xms);//ms級(jí)延時(shí)函數(shù)
  30. void WriteLcd(uchar Dat,bit x);//寫1602LCD指令、數(shù)據(jù)函數(shù)
  31. void InitLcd(void);//初始化1602LCD函數(shù)
  32. void StatusLCD(void);//1602LCD顯示狀態(tài)函數(shù)
  33. void InitT0(void);//初始化定時(shí)器T0函數(shù)
  34. void Delayus(uchar xus);//us級(jí)延時(shí)函數(shù)
  35. bit Init_DS18B20(void);//初始化DS18B20函數(shù)
  36. uchar Read_DS18B20(void);//讀DS18B20函數(shù)
  37. void Write_DS18B20(uchar Dat);//寫DS18B20函數(shù)
  38. void GetTemp();//取溫度函數(shù)
  39. void MotoControl();
  40. /*****************************************************/
  41. uchar FirstLine[16]={"       C STOP"};        //用于1602LCD第一行顯示的數(shù)組
  42. uchar SecondLine[16]={"TG! H/L:  0%"};        //用于1602LCD第二行顯示的數(shù)組



  43. //ms級(jí)延時(shí)函數(shù)
  44. void Delayms(uint xms)//1ms左右延時(shí)
  45. {
  46.         uint i,j;
  47.         for(i=xms; i>0; i--)
  48.                 for(j=110; j>0; j--);
  49. }

  50. //寫1602LCD指令、數(shù)據(jù)函數(shù)
  51. void WriteLcd(uchar Dat,bit x)
  52. {
  53.         E=0;
  54.         LcdData=Dat;
  55.         RS=x;//寫指令時(shí)x=0,寫數(shù)據(jù)時(shí)x=1
  56.         RW=0;
  57.         E=1;
  58.         Delayms(1);
  59.         E=0;
  60. }

  61. //初始化1602LCD函數(shù)
  62. void InitLcd(void)
  63. {
  64.         WriteLcd(0x38,0);//功能設(shè)定(38H)
  65.         WriteLcd(0x0C,0);//顯示開(kāi)、關(guān)設(shè)定(0CH)
  66.         WriteLcd(0x06,0);//輸入模式設(shè)定(06H)
  67.         WriteLcd(0x01,0);//清除顯示(01H)
  68. }

  69. //1602LCD顯示狀態(tài)函數(shù)
  70. void StatusLCD(void)
  71. {
  72.         if(TempFlag) FirstLine[0]='-';//如果溫度值為負(fù),顯示負(fù)符號(hào)
  73.         else FirstLine[0]=' ';//否則不顯示溫度符號(hào)

  74.         if(Temp<1000) FirstLine[1]=' ';//如果溫度值小于100,百位顯示空白(不顯示0)
  75.         else FirstLine[1]=Temp/1000+0x30;//取溫度百位并轉(zhuǎn)換成ASCII碼

  76.         if(Temp<100) FirstLine[2]=' ';//如果溫度值小于10,十位顯示空白(不顯示0)
  77.         else FirstLine[2]=Temp%1000/100+0x30;//取溫度十位并轉(zhuǎn)換成ASCII碼

  78.         FirstLine[3]=Temp%100/10+0x30;//取溫度個(gè)位并轉(zhuǎn)換成ASCII碼
  79.         FirstLine[4]='.';//顯示小數(shù)點(diǎn)
  80.         FirstLine[5]=Temp%10+0x30;//取溫度十分位并轉(zhuǎn)換成ASCII碼
  81.         FirstLine[6]=0xDF;//顯示℃中C前面的小圓

  82.         if(NumChange!=0)
  83.         {
  84.                 if(MotoStatus==1)//順時(shí)針時(shí)顯示CWD
  85.                 {
  86.                         FirstLine[9]=' ';
  87.                         FirstLine[10]='C';
  88.                         FirstLine[11]='W';
  89.                         FirstLine[12]='D';
  90.                 }
  91.                 if(MotoStatus==2)//逆時(shí)針時(shí)顯示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))//如果溫度為負(fù)或小于25度,溫度過(guò)低
  107.                 SecondLine[1]='L';//改寫1602LCD第二行顯示內(nèi)容

  108.         if((!TempFlag)&(Temp>=250)&(Temp<=300))//如果溫度為正且在25℃~30℃之間,溫度正常
  109.                 SecondLine[1]='G';//改寫1602LCD第二行顯示內(nèi)容

  110.         if((!TempFlag)&(Temp>300))//如果溫度為正且大于30度,溫度過(guò)高
  111.                 SecondLine[1]='H';//改寫1602LCD第二行顯示內(nèi)容

  112.         //占空比小于100%時(shí),不顯示百位
  113.         if(NumChange<100)
  114.                 SecondLine[8]=' ';
  115.         else
  116.         //取占空比百位并轉(zhuǎn)換成ASCII碼
  117.                 SecondLine[8]=NumChange/100+0x30;
  118.        
  119.         //占空比小于10%時(shí),不顯示十位
  120.         if(NumChange<10)
  121.                 SecondLine[9]=' ';
  122.         else
  123.         //取占空比十位并轉(zhuǎn)換成ASCII碼
  124.                 SecondLine[9]=NumChange%100/10+0x30;
  125.        
  126.         //取占空比個(gè)位并轉(zhuǎn)換成ASCII碼
  127.         SecondLine[10]=NumChange%10+0x30;
  128. }





  129. //us級(jí)延時(shí)函數(shù)
  130. void Delayus(uchar xus)//晶振為12MHz,延時(shí)時(shí)間為2i+5 us
  131. {
  132.         while(--xus);
  133. }

  134. //初始化DS18B20函數(shù)
  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函數(shù)
  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函數(shù)
  166. void Write_DS18B20(uchar Dat)
  167. {
  168.         uchar i=0;
  169.         for(i=0;i<8;i++)//循環(huán)8次,寫入一個(gè)字節(jié)
  170.         {
  171.                 DQ=1;//未發(fā)送前的狀態(tài)
  172.                 Dat >>= 1;//將要傳送的最低位放入CY
  173.                 DQ=0;//將總線拉低,產(chǎn)生寫時(shí)序
  174.                 DQ=CY;//將要傳送的位狀態(tài)送到總線上
  175.                 Delayus(30);//延時(shí)50us,即保持總線狀態(tài),待DS18B20采樣
  176.                 DQ=1;//恢復(fù)期,總線置1
  177.         }
  178. }

  179. //取溫度函數(shù)
  180. void GetTemp(void)//獲取溫度函數(shù)
  181. {
  182.         uchar a=0,b=0;
  183.         TR0=0;
  184.         Init_DS18B20();
  185.         Write_DS18B20(0xcc);//跳過(guò)ROM
  186.         Write_DS18B20(0x44);//開(kāi)啟溫度轉(zhuǎn)換
  187.         Init_DS18B20();
  188.         Write_DS18B20(0xcc);//跳過(guò)ROM
  189.         Write_DS18B20(0xbe);//讀暫存器
  190.         a=Read_DS18B20();//讀取高速暫存字節(jié)0,溫度低8位
  191.         b=Read_DS18B20();//讀取高速暫存字節(jié)1,溫度高8位
  192.         Temp=b;
  193.         Temp<<=8;
  194.         Temp=Temp|a;//將高、低位溫度編碼合在一起
  195.         if(b>=8)//判斷溫度值是否為負(fù),如果溫度高字節(jié)大于等于8說(shuō)明溫度值為負(fù)
  196.         {
  197.                 Temp=~Temp+1;//將補(bǔ)碼轉(zhuǎn)換成原碼
  198.                 TempFlag=1;//溫度標(biāo)志為1,表示溫度為負(fù)
  199.         }
  200.         else
  201.         {
  202.                 TempFlag=0;//溫度標(biāo)志為0,表示溫度為正
  203.         }
  204.         Temp=Temp*0.0625*10+0.5;//將溫度編碼轉(zhuǎn)換成溫度值  放大10倍  加0.5是為了四舍五入
  205.         TR0=1;
  206. }

  207. //初始化外部中斷INT0和定時(shí)器T0
  208. void InitT0(void)
  209. {
  210.         EA=1;
  211.         ET0=1;
  212.         TMOD=0x02;//T0工作于定時(shí)、方式2
  213.         TH0=256-250;//250us定時(shí)
  214.         TL0=256-250;
  215.         TR0=1;//啟動(dòng)定時(shí)器
  216. }

  217. //T0定時(shí)器中斷服務(wù)函數(shù)
  218. void T0Serv() interrupt 1
  219. {
  220.         if(!PulseStatus)//如果當(dāng)前處于PWM波高電平段         PulseStatus:PWM波狀態(tài),0高電平 1低電平
  221.         {
  222.                 if(HPulseNum--!=0)//如果高電平段延時(shí)計(jì)數(shù)不為0
  223.                 {
  224.                         if(MotoStatus!=0)//如果MotoStatus!=0(為0是停止?fàn)顟B(tài))
  225.                         {
  226.                                 if(MotoStatus==1)
  227.                                         {
  228.                                                 CWD;//順時(shí)針驅(qū)動(dòng)直流電機(jī)
  229.                                         }
  230.                                         else//MotoStatus=1(逆時(shí)針)
  231.                                         {
  232.                                                 CCWD;//逆時(shí)針驅(qū)動(dòng)直流電機(jī)
  233.                                         }
  234.                         }
  235.                 }
  236.                 else//高電平段延時(shí)計(jì)數(shù)為0
  237.                 {                               
  238.                         PulseStatus=!PulseStatus;//取反PWM波電平狀態(tài)
  239.                         LPulseNum=100-NumChange; //裝載低電平段延時(shí)計(jì)數(shù),為低電平段延時(shí)做準(zhǔn)備
  240.                 }
  241.         }
  242.         else//當(dāng)前處于PWM波低電平段
  243.         {
  244.                 //如果低電平段延時(shí)計(jì)數(shù)不為0
  245.                 if(LPulseNum--!=0)
  246.                 {
  247.                         Stop;//停止驅(qū)動(dòng)直流電機(jī)
  248.                 }
  249.                 //低電平段延時(shí)計(jì)數(shù)為0
  250.                 else
  251.                 {       
  252.                         PulseStatus=!PulseStatus;         //取反PWM波電平狀態(tài)
  253.                         HPulseNum=NumChange;                //裝載高電平段延時(shí)計(jì)數(shù),為高電平段延時(shí)做準(zhǔn)備
  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. …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼

所有資料51hei提供下載:
任務(wù)5 數(shù)字溫度控制器.rar (71.55 KB, 下載次數(shù): 66)




作者: LIuwEI.    時(shí)間: 2018-10-30 16:35
為什么仿真不對(duì) 有錯(cuò)誤?




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1