Periférico de control de tiempo analógico GPIO 2 - DHT11

prefacio

En el artículo anterior, se introdujo que GPIO se usa para simular la secuencia de control de WS2812B para realizar el control de luces RGB.Este artículo continúa usando la simulación GPIO para comunicarse con el sensor de temperatura y humedad DHT11 por MCU para obtener información de temperatura y humedad. .

Introducción al módulo

DHT11 es uno de los módulos comúnmente utilizados para recolectar temperatura y humedad. Integra sensores para detectar humedad y temperatura y una microcomputadora de un solo chip de 8 bits para procesar información de temperatura y humedad. Gracias a esta MCU incorporada de 8 bits, los usuarios guardar Los pasos de procesamiento de datos de temperatura y humedad se omiten, y la temperatura y la humedad se pueden obtener directamente de acuerdo con el diagrama de tiempo.
inserte la descripción de la imagen aquí

introducción de hardware

Hay dos módulos comunes, uno son los cuatro pines que se muestran en la figura anterior sin una placa adaptadora, al usar este tipo de módulo, debe agregar una resistencia pull-up al pin DATA durante el dibujo del diagrama esquemático, de lo contrario, hay hay una alta probabilidad de que los datos no se puedan obtener a través de una comunicación normal.
inserte la descripción de la imagen aquí
También hay un módulo con 3 pines, que generalmente está equipado con una resistencia pull-up en la placa adaptadora. Para reducir el impacto de la fuente de alimentación en los datos recopilados, intente usar la fuente de alimentación LDO, y C1 en la figura a continuación también desempeña un papel de filtrado de la fuente de alimentación.
inserte la descripción de la imagen aquí
Aquí el autor elige un módulo con una placa adaptadora.

conexión de hardware

Después de obtener una comprensión general del módulo, debe comparar el diagrama esquemático para encontrar el GPIO utilizado para la comunicación real. A través del diagrama esquemático, el GPIO utilizado es PA15.
inserte la descripción de la imagen aquí

secuencia de comunicación

De acuerdo con los pasos de la simulación anterior, el siguiente paso es verificar su tiempo de comunicación y usar GPIO para simular el tiempo para realizar la función.
DHT11 adopta un protocolo de comunicación de bus único (1 cable) y utiliza una línea de datos para completar el intercambio de datos entre las dos partes. Dado que es una línea de datos única, debe ser un método de comunicación semidúplex. Al mismo tiempo , la MCU envía datos o DHT11 envía datos. Además, DHT11 no puede transmitir datos de forma activa a la MCU.Después de que la MCU envíe una señal de inicio a DHT11, DHT11 responderá y luego transmitirá datos.
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
Cabe señalar que cuando se realiza el intercambio de datos entre DHT11 y MCU, las líneas de señal se utilizan a su vez.
De acuerdo con esta descripción, la secuencia de comunicación de DHT11 se puede resumir aproximadamente:
1. El maestro (MCU) envía una señal de inicio a DHT11 (esclavo);
2. Después de que DHT11 (esclavo) recibe la señal de inicio, devuelve una respuesta y una señal para la transmisión de datos
3. Después de recibir la señal de respuesta y la señal de transmisión de datos, el host (MCU) comienza a recibir datos de 40 bits 4. La
transmisión de datos DHT11 se completa, se genera una señal final y la MCU deja de recibir datos.
inserte la descripción de la imagen aquí

Formato de trama de datos DHT11

DHT11 transmitirá 40 bits de datos a la vez, cada uno de los cuales se define de la siguiente manera: los
primeros ocho bits de datos son bits enteros de humedad, los segundos ocho bits de datos son bits decimales de humedad y los terceros ocho bits son bits de humedad. enteros del dígito de temperatura, el cuarto ocho dígitos es el lugar decimal de la temperatura, los últimos datos de ocho dígitos son el dígito de control, el dígito de control = la suma de los primeros cuatro ocho dígitos, y luego toma el valor de los ocho dígitos inferiores .
inserte la descripción de la imagen aquí

El ejemplo en el manual es el siguiente:
inserte la descripción de la imagen aquí
La forma de onda real capturada por el analizador lógico es la siguiente:
inserte la descripción de la imagen aquí

temporización de la señal

Después de aclarar el proceso de comunicación general, el marco general del programa está disponible, pero el método de representación de señal específico debe verificarse más en el manual.

1. Señal de inicio

Primero mire la señal de inicio. La MCU envía la señal de inicio al DHT11. En este momento, el GPIO de la MCU se usa como un pin de salida para generar niveles altos y bajos durante una duración específica.
La forma de onda correspondiente a la señal de inicio es el contenido dentro del cuadro rojo en la figura a continuación.
inserte la descripción de la imagen aquí
Después de acercar, se muestra en la figura a continuación:
inserte la descripción de la imagen aquí
a través de esta descripción y la forma de onda, se puede ver que la señal de inicio primero requiere que la MCU baje el pin de datos durante al menos 18 ms y luego lo suba para liberar el autobús.
¿Cómo entiende el bus pull-up y release aquí? Como se mencionó anteriormente, siempre hay una resistencia pull-up en el pin DATA. Cuando ni la MCU ni el DHT11 tienen salidas para controlar el pin DATA, el voltaje del pin DATA siempre se mantiene en un nivel alto, es decir, se dice que la línea de DATOS se pone alta e inactiva, liberando el estado. Aquí hay un recordatorio, siempre que MCU y DHT11 no controlen DATOS, el estado predeterminado de DATOS es de alto nivel.
A partir de esto, la función de la señal de inicio se puede escribir aproximadamente:

/*********************************
函数名:DHT11_Start
函数功能:DHT11复位(起始信号开始转换)
形参:void
返回值:void
备注:
主机拉低至少18MS,再拉高20-40us,等待应答
**********************************/
void DHT11_Start(void)
{
    
    
	//DATA脚拉低18ms以上30ms以下
	DHT11_OUT_L;
	Systick_Delay_ms(20);
	//再拉高20-40us
	DHT11_OUT_H;
	Systick_Delay_us(30);
}

2. Señal de respuesta (señal de respuesta)

La señal de respuesta de DHT11 se muestra en el cuadro rojo de la figura a continuación. Justo después de que el host envía la señal de inicio, eleva la línea de DATOS y la libera. Es decir, la línea de DATOS está en el estado de nivel alto al predeterminado Cuando DHT11 recibe la señal de inicio, bajará la línea de datos de DATOS, este menú desplegable se llama señal de respuesta, después de la respuesta, para la estabilidad de la recepción de datos, DHT11 también levantará la línea de datos nuevamente, liberará los datos y dígale al host que se prepare para comenzar a transmitir datos.
inserte la descripción de la imagen aquí
Esta parte del diagrama de temporización se amplía como se muestra en la siguiente figura:
DHT11 bajará el pin de DATOS durante aproximadamente 80us, y luego DHT11 levantará el pin de datos para decirle al maestro que comience a recibir datos.
Una cosa a tener en cuenta aquí es que la línea de datos está controlada por DHT11 en este momento.Para obtener la señal transmitida desde DHT11, la MCU necesita cambiar el modo de salida anterior al modo de entrada. Hay dos métodos de conmutación específicos, que se describirán en detalle más adelante. Es suficiente saber que la MCU lee el estado de DATOS en este momento.
inserte la descripción de la imagen aquí
Aquí, primero escriba un código para obtener la señal de respuesta, y la señal de que los datos están listos para enviarse se implementa cuando se lee el bit de datos.

/*********************************
函数名:DHT11_Check
函数功能:DHT11应答检测
形参:void
返回值:u8 
备注:返回1:未检测到DHT11的存在
返回0:检测到DHT11
**********************************/
u8 DHT11_Check(void)
{
    
    
	u8 retry=0;	 	 
	//等待起始信号的高电平时间结束
   while (DHT11_IN && retry<100)
	{
    
    
		retry++;
		Systick_Delay_us(1);
	};	 
	if(retry>=100)return 1;//如果DATA脚空闲时间超过100us还没有被DHT11拉低,说明应答失败
	else retry=0;
	//检测DHT11应答拉低的时间是否正常
  while (!DHT11_IN && retry<100)//DHT11会拉低40~80us
	{
    
    
		retry++;
		Systick_Delay_us(1);
	};
	if(retry>=100)return 1;	//如果低电平时间超过了100us说明应答失败    
	return 0;//否则就应答成功
}	

3. Recibir datos 0 y 1

Después de obtener la señal de respuesta, es necesario procesar la temporización de los datos que se enviarán y luego juzgar si el bit de datos es 0 o 1 de acuerdo con el estado de DATA. Al igual que la comunicación WS2812B del artículo anterior, el "1" y el "0" de DHT11 también se componen de niveles altos y bajos para un período de tiempo específico.
Las expresiones específicas de "0" lógico y "1" lógico se muestran en la siguiente figura. Primero hay un nivel de 54us, y luego se distinguen el "0" lógico y el "1" lógico según la duración del nivel alto. .
El tiempo de alto nivel de la lógica "0" dura 23-27 us, y el tiempo de alto nivel de la lógica "1" dura 68 = 74 us.
inserte la descripción de la imagen aquí
Entonces, cómo detectar la lógica "0" y la lógica "1", una solución simple, ya que el tiempo de nivel bajo es el mismo, luego, al leer, espere el final del nivel bajo, y luego retrase más de 40 us, y luego lea Tome el estado de DATA, si todavía es alto en este momento, significa "1 lógico", si se vuelve bajo, significa "0" lógico.
el código se muestra a continuación:

/*********************************
函数名:DHT11_Read_Bit
函数功能:从DHT11获取1位数据
形参:void
返回值:u8  1/0
备注:
数据线低50us表示开始传输数据,数据变为高电平时开始记录高电平持续时间
如果高电平时间持续26-28us表示数据位为0
如果高电平时间持续70us表示数据位为1
**********************************/
u8  DHT11_Read_Bit(void)
{
    
    
	u8 retry=0;
	//等待准备接收数据的信号结束
	while(DHT11_IN && retry<100)//等待变为低电平(应答后会拉低拉高,所以在这里要等待80)
	{
    
    
		retry++;
		Systick_Delay_us(1);
	}
	retry=0;
	//0和1的低电平时间段不作判定,直接等待
	while(!DHT11_IN &&retry<100)//等待变高电平
	{
    
    
		retry++;
		Systick_Delay_us(1);
	}
	Systick_Delay_us(40);//等待40us
	if(DHT11_IN)return 1;//“1”的高电平时间持续68us以上,延时40us后还是高电平
	else return 0;		//“0”的高电平时间持续26-28us,经过上面的延时已经变回低电平了。
}

4. Obtener datos

Luego llame a la función de recepción de bits anterior para realizar la recepción de datos de 40 bits, el bit alto es primero, y luego encapsule la función de recepción de bytes correspondiente, y luego, después de recibir 5 bytes de datos, juzgue el dígito de control de acuerdo con el formato de trama de datos anterior, solo leer el valor deseado.

/*********************************
函数名:DHT11_Read_Byte
函数功能:从DHT11获取1字节数据
形参:void
返回值:u8 
备注:

**********************************/
u8  DHT11_Read_Byte(void)
{
    
    
	u8 i,dat;
  dat=0;
	for (i=0;i<8;i++) 
	{
    
    
   		dat<<=1; 
	    dat|=DHT11_Read_Bit();
    }						    
    return dat;
}

/*********************************
函数名:DHT11_Read_Data
函数功能:从DHT11获取数据
形参:void
返回值:u8 0,正常;1,读取失败
备注:
8bit湿度整数数据+8bit湿度小数数据
+8bi温度整数数据+8bit温度小数数据
+8bit校验和
**********************************/
u8  DHT11_Read_Data(u8 *temp,u8 *humi)
{
    
    
	u8 buf[5];
	u8 i;
	DHT11_Start();
	if(DHT11_Check()==0)
	{
    
    
		for(i=0;i<5;i++)//读取40位数据
		{
    
    
			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;	    
}

5 señal final

En cuanto a la señal final, es generada por DHT11 y generalmente no necesita ser procesada, la MCU solo necesita encargarse de recibir los datos de 40 bits.
inserte la descripción de la imagen aquí

Conmutación de entrada y salida

El código de todo el proceso de comunicación es aproximadamente el contenido anterior, pero todavía hay un problema, GPIOA15 no solo proporciona la señal de inicio como salida durante todo el proceso de comunicación, sino que también obtiene los datos de DHT11 como entrada, cómo realmente Como se mencionó anteriormente, hay dos soluciones, una de las cuales también es la favorita del autor, inicializar directamente GPIOA15 en modo de drenaje abierto, en este momento, el PMOS responsable de la salida de alto nivel está protegido, cuando escribimos 1 en ODR , GPIOA15 ya no tiene salida de alto nivel, es decir, la MCU ya no ocupa el pin de DATOS. En este momento, la línea de DATOS está controlada por la resistencia pull-up externa y DHT11. En este momento, llame directamente a la biblioteca función para obtener el nivel alto y bajo de GPIOA15, que es el estado de DATOS real. .

/*********************************
函数名:DHT11_Init
函数功能:DHT11初始化
形参:void
返回值:void
备注:既要输入又要输出
DHT11_DATA-----PA15-------开漏输出//jtag脚需要关闭
**********************************/
u8 DHT11_Init(void)//初始化DHT11
{
    
    
	GPIO_InitTypeDef  GPIO_InitStructure;//定义一个结构体的变量
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//初始化GPIOA端口的时钟
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_OD;//通用开漏输出
	GPIO_Init(GPIOA,&GPIO_InitStructure );
	DHT11_Start();  //复位DHT11
	return DHT11_Check();//等待DHT11的回应
}

Otra solución es utilizar el modo de salida push-pull, cambiar al obtener el estado GPIO y cambiar el GPIOA15 de nuevo al modo de entrada. ¿Por qué necesita cambiar de modo cuando usa el modo push-pull? Esto se debe a que, en el modo de salida push-pull, GPIOA15 emite 0 o 1. Solo es posible cambiar los modos de entrada y salida de GPIO continuamente durante el proceso.
El código de inicialización para este método es el siguiente:

//PA11
#define DHT11_IO_IN()  {
    
    GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=8<<15;}//切换为输入模式
#define DHT11_IO_OUT() {
    
    GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=3<<15;} //切换为输出模式
//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在    	 
u8 DHT11_Init(void)
{
    
    	 
 	GPIO_InitTypeDef  GPIO_InitStructure;	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 //使能PA端口时钟
 	GPIO_InitStructure.GPIO_Pin = DT;				 //PA15端口配置
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);				 //初始化IO口
 	GPIO_SetBits(GPIOA,DT);						 //PG11 输出高
			    
	DHT11_Rst();  //复位DHT11
	return DHT11_Check();//等待DHT11的回应
} 
//需要注意,使用此法时,上面的通讯流程代码都要稍作修改,代码太多了,这里就不贴出来了。

efecto real

Después de la inicialización de la llamada a la función principal, la temperatura y la humedad se pueden obtener normalmente.
inserte la descripción de la imagen aquí
Cabe señalar que la tasa de muestreo de DHT11 en el mercado es diferente debido a los diferentes fabricantes. Algunos módulos pueden recopilar 100 veces por segundo, pero algunos módulos solo pueden recopilar 2 veces por segundo. El intervalo de tiempo de una sola adquisición es inferior a esto Habrá caracteres ilegibles en el tiempo.

Resumir

Este documento realiza una simulación de tiempo del módulo de adquisición de temperatura y humedad DHT11 de uso común. Si hay deficiencias en el artículo, todos son bienvenidos a criticar y corregir.

Supongo que te gusta

Origin blog.csdn.net/qq_41954556/article/details/131355197
Recomendado
Clasificación