標(biāo)題:
stm32驅(qū)動(dòng)ds18b20溫度讀取源程序
[打印本頁]
作者:
xu2509674896
時(shí)間:
2020-12-19 16:57
標(biāo)題:
stm32驅(qū)動(dòng)ds18b20溫度讀取源程序
發(fā)上來的程序是主要基于stm32f1的驅(qū)動(dòng)程序,如果你需要清楚了解ds18b20的工作時(shí)序,寄存器配置,那么在論壇上找找看看數(shù)據(jù)手冊,如果你想直接用,那么把頭文件和c文件直接添加到你的工程中就可以了。 本程序在實(shí)質(zhì)上和51驅(qū)動(dòng)的沒有區(qū)別,都是模擬I2C。兩者區(qū)別在于大部分51對于IO口的輸入輸出配置沒有硬性規(guī)定,既可以當(dāng)輸入又可以當(dāng)輸出,而stm32的輸入輸出必須明確模式配置。而ds18b20是一線通信,所以需要輸入輸出模式來回配置。
本程序我通過硬件明確測試過,可以準(zhǔn)確讀出數(shù)據(jù),如果數(shù)據(jù)無法讀出,可能是以下幾點(diǎn)問題:
1、引腳配置未修改。可在h文件中修改宏定義即可
2、請注意該函數(shù)void DS18B20_DQ_DDR(uint8_t ddr),他是用于修改IO輸入輸出模式的,本程序使用的標(biāo)準(zhǔn)庫函數(shù)進(jìn)行操作,用到的時(shí)間可能會(huì)有一點(diǎn)長,影響到了I2C的模擬時(shí)序,建議可以直接對寄存器進(jìn)行操作,庫函數(shù)的實(shí)質(zhì)也是修改寄存器,只是由于為了程序兼容性,犧牲了時(shí)間。
3、由于是模擬的I2C時(shí)序,請務(wù)必注意中斷對于通信時(shí)序的影響。
單片機(jī)源程序如下:
#include "ds18b20.h"//主要包含了一些引腳宏定義,移植時(shí)必須包含
#include "delay.h"//主要是聲明了延時(shí)函數(shù),由于是模擬I2C,延時(shí)必須精準(zhǔn)
#include "math.h"//使用了庫函數(shù)pow()函數(shù),該函數(shù)為冪次函數(shù),如pow(10,2),相當(dāng)于10^2,移植時(shí)必須包含
/*******************************************************************************
函數(shù)名:DS18B20_DQ_DDR
功能:配置IO輸入/輸出狀態(tài)
輸入:0/1 輸入0配置為輸入,輸入1配置為輸出
輸出:
返回值:
*******************************************************************************/
void DS18B20_DQ_DDR(uint8_t ddr)
{
GPIO_InitTypeDef GPIO_InitStructure;
//使能GPIO時(shí)鐘
RCC_APB2PeriphClockCmd(DS18B20_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
//配置為輸出
if(ddr == 1)
{
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_PIN;
GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStructure);
}
//配置為輸入
else
{
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_PIN;
GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStructure);
}
}
/*******************************************************************************
函數(shù)名:DS18B20_Init
功能:初始化DS18B20
輸入:
輸出:
返回值:初始化成功為0,不成功為1
備注:
*******************************************************************************/
u8 DS18B20_Init(void)
{
u8 x = 0;
//改變DQ引腳為輸出
DS18B20_DQ_DDR(1);
//先置高
DS18B20_DQ_H;
//延時(shí)700us,使總線穩(wěn)定
delay_us(700);
//復(fù)位脈沖,低電位
DS18B20_DQ_L;
//保持至少480us,這里500us
delay_us(500);
//改變DQ引腳為輸入
DS18B20_DQ_DDR(0);
//拉高數(shù)據(jù)線,釋放總線
DS18B20_DQ_H;
//等待15-60us,這里40us
delay_us(40);
//等待35us
delay_us(35);
//聆聽,判斷有沒有初始化成功(DS18B20有沒有發(fā)送應(yīng)答脈沖)
x = DS18B20_DQ_ReadPin;
//至少480us后進(jìn)入接收狀態(tài),這里500us
delay_us(500);
return x;
}
/*******************************************************************************
函數(shù)名:DS18B20_Wbyte
功能:寫一個(gè)字節(jié)
輸入:uint8_t xbyte
輸出:
返回值:
備注:
*******************************************************************************/
void DS18B20_Wbyte(uint8_t xbyte)
{
//i:循環(huán)控制變量,x:取位運(yùn)算變量
int8_t i ,x = 0;
//改變DQ引腳為輸出
DS18B20_DQ_DDR(1);
//8次循環(huán)實(shí)現(xiàn)逐位寫入
for(i = 1; i <= 8; i++)
{
//先取低位
x = xbyte & 0x01;
//寫1
if(x)
{
DS18B20_DQ_H;
//拉低總線
DS18B20_DQ_L;
//延時(shí)15us
delay_us(15);
//總線寫1
DS18B20_DQ_H;
//延時(shí)15us
delay_us(15);
//保持高電平
DS18B20_DQ_H;
delay_us(4);
}
//寫0
else
{
DS18B20_DQ_H;
//總線拉低
DS18B20_DQ_L;
//延時(shí)15us
delay_us(15);
//總線寫0
DS18B20_DQ_L;
//延時(shí)15us
delay_us(15);
//保持高電平
DS18B20_DQ_H;
delay_us(4);
}
//xbyte右移一位
xbyte = xbyte >> 1;
}
}
/*******************************************************************************
函數(shù)名:DS18B20_Rbit
功能:從DS18B20讀一個(gè)位
輸入:
輸出:
返回值:讀取到的位
備注:
*******************************************************************************/
uint8_t DS18B20_Rbit(void)
{
//rbit是最終位數(shù)據(jù),x是取狀態(tài)變量
uint8_t rbit = 0x00,x = 0;
//改變DQ為輸出模式
DS18B20_DQ_DDR(1);
DS18B20_DQ_H;
//總線寫0
DS18B20_DQ_L;
//延時(shí)15us以內(nèi)
delay_us(5);
//釋放總線
DS18B20_DQ_H;
//改變DQ為輸入模式
DS18B20_DQ_DDR(0);
//延時(shí)大約3us
delay_us(3);
//獲取總線電平狀態(tài)
x = DS18B20_DQ_ReadPin;
//如果是1,則返回0x80,否則返回0x00
if(x)
rbit = 0x80;
//延時(shí)大約60us
delay_us(60);
return rbit;
}
/*******************************************************************************
函數(shù)名:DS18B20_Rbyte
功能:從DS18B20讀一個(gè)字節(jié)
輸入:
輸出:
返回值:讀取到的字節(jié)
備注:
*******************************************************************************/
uint8_t DS18B20_Rbyte(void)
{
//rbyte:最終得到的字節(jié)
//tempbit:中間運(yùn)算變量
uint8_t rbyte = 0,i = 0, tempbit =0;
for (i = 1; i <= 8; i++)
{
//讀取位
tempbit = DS18B20_Rbit();
//右移實(shí)現(xiàn)高低位排序
rbyte = rbyte >> 1;
//或運(yùn)算移入數(shù)據(jù)
rbyte = rbyte|tempbit;
}
return rbyte;
}
int ReadTemperature(void)
{
//fg:符號位
//data:溫度的整數(shù)部分
int fg;
int data;
//DS18B20初始化
DS18B20_Init();
//跳過讀序列號
DS18B20_Wbyte(0xcc);
//啟動(dòng)溫度轉(zhuǎn)換
DS18B20_Wbyte(0x44);
//等待溫度轉(zhuǎn)換
delay_ms(1);
DS18B20_Init();
DS18B20_Wbyte(0xcc);
//讀溫度寄存器
DS18B20_Wbyte(0xbe);
uint8_t TempL = DS18B20_Rbyte();//讀取低8位
uint8_t TempH = DS18B20_Rbyte();//讀取高8位
//符號位為負(fù)
if(TempH > 0x70)
{
TempL = ~TempL;
TempH = ~TempH;
fg = 0;
}
else fg = 1;
//將數(shù)據(jù)高低位合并
data = TempH;//數(shù)據(jù)高八位
data <<= 8;//左移8位
data += TempL;//加上低八位
//data的"1"相當(dāng)于0.0625℃
//換句話說,想要多少精度可以這樣寫:data=(float)data*0.0625*pow(10,n)
//其中n為保留的小數(shù)精度位數(shù),可以從目前對ds18b20配置情況下看出最高保留小數(shù)的精度位數(shù)為4位
//這樣只需要對返回值進(jìn)行處理就可以用于顯示了
//特別注意的是,int類型的數(shù)據(jù)長度為16位,最大值為65535,因此需要注意使用范圍
data=(float)data*0.0625*pow(10,1);//這樣寫等同于下面一句
//data = (float)data*0.625;//這樣相當(dāng)于精度為0.1℃
if(fg)
return data;
else
return -data;
}
復(fù)制代碼
51hei.png
(2.51 KB, 下載次數(shù): 76)
下載附件
2020-12-19 17:13 上傳
所有資料51hei提供下載:
DS18B20.rar
(2.56 KB, 下載次數(shù): 101)
2020-12-19 16:55 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1