/************************************************************************
*							  ---- 居加居 ----							 
*  文件名:		DHT11.c
*  编写人员:		Kinve JQ
*  说明:		 
*  版本:			V0.1
*  编写日期:		2018-09-30
*  程序维护:	 
*  维护记录:	
*	 2018-09-30.Kinve:1.创建文件
* 免责声明：
* (c) Author Kinve JQ. All rights reserved.
**************************************************************************/

#include "DHT11.h"

#define delay_ms(ms)	Timer3_Delay1ms(ms)
#define delay_us(us)	Timer3_Delay1us(us)	//{u8 i; for(i=0;i<us;i++) {nop;}}

DHT11_Data_TypeDef DHT11_Data;

//全局变量定义区
//***************************************************************************/
//      //uchar       i;
//      uchar    U8FLAG,k;
//      uchar    U8count,U8temp;
//      uchar    U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
//      uchar    U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
//      uchar    U8comdata;
//      uint   ReceiveHighByte;
//      uint   ReceiveLowByte;
//***************Global defination for DHT11 end****//

void DHT11_PortIN ( void )
{
#if 0
    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_APB2PeriphClockCmd ( DHT11_IORCC, ENABLE );

    //切换为输入口
    GPIO_InitStructure.GPIO_Pin = DHT11_DATA_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init ( DHT11_PORT, &GPIO_InitStructure );
#endif
}
void DHT11_PortOUT ( void )
{
#if 0
    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_APB2PeriphClockCmd ( DHT11_IORCC, ENABLE );

    GPIO_InitStructure.GPIO_Pin = ( DHT11_DATA_PIN );
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	  //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init ( DHT11_PORT, &GPIO_InitStructure );
#endif	
}

/*
1.主机L >18ms
2.主机H 20-40us
3.DHT     L 80us
4.DHT     H 80us
5.DHT 	DATA....
*/
static u8 _us = 0;
unsigned char DHT11_Start ( void )
{

    //主机开始信号
    /*
    	低18ms->高30us->等待dht响应(拉低)
    */
    DHT11_PortOUT();
    DHT11_Out = 0;
    delay_ms ( 20 );  	//触发开始,总线拉低要大于18ms
    DHT11_Out = 1;	//释放总线
    delay_us(30);	//拉低 20-40uS 等待DHT11的低电平响应信号

    //dht响应
    /*
    	正确，拉低(80us) ->拉高(80us)->传送数据
    */
    DHT11_PortIN(); //改为输入

	#if 0
    //实际6
    _us = 0;

    while ( DHT11_In ) //低电平的响应信号，20-40uS
    {
        if ( ++_us > 40 )
        {
            return 0;
        }

        delay_us ( 1 );
    }
	#endif

    //实际53
    _us = 0;

    while ( !DHT11_In ) //低电平的响应信号，80us
    {
        if ( ++_us > 80 )
        {
            return 0;
        }

        delay_us ( 1 );
    }

    //实际54
    _us = 0;

    while ( DHT11_In ) //紧接着是80us的高电平数据准备信号
    {
        if ( ++_us > 80 )
        {
            return 0;
        }

        delay_us ( 1 );
    }

    //拉低后DHT11会拉高总线80us,接着会开始传数据

    return 1;

}


/*
	传输数据:
	1.一次8bit
	2.
		开始(50us 低)->
		0:	26-28us 高+ (50us 低) = 80us
		1:	70us 高+ (50us 低) = 120us

	3.判断0/1，
		1. 26-28us < n <  26-28us+50us
		2. 0us < n < 70us
	即，
	延时35-40us，
	高 = 1，是70us的，需要延时40us
	低 = 0，是26-28us的

*/
static uint8_t Read_Byte ( void )
{
    u8 i, temp = 0xff;

    //开始必须是为低的50us 开始信号
    if ( !DHT11_In )
    {
        for ( i = 0; i < 8; i++ )
        {
            //等待高电平,消耗50us
            _us = 0;

            while ( !DHT11_In )
            {
                if ( ++_us > 50 )
                {
                    return temp;
                }

                delay_us ( 1 );
            }

            //等待低电平,真实数据的结束
            _us = 0;

            while ( DHT11_In )
            {
                if ( ++_us > 80 )
                {
                    return temp;
                }

                delay_us ( 1 );
            }

            if ( _us >  37 ) //35-40us后仍为高电平表示数据“1”
            {
                temp |= ( uint8_t ) ( 0x01 << ( 7 - i ) ); //把第7-i位置1
            }
            else	 //40us后为低电平表示数据“0”
            {
                temp &= ( uint8_t ) ~ ( 0x01 << ( 7 - i ) ); //把第7-i位置0
            }
        }
    }

    return temp;
}



uint8_t DHT11_Read_Data ( DHT11_Data_TypeDef *DHT11_Data )
{
    uint8_t  res;
    uint8_t  check_sum;

    if ( DHT11_Start() )	//判断是否已经响应
    {
        /*开始接收数据*/
        DHT11_Data->humi_int = Read_Byte();
        DHT11_Data->humi_deci = Read_Byte();
        DHT11_Data->temp_int = Read_Byte();
        DHT11_Data->temp_deci = Read_Byte();
        DHT11_Data->check_sum = Read_Byte();

        check_sum = DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int + DHT11_Data->temp_deci;

        /*检查读取的数据是否正确*/
        if ( DHT11_Data->check_sum == check_sum )
        {
            res = SUCCESS;
        }
        else
        {
            res = ERROR;
        }
    }
    else
    {
        res = ERROR;
    }

    return res;
}

/********************* (C) COPYRIGHT Kinve JQ  *******END OF FILE ********/


