/*******************************************************************
* @file hal_dht11.c
* @brief Temperature & Humidity Sensor Driver - DHT11
*
* Copyright (c) 2017~2020 ShenZhen IoT-College Technology Co., Ltd.
* All rights reserved.
*
* @version 1.0.0
* @author IoT-College <1805593021@qq.com>
* @date 2017-12-11 13:18:22
*
* @note 1. The official flagship store:
* https://shop115377068.taobao.com
*
* 2. Blog:
* *GitHub: https://github.com/IoT-College
* *CSDN: https://blog.csdn.net/IoT_College
* *StackOverflow:
* https://stackoverflow.com/users/9555987/iot-college
*
* 3. QQ Communication group:
* *Group 1: 575036716
* *Group 2: 684572410
* *Group 3: 587518203
*******************************************************************/
/*******************************************************************
* Includes
*******************************************************************
*/
#include "hal_dht11.h"
#include "CC2530_IoConfig.h"
/*******************************************************************
* Constant-Macros And Enumerations
*******************************************************************
*/
/** @brief DHT11 Boolean
*/
#define HAL_DHT11_FALSE 0
#define HAL_DHT11_TRUE 1
/** @brief DHT11 Status Code
*/
#define HAL_DHT11_SC_ERR HAL_DHT11_FALSE
#define HAL_DHT11_SC_OK HAL_DHT11_TRUE
#define HAL_DHT11_SC_HUMI_OUTOFRANGE 0xF1
#define HAL_DHT11_SC_TEMP_OUTOFRANGE 0xF2
#define HAL_DHT11_SC_HT_OUTOFRANGE 0xF3
/** @brief Delay Function
* us,
* ms
*/
#define HAL_DHT11_DELAY_US(x) delayUsIn32Mhz((x))
#define HAL_DHT11_DELAY_MS(x) delayMs(HAL_DELAY_32MHZ ,(x))
/** @brief Set DHT11 GPIO
* output,
* input
*/
#define HAL_DHT11_IO_OUTPUT() CC2530_GPIOMODE_CONFIG(HAL_DHT11_PORT, \
HAL_DHT11_PIN, \
CC2530_GPIO_OUTPUT)
#define HAL_DHT11_IO_INPUT() CC2530_GPIOMODE_CONFIG(HAL_DHT11_PORT, \
HAL_DHT11_PIN, \
CC2530_GPIO_INPUT_PULLDOWN)
/** @brief Set DHT11 GPIO Level
* low-level,
* high-level
*/
// set IO level
#define HAL_DHT11_IO_SET(port, pin, level){ \
if(level) CC2530_GPIO_SET(port, pin); \
else CC2530_GPIO_CLEAR(port, pin); \
}
// Set IO as high-level
#define HAL_DHT11_IO_SET_LO() HAL_DHT11_IO_SET(HAL_DHT11_PORT, HAL_DHT11_PIN, 0)
// Set IO as low-level
#define HAL_DHT11_IO_SET_HI() HAL_DHT11_IO_SET(HAL_DHT11_PORT, HAL_DHT11_PIN, 1)
/** @brief DHT11 GPIO Status
*/
#define HAL_DHT11_IO_GET_STA(port, pin) CC2530_GPIO_GET(port, pin)
#define HAL_DHT11_IO() HAL_DHT11_IO_GET_STA(HAL_DHT11_PORT, HAL_DHT11_PIN)
/** @brief DHT11 Measurement range detection
* Temperature: 0~50 C
* Humidity: 20~95%RH
*/
#define HAL_DHT11_TEMP_OK(t) ((t) <= 50)
#define HAL_DHT11_HUMI_OK(h) ((h) >= 20 && (h) <= 95)
/*******************************************************************
* Local Functions Declarations
*******************************************************************
*/
static void halDHT11SetIdle(void);
static uint8 halDHT11ReadByte(void);
static uint8 halDHT11CheckData(uint8 TempI, uint8 HumiI);
/*******************************************************************
* Global Functions
*******************************************************************
*/
/**
* @fn halDHT11Init
*
* @brief Init. DHT11
*/
void halDHT11Init(void)
{
halDHT11SetIdle();
}
/**
* @fn halDHT11GetData
*
* @brief Get data from DHT11
*
* @param None
*
* @note Temperature: 0~50 C
* Humidity: 20~95%
*/
halDHT11Data_t halDHT11GetData(void)
{
halDHT11Data_t dht11Dat = { .ok = 0 };
uint8 HumiI, HumiF, TempI, TempF, CheckSum;
/* >18ms, keeping gpio low-level */
HAL_DHT11_IO_SET_LO();
HAL_DHT11_DELAY_MS(60);
HAL_DHT11_IO_SET_HI();
/* Wait 20~40us then read ACK */
HAL_DHT11_DELAY_US(35);
HAL_DHT11_IO_INPUT();
if(!HAL_DHT11_IO())
{
uint16 cnt = 1070; // ~1ms
/* Wait for the end of ACK */
while(!HAL_DHT11_IO() && cnt--);
if(!cnt)
{
goto Exit;
}
/* ~80us, DHT11 GPIO will be set after ACK */
cnt = 1070; // ~1ms
HAL_DHT11_DELAY_US(80);
while(HAL_DHT11_IO() && cnt--);
if(!cnt)
{
goto Exit;
}
/* Read data */
HumiI = halDHT11ReadByte();
HumiF = halDHT11ReadByte();
TempI = halDHT11ReadByte();
TempF = halDHT11ReadByte();
CheckSum = halDHT11ReadByte();
/* Checksum */
if(CheckSum == (HumiI + HumiF + TempI + TempF))
{
dht11Dat.temp = TempI;
dht11Dat.humi = HumiI;
dht11Dat.ok = halDHT11CheckData(TempI, HumiI);
}
}
Exit:
/* Idle */
halDHT11SetIdle();
return dht11Dat;
}
/*******************************************************************
* Local Functions
*******************************************************************
*/
/**
* @fn halDHT11SetIdle
*
* @brief DHT11 Idle
*/
static void halDHT11SetIdle(void)
{
HAL_DHT11_IO_OUTPUT();
HAL_DHT11_IO_SET_HI();
}
/**
* @fn halDHT11ReadByte
*
* @brief Read a byte from DHT11
*/
static uint8 halDHT11ReadByte(void)
{
uint8 dat = 0;
for(uint8 i = 0; i < 8; i++)
{
uint16 cnt = 5350; // ~5ms
/* Busy */
while(!HAL_DHT11_IO() && cnt--);
if(!cnt)
{
break;
}
/* Read bit based on high-level duration:
* 26~28us: 0
* >70us: 1
*/
HAL_DHT11_DELAY_US(50);
if(HAL_DHT11_IO())
{
dat <<= 1;
dat |= 1;
}
else
{
dat <<= 1;
continue;
}
/* Waiting end */
cnt = 1070; // ~1ms
while(HAL_DHT11_IO() && cnt--);
if(!cnt)
{
break;
}
}
return dat;
}
/**
* @fn halDHT11CheckData
*
* @brief Check measured value
*/
static uint8 halDHT11CheckData(uint8 TempI, uint8 HumiI)
{
if(HAL_DHT11_HUMI_OK(HumiI))
{
if(HAL_DHT11_TEMP_OK(TempI))
return HAL_DHT11_SC_OK;
else
return HAL_DHT11_SC_TEMP_OUTOFRANGE;
}
if(HAL_DHT11_TEMP_OK(TempI))
return HAL_DHT11_SC_HUMI_OUTOFRANGE;
else
return HAL_DHT11_SC_HT_OUTOFRANGE;
}