STM32扩展板 温度传感器和温湿度传感器的使用

本文介绍了DS18B20数字温度传感器的工作原理,包括其单线接口、测量范围和精度,并提供了C语言实现的驱动代码。同时,也详细阐述了DHT11温湿度传感器的通信协议和读取数据的步骤,附带了相关代码。这些传感器广泛应用于物联网和智能家居系统中。
摘要由CSDN通过智能技术生成

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);
	
}
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wu小燕呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值