目录
首先我用的是一块STM32F103VCT6
复位脉冲和应答脉冲
将总线切换为输出模式,主机先拉低电平480us,再拉高15~60us,我直接拉高60us,将总线切换为输入模式,读取ds18b20的应答,设置延时为240us,没超时的话最后切换为输出模式,拉高总线。
uint8_t DS18B20_Rst(void)
{
uint8_t retry=0;
DS18B20_IO_OUT(); //设置为输出
W1DQ_Write(0); //拉低DQ
delay_us(480); //拉480us
W1DQ_Write(1); //DQ=1
delay_us(60); //60US
DS18B20_IO_IN(); //设置为输入
//等待ds18b20回应
while (!W1DQ_Read()&&retry<240)
{
retry++;
delay_us(1);
};
if(retry>=200)
return -1;
else
retry=0;
DS18B20_IO_OUT();
W1DQ_Write(1);
delay_us(240);
return retry;
}
初始化
//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回-1:不存在
//返回0:存在
uint8_t DS18B20_Init(void)
{
rv=DS18B20_Rst();
if(rv<0)
return -1;
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟
GPIO_Initure.Pin=GPIO_PIN_7; //PA7
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_Initure.Pull=GPIO_NOPULL; //不拉
GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化
return rv;
}
读时序
总线设为输出拉低2us,设为输入,延时13us再开始读ds18b20的回应,读完数据后延时50us再读下一个位。
//从DS18B20读取一个字节
//返回值:读到的数据
uint8_t DS18B20_Read_Byte(void)
{
uint8_t i,dt,date;
date=0;
for (i=1;i<=8;i++)
{
DS18B20_IO_OUT(); //设置为输出
W1DQ_Write(0);
delay_us(2);
DS18B20_IO_IN(); //设置为输入
delay_us(13);
if(W1DQ_Read())
dt=1;
else
dt=0;
delay_us(50);
//将获得的dt放在最前面,然后再右移一下空出最前面的位置
date=(dt<<7)|(date>>1);
}
return date;
}
写时序
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(uint8_t dat)
{
uint8_t j;
uint8_t testb;
DS18B20_IO_OUT(); //设置为输出
for (j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) // 写1
{
W1DQ_Write(0);
delay_us(2);
W1DQ_Write(1);
delay_us(60);
}
else //写0
{
W1DQ_Write(0);
delay_us(60);
W1DQ_Write(1);
delay_us(2);
}
}
}
温度转换
//开始温度转换
static inline int DS18B20_Start(void)
{
if(0!=DS18B20_Rst())
return -1;
DS18B20_Write_Byte(0xcc);// skip rom
DS18B20_Write_Byte(0x44);// convert
}
获取温度
//从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250)
short DS18B20_Get_Temp(void)
{
uint8_t temp;
uint8_t LSB,MSB;
short tem;
DS18B20_Start (); //开始转换
DS18B20_Rst();
// DS18B20_Check();
DS18B20_Write_Byte(0xcc); // skip rom
DS18B20_Write_Byte(0xbe); // convert
LSB=DS18B20_Read_Byte(); // LSB
MSB=DS18B20_Read_Byte(); // MSB
if(MSB>7)
{
MSB=~MSB;
LSB=~LSB;
temp=0;//温度为负
}else temp=1;//温度为正
tem=MSB; //获得高八位
tem<<=8;
tem+=LSB;//获得底八位
tem=(double)tem*0.625;//转换
if(temp)
return tem; //返回温度值
else
return -tem;
}
运行结果:
用手捂住之后温度上升: