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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4967|回復: 6
收起左側

ds18b20溫度感應詳解

[復制鏈接]
ID:68618 發表于 2014-11-11 19:04 | 顯示全部樓層 |閱讀模式
DS18B20是一種常用的溫度傳感器,可以實現多點網絡式測量,這里簡單介紹單個ds18b20的使用。
DS18B20看起來像一個三極管,有三個引腳,1:地,2:數據端,3:電源,DS18B20的通信方式有點特別,僅靠一根線進行通信,而且多個DS18B20也是連在一個線上的,所以通信協議僅靠高低電平實現,而且速度較慢,因為傳輸數據較少,所以時間還是可以忍受。


簡單起見,這里介紹單個DS18B20的使用方法,忽略地址匹配等方法,下面結合程序,說明一下主流程:
unsigned int ds18b20_read_temperature(void)
{
  unsigned int temperature;
  ds18b20_init();  //初始化(復位)
  ds18b20_write_byte(0xCC);  //發送命令,跳過ROM
  ds18b20_write_byte(0x44);  //溫度轉換
  delayms(1000);  //給必要的轉換時間
  ds18b20_init();   //DS1302 復位
  ds18b20_write_byte(0xCC);  //跳過ROM
  ds18b20_write_byte(0xbe);  //讀取RAM
  temperature = ds18b20_read_byte(); //讀低八位,LS Byte, RAM0
  temperature |= ds18b20_read_byte() << 8; //讀高八位,MS Byte, RAM1
  return temperature*0.0625; //0.0625=xx, 0.625=xx.x, 6.25=xx.xx
}

很簡單,啟動溫度轉換,等待,讀取結果。


下面介紹DS18B20的單線通信方式:
這個要細細研究手冊的時序圖,才能寫好程序。

1.DS18B20的復位:


總線先給一個480us的低電平,等待15-60us,DS18B20會有一個60-240us的低電平響應,注意用時候可能因為軟件或硬件的問題,并沒有使DS18B20成功初始化,這樣程序會進入無限等待的死循環里,這里為了防止死循環的發生,使用最大延時限制,一旦延時到且初始化未成功,就重新初始化。
程序如下:
void ds18b20_init(void)
{
  int i;
again:        //這里為了方便,用了一個C語言的禁忌指令:goto label
      TD = 1; //T 為輸出狀態
      TO = 0; //輸出低電平
      delayus(500); //延遲480~960 us
      TO = 1; //釋放總線
      TD = 0; //DQ 位輸狀入態
      
#define MAX 480   //定義一個最大延時數,防止死循環
      
      for(i=MAX;i>0;i--)
      {
        if(!TI)  break;//檢測到低電平,跳到下一步
      }
      if(i == 0) goto again;//最大延時到,重新檢測
      
      for(i=MAX;i>0;i--)
      {
        if(TI)  break;//檢測到高電平,跳到下一步
      }
      if(i == 0) goto again;//最大延時到,重新檢測
}

2.向DS18B20寫一位:
如果寫0,則給60~120us的低電平;如果寫1,先給至少1us的低電平,然后給高電平,直至60us。
void write_bit(char b)
{
  TD = 1;
  
  TO = 0;//拉低總線
  delayus(2); //至少1us
  
  TO = !!b;   //  !!是為了把非零數轉換 為1
  delayus(58); //保證60us
  TO = 1; //釋放總線
}

3.讀DS18B20一位:
先給至少1us的低電平,然后在15us內讀取,高為1,低為0,在等待,直至60us。
char read_bit(void)
{
  char b;
  TD = 1;//置位輸出
  
  TO = 0;//拉低總線,至少1us
  delayus(2);
  TO = 1;
  
  TD = 0;//置位輸入
  delayus(4);//必須在15us內讀取
  b = TI;
  delayus(54);
  
  TD = 1;//置位輸出
  TO = 1;//釋放總線
  return b;
}



下面是完整的程序:
編譯器:IAR
單片機:ATmega32 或 16

#include "main.h"
//定義 T 引腳
#define TD DDRC_Bit7
#define TO PORTC_Bit7
#define TI PINC_Bit7
//根據時序圖,先給至少1us的低電平,
//寫1則拉高       直至60us
//寫0則繼續保持   直至60us
void write_bit(char b)
{
  TD = 1;
  
  TO = 0;//拉低總線
  delayus(2); //至少1us
  
  TO = !!b;   //  !!是為了把非零數轉換 為1
  delayus(58); //保證60us
  TO = 1; //釋放總線
}
void ds18b20_write_byte(char val)
{
  char i;
  for(i=0;i<8;i++)
  {
    write_bit( val&(1<<i) );
  }
}
//根據時序圖,先給至少1us的低電平,
//然后在15us內讀取
//高為1       直至60us
//低為0       直至60us
char read_bit(void)
{
  char b;
  TD = 1;//置位輸出
  
  TO = 0;//拉低總線,至少1us
  delayus(2);
  TO = 1;
  
  TD = 0;//置位輸入
  delayus(4);//必須在15us內讀取
  b = TI;
  delayus(54);
  
  TD = 1;//置位輸出
  TO = 1;//釋放總線
  return b;
}
char ds18b20_read_byte(void)
{
  char i;
  char value=0; //讀出溫度
  for(i=0;i<8;i++)
  {
    value |= read_bit() << i;
  }
  return(value);
}
//根據時序圖,先給一個480~960us的低電平,然后釋放總線等待DS18B20響應(一個低脈沖)
//為了穩定性,使用延時循環以防止了死循環的發生
void ds18b20_init(void)
{
  int i;
again:        //這里為了方便,用了一個C語言的禁忌指令:goto label
      TD = 1; //T 為輸出狀態
      TO = 0; //輸出低電平
      delayus(500); //延遲480~960 us
      TO = 1; //釋放總線
      TD = 0; //DQ 位輸狀入態
      
#define MAX 480   //定義一個最大延時數,防止死循環
      
      for(i=MAX;i>0;i--)
      {
        if(!TI)  break;//檢測到低電平,跳到下一步
      }
      if(i == 0) goto again;//最大延時到,重新檢測
      
      for(i=MAX;i>0;i--)
      {
        if(TI)  break;//檢測到高電平,跳到下一步
      }
      if(i == 0) goto again;//最大延時到,重新檢測
}
unsigned int ds18b20_read_temperature(void)
{
  unsigned int temperature;
  ds18b20_init();
  ds18b20_write_byte(0xCC); //跳過ROM
  ds18b20_write_byte(0x44); //溫度轉換
  delayms(1000);//給必要的轉換時間
  ds18b20_init(); //DS1302 復位
  ds18b20_write_byte(0xCC); //跳過ROM
  ds18b20_write_byte(0xbe); //讀取RAM
  temperature = ds18b20_read_byte(); //讀低八位,LS Byte, RAM0
  temperature |= ds18b20_read_byte() << 8; //讀高八位,MS Byte, RAM1
  return temperature*0.0625; //0.0625=xx, 0.625=xx.x, 6.25=xx.xx
}
/*
int main( void )
{
  unsigned int Temp;
  while(1)
  {
  Temp = ds18b20_read_temperature(); //調用讀取溫度函數
// delayus(100); //稍微延遲
  }
}
*/

回復

使用道具 舉報

無效樓層,該帖已經被刪除
ID:7485 發表于 2014-11-13 18:46 | 顯示全部樓層
游客 183.69.216.x 發表于 2014-11-12 11:26
比較詳細,不錯,18B20最不好弄的是時間,比如1US的延時程序,不同的IC不同的晶振,沒有示波器的話,不太好 ...

沒有這么難吧?
只要按照資料上給出的時間隙編寫程序不會有問題的。時間隙的彈性還是比較大的。最好是使用匯編寫這一段。
回復

使用道具 舉報

ID:68356 發表于 2014-11-13 22:16 | 顯示全部樓層
學習了,收藏
回復

使用道具 舉報

ID:67678 發表于 2014-11-13 23:08 | 顯示全部樓層
學習了
謝謝
回復

使用道具 舉報

ID:75749 發表于 2015-3-30 23:56 | 顯示全部樓層
支持一下
回復

使用道具 舉報

ID:111517 發表于 2016-4-3 12:57 | 顯示全部樓層
請問下樓主那個讀“0”操作中的45us是做什么用的,可以不用嗎,讀取過后直接用個大于1us的延時(即兩個讀時序的恢復期),然后進行下次的讀操作可以嗎??
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 99精品国产成人一区二区 | xx视频在线| 天天操夜夜拍 | 久久久久国产精品人 | 日韩av在线不卡 | 欧美亚洲视频在线观看 | 99精品欧美一区二区蜜桃免费 | 亚洲欧美在线观看 | 欧美午夜一区 | 日韩精品在线免费观看视频 | 欧美不卡在线 | 国产女人精品视频 | 成人在线视频免费观看 | 亚洲日韩欧美一区二区在线 | 精品国产一区二区在线 | 亚洲精品国产综合区久久久久久久 | 日韩精品一区二区三区 | 亚欧性视频 | 亚洲精品久久嫩草网站秘色 | 精品久久久久久亚洲综合网站 | 在线观看国产视频 | 久久久一区二区三区 | 日韩在线观看中文字幕 | 国产午夜精品一区二区三区四区 | 国产成人免费网站 | 日本超碰| 人干人人 | hsck成人网 | 成人精品久久 | 污片在线观看 | 久精品久久 | 九九亚洲精品 | 日韩在线三级 | 99久久精品免费看国产免费软件 | 九色在线观看 | 亚洲精品成人在线 | 国内精品久久久久久久影视简单 | 91精品国产色综合久久不卡蜜臀 | 久久专区 | 日韩精品视频一区二区三区 | 中文字幕免费视频 |