目錄
DS18B20概述
工程配置
?命令手冊
單總線協(xié)議
?初始化時(shí)序
?寫時(shí)序
讀時(shí)序
讀取溫度
驅(qū)動附錄
DS18B20概述
?DS18B20是一款單總線(one wire)芯片,因此其DQ引腳與單片機(jī)相連的IO口既要是輸入也要是輸出,cubeMX的初始化引腳設(shè)置只能選擇其一,這里我們使用手動配置引腳。
工程配置
先用cubeMX生成一個工程模板,初始化時(shí)鐘等等。
?命令手冊
?這里有兩個重要的指令,0x44表示觸發(fā)芯片進(jìn)行溫度轉(zhuǎn)化,0xbe表示請求讀取溫度轉(zhuǎn)化后的值。
還有一個常用指令為0xCC,意義是跳過讀取芯片ROM而節(jié)約時(shí)間。
單總線協(xié)議
由于是單總線協(xié)議,要想寫指令,收數(shù)據(jù)都要遵循其標(biāo)準(zhǔn),下面查看其時(shí)序
?初始化時(shí)序
單片機(jī)將DQ線拉低480us至960us后釋放總線,ds18b20檢測到總線電平變化,會等待15-60us,這段時(shí)間總線電平被電阻拉高,然后ds18b20會將總線拉低60-240us,作為應(yīng)答信號,表明總線上存在ds18b20芯片。然后ds18b20釋放總線,電阻將總線拉高。
整個過程為初始化
代碼如下
void onewire_init()
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pin=GPIO_PIN_9;
GPIO_InitStruct.Pull=GPIO_NOPULL;
GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
HAL_Delay_us(500);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);
HAL_Delay_us(50);
onewire_release();
HAL_Delay_us(500);
}
用邏輯分析儀檢測如下
實(shí)際應(yīng)答時(shí)間約為110us?
?寫時(shí)序
寫時(shí)序分為寫0時(shí)序和寫1時(shí)序.
寫0時(shí)序
單片機(jī)拉低總線,產(chǎn)生一個下降沿并保持總線低電平60us-120us,在這期間,18b20會在下降沿出現(xiàn)后大約15us-60us內(nèi)讀取總線電平。然后單片機(jī)釋放總線,由上拉電阻拉高,直至下一次寫時(shí)序,這段時(shí)間為恢復(fù)時(shí)間,需要大于1us
寫1時(shí)序
單片機(jī)拉低總線,產(chǎn)生一個下降沿并保持總線低電平1-15us,在這期間,18b20會在下降沿出現(xiàn)后大約15us-60us內(nèi)讀取總線電平。然后單片機(jī)釋放總線,由上拉電阻拉高,直至下一次寫時(shí)序,這段時(shí)間為恢復(fù)時(shí)間,需要大于1us
void onewire_write(uint8_t dat)
{
onewire_hold();
if(dat==0)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
HAL_Delay_us(60);
onewire_release();
HAL_Delay_us(2);
}
else
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
HAL_Delay_us(2);
onewire_release();
HAL_Delay_us(60);
}
}
讀時(shí)序
?
讀時(shí)序分為讀0時(shí)序和讀1時(shí)序
讀0時(shí)序
單片機(jī)拉低總線并至少保持1us的總線低電平,然后釋放總線,此時(shí)總線電平將由18b20決定,單片機(jī)在下降沿后15us處讀取總線電平值,為低電平
讀1時(shí)序
單片機(jī)拉低總線并至少保持1us的總線低電平,然后釋放總線,此時(shí)總線電平將由18b20決定,單片機(jī)在下降沿后15us處讀取總線電平值,為高電平
uint8_t onewire_read()
{
uint8_t t;
onewire_hold();
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
HAL_Delay_us(2);
onewire_release();
HAL_Delay_us(12);
t=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_9);
HAL_Delay_us(50);
return t;
}
讀取溫度
float ds18b20_getTemp()
{
uint16_t temp;
float value;
uint8_t lsb,msb;
onewire_init();
onewire_sendbyte(0xcc);
onewire_sendbyte(0x44);
HAL_Delay(750);
onewire_init();
onewire_sendbyte(0xcc);
onewire_sendbyte(0xbe);
lsb=onewire_readbyte();
msb=onewire_readbyte();
temp=msb;
temp=(temp<<8)+lsb;
if((temp&0xf800)==0xf800)
{
temp=(~temp)+1;
value=temp*(-0.0625);
}
else
{
value=temp*0.0625;
}
return value;
}
邏輯分析儀波形
?上圖為開啟溫度轉(zhuǎn)化的引腳邏輯電平變化
上圖為讀取溫度值
讀取到的值為0000 0001 1011 1110
?由圖可知為16*1+8*1+2*1+1*1+0.5+0.25+0.125=27.875°C
與串口顯示溫度值一致
?至此,ds18b20的溫度轉(zhuǎn)化,溫度讀取已經(jīng)完成
驅(qū)動附錄
onewire.c
#include "onewire.h"
void HAL_Delay_us(uint32_t nus)
{
uint32_t ticks;
uint32_t told,tnow,tcnt=0;
uint32_t reload=SysTick->LOAD;
ticks=nus*72;
told=SysTick->VAL;
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow;
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break;
}
}
}
void onewire_release()
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Mode=GPIO_MODE_INPUT;
GPIO_InitStruct.Pull=GPIO_NOPULL;
GPIO_InitStruct.Pin=GPIO_PIN_9;
GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);
}
void onewire_hold()
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pin=GPIO_PIN_9;
GPIO_InitStruct.Pull=GPIO_PULLUP;
GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);
}
void onewire_init()
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pin=GPIO_PIN_9;
GPIO_InitStruct.Pull=GPIO_NOPULL;
GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
HAL_Delay_us(500);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);
HAL_Delay_us(50);
onewire_release();
HAL_Delay_us(500);
}
void onewire_write(uint8_t dat)
{
onewire_hold();
if(dat==0)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
HAL_Delay_us(60);
onewire_release();
HAL_Delay_us(2);
}
else
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
HAL_Delay_us(2);
onewire_release();
HAL_Delay_us(60);
}
}
uint8_t onewire_read()
{
uint8_t t;
onewire_hold();
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
HAL_Delay_us(2);
onewire_release();
HAL_Delay_us(12);
t=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_9);
HAL_Delay_us(50);
return t;
}
void onewire_sendbyte(uint8_t dat)
{
uint8_t i;
for(i=0;i<8;i++)
{
if((dat&0x01)==1)
onewire_write(1);
else
onewire_write(0);
dat=dat>>1;
}
}
uint8_t onewire_readbyte(void) // read one byte
{
uint8_t i,j,dat;
dat=0;
for (i=1;i<=8;i++)
{
j=onewire_read();
dat=(j<<7)|(dat>>1);
}
return dat;
}
onewire.h
#ifndef ONEWIRE_H
#define ONEWIRE_H
#include "main.h"
void onewire_init();
void onewire_write(uint8_t dat);
uint8_t onewire_read();
uint8_t onewire_readbyte(void);
void onewire_sendbyte(uint8_t dat);
#endif
ds18b20.c文章來源:http://www.zghlxwxcb.cn/news/detail-757354.html
#include "ds18b20.h"
#include "onewire.h"
void ds18b20_init()
{
onewire_init();
}
float ds18b20_getTemp()
{
uint16_t temp;
float value;
uint8_t lsb,msb;
onewire_init();
onewire_sendbyte(0xcc);
onewire_sendbyte(0x44);
HAL_Delay(750);
onewire_init();
onewire_sendbyte(0xcc);
onewire_sendbyte(0xbe);
lsb=onewire_readbyte();
msb=onewire_readbyte();
temp=msb;
temp=(temp<<8)+lsb;
if((temp&0xf800)==0xf800)
{
temp=(~temp)+1;
value=temp*(-0.0625);
}
else
{
value=temp*0.0625;
}
return value;
}
ds18b20.h文章來源地址http://www.zghlxwxcb.cn/news/detail-757354.html
#ifndef DS18B20_H
#define DS18B20_H
#include "main.h"
void ds18b20_init();
float ds18b20_getTemp();
#endif
到了這里,關(guān)于STM32F1使用HAL庫驅(qū)動DS18B20的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!