久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4267|回復: 4
打印 上一主題 下一主題
收起左側

原創 基于DS18B20的溫度計設計,含有仿真文件,單片機源程序

[復制鏈接]
跳轉到指定樓層
樓主
這是我學習單片機制作的,設計參數主要有:
   1.溫度傳感器采用DS18B20芯片;
   2.LCD1602液晶模塊作為顯示器;
   3.能夠實現按鍵調整溫度上下限;
   4.能夠顯示年月日。

里面有電路仿真圖,c程序等,希望能夠幫助到大家。


  1. #include<reg51.h>                                   //將AT89X52.h頭文件包含到主程序
  2. #include<intrins.h>                                   //將intrins.h頭文件包含到主程序(調用其中的_nop_()空操作函數延時)
  3. #define uint  unsigned int                      //變量類型宏定義,用uint表示無符號整形(16位)
  4. #define uchar unsigned char                   //變量類型宏定義,用uchar表示無符號字符型(8位)
  5. sbit lcdrs=P2^4;
  6. sbit lcdrw=P2^5;
  7. sbit lcden=P2^6;
  8. sbit ds=P1^3;
  9. sbit k1=P3^0;//設置按鍵
  10. sbit k2=P3^1;//加1按鍵
  11. sbit k3=P3^2;//減1按鍵
  12. //sbit k4=P3^3;//關蜂鳴器按鍵
  13. sbit D1=P1^0;
  14. sbit D2=P1^1;
  15. uchar flag,num;
  16. uint aa,bb;
  17. uchar miao,fen,shi,ri=3,month=7,year=18,num11;
  18. long uint temp,biaozhi;               //參數temp一定要聲明為 int 型
  19. //延時函數
  20. void Tempdelay11(uchar us)  //經驗表明,這里us=1時約等于6.9us
  21. {
  22.         while(us--);
  23. }
  24. void delay11(uint count) //延時子函數,當count=1是,延時大概2ms
  25. {
  26.         uint i;
  27.         while(count)
  28.         {
  29.                 i=200;
  30.                 while(i>0)
  31.                         i--;
  32.                 count--;
  33.         }
  34. }
  35. void delay(uint z)  
  36. {
  37.         uint x,y;
  38.         for(x=z;x>0;x--)
  39.                   for(y=110;y>0;y--);
  40. }
  41. /******************lcd液晶程序部分**************************/
  42. void write_com(uchar com)        //lcd寫指令
  43. {
  44.         lcdrs=0;
  45.     lcdrw=0;
  46.         P0=com;
  47.         lcden=1;
  48.         delay(5);
  49.         lcden=0;        
  50. }
  51. void write_date(uchar date)                //lcd寫數據
  52. {
  53.         lcdrs=1;
  54.     lcdrw=0;
  55.         P0=date;
  56.         lcden=1;
  57.         delay(5);
  58.         lcden=0;        
  59. }
  60. void init()                                  //lcd初始化
  61. {
  62.         lcdrw=0;
  63.         write_com(0x38);                 //lcd液晶 顯示模式設置
  64.         write_com(0x0c);                  //lcd液晶 開顯示 關光標 關閃爍
  65.         write_com(0x06);                  //讀一個字節 光標指針加一  不整屏移動
  66.         write_com(0x01);                  //清屏
  67.         write_com(0x80);                  //設置數據指針
  68. }
  69. void key()
  70. {
  71.         if(k1==0)//判斷k1按鍵是否按下
  72.         {
  73.                 delay(10);//延時,消抖
  74.                 if(k1==0)//再次判斷k1按鍵是否按下
  75.                 {
  76.                         while(k1==0);//按鍵松手檢測
  77.                         num++;
  78.                         if(num==1)
  79.                         {
  80.                                 write_com(0x80+9);
  81.                                 write_com(15);        
  82.                         }
  83.                         if(num==2)
  84.                         {
  85.                                 write_com(0x80+15);        
  86.                         }
  87.                         if(num==3)
  88.                         {
  89.                                 num=0;
  90.                                 write_com(12);        
  91.                         }
  92.                 }
  93.         }
  94.         if(num!=0)
  95.         {
  96.                 if(k2==0)//判斷k1按鍵是否按下
  97.                 {
  98.                         delay(10);//延時,消抖
  99.                         if(k2==0)//再次判斷k1按鍵是否按下
  100.                         {
  101.                                 while(k2==0);//按鍵松手檢測
  102.                                 if(num==1)
  103.                                 {
  104.                                         aa++;
  105.                                         if(aa==1000)
  106.                                                 aa=0;
  107.                                         write_com(0x80+6);
  108.                                         write_date(48+aa/100);
  109.                                         write_com(0x80+7);
  110.                                         write_date(48+aa/10%10);
  111.                                         write_com(0x80+9);
  112.                                         write_date(48+aa%10);
  113.                                         write_com(0x80+8);
  114.                                         write_date('.');
  115.                                 }
  116.                                 if(num==2)
  117.                                 {
  118.                                         if(bb<aa)
  119.                                                 bb++;
  120.                                         if(bb==1000)
  121.                                                 bb=0;
  122.                                         write_com(0x80+12);
  123.                                         write_date(48+bb/100);
  124.                                         write_date(48+bb/10%10);
  125.                                         write_com(0x80+15);
  126.                                         write_date(48+bb%10);
  127.                                         write_com(0x80+14);
  128.                                         write_date('.');
  129.                                 }
  130.                         }
  131.                 }
  132.                 if(k3==0)//判斷k1按鍵是否按下
  133.                 {
  134.                         delay(10);//延時,消抖
  135.                         if(k3==0)//再次判斷k1按鍵是否按下
  136.                         {
  137.                                 while(k3==0);//按鍵松手檢測
  138.                                 if(num==1)
  139.                                 {
  140.                                         if(aa>0)
  141.                                                 aa--;
  142.                                         if(aa==-1)
  143.                                                 aa=999;
  144.                                         write_com(0x80+6);
  145.                                         write_date(48+aa/100);
  146.                                         write_date(48+aa/10%10);
  147.                                         write_com(0x80+9);
  148.                                         write_date(48+aa%10);
  149.                                         write_com(0x80+8);
  150.                                         write_date('.');
  151.                                 }
  152.                                 if(num==2)
  153.                                 {
  154.                                         if(bb>0)
  155.                                                 bb--;
  156.                                         if(bb==-1)
  157.                                                 bb=999;
  158.                                         write_com(0x80+12);
  159.                                         write_date(48+bb/100);
  160.                                         write_date(48+bb/10%10);
  161.                                         write_com(0x80+15);
  162.                                         write_date(48+bb%10);
  163.                                         write_com(0x80+14);
  164.                                         write_date('.');
  165.                                 }
  166.                         }
  167.                 }
  168.         }
  169. }
  170. //LCD1602液晶的顯示
  171. void display(uint temp)
  172. {   
  173.     uchar bai,shi,ge;
  174.         bai=temp/100;
  175.         shi=temp/10%10;
  176.         ge=temp%10;
  177.         if(num==0)
  178.         {
  179.                 if(biaozhi==1)
  180.                 {
  181.                         biaozhi=0;
  182.                 }
  183.                 write_com(0x80);
  184.                 write_date(48+bai);
  185.                 write_date(48+shi);
  186.                 write_date('.');
  187.                 write_date(48+ge);
  188.                 write_date(' ');
  189.                 write_date('H');
  190.                 write_date(48+aa/100);
  191.                 write_date(48+aa/10%10);
  192.                 write_date('.');
  193.                 write_date(48+aa%10);
  194.                 write_date(' ');
  195.                 write_date('L');
  196.                 write_date(48+bb/100);
  197.                 write_date(48+bb/10%10);
  198.                 write_date('.');
  199.                 write_date(48+bb%10);
  200.                 if(temp>aa)
  201.                 {
  202.                         D1=0;
  203.                 }
  204.                 else
  205.                         D1=1;
  206.                 if(temp<bb)
  207.                         D2=0;
  208.                 else
  209.                         D2=1;
  210.         }
  211.         write_com(0xc0+3);
  212.         write_date('2');
  213.         write_date('0');
  214.         write_date(48+year/10);
  215.         write_date(48+year%10);
  216.         write_date('-');
  217.         write_date(48+month/10);
  218.         write_date(48+month%10);
  219.         write_date('-');
  220.         write_date(48+ri/10);
  221.         write_date(48+ri%10);
  222. }
  223. /*****************************************
  224. 時序:初始化時序、讀時序、寫時序。
  225. 所有時序都是將主機(單片機)作為主設備,單總
  226. 線器件作為從設備。而每一次命令和數據的傳輸
  227. 都是從主機主動啟動寫時序開始,如果要求單總
  228. 線器件回送數據,在進行寫命令后,主機需啟動
  229. 讀時序完成數據接收。數據和命令的傳輸都是低
  230. 位在先。
  231. 初始化時序:復位脈沖 存在脈沖
  232.         讀;1 或 0時序
  233.         寫;1 或 0時序
  234. 只有存在脈沖信號是從18b20(從機)發出的,其
  235. 它信號都是由主機發出的。
  236. 存在脈沖:讓主機(總線)知道從機(18b20)已
  237. 經做好了準備。
  238. ******************************************/
  239. /*--------------------------------------------------------------------------------------------------------------------
  240. 初始化:檢測總線控制器發出的復位脈沖
  241. 和ds18b20的任何通訊都要從初始化開始

  242. 初始化序列包括一個由總線控制器發出的復位脈沖
  243. 和跟在其后由從機發出的存在脈沖。

  244. 初始化:復位脈沖+存在脈沖

  245. 具體操作:
  246. 總線控制器發出(TX)一個復位脈沖 (一個最少保持480μs 的低電平信號),然后釋放總線,
  247. 進入接收狀態(RX)。單線總線由5K 上拉電阻拉到高電平。探測到I/O 引腳上的上升沿后
  248. DS1820 等待15~60μs,然后發出存在脈沖(一個60~240μs 的低電平信號)。

  249. 具體看18b20 單線復位脈沖時序和1-wire presence detect "的時序圖
  250. -------------------------------------------------------------------------------------------------------------------*/
  251. void ds_reset()
  252. {
  253.         ds=1;
  254.            _nop_();        //1us
  255.            ds=0;
  256.            Tempdelay11(80); //當總線停留在低電平超過480us,總線上所以器件都將被復位,這里
  257.         //延時約530us總    線停留在低電平超過480μs,總線上的所有器件都將被復位。
  258.            _nop_();
  259.            ds=1;           //產生復位脈沖后,微處理器釋放總線,讓總線處于空閑狀態,原因查
  260.         //18b20中文資料

  261.            Tempdelay11(5); //釋放總線后,以便從機18b20通過拉低總線來指示其是否在線,
  262.                   //存在檢測高電平時間:15~60us, 所以延時44us,進行1-wire presence //detect(單線存在檢測)
  263.            _nop_();
  264.            _nop_();
  265.            _nop_();
  266.            if(ds==0)
  267.             flag=1;       //detect 18b20 success
  268.            else
  269.         flag=0;       //detect 18b20 fail
  270.         Tempdelay11(20);    //存在檢測低電平時間:60~240us,所以延時約140us
  271.            _nop_();
  272.            _nop_();
  273.            ds=1;          //再次拉高總線,讓總線處于空閑狀態
  274. }
  275. /*----------------------------------------
  276. 讀/寫時間隙:
  277. DS1820 的數據讀寫是通過時間隙處理
  278. 位和命令字來確認信息交換。
  279. ------------------------------------------*/
  280. bit ds_read_bit()    //讀一位
  281. {
  282.         bit dat;
  283.            ds=0;         //單片機(微處理器)將總線拉低
  284.         _nop_();       //讀時隙起始于微處理器將總線拉低至少1us
  285.            ds=1;        //拉低總線后接著釋放總線,讓從機18b20能夠接管總線,輸出有效數據
  286.            _nop_();
  287.            _nop_();          //小延時一下,讀取18b20上的數據 ,因為從ds18b20上輸出的數據
  288.         //在讀"時間隙"下降沿出現15us內有效
  289.            dat=ds;           //主機讀從機18b20輸出的數據,這些數據在讀時隙的下降沿出現15us內有效
  290.            Tempdelay11(10);    //所有讀"時間隙"必須60~120us,這里77us
  291.            return(dat);       //返回有效數據
  292. }
  293. uchar ds_read_byte() //讀一字節
  294. {
  295.         uchar value,i,j;
  296.         value=0;           //一定別忘了給初值
  297.         for(i=0;i<8;i++)
  298.         {
  299.             j=ds_read_bit();
  300.              value=(j<<7)|(value>>1);   //這一步的說明在一個word文檔里面
  301.         }
  302.         return(value);        //返回一個字節的數據
  303. }
  304. void ds_write_byte(uchar dat) //寫一個字節
  305. {
  306.         uchar i;
  307.         bit onebit;        //一定不要忘了,onebit是一位
  308.         for(i=1;i<=8;i++)
  309.         {
  310.             onebit=dat&0x01;
  311.             dat=dat>>1;
  312.                 if(onebit)      //寫 1
  313.                 {
  314.                         ds=0;
  315.                         _nop_();   
  316.                       _nop_();      //看時序圖,至少延時1us,才產生寫"時間隙"
  317.                         ds=1;       //寫時間隙開始后的15μs內允許數據線拉到高電平
  318.                      Tempdelay11(5); //所有寫時間隙必須最少持續60us
  319.                 }
  320.                 else         //寫 0
  321.                 {
  322.                         ds=0;
  323.                      Tempdelay11(8);    //主機要生成一個寫0 時間隙,必須把數據線拉到低電平并保持至少60μs,這里64us
  324.                         ds=1;
  325.                         _nop_();
  326.                      _nop_();
  327.                 }
  328.         }
  329. }
  330. /*****************************************
  331. 主機(單片機)控制18B20完成溫度轉換要經過三個步驟:
  332. 每一次讀寫之前都要18B20進行復位操作,復位成功后發送
  333. 一條ROM指令,最后發送RAM指令,這樣才能對DS18b20進行
  334. 預定的操作。
  335. 復位要求主CPU將數據線下拉500us,然后釋放,當ds18B20
  336. 受到信號后等待16~60us,后發出60~240us的存在低脈沖,
  337. 主CPU收到此信號表示復位成功
  338. ******************************************/

  339. /*----------------------------------------
  340. 進行溫度轉換:
  341. 先初始化
  342. 然后跳過ROM:跳過64位ROM地址,直接向ds18B20發溫度轉換命令,適合單片工作
  343. 發送溫度轉換命令
  344. ------------------------------------------*/
  345. void tem_change()
  346. {
  347.         ds_reset();
  348.         delay11(1);              //約2ms
  349.         ds_write_byte(0xcc);
  350.         ds_write_byte(0x44);
  351. }

  352. /*----------------------------------------
  353. 獲得溫度:
  354. ------------------------------------------*/
  355. uint get_temperature()
  356. {
  357.         float wendu;
  358.         uchar a,b;
  359.         ds_reset();
  360.         delay11(1);              //約2ms
  361.         ds_write_byte(0xcc);
  362.         ds_write_byte(0xbe);
  363.         a=ds_read_byte();
  364.         b=ds_read_byte();
  365.         temp=b;
  366.         temp<<=8;
  367.         temp=temp|a;
  368.         /*if((b&0x80)==0x80)
  369.         {
  370.                    biaozhi=1;//設置溫度正負的標志
  371.               temp=0xffff-temp;
  372.                    temp=temp+1;
  373.         }*/
  374.         wendu=temp*0.0625;     //得到真實十進制溫度值,因為DS18B20
  375.                        //可以精確到0.0625度,所以讀回數據的最低位代表的是0.0625度
  376.         temp=wendu*10.0+0.5;       //放大十倍,這樣做的目的將小數點后第一位
  377.                          //也轉換為可顯示數字,同時進行一個四舍五入操作。
  378.         return temp;
  379. }
  380. void main()
  381. {
  382.         aa=500;
  383.         bb=50;
  384.         EA=1;
  385.         ET0=1;
  386.         TMOD=0x01;
  387.         TH0=(65536-50000)/256;
  388.         TL0=(65536-50000)%256;
  389.         TR0=1;
  390.            init();
  391.            while(1)
  392.            {        
  393.                 key();
  394.                 if(num==0)
  395.                 {
  396.                         tem_change();    //開始轉換12位轉換時間最大為750ms
  397.                         get_temperature();//000000000000
  398.                 }
  399.                 display(temp);
  400.            }
  401. }
  402. //定時器0中斷子函數
  403. void t0() interrupt 1
  404. {
  405.         TH0=(65536-50000)/256;
  406.         TL0=(65536-50000)%256;
  407.         num11++;
  408.         if(num11==20)
  409.         {
  410.                 num11=0;
  411.                 miao++;
  412.                 if(miao==60)
  413.                 {
  414.                         miao=0;
  415.                         fen++;
  416.                         if(fen==60)
  417.                         {
  418.                                 fen=0;
  419.                                 shi++;
  420.                                 if(shi==24)
  421.                                 {
  422.                                         shi=0;
  423.                                         fen=0;
  424.                                         miao=0;
  425.                                         ri++;
  426.                                         if(ri==29)
  427.                                                 if((year%4!=0)&&(month==2))
  428.                                                 {
  429.                                                         ri=1;
  430.                                                         month++;
  431.                                                         if(month==13)
  432.                                                         {
  433.                                                                 month=1;
  434.                                                                 year++;
  435.                                                         }
  436.                                                 }
  437.                                         if(ri==30)
  438.                                                 if((year%4==0)&&(month==2))
  439.                                                 {
  440.                                                         ri=1;
  441.                                                         month++;
  442.                                                         if(month==13)
  443.                                                         {
  444.                                                                 month=1;
  445.                                                                 year++;
  446.                                                         }
  447.                                                 }
  448.                                         if(ri==31)
  449.                                                 if((month==4)||(month==6)||(month==9)||(month==11))
  450.                                                 {
  451.                                                         ri=1;
  452.                                                         month++;
  453.                                                         if(month==13)
  454.                                                         {
  455.                                                                 month=1;
  456.                                                                 year++;
  457.                                                         }
  458.                                                 }
  459.                                         if(ri==32)
  460.                                                 if((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==10)||(month==12))
  461.                                                 {
  462.                                                         ri=1;
  463.                                                         month++;
  464.                                                         if(month==13)
  465.                                                         {
  466.                                                                 month=1;
  467.                                                                 year++;
  468.                                                         }
  469.                                                 }
  470.                                 }
  471.                         }
  472.                 }
  473.         }
  474. }        
復制代碼
全部資料51hei下載地址:
基于DS18B20的溫度計.zip (79.31 KB, 下載次數: 132)
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏4 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發
ID:592038 發表于 2021-2-25 23:49 | 只看該作者
怎么添加蜂鳴器
回復

使用道具 舉報

板凳
ID:592038 發表于 2021-2-26 01:49 | 只看該作者
通電顯示溫度85,一秒后恢復正常,怎么修改這個85
回復

使用道具 舉報

地板
ID:917252 發表于 2021-5-26 10:13 | 只看該作者
負數部分怎么不顯示呢
回復

使用道具 舉報

5#
ID:917252 發表于 2021-5-26 10:13 | 只看該作者
大佬可以加上負數部分顯示嗎
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 在线视频亚洲 | 日韩精品在线免费观看视频 | 国产综合在线视频 | 欧美黄色片 | 91在线网站 | 日韩在线观看一区二区三区 | 国产第一亚洲 | 国产精品久久久久久久久免费丝袜 | 亚洲欧美日韩精品久久亚洲区 | 日本在线观看视频 | 久久99深爱久久99精品 | 精品国产高清一区二区三区 | 黄a在线观看| 欧美精品一区二区三区蜜桃视频 | 国产乱码精品一区二区三区中文 | 国产精品久久久久久久免费大片 | 中文字幕精品一区 | 在线免费黄色小视频 | 在线欧美一区 | 中文字幕 在线观看 | 午夜tv免费观看 | 就操在线 | 美女黄网站视频免费 | 狠狠爱免费视频 | 91视频在线| 日韩高清国产一区在线 | 日本不卡一区二区三区 | 成人国产精品入口免费视频 | 欧美一区免费 | 精品久久网 | 国产黄色在线观看 | 在线观看成年视频 | 成人午夜在线视频 | 国产日韩一区二区三免费 | 亚洲国产成人在线视频 | av网站在线看 | 色吧久久 | 亚洲乱码国产乱码精品精98午夜 | 一级片在线观看视频 | 91视频网址 | 91精品国产91久久久久久最新 |