玩轉STM32CubeMX | DS18B20溫度傳感器

1.DS18B20簡介

DS18B20是由DALLAS半導體公司推出的一種單總線接口的溫度傳感器,與傳統的熱敏電阻等測溫元件相比,它是一種新型的體積小、實用電壓寬、與微處理器接口簡單的數字化溫度傳感器。
DS18B20的內部結構以下圖示編程

玩轉STM32CubeMX | DS18B20溫度傳感器

ROM中的64位序列號是出廠前就被光刻好的,能夠看作是DS18B20的地址序列號。64位光刻ROM的排列是:8位產品類型標號+48位DS18B20序列號+8位循環冗餘校驗碼。光刻ROM 的做用是使每個DS18B20都各不相同,這樣就能夠實現一根總線上掛接多個DS18B20markdown

DS18B20的內部存儲器(9個字節)包括一個高速暫存器RAM和一個EEPROM,EEPROM裏存放高溫和低溫觸發器和配置寄存器,存儲器詳細組成見下圖:異步

玩轉STM32CubeMX | DS18B20溫度傳感器

配置寄存器是配置不一樣的位數來肯定溫度和數字的轉化,其結構下圖示:低五位都是1,TM是測試模式位(設置工做模式或測試模式,默認爲0即工做模式),R1和R0用來設置精度,可設9~12位精度,對應的溫度分辨率爲0.5, 0.25, 0.125, 0.0625℃
玩轉STM32CubeMX | DS18B20溫度傳感器
全部的單總線器件都要求採樣嚴格的信號時序,以保證設局的完整性。DS18B20的時序有:初始化時序、寫(0和1)時序、讀(0和1)時序。DS18B20發送全部的命令和數據都是字節的低位在前,下面介紹這幾個信號的時序:ide

⏩ 初始化時序函數

內置閃存模塊能夠在通用地址空間直接尋址,任何32位數據的讀操做都能訪問閃存模塊的內容並獲得相應的數據。
玩轉STM32CubeMX | DS18B20溫度傳感器
⏩ 寫時序測試

寫時序包括寫0和寫1時序。全部寫時序至少須要60us,而且在2次獨立的寫時序之間至少須要1us的恢復時間,兩種寫時序均起始於主機拉低總線。寫1時序,主機輸出低電平,延時2us,而後釋放總線,延時60us;寫0時序,主機輸出低電平,延時60us,而後釋放總線,延時2us。寫時序圖以下
玩轉STM32CubeMX | DS18B20溫度傳感器
⏩ 讀時序ui

單總線器件僅在主機發出讀時序時,才向主機傳輸數據,因此在主機發出讀數據命令後,必須立刻產生讀時序,以便從機可以傳輸數據。全部讀時序至少須要60us,且在2次獨立的讀時序之間至少須要1us的恢復時間。每一個讀時序都由主機發起,至少拉低總線1us,主機在讀時序器件必須釋放總線,而且在時序起始後的15us以內採樣總線狀態。典型的讀時序過程爲,主機輸出低電平延時2us,而後主機轉入輸入模式延時12us,而後讀取單總線當前的電平,而後延時50us
玩轉STM32CubeMX | DS18B20溫度傳感器
DS18B20的典型溫度讀取過程:復位 --> 發SKIP ROM命令(0XCC) --> 發開始轉換命令(0X44) --> 延時 --> 復位 --> 發SKIP ROM命令(0XCC) --> 發讀存儲器命令(0XBE) --> 連續讀出兩個字節數據(即溫度) --> 結束設計

2.硬件設計

D1指示燈用來提示系統運行狀態,DS18B20溫度傳感器用來檢測環境溫度,串口1用來打印溫度值3d

  • 指示燈D1code

  • USART1串口

  • DS18B20

  • TIM7(提供us延時)

玩轉STM32CubeMX | DS18B20溫度傳感器

3.軟件設計

3.1 STM32CubeMX設置

➡️ RCC設置外接HSE,時鐘設置爲72M

➡️ PC0設置爲GPIO推輓輸出模式、上拉、高速、默認輸出電平爲高電平

➡️ USART1選擇爲異步通信方式,波特率設置爲115200Bits/s,傳輸數據長度爲8Bit,無奇偶校驗,1位中止位

➡️ PG11設置爲GPIO推輓輸出模式、上拉、高速

➡️ 激活TIM7,預分頻因子設爲72-1,向上計數,自動重載值爲65535;所以計數器CNT_CLK = 1MHz,計數器週期爲1us

玩轉STM32CubeMX | DS18B20溫度傳感器
➡️輸入工程名,選擇路徑(不要有中文),選擇MDK-ARM V5;勾選Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;點擊GENERATE CODE,生成工程代碼

3.2 MDK-ARM軟件編程

➡️ 在tim.c文件下實現微秒延時(us)函數

void delay_us(uint16_t us){
  uint16_t differ = 0xffff-us-5;
  //設定TIM7計數器起始值                
  __HAL_TIM_SET_COUNTER(&htim7,differ); 
  //啓動定時器
  HAL_TIM_Base_Start(&htim7);           

  while(differ < 0xffff-5){   //判斷
    //查詢計數器的計數值
    differ = __HAL_TIM_GET_COUNTER(&htim7);     
  }
  HAL_TIM_Base_Stop(&htim7);
}

➡️ 建立按鍵驅動文件ds18b20.c 和相關頭文件ds18b20.h

void DS18B20_IO_IN(void){
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.Pin = GPIO_PIN_11;
  GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
  HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);
}

void DS18B20_IO_OUT(void){
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.Pin = GPIO_PIN_11;
  GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);
}

void DS18B20_Rst(void){
  DS18B
20_IO_OUT();
  DS18B20_DQ_OUT_LOW;
  delay_us(750);
  DS18B20_DQ_OUT_HIGH;
  delay_us(15);
}

uint8_t DS18B20_Check(void){
  uint8_t retry = 0;
  DS18B20_IO_IN();
  while(DS18B20_DQ_IN && retry < 200){
    retry++;
    delay_us(1);
  }

  if(retry >= 200)
    return 1;
  else
    retry = 0;

  while(!DS18B20_DQ_IN && retry < 240){
    retry++;
    delay_us(1);
  }

  if(retry >= 240)
    return 1;

  return 0;
}

uint8_t DS18B20_Read_Bit(void){
  uint8_t data;
  DS18B20_IO_OUT();
  DS18B20_DQ_OUT_LOW;
  delay_us(2);
  DS18B20_DQ_OUT_HIGH;
  DS18B20_IO_IN();
  delay_us(12);

  if(DS18B20_DQ_IN)
    data = 1;
  else
    data = 0;

  delay_us(50);
  return data;
}

uint8_t DS18B20_Read_Byte(void){
  uint8_t i,j,data;
  data = 0;
  for(i=1;i<=8;i++){
    j = DS18B20_Read_Bit();
    data = (j<<7)|(data>>1);
  }
  return data;
}

void DS18B20_Write_Byte(uint8_t data){
  uint8_t j;
  uint8_t testb;
  DS18B20_IO_OUT();
  for(j=1;j<=8;j++){
    testb=data&0x01;
    data=data>>1;
    if(testb){
      DS18B20_DQ_OUT_LOW;
      delay_us(2);
      DS18B20_DQ_OUT_HIGH;
      delay_us(60);
    }else{
      DS18B20_DQ_OUT_LOW;
      delay_us(60);
      DS18B20_DQ_OUT_HIGH;
      delay_us(2);
    }
  }
}

void DS18B20_Start(void){
  DS18B20_Rst();
  DS18B20_Check();
  DS18B20_Write_Byte(0xcc);
  DS18B20_Write_Byte(0x44);
}

uint8_t DS18B20_Init(void){
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.Pin = GPIO_PIN_11;
  GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStructure.Pull = GPIO_PULLUP;
  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);

  DS18B20_Rst();
  return DS18B20_Check();
}

short DS18B20_Get_Temperature(void){
  uint8_t temp;
  uint8_t TL,TH;
  short temperature;

  DS18B20_Start();
  DS18B20_Rst();
  DS18B20_Check();
  DS18B20_Write_Byte(0xcc);
  DS18B20_Write_Byte(0xbe);
  TL = DS18B20_Read_Byte();
  TH = DS18B20_Read_Byte();

  if(TH>7){
    TH = ~TH;
    TL = ~TL;
    temp = 0;
  }else
    temp = 1;

  temperature = TH;
  temperature <<= 8;
  temperature += TL;
  temperature = (float)temperature*0.625;
  if(temperature)
    return temperature;
  else
    return -temperature;
}

➡️ 在main.c文件下編寫ds18b20測試代碼

int main(void){
  float temperature;
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_TIM7_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  while(DS18B20_Init()){
    printf("DS18B20 checked failed!!!\r\n");
    HAL_Delay(500);
  }
  printf("DS18B20 checked success!!!\r\n");
  /* USER CODE END 2 */
  while (1){
    temperature = DS18B20_Get_Temperature();
    if(temperature < 0)
      printf("temperature = -%.2f degree\r\n",temperature/10);
    else
      printf("temperature = %.2f degree\r\n",temperature/10);

    HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
    HAL_Delay(200);
  }
}

4.下載驗證

編譯無誤下載到開發板後,能夠看到D1指示燈不斷閃爍,串口不斷打印出當前溫度值

玩轉STM32CubeMX | DS18B20溫度傳感器

相關文章
相關標籤/搜索