找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2798|回復(fù): 12
打印 上一主題 下一主題
收起左側(cè)

51單片機(jī)溫度控制系統(tǒng)(溫度控制部分有問題,求大佬解答)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:902047 發(fā)表于 2021-4-27 16:23 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
采用ds18b20溫度傳感器,將實(shí)時(shí)溫度與預(yù)設(shè)溫度進(jìn)行比較,若實(shí)時(shí)溫度低于預(yù)設(shè)溫度,則控制電阻絲進(jìn)行加熱,若實(shí)時(shí)溫度高于預(yù)設(shè)溫度,則停止電阻絲加熱,系統(tǒng)溫度在50~100攝氏度范圍內(nèi)可調(diào),溫度控制精度±0.5攝氏度。
我主程序的最后用if語句將實(shí)時(shí)溫度與預(yù)設(shè)溫度比較,但是用proteus仿真后,P3.1口一直輸出低電平,發(fā)現(xiàn)if語句好像沒有起作用,每次都直接執(zhí)行else語句。下面是我的程序和proteus電路圖。


單片機(jī)源程序如下:
  1. #include"reg51.h"
  2. #define uint unsigned int
  3. #define uchar unsigned char

  4. uchar code smg_duan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//數(shù)碼管段選定義
  5. uchar code smg_duan1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};//數(shù)碼管段選定義(小數(shù)點(diǎn))
  6. uchar code smg_wei[]={0xf7,0xfb,0xfd,0xfe};//數(shù)碼管位選定義

  7. sbit key1=P1^0;//輸入設(shè)定溫度50度
  8. sbit key2=P1^1;//輸入設(shè)定溫度75度
  9. sbit key3=P1^2;//輸入設(shè)定溫度100度
  10. sbit key4=P1^3;//增加2度
  11. sbit key5=P1^4;//減少2度
  12. sbit key6=P1^5;//增加0.5度
  13. sbit key7=P1^6;//減少0.5度
  14. sbit key8=P1^7;//確認(rèn)鍵
  15. float setH=0;//預(yù)設(shè)溫度上限
  16. float setL=0;//預(yù)設(shè)溫度下限
  17. uint bkey;
  18. sbit DQ=P3^0;//18b20 I/O口定義
  19. sbit jiare=P3^1;//加熱電阻絲I/O口定義
  20. /***********1ms延時(shí)函數(shù)********/
  21. void delay_1ms(uint i)
  22. {
  23.      while(i--);
  24. }

  25. /***********小延時(shí)函數(shù)**********/
  26. void delay_small(uint q)
  27. {
  28.       while(q--);
  29. }

  30. /**********18b20初始化函數(shù)*******/
  31. void Init_18b20()
  32. {
  33.      bit q;
  34.          DQ=1;//把總線拉高
  35.          delay_small(1);//15us
  36.          DQ=0;//給復(fù)位脈沖
  37.          delay_small(80);//750us
  38.          DQ=1;//把總線拉高,等待
  39.          delay_small(10);//110us
  40.          q=DQ;//讀取18b20初始化信號(hào)
  41.          delay_small(20);//200us
  42.          DQ=1;//把總線拉高,釋放總線


  43. }

  44. /**********寫18b20數(shù)據(jù)******/
  45. void write_18b20(uchar dat)
  46. {
  47.      uchar i;
  48.          for(i=0;i<8;i++)
  49.          {
  50.             DQ=0;
  51.                 DQ=dat&0x01;//向18b20總線寫數(shù)據(jù)
  52.                 delay_small(5);//60us
  53.                 DQ=1;//釋放總線
  54.                 dat>>=1;
  55.          }
  56. }

  57. /*********讀18b20數(shù)據(jù)******/
  58. uchar read_18b20()
  59. {
  60.      uchar i,r_dat;
  61.          for(i=0;i<8;i++)
  62.          {
  63.             DQ=0;
  64.                 r_dat>>=1;//讀數(shù)據(jù)從低位開始
  65.                 DQ=1;//釋放總線
  66.                 if(DQ==1)
  67.                   r_dat|=0x80;
  68.                 delay_small(5);//60us
  69.          }
  70.          return r_dat;//返回?cái)?shù)據(jù)
  71. }

  72. /**********讀取實(shí)時(shí)溫度數(shù)值*******/
  73. uint read_Tem()
  74. {
  75.      uint r_high;
  76.          uchar r_low;
  77.          Init_18b20();//初始化18b20
  78.          write_18b20(0xcc);//跳過64位ROM
  79.          write_18b20(0x44);//啟動(dòng)一次溫度轉(zhuǎn)換命令
  80.          delay_small(50);//500us
  81.          Init_18b20();//初始化18b20
  82.          write_18b20(0xcc);//跳過64位ROM
  83.          write_18b20(0xbe);//發(fā)出讀取暫存器命令
  84.          EA=0;//關(guān)總中斷
  85.          r_low=read_18b20();//讀溫度低字節(jié)
  86.          r_high=read_18b20();//讀溫度高字節(jié)
  87.          EA=1;//開總中斷
  88.          r_high<<=8;//把溫度的高字節(jié)左移8位
  89.          r_high|=r_low;//把讀出的溫度低位放到r_high的低八位中
  90.          r_high*=0.625;//轉(zhuǎn)換到溫度值小數(shù)
  91.          return r_high;//返回讀出的溫度


  92. }

  93. /**********數(shù)碼管顯示溫度函數(shù)(實(shí)時(shí)顯示)******/
  94. void DisplayTem(uint temperature)
  95. {
  96.         uint a,b;
  97.         P0=0x00;
  98.         P2=smg_wei[0];//位選小數(shù)位
  99.         P0=smg_duan[temperature%10];//段選顯示小數(shù)位
  100.         delay_1ms(2300);
  101.         P0=0x00;
  102.         P2=smg_wei[1];//位選個(gè)位
  103.         P0=smg_duan1[temperature/10%10];//段選顯示個(gè)位
  104.         delay_1ms(2300);
  105.         P0=0x00;
  106.         P2=smg_wei[2];//位選十位
  107.         P0=smg_duan[temperature/100%10];//段選顯示十位
  108.         delay_1ms(2300);
  109.         P0=0x00;
  110.         b=temperature/1000%10;
  111.         if(b==0)
  112.         {
  113.            a=0;
  114.         }
  115.         else
  116.         {
  117.            a=1;
  118.         }
  119.         switch(a)
  120.         {
  121.            case(0):break;
  122.            case(1):P2=smg_wei[3];//位選百位
  123.                    P0=smg_duan[temperature/1000%10];//段選顯示百位
  124.                    delay_1ms(2300);
  125.                    P0=0x00;
  126.                            break;
  127.         }
  128.         

  129. }

  130. void keyscan()
  131. {
  132.    bkey=0;
  133.   if(!key1)
  134.   {
  135.      delay_1ms(3000);
  136.          if(!key1)
  137.          bkey=1;
  138.   }
  139.   if(!key2)
  140.   {
  141.      delay_1ms(3000);
  142.          if(!key2)
  143.          bkey=2;
  144.   }
  145.   if(!key3)
  146.   {
  147.      delay_1ms(3000);
  148.          if(!key3)
  149.          bkey=3;
  150.   }
  151.   if(!key4)
  152.   {
  153.      delay_1ms(8000);
  154.          if(!key4)
  155.          bkey=4;
  156.   }
  157.   if(!key5)
  158.   {
  159.      delay_1ms(8000);
  160.          if(!key5)
  161.          bkey=5;
  162.   }
  163.   if(!key6)
  164.   {
  165.      delay_1ms(8000);
  166.          if(!key6)
  167.          bkey=6;
  168.   }
  169.   if(!key7)
  170.   {
  171.      delay_1ms(8000);
  172.          if(!key7)
  173.          bkey=7;
  174.   }
  175.   if(!key8)
  176.   {
  177.      delay_1ms(8000);
  178.          if(!key8)
  179.          bkey=8;
  180.   }
  181. }

  182. /***********數(shù)碼管顯示函數(shù)(按鍵顯示)******/
  183. void displaytem1(float temperature1)
  184. {
  185.     do
  186.    {
  187.         uint b;
  188.         float c;
  189.         P0=0x00;
  190.         P2=smg_wei[0];//位選小數(shù)位
  191.         c=temperature1*10;
  192.         P0=smg_duan[(int)c/1%10];//段選顯示小數(shù)位
  193.         delay_1ms(1325);
  194.         P0=0x00;
  195.         P2=smg_wei[1];//位選個(gè)位
  196.         P0=smg_duan1[(int)temperature1/1%10];//段選顯示個(gè)位
  197.         delay_1ms(1325);
  198.         P0=0x00;
  199.         P2=smg_wei[2];//位選十位
  200.         P0=smg_duan[(int)temperature1/10%10];//段選顯示十位
  201.         delay_1ms(1325);
  202.         P0=0x00;
  203.         b=(int)temperature1/100%10;
  204.         switch(b)
  205.         {
  206.            case(0):break;
  207.            case(1):P2=smg_wei[3];//位選百位
  208.                    P0=smg_duan[1];//段選顯示百位
  209.                    delay_1ms(1325);
  210.                    P0=0x00;
  211.                            break;
  212.         }
  213.         keyscan();
  214.    }
  215.    while(bkey==0);
  216. }


  217. void main()
  218. {
  219.    uint temperature;
  220.    jiare=0;
  221.    do
  222.    {
  223.     keyscan();
  224.         switch(bkey)
  225.     {
  226.       case(0):break;
  227.           case(1):setH=50.0;
  228.                   setL=50.0;
  229.                           displaytem1(50.0);
  230.                           break;
  231.           case(2):setH=75.0;
  232.                   setL=75.0;
  233.                           displaytem1(75.0);
  234.                           break;
  235.           case(3):setH=100.0;
  236.                   setL=100.0;
  237.                           displaytem1(100.0);
  238.                           break;
  239.           case(4):setH=setH+2.0;
  240.                   setL=setL+2.0;
  241.                           displaytem1(setH);
  242.                           break;
  243.           case(5):setH=setH-2.0;
  244.                           setL=setL-2.0;
  245.                           displaytem1(setH);
  246.                           break;
  247.           case(6):setH=setH+0.5;
  248.                   setL=setL+0.5;
  249.                           displaytem1(setH);
  250.                           break;
  251.           case(7):setH=setH-0.5;
  252.                   setL=setL-0.5;
  253.                           displaytem1(setH);
  254.                           break;
  255.           case(8):P0=0x00;
  256.                   break;

  257.     }
  258.    }
  259.    while(bkey<8);
  260.    while(1)
  261.    {
  262.      temperature=read_Tem();//讀出溫度的值
  263.      DisplayTem(temperature);//顯示實(shí)時(shí)溫度
  264.      if(temperature<setH)
  265.     {
  266.         jiare=1;
  267.     }
  268.      else
  269.     {
  270.       jiare=0;
  271.     }

  272.    }
  273.                      
  274. }
復(fù)制代碼



分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:213173 發(fā)表于 2021-4-27 17:49 | 只看該作者
把這個(gè)程序稍改一下即可用于溫度控制 DS18B20溫度上下限報(bào)警 仿真示例.zip (214.7 KB, 下載次數(shù): 50)

回復(fù)

使用道具 舉報(bào)

板凳
ID:213173 發(fā)表于 2021-4-27 18:32 | 只看該作者
這個(gè)程序可能更適合你,只要把LCD顯示改為數(shù)碼管顯示即可 ds18b20 0~120度PWM恒溫控制LCD顯示 仿真.zip (161.08 KB, 下載次數(shù): 49)



回復(fù)

使用道具 舉報(bào)

地板
ID:902047 發(fā)表于 2021-4-27 20:17 | 只看該作者
wulin 發(fā)表于 2021-4-27 17:49
把這個(gè)程序稍改一下即可用于溫度控制

謝謝,大佬,有時(shí)間的話再幫我看看我的程序應(yīng)該怎么改一下就可以用吧,
回復(fù)

使用道具 舉報(bào)

5#
ID:569384 發(fā)表于 2021-4-28 10:55 | 只看該作者
temperature有數(shù)值嗎?
回復(fù)

使用道具 舉報(bào)

6#
ID:902047 發(fā)表于 2021-4-28 11:12 | 只看該作者
haokey 發(fā)表于 2021-4-28 10:55
temperature有數(shù)值嗎?

我把第282行的if語句改成過:if(temperature),結(jié)果P3.1口可以正常輸出高電平,這應(yīng)該就說明temperature有數(shù)值吧
回復(fù)

使用道具 舉報(bào)

7#
ID:844772 發(fā)表于 2021-4-28 11:57 | 只看該作者
r_high*=0.625;//轉(zhuǎn)換到溫度值小數(shù)
沒太仔細(xì)看,但我覺得應(yīng)該0.0625,你看一下手冊。
回復(fù)

使用道具 舉報(bào)

8#
ID:569384 發(fā)表于 2021-4-28 17:23 | 只看該作者
各位都是大佬 發(fā)表于 2021-4-28 11:12
我把第282行的if語句改成過:if(temperature),結(jié)果P3.1口可以正常輸出高電平,這應(yīng)該就說明temperatur ...

那再數(shù)碼管把temperature和setH都顯示出來看看就知道了嘛。
回復(fù)

使用道具 舉報(bào)

9#
ID:902047 發(fā)表于 2021-4-28 19:48 | 只看該作者
glinfei 發(fā)表于 2021-4-28 11:57
r_high*=0.625;//轉(zhuǎn)換到溫度值小數(shù)
沒太仔細(xì)看,但我覺得應(yīng)該0.0625,你看一下手冊。

謝謝,我改成0.0625之后,數(shù)碼管顯示的實(shí)時(shí)溫度剛好是ds18b20溫度數(shù)值的十分之一。我突然發(fā)現(xiàn)如果預(yù)設(shè)溫度為56的話,數(shù)碼管顯示的實(shí)時(shí)溫度低于5.6則P3.1口輸出高電平,高于5.6度則輸出低電平。我把第282行的語句改為if(temperature/10<setH)后就實(shí)現(xiàn)正常功能了,但是我還是不太清楚為什么改成這樣就好了
回復(fù)

使用道具 舉報(bào)

10#
ID:902047 發(fā)表于 2021-4-28 19:51 | 只看該作者
haokey 發(fā)表于 2021-4-28 17:23
那再數(shù)碼管把temperature和setH都顯示出來看看就知道了嘛。

謝謝,我把第282行的語句改成if(temperature/10<setH)后就實(shí)現(xiàn)溫度控制的正常功能了,但是我不太清楚為什么這樣就好了
回復(fù)

使用道具 舉報(bào)

11#
ID:844772 發(fā)表于 2021-4-28 20:57 | 只看該作者
各位都是大佬 發(fā)表于 2021-4-28 19:48
謝謝,我改成0.0625之后,數(shù)碼管顯示的實(shí)時(shí)溫度剛好是ds18b20溫度數(shù)值的十分之一。我突然發(fā)現(xiàn)如果預(yù)設(shè)溫 ...

這就不該再問了,你temperature變量顯然存到了小數(shù)后一位,比如56.1度,就是561了也就是放大了10倍,所以我建議你用0.0625。你看看void DisplayTem(uint temperature) 函數(shù),它取了temperature個(gè)為作為小數(shù)位顯示的。
回復(fù)

使用道具 舉報(bào)

12#
ID:902047 發(fā)表于 2021-4-29 09:03 | 只看該作者
glinfei 發(fā)表于 2021-4-28 20:57
這就不該再問了,你temperature變量顯然存到了小數(shù)后一位,比如56.1度,就是561了也就是放大了10倍,所以 ...

好的,謝謝大佬
回復(fù)

使用道具 舉報(bào)

13#
ID:923364 發(fā)表于 2021-5-18 16:49 | 只看該作者
大佬你好,請問你這個(gè)原理圖右下角那個(gè)原件叫什么。
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表