DS18B20
DS18B20是单线接口数字温度传感器,测量范围是-55℃~+125℃,-10℃~+85℃范围内精度是±0.5℃,测量分辨率为9~12位(复位值为12位,最大转换时间为750ms)。
DS18B20包括寄生电源电路、64位ROM和单线接口电路、暂存器、EEPROM、8位CRC生成器和温度传感器等。寄生电源电路可以实现外部电源供电和单线寄生供电,64位ROM中存放的48位序列号用于识别同一单线上连接的多个DS18B20,以实现多点测温。
64位(激)光刻只读存储器
每只DS18B20都有一个唯一存储在ROM中的64位编码。最前面8位是单线系列编码:28H.接着的48位是一个唯一的序号列。最后8位是以上56位的CRC编码。CRC的详细解释见CRC发生器节。64位ROM和ROM操作控制器允许DS18B20作为单总线器件并按照详述单总线系统节的单总线协议工作。
温度传感器时序(操作步骤) 还请查看手册。。
中文手册
链接:https://pan.baidu.com/s/1AJiUh0PfLi-EYOQFXrFkzA?pwd=8elx
提取码:8elx
代码
ds18b20_hal.c
#include "ds18b20_hal.h"
#define delay_us(X) delay((X)*80/5)
void delay(unsigned int n)
{
while(n--);
}
void ds18b20_init_x(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = OW_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH ;
GPIO_InitStruct.Pull = GPIO_PULLUP ;
HAL_GPIO_Init(OW_PIN_PORT, &GPIO_InitStruct);
}
//
void mode_input1(void )
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
GPIO_InitStruct.Pin = OW_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(OW_PIN_PORT, &GPIO_InitStruct);
}
void mode_output1(void )
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = OW_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pull = GPIO_NOPULL ;
HAL_GPIO_Init(OW_PIN_PORT, &GPIO_InitStruct);
}
//
uint8_t ow_reset(void)
{
uint8_t err;
OW_DIR_OUT(); // pull OW-Pin low for 480us
OW_OUT_LOW(); // disable internal pull-up (maybe on from parasite)
delay_us(400); //about 480us
// set Pin as input - wait for clients to pull low
OW_DIR_IN(); // input
delay_us(66);
err = OW_GET_IN(); // no presence detect
// nobody pulled to low, still high
// after a delay the clients should release the line
// and input-pin gets back to high due to pull-up-resistor
delay_us(480 - 66);
if( OW_GET_IN() == 0 ) // short circuit
err = 1;
return err;
}
uint8_t ow_bit_io( uint8_t b )
{
OW_DIR_OUT(); // drive bus low
OW_OUT_LOW();
delay_us(1); // Recovery-Time wuffwuff was 1
if ( b ) OW_DIR_IN(); // if bit is 1 set bus high (by ext. pull-up)
#define OW_CONF_DELAYOFFSET 5
delay_us(15 - 1 - OW_CONF_DELAYOFFSET);
if( OW_GET_IN() == 0 ) b = 0; // sample at end of read-timeslot
delay_us(60 - 15);
OW_DIR_IN();
return b;
}
uint8_t ow_byte_wr( uint8_t b )
{
uint8_t i = 8, j;
do
{
j = ow_bit_io( b & 1 );
b >>= 1;
if( j ) b |= 0x80;
}
while( --i );
return b;
}
//
uint8_t ow_byte_rd( void )
{
return ow_byte_wr( 0xFF );
}
uint_least16_t ds18b20_read(void)
{
uint8_t low,high;
uint_least16_t temp;
ow_reset();
ow_byte_wr(OW_SKIP_ROM);
ow_byte_wr(DS18B20_CONVERT);
delay(750000);
ow_reset();
ow_byte_wr(OW_SKIP_ROM);
ow_byte_wr(DS18B20_READ);
low = ow_byte_rd();
high = ow_byte_rd();
temp = (high << 8 | low) & 0x07ff;
return temp;
}
ds18b20_hal.h
#ifndef __DS18B20_HAL_H
#define __DS18B20_HAL_H
#include "stm32g4xx_hal.h"
#define OW_PIN_PORT GPIOA
#define OW_PIN GPIO_PIN_6
#define OW_DIR_OUT() mode_output1()
#define OW_DIR_IN() mode_input1()
#define OW_OUT_LOW() (HAL_GPIO_WritePin(OW_PIN_PORT, OW_PIN, GPIO_PIN_RESET))
#define OW_GET_IN() (HAL_GPIO_ReadPin(OW_PIN_PORT, OW_PIN))
#define OW_SKIP_ROM 0xCC
#define DS18B20_CONVERT 0x44
#define DS18B20_READ 0xBE
void ds18b20_init_x(void);
uint_least16_t ds18b20_read(void);
#endif
显示温度
__IO uint32_t lcd_uwTick = 0; //控制lcd_proc()的执行速度
uint8_t lcd_disp_string[20];
void lcd_proc()
{
if(uwTick - lcd_uwTick < 200)
return;
lcd_uwTick = uwTick;
sprintf((char *)lcd_disp_string,"temp:%.2f",ds18b20_read()/16.);
LCD_DisplayStringLine(Line2,lcd_disp_string);
}
DHT11
接口说明
建议连接线长度短于20米时用5K上拉电阻,大于20米时根据实际情况使用合适的上拉电阻。
dht11手册
链接:https://pan.baidu.com/s/1y5T_SZC5eOOCBZOybGxxmQ?pwd=hnkp
提取码:hnkp
*复位DHT11
//复位DHT11
void DHT11_Rst(void)
{
DHT11_PIN_OUT(); //设置为输出
DHT11_PIN_OUT_L; //低电平
HAL_Delay(20); //拉低至少18ms
DHT11_PIN_OUT_H; //高电平
Delay_us(60); //主机拉高20~40us
}
*发出开始信号和回应
//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
uint8_t DHT11_Check(void)
{
uint8_t re = 0;
DHT11_PIN_INPUT(); //设置为输出
while (DHT11_PIN_IN && re < 100) //DHT11会拉低40~80us
{
re++;
Delay_us(1);
};
if(re >= 100)return 1;
else re = 0;
while (!DHT11_PIN_IN && re < 100) //DHT11拉低后会再次拉高40~80us
{
re++;
Delay_us(1);
};
if(re >= 100)return 1;
return 0;
}
* 读0和读1
//从DHT11读取一个位
uint8_t DHT11_Read_Bit(void)
{
uint8_t re = 0;
while(DHT11_PIN_IN && re < 110) //等待变为低电平
{
re++;
Delay_us(1);
}
re = 0;
while(!DHT11_PIN_IN && re < 110) //等待变高电平
{
re++;
Delay_us(1);
}
Delay_us(80);//等待40us
if(DHT11_PIN_IN)return 1;
else return 0;
}
//从DHT11读取一个字节
uint8_t DHT11_Read_Byte(void)
{
uint8_t i, dat;
dat = 0;
for (i = 0; i < 8; i++)
{
dat <<= 1;
dat |= DHT11_Read_Bit();
}
return dat;
}
读取数据
//从DHT11读取一次数据
uint8_t DHT11_Read_Data(uint8_t *temp, uint8_t *humi)
{
uint8_t buf[5];
uint8_t i;
DHT11_Rst();
if(DHT11_Check() == 0)
{
for(i = 0; i < 5; i++)
{
buf[i] = DHT11_Read_Byte();
}
if((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
{
*humi = buf[0];
*temp = buf[2];
}
}
else return 1;
return 0;
}
实现代码
dht11.c
#include "dht11.h"
#define Delay_us(X) delay((X)*80/5)
void delay(unsigned int n)
{
while(n--);
}
void DHT11_PIN_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/**/
GPIO_InitStruct.Pin = DHT11_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DHT11_PIN_PORT, &GPIO_InitStruct);
}
void DHT11_PIN_INPUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
DHT11_PIN_CLOCK;
/**/
GPIO_InitStruct.Pin = DHT11_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(DHT11_PIN_PORT, &GPIO_InitStruct);
}
//复位DHT11
void DHT11_Rst(void)
{
DHT11_PIN_OUT(); //设置为输出
DHT11_PIN_OUT_L; //低电平
HAL_Delay(20); //拉低至少18ms
DHT11_PIN_OUT_H; //高电平
Delay_us(60); //主机拉高20~40us
}
//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
uint8_t DHT11_Check(void)
{
uint8_t re = 0;
DHT11_PIN_INPUT(); //设置为输出
while (DHT11_PIN_IN && re < 100) //DHT11会拉低40~80us
{
re++;
Delay_us(1);
};
if(re >= 100)return 1;
else re = 0;
while (!DHT11_PIN_IN && re < 100) //DHT11拉低后会再次拉高40~80us
{
re++;
Delay_us(1);
};
if(re >= 100)return 1;
return 0;
}
//从DHT11读取一个位
uint8_t DHT11_Read_Bit(void)
{
uint8_t re = 0;
while(DHT11_PIN_IN && re < 110) //等待变为低电平
{
re++;
Delay_us(1);
}
re = 0;
while(!DHT11_PIN_IN && re < 110) //等待变高电平
{
re++;
Delay_us(1);
}
Delay_us(80);//等待40us
if(DHT11_PIN_IN)return 1;
else return 0;
}
//从DHT11读取一个字节
uint8_t DHT11_Read_Byte(void)
{
uint8_t i, dat;
dat = 0;
for (i = 0; i < 8; i++)
{
dat <<= 1;
dat |= DHT11_Read_Bit();
}
return dat;
}
//从DHT11读取一次数据
uint8_t DHT11_Read_Data(uint8_t *temp, uint8_t *humi)
{
uint8_t buf[5];
uint8_t i;
DHT11_Rst();
if(DHT11_Check() == 0)
{
for(i = 0; i < 5; i++)
{
buf[i] = DHT11_Read_Byte();
}
if((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
{
*humi = buf[0];
*temp = buf[2];
}
}
else return 1;
return 0;
}
//初始化DHT11的IO口,同时检测DHT11的存在
uint8_t DHT11_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
DHT11_PIN_CLOCK;;
GPIO_InitStruct.Pin = DHT11_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DHT11_PIN_PORT, &GPIO_InitStruct);
DHT11_Rst();
return DHT11_Check();
}
dht11.h
#ifndef __DHT11_H
#define __DHT11_H
#include "main.h"
#define DHT11_PIN_PORT GPIOA
#define DHT11_PIN GPIO_PIN_7
#define DHT11_PIN_CLOCK __HAL_RCC_GPIOA_CLK_ENABLE()
#define DHT11_PIN_OUT_H HAL_GPIO_WritePin(DHT11_PIN_PORT, DHT11_PIN, GPIO_PIN_SET)
#define DHT11_PIN_OUT_L HAL_GPIO_WritePin(DHT11_PIN_PORT, DHT11_PIN, GPIO_PIN_RESET)
#define DHT11_PIN_IN HAL_GPIO_ReadPin(DHT11_PIN_PORT, DHT11_PIN)
uint8_t DHT11_Init(void);//初始化DHT11
uint8_t DHT11_Read_Data(uint8_t *temp, uint8_t *humi); //读取温湿度
uint8_t DHT11_Read_Byte(void);//读出一个字节
uint8_t DHT11_Read_Bit(void);//读出一个位
uint8_t DHT11_Check(void);//检测是否存在DHT11
void DHT11_Rst(void);//复位DHT11
#endif
显示温度湿度
void Lcd_Proc()
{
if(uwTick - lcd_uwTick < 200)
return;
lcd_uwTick = uwTick;
DHT11_Read_Data(&temp,&damp);
sprintf((char *)lcd_disp_string,"temp: %d damp: %d",(uint32_t)temp,(uint32_t)damp);
HAL_Delay(200);
LCD_DisplayStringLine(Line3,lcd_disp_string);
}