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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

51單片機學習:DS18B20測溫程序

[復制鏈接]
跳轉到指定樓層
樓主
ID:161768 發表于 2017-1-14 23:34 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
  1. #include "my51.h"
  2. #include "smg.h"
  3. #include "ds18b20.h"

  4. void main()                          //測試 ,6位數碼管顯示溫度值
  5. {
  6.     u8 i=0;
  7.     u16 temp=0;
  8.     while(1)
  9.     {       
  10.                 temp=ds18b20_readTemperaData();
  11.                 for(i=0;i<100;i++)
  12.                 {
  13.                         displaySMG(ds18b20_processTempData(temp));        
  14.                 }                    
  15.     }
  16. }
復制代碼

  1. #ifndef                _DS18B20_H   
  2. #define                _DS18B20_H
  3. #include   "my51.h"
  4. #include   "smg.h"

  5. extern u8 smgWela[7];                          //數碼管位選數據
  6. sbit DQ=P2^2;                                          //總線定義
  7. bool ds18b20_init();              //初始化函數
  8. u8*  ds18b20_processTempData(u16 temp);//將temp數據處理成數碼管可顯示數據
  9. u16  ds18b20_readTemperaData();   //讀溫度
  10. u8          ds18b20_readByte() ;         //讀一個字節
  11. void ds18b20_writeByte(u8 dat);   //mcu向18b20寫一個字節

  12. #endif
復制代碼


  1. #include "ds18b20.h"

  2. /******************************************************************
  3. 當主機總線t0時刻從高拉至低電平時就產生寫時間隙
  4. 從to 時刻開始的1us之后,15us之前將所需寫的位送到總線上
  5. DSl820 在t0后的15-60us 對總線采樣若低電平寫入的位是0 ,若高電平寫入的位是1
  6. 連續寫2 個位之間的間隙應大于1us
  7. 寫1,總時間大于60us,在t0開始延時1us就可以寫1,15us之后ic來采樣,采樣時間最大45us
  8. 寫0,總時間是60~120us,15~60us是ic在采樣,120以外就沒必要了,mcu總得釋放總線吧
  9. 不管寫1還是寫0,大于60us的話,ic肯定已經采樣完成了,那mcu就可以釋放了
  10. *******************************************************************/
  11. void ds18b20_writeByte(u8 dat)  //mcu向ic寫一個字節
  12. {
  13.     u8 i;
  14.         u8 tmep=dat;
  15.     for(i=0;i<8;i++)
  16.     {
  17.         DQ=0;           //產生讀寫時序的起始信號
  18.         _nop_();        //要求至少1us的延時
  19.         DQ=dat & 0x01; //對總線賦值,從最低位開始寫起
  20.         delayXus(10);//延時74us,寫0在60~120us之間釋放,寫1的話大于60us均可釋放
  21.         DQ=1;          //釋放總線,為下一次mcu送數據做準備,      
  22.                 dat>>=1;           //有效數據移動到最低位,2次寫數據間隙至少需1us
  23.     }
  24. }

  25. /**************************************************************************
  26. 下降沿產生讀時序
  27. 整個讀時序必須至少有60us的持續時間,相鄰兩個讀時序必須要有至少1us的恢復時間
  28. DS18B20在讀時序產生1us后輸出數據到總線上,也有可能需要2~3個微秒,但不會更多
  29. 而要求主機釋放總線和采樣總線等動作要在15μs內完成,那么讓mcu采樣的最佳時機
  30. 是讀時序產生后的5~13us之間,在15~60us這段時間是18b20的私有時間,它會在這段
  31. 時間內的任意時刻釋放總線,是不穩定期,我們不要讓mcu在這段時間里對總線操作
  32. *******************************************************/
  33. u8 ds18b20_readByte()    //mcu讀一個字節
  34. {
  35.     u8 i,value=0;
  36.     for(i=0;i<8;i++)
  37.     {
  38.         DQ=0;                       //起始信號
  39.         value>>=1;                  //順便延時3~4個機器周期
  40.         DQ=1;                       //mcu釋放總線
  41.         _nop_();_nop_();_nop_();        //再延時3.3us
  42.         if(DQ)         
  43.         {
  44.             value|=0x80;//保存高電平數據,低電平的話不用保存,移位后默認是0
  45.         }
  46.         delayXus(8); //延時60.76us  
  47.     }
  48.     return value;
  49. }

  50. u16 ds18b20_readTemperaData()  //讀取溫度值
  51. {
  52.     u16 temp=0;
  53.     if(ds18b20_init())
  54.     {
  55.         ds18b20_writeByte(0xcc);      //寫指令:跳過rom檢測
  56.         ds18b20_writeByte(0x44);     //寫指令:溫度轉換
  57.         //delayms(750);// 轉換延時需要750ms以上,我們不等它
  58.                 //首次轉換未完成時,得到的初始化數據是85度,處理一下就可以了
  59.                 //溫度轉換電路是硬件獨立的,不會阻塞初始化功能
  60.         if(ds18b20_init())
  61.         {
  62.             ds18b20_writeByte(0xcc);  //寫指令:跳過檢測rom
  63.             ds18b20_writeByte(0xbe);  //寫指令:讀取溫度值
  64.             temp=ds18b20_readByte();  //先讀低8位數據
  65.                         temp|=(u16)ds18b20_readByte()<<8; //再讀高8位數據,然后合并
  66.                         temp&= 0x0FFF;        //高4位數據反正沒用上,我們用來存放錯誤碼
  67.         }
  68.                 else
  69.                 {
  70.                         led5=0;                 //調試代碼
  71.                         temp=0x2000; //錯誤碼,初始化失敗
  72.                 }
  73.     }
  74.         else
  75.         {
  76.                 led6=0;                        //調試代碼
  77.                 temp=0x1000;           //錯誤碼,初始化失敗,可能器件損壞
  78.         }
  79.     return temp;
  80. }

  81. bool ds18b20_init()   //初始化
  82. {
  83.     u8 checkState=0;
  84.     DQ=1;             //總線初始狀態
  85.     _nop_();_nop_();
  86.     DQ=0;             //mcu先將總線拉低
  87.     delayXus(80);     //延時530us,要求480us~960us的低電平信號
  88.                       //當ic接受到此復位信號后會回發一個存在信號
  89.                       //mcu若要接收此存在信號則先要釋放總線,讓ic控制該總線
  90.                       //當mcu釋放總線后的15~60us之后,ic才向總線發一個低電平信號
  91.                       //該信號存在時間為60~240us
  92.     DQ=1;             //mcu釋放總線
  93.     delayXus(10);     //mcu釋放15~60us以上,(8+6*10)*1.085=73us,
  94.                       //這時DS18B20已經拉低信號,大約60~240us應答保持時間,
  95.     checkState=DQ;    //在這段60~240us時間內,mcu采樣是否有器件響應,0表示有響應
  96.     delayXus(70);     //延時464us,加上之前的73us,共537us
  97.                       //雖然ic在拉低電平60~240us之后,會釋放總線,但整個時間至少480us
  98.                       //故我們共用時537us,這樣是為了不影響后續的操作                    
  99.     if(checkState)    //checkstate為0說明有器件響應,為1無器件響應
  100.     {
  101.         return FALSE;
  102.     }
  103.     return TRUE;          //初始化成功
  104. }

  105. u8* ds18b20_processTempData(u16 temp) //返回數碼管可直接顯示的數據指針
  106. {
  107.         u8 i=0;       
  108.         if(0x0550==temp)          //如果初始化溫度數據是85度的話
  109.         {
  110.                 led7=0;                             //亮燈報警,調試
  111.                 smgWela[5]=18;          //當溫度是85度,第6個數碼管顯示負號
  112.                 return         smgWela;  //一般剛上電時能看到這個負號
  113.         }

  114.         if(1==(temp&0x0800))  //檢測第11位是否為1,為1是負溫度
  115.         {
  116.                 temp&=0x07ff;          //只取第0~10共11個位
  117.                 temp=(~temp+1) & 0x07ff;//將補碼還原
  118.                 smgWela[0]=18;         //第一個數碼管顯示18號元素,即負號
  119.         }
  120.         else
  121.         {
  122.                 smgWela[0]=dark;           //正溫度的話這個數碼管就不要顯示了
  123.         }
  124.     temp=(u16)(temp*6.25);         //精度的1000倍,我們將小數點另外疊加顯示
  125.         if(temp>=10000)
  126.         {
  127.                  smgWela[1]=1;            //第二個數碼管顯示1,是百位上,100度以上啊
  128.         }
  129.         else
  130.         {
  131.                 smgWela[1]=dark;     //百位上是0的話不要顯示這個0
  132.         }
  133.     smgWela[2]=temp%10000/1000;           //第三個數碼管 十位
  134.     smgWela[3]=temp%1000/100;           //第四個數碼管 個位疊加小數點
  135.     smgWela[4]=temp%100/10;                   //第五個數碼管
  136.     smgWela[5]=temp%10;                           //第六個數碼管
  137.         smgWela[6]=0xf7;                           //第4個數碼管疊加小數點
  138.         return smgWela;                                   //返回數組
  139. }
復制代碼


  1. #ifndef _51SMG_H_
  2. #define _51SMG_H_

  3. #include <reg52.h>
  4. #include "mytype.h"
  5. sbit dula =P2^6;                  //段選鎖存器控制  控制筆段
  6. sbit wela =P2^7;                  //位選鎖存器控制  控制位置

  7. #define dark        0x11//在段中,0x11是第17號元素,0x00是低電平,數碼管不亮,即table[17]
  8. #define dotDark 0xff//小數點全暗

  9. void displaySMG(u8* pWela); //數碼管顯示函數,參數是數組指針

  10. #endif
復制代碼


  1. #include "smg.h"
  2. #include "my51.h"

  3. static u8 code table[]= {                 //0~F外加小數點和空輸出的數碼管編碼
  4.         0x3f , 0x06 , 0x5b , 0x4f , // 0 1 2 3
  5.         0x66 , 0x6d , 0x7d , 0x07 , // 4 5 6 7
  6.         0x7f , 0x6f , 0x77 , 0x7c , // 8 9 A B
  7.         0x39 , 0x5e , 0x79 , 0x71 , // C D E F
  8.         0x80 , 0x00 ,0x40           // . 空 負號    空為第17號元素
  9. };

  10. /*  由于此表只能一次顯示一個小數點,故已注釋掉,僅供查詢
  11.         例如想要第一個和第六個數碼管小數點同時點亮,
  12.         則執行 pWela->dot = 0xfe & 0xdf  即可
  13.         u8 code dotTable[]={   //小數點位置,某一位置0時,小數點亮
  14.         0xff ,                 //全暗
  15.         0xfe , 0xfd , 0xfb ,   //1 2 3
  16.         0xf7 , 0xef , 0xdf     //4 5 6                    
  17. };*/

  18. u8 data smgWela[7]={0,0,0,0,0,0,0}; //第一位到第六位,最后一個是小數點位置控制

  19. //P0口的數碼管位選控制鎖存器只用了低6位,我們保留高2位的數據,留作它用
  20. void displaySMG(u8* pWela)
  21. {
  22.         u8 i=0;       
  23.     //控制6位數碼管顯示函數,不顯示的位用參數dark
  24.     u8 preState=P0|0x3f;  //保存高2位狀態,其中最高位是ADC0804的片選信號
  25.         wela=0;dula=0;_nop_();//先鎖定數據,防止吳亮及位選鎖存器高2位數據被改變
  26.                
  27.         P0=0;                                 //由于數碼管是共陰極的,陽極送低電平,燈不亮
  28.     dula=1;_nop_();
  29.     dula=0;                                 //段選數據清空并鎖定

  30.     P0=preState;                    //共陰極數碼管是陰極置高不亮,低6位置1,高2位保留       
  31.     wela=1;_nop_();                  //注:wela和dula上電默認為1                 
  32.     wela=0;                                    //位選鎖定,初始保留高2位的數據,低6位置高不亮

  33.         for(i=0;i<6;i++)          //顯示6位數碼管
  34.         {
  35.                 P0=table[pWela[i]]|(((1<<i) & pWela[6])?0x00:0x80);
  36.             dula=1;_nop_();             //送段數據,疊加小數點的顯示,0x00點亮小數點
  37.             dula=0;
  38.             
  39.                    P0=preState&~(1<<i); //不影響高2位數據,低6位是數碼管位選,低電平有效
  40.             wela=1;        _nop_();         //送位選號
  41.             wela=0;       
  42.             delayms(1);                         //稍作延時,讓燈管亮起來                       
  43.                 {  //消除疊影及誤亮,陰極置1不亮,低6位置1,高2位保留并鎖定
  44.                 P0=preState;
  45.                 wela=1;        _nop_();                       
  46.                 wela=0;       
  47.             }
  48.         }
  49. }
復制代碼


  1. #ifndef _MY51_H
  2. #define _MY51_H
  3. #include <reg52.h>
  4. //#include <math.h>
  5. #include <intrins.h>
  6. #include "mytype.h"


  7. #define high        1   //高電平
  8. #define low                0   //低電平

  9. #define led P1    //燈總線控制

  10. sbit led0=P1^0;     //8個led燈,陰極送低電平點亮
  11. sbit led1=P1^1;
  12. sbit led2=P1^2;
  13. sbit led3=P1^3;
  14. sbit led4=P1^4;
  15. sbit led5=P1^5;
  16. sbit led6=P1^6;
  17. sbit led7=P1^7;       
  18. sbit ledLock=P2^5;        //led鎖存的狀態,0鎖定 ,1不鎖定
  19.    
  20. sbit beep=P2^3;     //蜂鳴器

  21. void delayms(u16 ms);
  22. void delayXus(u8 us); //函數執行(8+6x)個機器周期, 即t=(8+6x)*1.085
  23. /////////////////////////////////////////////////////////////////////////////


  24. #endif
復制代碼


  1. #include "MY51.h"

  2. void delayms(u16 ms)     //毫秒級軟延時函數
  3. {       
  4.         u16 i,j;
  5.         for(i=ms;i>0;i--)
  6.         {
  7.         for(j=113;j>0;j--)
  8.         {}
  9.         }
  10. }

  11. /****************************************************************
  12. 若使用12分頻模式的mcu,晶振頻率為11059200Hz
  13. 則每個機器周期用時12/11059200=1.085微秒
  14. keil4編譯,在默認的8級優化方式下
  15. 參數us=0時,函數執行9個機器周期,即t=9*1.085=9.77 us
  16. 參數us!=0時,函數執行(8+6x)個機器周期, 即t=(8+6x)*1.085 us
  17. *****************************************************************/
  18. void delayXus(u8 us)        //微秒級軟延時函數
  19. {
  20.         while(us)           //這種寫法有利于減小us=0時的機器周期
  21.         {
  22.                 us--;
  23.         }
  24. }
復制代碼




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

使用道具 舉報

沙發
ID:829862 發表于 2022-2-7 14:13 | 只看該作者
:loveliness::hug::'(
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲永久 | 国产精品视频久久久 | 日日爱av | 中文字幕一区二区三区日韩精品 | 日韩成人免费中文字幕 | 久久伊人一区 | 亚洲成人精品在线 | 黄网站涩免费蜜桃网站 | 亚洲第一av网站 | 欧美日韩高清 | 日韩免费电影 | 欧美日韩国产一区 | 蜜桃毛片 | 日韩精品一区二区三区在线观看 | 欧美精品成人影院 | 精品国产乱码久久久久久牛牛 | 国产成人精品高清久久 | 91香蕉视频在线观看 | 精精国产xxxx视频在线野外 | 国产一区二区三区精品久久久 | 欧美一区免费在线观看 | 日韩在线视频一区二区三区 | 国产精品久久九九 | 欧美国产视频 | 国产黄色精品 | 国产精品99久久久久久www | 国产精品视频导航 | 91久久 | a级黄色片视频 | 91看片网 | 国产清纯白嫩初高生在线播放视频 | 天天操天天射综合 | 亚洲精品2 | 成人1区2区| 老司机成人在线 | 乳色吐息在线观看 | 一区中文字幕 | 国产高清精品一区二区三区 | 韩国av一区二区 | 99久久国产综合精品麻豆 | 亚洲二区在线 |