一、前言
使用stm32f103c8t6的芯片,在OLED顯示屏上顯示DS18B20的溫度值。
二、傳感器概述


?讀時序:
寫時序:
以下是DS18B20的特性:
1.獨特的單線接口 ,只需 1 個接口引腳即可通信。
2.每個設備的內部ROM上都燒寫了一個獨一無二的64位序列號。
3無需外部元件。
4.能夠采用數(shù)據(jù)線供電,供電范圍為3.0V至5.5V。
5.溫度可測量范圍為:-55℃至+125℃(-67℉至+257℉)。
6.溫度范圍超過-10℃至85℃之外時測溫分辨率0.5℃。
7.以 9 位數(shù)字值方式讀出溫度。
8.在 1 秒( 典型值 )內把溫度變換為數(shù)字。
9.用戶可定義的 非易失性的溫度告警設置。
10.告警搜索命令識別和尋址溫度在編定的極限之外的器件(溫度告警情況)。
11.應用范圍包括恒溫控制 工業(yè)系統(tǒng) 消費類產(chǎn)品 溫度計或任何熱敏系統(tǒng)。

三、接線說明
本文使用的是stm32f103c8的芯片,VCC接3.3V,信號線接PB12 引腳。
四、程序編寫
1.DS18B20.C
#include "ds18b20.h"
#include "stm32f10x.h"
/**************************************************************************************
* 描 述 : 配置DS18B20用到的I/O口
* 入 參 : 無
* 返回值 : 無
**************************************************************************************/
static void DS18B20_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(DS18B20_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
GPIO_SetBits(DS18B20_PORT, DS18B20_PIN); //DS18B20數(shù)據(jù)引腳初始化配置為高電平輸出
}
/**************************************************************************************
* 描 述 : 配置使DS18B20-DATA引腳變?yōu)檩斎肽J? * 入 參 : 無
* 返回值 : 無
**************************************************************************************/
static void DS18B20_Mode_IPU(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉輸入
GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
}
/**************************************************************************************
* 描 述 : 配置使DS18B20-DATA引腳變?yōu)檩敵瞿J? * 入 參 : 無
* 返回值 : 無
**************************************************************************************/
static void DS18B20_Mode_Out_PP(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
}
/**************************************************************************************
* 描 述 : 主機給從機發(fā)送復位脈沖
* 入 參 : 無
* 返回值 : 無
**************************************************************************************/
static void DS18B20_Rst(void)
{
DS18B20_Mode_Out_PP(); //主機設置為推挽輸出
DS18B20_DATA_OUT(LOW); //主機至少產(chǎn)生480us的低電平復位信號
Delay_us(750);
DS18B20_DATA_OUT(HIGH); //主機在產(chǎn)生復位信號后,需將總線拉高
Delay_us(15); //從機接收到主機的復位信號后,會在15~60us后給主機發(fā)一個存在脈沖
}
/**************************************************************************************
* 描 述 : 檢測從機給主機返回的存在脈沖
* 入 參 : 無
* 返回值 : 0:成功 1:失敗
**************************************************************************************/
static u8 DS18B20_Presence(void)
{
u8 pulse_time = 0;
DS18B20_Mode_IPU(); //主機設置為上拉輸入
/* 等待存在脈沖的到來,存在脈沖為一個60~240us的低電平信號
* 如果存在脈沖沒有來則做超時處理,從機接收到主機的復位信號后,會在15~60us后給主機發(fā)一個存在脈沖
*/
while( DS18B20_DATA_IN() && pulse_time<100 )
{
pulse_time++;
Delay_us(1);
}
if( pulse_time >=100 ) //經(jīng)過100us后,存在脈沖都還沒有到來
return 1; //讀取失敗
else //經(jīng)過100us后,存在脈沖到來
pulse_time = 0; //清零計時變量
while( !DS18B20_DATA_IN() && pulse_time<240 ) // 存在脈沖到來,且存在的時間不能超過240us
{
pulse_time++;
Delay_us(1);
}
if( pulse_time >=240 ) // 存在脈沖到來,且存在的時間超過了240us
return 1; //讀取失敗
else
return 0;
}
/**************************************************************************************
* 描 述 : 從DS18B20讀取一個bit
* 入 參 : 無
* 返回值 : u8
**************************************************************************************/
static u8 DS18B20_Read_Bit(void)
{
u8 dat;
/* 讀0和讀1的時間至少要大于60us */
DS18B20_Mode_Out_PP();
/* 讀時間的起始:必須由主機產(chǎn)生 >1us <15us 的低電平信號 */
DS18B20_DATA_OUT(LOW);
Delay_us(10);
/* 設置成輸入,釋放總線,由外部上拉電阻將總線拉高 */
DS18B20_Mode_IPU();
if( DS18B20_DATA_IN() == SET )
dat = 1;
else
dat = 0;
/* 這個延時參數(shù)請參考時序圖 */
Delay_us(45);
return dat;
}
/**************************************************************************************
* 描 述 : 從DS18B20讀一個字節(jié),低位先行
* 入 參 : 無
* 返回值 : u8
**************************************************************************************/
u8 DS18B20_Read_Byte(void)
{
u8 i, j, dat = 0;
for(i=0; i<8; i++)
{
j = DS18B20_Read_Bit(); //從DS18B20讀取一個bit
dat = (dat) | (j<<i);
}
return dat;
}
/**************************************************************************************
* 描 述 : 寫一個字節(jié)到DS18B20,低位先行
* 入 參 : u8
* 返回值 : 無
**************************************************************************************/
void DS18B20_Write_Byte(u8 dat)
{
u8 i, testb;
DS18B20_Mode_Out_PP();
for( i=0; i<8; i++ )
{
testb = dat&0x01;
dat = dat>>1;
/* 寫0和寫1的時間至少要大于60us */
if (testb)
{
DS18B20_DATA_OUT(LOW);
Delay_us(8); //1us < 這個延時 < 15us
DS18B20_DATA_OUT(HIGH);
Delay_us(58); //58us+8us>60us
}
else
{
DS18B20_DATA_OUT(LOW);
/* 60us < Tx 0 < 120us */
Delay_us(70);
DS18B20_DATA_OUT(HIGH);
/* 1us < Trec(恢復時間) < 無窮大*/
Delay_us(2);
}
}
}
/**************************************************************************************
* 描 述 : 起始DS18B20
* 入 參 : 無
* 返回值 : 無
**************************************************************************************/
void DS18B20_Start(void)
{
DS18B20_Rst(); //主機給從機發(fā)送復位脈沖
DS18B20_Presence(); //檢測從機給主機返回的存在脈沖
DS18B20_Write_Byte(0XCC); // 跳過 ROM
DS18B20_Write_Byte(0X44); // 開始轉換
}
/**************************************************************************************
* 描 述 : DS18B20初始化函數(shù)
* 入 參 : 無
* 返回值 : u8
**************************************************************************************/
u8 DS18B20_Init(void)
{
DS18B20_GPIO_Config();
DS18B20_Rst();
return DS18B20_Presence();
}
/**************************************************************************************
* 描 述 : 從DS18B20讀取溫度值
* 入 參 : 無
* 返回值 : float
**************************************************************************************/
float DS18B20_Get_Temp(void)
{
u8 tpmsb, tplsb;
short s_tem;
float f_tem;
DS18B20_Rst();
DS18B20_Presence();
DS18B20_Write_Byte(0XCC); /* 跳過 ROM */
DS18B20_Write_Byte(0X44); /* 開始轉換 */
DS18B20_Rst();
DS18B20_Presence();
DS18B20_Write_Byte(0XCC); /* 跳過 ROM */
DS18B20_Write_Byte(0XBE); /* 讀溫度值 */
tplsb = DS18B20_Read_Byte();
tpmsb = DS18B20_Read_Byte();
s_tem = tpmsb<<8;
s_tem = s_tem | tplsb;
if( s_tem < 0 ) /* 負溫度 */
f_tem = (~s_tem+1) * 0.0625;
else
f_tem = (s_tem * 0.0625);
//這樣做的目的將小數(shù)點后第一位也轉換為可顯示數(shù)字
//同時進行一個四舍五入操作。
return f_tem;
}
/*************************************END OF FILE******************************/
2.DS18B20.H
#ifndef __DS18B20_H
#define __DS18B20_H
#include "stm32f10x.h"
#include "delay.h"
#define HIGH 1
#define LOW 0
#define DS18B20_CLK RCC_APB2Periph_GPIOB
#define DS18B20_PIN GPIO_Pin_12
#define DS18B20_PORT GPIOB
//帶參宏,可以像內聯(lián)函數(shù)一樣使用,輸出高電平或低電平
#define DS18B20_DATA_OUT(a) if (a) \
GPIO_SetBits(GPIOB,GPIO_Pin_12);\
else \
GPIO_ResetBits(GPIOB,GPIO_Pin_12)
//讀取引腳的電平
#define DS18B20_DATA_IN() GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)
typedef struct
{
u8 humi_int; //濕度的整數(shù)部分
u8 humi_deci; //濕度的小數(shù)部分
u8 temp_int; //溫度的整數(shù)部分
u8 temp_deci; //溫度的小數(shù)部分
u8 check_sum; //校驗和
}DS18B20_Data_TypeDef;
u8 DS18B20_Init(void);
float DS18B20_Get_Temp(void);
#endif /* __DS18B20_H */
3.讀取DS8B20溫度值并顯示在OLED顯示屏上。
void TEMP_Value_Conversion()
{
temp_data=DS18B20_Get_Temp();
temp_data1=temp_data;
sprintf((char*)ucbuf,"%4.2f",temp_data1);
OLED_ShowString(72,48,(uint8_t*)ucbuf,16,1);
OLED_ShowChinese(0,48,0,16,1);
OLED_ShowChinese(16,48,1,16,1);
OLED_ShowChinese(32,48,2,16,1);
OLED_ShowChinese(48,48,3,16,1);
OLED_ShowChar(64,48,':',16,1);
OLED_ShowChinese(112,48,4,16,1);
}
4.main函數(shù)代碼:
main (void)
{
/* 配置系統(tǒng)時鐘為72M */
SystemInit();
DS18B20_Init();
OLED_Init();
OLED_ColorTurn(0);//0正常顯示,1 反色顯示
OLED_DisplayTurn(0);//0正常顯示 1 屏幕翻轉顯示
OLED_ShowChinese(48,16,3,16,1);
while(1)
{
OLED_Refresh();
TEMP_Value_Conversion();
Delay_ms(500);
}
}
其中OLED的配置程序及接線參考之前的文章https://blog.csdn.net/qq_50749196/article/details/131022176
五、最終效果
我這里使用的是貼片式DS18B20溫度傳感器(圖片上方藍色線頭),OLED顯示的溫度保留小數(shù)點后兩位數(shù)字。
完整程序已上傳,有需要者自行下載:文章來源:http://www.zghlxwxcb.cn/news/detail-610825.html
鏈接:https://pan.baidu.com/s/1KbtNQGjrHjWSbZUC1efnSA?pwd=ydlz?
提取碼:ydlz文章來源地址http://www.zghlxwxcb.cn/news/detail-610825.html
到了這里,關于通過stm32讀取DS18B20并在顯示屏上顯示溫度值(附源碼)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!