DS18B20是很常用的溫度傳感器,精度很高,測試結果如下:
整個驅動程序基本是根據時序寫的。要注意的地方有兩個:
1 讀數據的時間 < 15us,這個值要實際測試,跟自己實現的延時函數效率有關,我使用的是10us,這個值如果設置的不合理,會直接導致整個數據讀取出錯;
2 建議使用DS18B20_GetTemp_SkipRom函數,不推薦使用設備號相關的那個讀取函數,不太穩定;
HAL庫驅動程序源碼:
bsp_ds18b20.c
/**
******************************************************************************
* @file bsp_ds18b20.c
* @author
* @date
* @version v1.0
* @note DHT11 driver
******************************************************************************
*/
#include "bsp_ds18b20.h"
/**
* @brief DS18B20 輸出模式
*/
static void DS18B20_Mode_OUT_PP(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = BSP_DS18B20_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(BSP_DS18B20_PORT, &GPIO_InitStruct);
}
/**
* @brief DS18B20 輸入模式
*/
static void DS18B20_Mode_IN_NP(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = BSP_DS18B20_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(BSP_DS18B20_PORT, &GPIO_InitStruct);
}
/**
* @brief 主機給從機發送復位脈沖
*/
static void DS18B20_Reset(void)
{
DS18B20_Mode_OUT_PP(); // 主機輸出
DS18B20_OUT_0; // 主機至少產生 480us 的低電平復位信號
bsp_delay_us(750);
DS18B20_OUT_1; // 主機在產生復位信號后,需將總線拉高
// 從機接收到主機的復位信號后,會在 15 ~ 60 us 后給主機發一個存在脈沖
bsp_delay_us(15);
}
/**
* @brief 檢測從機給主機返回的存在脈沖
* @return 0:成功 1:失敗
*/
static uint8_t DS18B20_Presence(void)
{
uint8_t pulse_time = 0;
DS18B20_Mode_IN_NP(); // 主機設為輸入
// 等待存在脈沖的到來,存在脈沖為一個 60 ~ 240 us 的低電平信號
// 如果存在脈沖沒有來則做超時處理,從機接收到主機的復位信號后,會在 15 ~ 60 us 后給主機發一個存在脈沖
while (DS18B20_IN && (pulse_time < 100)) // 等待低電平響應脈沖
{
pulse_time++;
bsp_delay_us(1);
}
// 經過 100 us 后,存在脈沖都還沒有到來
if (pulse_time >= 100)
{
return 1;
}
else
{
pulse_time = 0;
}
// 響應脈沖(低電平)到來,且存在的時間不能超過 240 us
while(!(DS18B20_IN) && pulse_time < 240)
{
pulse_time++;
bsp_delay_us(1);
}
if(pulse_time >= 240)
{
return 1;
}
else
{
return 0;
}
}
/**
* @brief DS18B20 初始化函數
* @reurn 0:成功 1:失敗
*/
uint8_t DS18B20_Init(void)
{
DS18B20_Mode_OUT_PP();
DS18B20_OUT_1;
DS18B20_Reset();
return DS18B20_Presence();
}
/**
* @brief 從DS18B20讀取一個bit
*/
static uint8_t DS18B20_ReadBit(void)
{
uint8_t dat;
DS18B20_Mode_OUT_PP(); // 讀 0 和讀 1 的時間至少要大于 60 us
DS18B20_OUT_0; // 讀時間的起始:必須由主機產生 > 1us < 15us 的低電平信號
// 這個時間非常重要,設置為 < 15,需要多次嘗試;如果設置不合理,數據會直接出錯
// 參數建議設為 10 11 12,具體值要根據延時函數的執行效率測試
bsp_delay_us(10);
DS18B20_Mode_IN_NP(); // 設置成輸入,釋放總線,由外部上拉電阻將總線拉高
if (DS18B20_IN == 1)
{
dat = 1;
}
else
{
dat = 0;
}
bsp_delay_us(45); // 這個延時參數參考時序圖
return dat;
}
/**
* @brief 從 DS18B20 讀一個字節,低位先行
*/
static uint8_t DS18B20_ReadByte(void)
{
uint8_t i, j, dat = 0;
for(i = 0; i < 8; i++)
{
j = DS18B20_ReadBit();
dat = (dat) | (j << i);
}
return dat;
}
/**
* @brief 寫一個字節到 DS18B20,低位先行
*/
static void DS18B20_WriteByte(uint8_t dat)
{
uint8_t i, testb;
DS18B20_Mode_OUT_PP();
for( i = 0; i < 8; i++ )
{
testb = dat & 0x01;
dat = dat >> 1;
// 寫 0 和寫 1 的時間至少要大于60us
if (testb) // 當前位寫 1
{
DS18B20_OUT_0;
bsp_delay_us(5); // 拉低發送寫時段信號
DS18B20_OUT_1; // 讀取電平時間保持高電平
bsp_delay_us(65);
}
else // 當前位寫 0
{
DS18B20_OUT_0; // 拉低發送寫時段信號
bsp_delay_us(70); // 讀取電平時間保持低電平
DS18B20_OUT_1;
bsp_delay_us(2); // 恢復時間
}
}
}
/**
* @brief 跳過匹配 DS18B20 ROM
*/
static void DS18B20_SkipRom(void)
{
DS18B20_Reset();
DS18B20_Presence();
DS18B20_WriteByte(0XCC); /* 跳過 ROM */
}
/**
* @brief 執行匹配 DS18B20 ROM
*/
static void DS18B20_MatchRom(void)
{
DS18B20_Reset();
DS18B20_Presence();
DS18B20_WriteByte(0X55); /* 匹配 ROM */
}
/**
* 存儲的溫度是16 位的帶符號擴展的二進制補碼形式
* 當工作在12位分辨率時,其中5個符號位,7個整數位,4個小數位
*
* |---------整數----------|-----小數 分辨率 1/(2^4)=0.0625----|
* 低字節 | 2^3 | 2^2 | 2^1 | 2^0 | 2^(-1) | 2^(-2) | 2^(-3) | 2^(-4) |
*
*
* |-----符號位:0->正 1->負-------|-----------整數-----------|
* 高字節 | s | s | s | s | s | 2^6 | 2^5 | 2^4 |
*
*
* 溫度 = 符號位 + 整數 + 小數*0.0625
*/
/**
* @brief 在跳過匹配 ROM 情況下獲取 DS18B20 溫度值
* @param 無
* @retval 溫度值
*/
float DS18B20_GetTemp_SkipRom(void)
{
uint8_t tpmsb, tplsb;
int16_t s_tem;
float f_tem;
DS18B20_SkipRom();
DS18B20_WriteByte(0X44); /* 開始轉換 */
DS18B20_SkipRom();
DS18B20_WriteByte(0XBE); /* 讀溫度值 */
tplsb = DS18B20_ReadByte();
tpmsb = DS18B20_ReadByte();
s_tem = tpmsb << 8;
s_tem = s_tem | tplsb;
if(s_tem < 0) /* 負溫度 */
{
f_tem = (~s_tem + 1) * 0.0625f;
}
else
{
f_tem = s_tem * 0.0625f;
}
return f_tem;
}
/**
* @brief 在匹配 ROM 情況下獲取 DS18B20 溫度值
* @param ds18b20_id:用于存放 DS18B20 序列號的數組的首地址
*/
void DS18B20_ReadId(uint8_t *ds18b20_id)
{
uint8_t uc;
DS18B20_WriteByte(0x33); //讀取序列號
for (uc = 0; uc < 8; uc++)
{
ds18b20_id[uc] = DS18B20_ReadByte();
}
}
/**
* @brief 在匹配 ROM 情況下獲取 DS18B20 溫度值
* @param ds18b20_id:存放 DS18B20 序列號的數組的首地址
* @retval 溫度值
*/
float DS18B20_GetTemp_MatchRom(uint8_t * ds18b20_id)
{
uint8_t tpmsb, tplsb, i;
int16_t s_tem;
float f_tem;
DS18B20_MatchRom(); /* 匹配ROM */
for(i = 0;i < 8; i++)
{
DS18B20_WriteByte(ds18b20_id[i]);
}
DS18B20_WriteByte(0X44); /* 開始轉換 */
DS18B20_MatchRom(); /* 匹配ROM */
for(i = 0; i < 8; i++)
{
DS18B20_WriteByte(ds18b20_id[i]);
}
DS18B20_WriteByte(0XBE); /* 讀溫度值 */
tplsb = DS18B20_ReadByte();
tpmsb = DS18B20_ReadByte();
s_tem = tpmsb << 8;
s_tem = s_tem | tplsb;
if (s_tem < 0) /* 負溫度 */
{
f_tem = (~s_tem + 1) * 0.0625f;
}
else
{
f_tem = s_tem * 0.0625f;
}
return f_tem;
}
// 測試程序
#if 0
uint8_t uc, ucDs18b20Id[8];
while (DS18B20_Init())
{
printf("rn no ds18b20 exit rn");
}
printf("rn ds18b20 exit rn");
DS18B20_ReadId(ucDs18b20Id); // 讀取 DS18B20 的序列號
printf("rnDS18B20的序列號是: 0x");
for (uc = 0; uc < 8; uc++) // 打印 DS18B20 的序列號
{
printf("%.2x", ucDs18b20Id[uc]);
}
while (1)
{
printf("rn溫度: %.1frn", DS18B20_GetTemp_SkipRom());
HAL_Delay(1000); /* 1s 讀取一次溫度值 */
}
#endif
bsp_ds18b20.h
/**
******************************************************************************
* @file bsp_ds18b20.h
* @author
* @date
* @version v1.0
* @note DS18B20 driver
******************************************************************************
*/
#ifndef __BSP_DS18B20_H
#define __BSP_DS18B20_H
#include "bsp_conf.h"
#define BSP_DS18B20_PORT TEMP_SENSOR_GPIO_Port
#define BSP_DS18B20_PIN TEMP_SENSOR_Pin
#define DS18B20_OUT_1 HAL_GPIO_WritePin(BSP_DS18B20_PORT, BSP_DS18B20_PIN, GPIO_PIN_SET)
#define DS18B20_OUT_0 HAL_GPIO_WritePin(BSP_DS18B20_PORT, BSP_DS18B20_PIN, GPIO_PIN_RESET)
#define DS18B20_IN HAL_GPIO_ReadPin(BSP_DS18B20_PORT, BSP_DS18B20_PIN)
uint8_t DS18B20_Init(void);
void DS18B20_ReadId(uint8_t *ds18b20_id);
float DS18B20_GetTemp_SkipRom(void);
float DS18B20_GetTemp_MatchRom(uint8_t * ds18b20_id);
#endif /* __BSP_DS18B20_H */
上一篇:stm32實用篇5:HAL庫 DHT11 驅動
下一篇:STM32的DMA串口直通
推薦閱讀
史海拾趣
在DAQ Electronics LLC公司的發展歷程中,質量一直是其堅守的核心原則。公司建立了嚴格的質量控制體系,從原材料采購到產品生產、檢測、包裝等各個環節都進行嚴格把控。這種對質量的堅持,使得DAQ Electronics LLC公司的產品在市場上獲得了良好的口碑和信譽。客戶對公司的產品和服務給予了高度評價,也為公司的持續發展提供了有力保障。
隨著技術的不斷進步和市場的不斷變化,Elite意識到單一市場已經無法滿足公司的發展需求。因此,公司開始積極拓展國際市場,尋求更廣闊的發展空間。在海外市場拓展過程中,Elite注重了解當地市場的需求和文化特點,制定針對性的市場策略。同時,公司還積極與當地企業建立合作關系,共同開拓市場。這些努力讓Elite在國際市場上取得了不俗的成績,也為公司的持續發展注入了新的動力。
為了進一步擴大市場份額,Calmos Systems Inc公司積極尋求與行業內外的合作伙伴建立合作關系。公司與多家知名企業簽訂了戰略合作協議,共同開發新產品、拓展新市場。同時,公司還積極參加各類行業展會和交流活動,與業內同行進行深入交流,了解行業動態和發展趨勢。通過這些努力,公司的品牌知名度和影響力不斷提升,為公司的長期發展打下了堅實的基礎。
Calmos Systems Inc公司注重企業文化建設和團隊建設。公司倡導創新、協作、務實的企業文化,鼓勵員工敢于嘗試、勇于創新。同時,公司還注重員工的培訓和發展,為員工提供廣闊的職業發展空間和晉升機會。在團隊建設方面,公司定期組織各類團建活動,增強員工之間的凝聚力和向心力。這些舉措使得公司擁有一支高效、團結、富有創造力的團隊,為公司的發展提供了有力保障。
以上便是關于Calmos Systems Inc公司在電子行業里發展起來的5個相關故事。這些故事展示了公司在創立初期、技術創新、市場拓展、國際化戰略以及企業文化與團隊建設等方面的努力和成果,為公司的發展奠定了堅實的基礎。
Calmos Systems Inc公司創立之初,面臨著資金短缺、市場競爭激烈的挑戰。公司創始人憑借對電子技術的深厚理解和對市場需求的敏銳洞察,帶領團隊研發出了一款具有創新性的電子產品。然而,由于品牌知名度低,市場推廣困難,產品銷量一度不佳。為了打開市場,創始人親自拜訪潛在客戶,了解他們的需求,不斷優化產品功能。經過不懈的努力,產品逐漸贏得了客戶的認可,為公司的發展奠定了基礎。
DT-1在線液體密度測試變送器可對各種液體或液態混合物在線進行密度測量。故在石化行業可廣泛應用于煉油、調油、油水介面監測;在食品工業用于葡萄汁、番茄汁、果糖漿、植物油及軟飲料加工等生產現場;奶制品業;造紙業,黑漿、綠漿、白漿、堿溶液的 ...… 查看全部問答∨ |
External Medical and IT Power Supplies Meet Latest Energy Efficiency Standards XP Power has announced the launch of the AEF and AFM series of external AC/DC power supply units. Designed for a wide range of IT and portable medical equipment, the units provide single outputs with power output between 100 - 150 ...… 查看全部問答∨ |
寫過casio dt930手持機程序的朋友對日趨公司提供的rich_XXX 中間層函數了解多少? 我們公司以前開發casio dt930手持機程序都是用的這個日趨函數,但是因為不清楚其函數內部源碼,現在公司要求自己寫一個類似于這個日趨中間層函數庫的東西,其實現函數 ...… 查看全部問答∨ |
我把CxImage移植到EVC4.0的時候,編譯庫沒發現什么問題,但是鏈接到exe(exe是基于MFC的)的時候發現了如下的鏈接錯誤: ximapng.obj : error LNK2019: unresolved external symbol ___CxxLongjmpUnwind@4 referenced in function "public: bool __th ...… 查看全部問答∨ |
在將程序寫入單片機后,程序沒有運行(B口驅動的二極管沒有發光);用手一碰單片機的晶振輸入腿,單片機就能運行了。 奇怪!是晶振沒有七振嗎?… 查看全部問答∨ |
|
LED日光燈電源,今年非常火爆,有很多公司設計由于不懂規范,做出來的產品,往往在認證階段出現問題,花費大量的人力物力去整改, 下面我簡單介紹一下T8電源能滿足認證的的設計要求: 1.安全距離,由于電源是AC-DC的電源,有高壓存在,在UL里的安 ...… 查看全部問答∨ |
|
各位大神,小弟按VCA820 datasheet 23頁Figure84搭出來的圖檢測,Rf和Rg分別為1K與200,增益按道理應該是10倍,現在最大只有2~3倍,極度郁悶,求解中!!!… 查看全部問答∨ |
設計資源 培訓 開發板 精華推薦
- 試用Vishay新型“IHLP磁芯損耗計算器”,搶樓贏好禮
- LPC4370重磅來襲 有獎問答贏好禮!
- 電子工程師,如何更好地擁抱GaN?參與問卷有好禮!
- 報名贏京東卡 | 國產FPGA安路科技2024線上新品發布會
- 兆易GD32450I-EVAL免費測評試用
- 追更有驚喜:解救被FSM折磨過的你,justd0解析LSM6DSOX有限狀態機官方例程
- 電路圖站2.0版上線,公開征集網友建議,填寫調查問卷贏積分!
- 全球首款Cortex-M23內核物聯網芯片SAML10和SAM L11系列 闖關獲取SAML10/SAML11法寶,拆除電子界安全危機,贏好禮!
- 邀請好友體驗WEBENCH,禮品豐厚你有他也有!