Yo me estoy basando en lo que es una comunicacion de 2 vias por un mismo canal, el cual tenes que tener protecciones, y la forma de hacerlo es tener salidas open-colector. Sino mira el I2C, en el que si ambos dispositivos activan al mismo tiempo no exista problemas. En eso me estoy basando. Voy a explicar nuevamente como seria el funcionamiento.
Saludos:Si te fijas en el link que envio palitroquez muy amablemente ,la linea en color rojo es enviada por el pic y hay un pulso de 20 a 40us alto.
Voy a copiar la imagen y voy a explicar el por que lo que asumo es verdad..

Justamente esa imagen corresponde al paso 2 (lo del PIC) y paso 3 que te dije yo.
Lo que estoy diciendo yo es que por mas que vos pongas tu PORTA,0 en 1 o lo pases como entrada, vas a tener SI o SI 5V en el bus de datos. Nomas que con el PIC vas a "eliminar" el efecto del pull-up, ya que estarias uniendo directo el canal de datos con VCC sin resistencia de por medio.
El circuito equivalente (del sensor y micro) seria asi:

Analicemos lo que yo digo ( Pensa nuevamente los transistores como llaves ).
- El Q del DHT11 esta abierto, es decir no hay paso. y el Q del PIC tampoco (como entrada, abierto). Por lo tanto la tension en el bus de datos es 5V.
- Comienza conduciendo el Q del pic, conectando la linea de datos a GND, para darle el pulso inciial de 18ms por eso tenes un 0 en la linea de datos.
- Aca tenes 2 opciones, pasarlo a entrada, o ponerlo en salida y en 1. Veamos la direfenrencia:
Salida: Si pones en salida, y en 1, la linea de bus de datos va a tener 5V, por que se va a cerrar el transistor que no dibuje del PIC, el cual va a unir la linea de datos con VCC.
Entrada: este se vuelve alta impedancia , es decir que se abre el Qpic. Por lo tanto la linea de datos no posee "conexion" a GND, y el unico voltaje es VCC a traves de la resistencia de pull-up, que como no hay corriente no hay caida de tension, por lo tanto queda con la misma tension de VCC ( la linea de datos ).
Entonces sigo sin comprender por que uno es distinto de otro cuando ambos tienen VCC en su salida.
Es interesante ademas ver como la persona que explica en español omite esa parte:
El microcontrolador debe iniciar la comunicación con el DHT11 manteniendo la linea de datos en estado bajo durante al menos 18 ms. (Aca parte faltante) Luego el DHT11 envía una respuesta con un pulso a nivel bajo de 80 uS y luego deja “flotar” la linea de datos por otros 80 uS
No dice nada de ponerlo a 1 ni pasarlo a entrada. Simplemente omite esa explicacion.
En el PDF que pase yo te lo voy a traducir:
Microprocessor I / O set to output at the same time output low, and low hold time can not be less than 18ms, then the microprocessor I / O is set to input state, due to the pull-up resistor, a microprocessor/ O DHT11 the dATA data lines also will be high
"El microcontrolador cambia el pin a salida, al mismo tiempo lo pone en bajo ( a 0 ), y mantiene ese pin en bajo por un tiempo no menor a 18ms, entonces el microcontrolador cambia el pin a entrada, que debido a la resistencia de pull-up la linea de datos del microcontrolador y del DHT11 va a estar en alto."Y esto esta por fuera de todo lo que se podria llamar funcionamiento del DHT, la explicacion del pull-up es electronica basica. Y no posee relacion directa con como leer el sensor u otra cosa. Estamos hablando de tener 5V o no en la linea de datos, y con ambas soluciones se logra, poniendo a 1 la salida o poniendolo como entrada. Y no hay forma para el DHT11 discriminar su los 5V provienen del PIC o de la resistencia de pull-up.
Mirando un par de codigos de librerias estan poniendo la salida a 5V, justamente como yo estoy evitando. Me parece absurdo que se haga esto.
Algunos como los del link en español que paso PalitroqueZ hacen esto:
dhtlib_outhi();
dhtlib_setin(); // Turn pin to input
Es decir, lo ponen a 1, y ahi nomas lo ponen como entrada. Como dandole un pulsito. ( pulsito que no tiene sentido gracias a la resistencia de pull-up y lo que explique antes).
Este "metodo"
si todo funciona bien no habria problemas. ya que es un pulsito muy muy pequeño comparado con los 28 a 40us que dice el pulso alto ( lo cual no correria riesgo de cortocircuito )
Buscando en Adafruit me encuentro con otro PEOR, en todo sentido de aplicacion, realmente estos tipos esta muy locos:
// First set data line low for 20 milliseconds.
pinMode(_pin, OUTPUT);
digitalWrite(_pin, LOW);
delay(20);
// End the start signal by setting data line high for 40 microseconds.
digitalWrite(_pin, HIGH);
delayMicroseconds(40);
// Now start reading the data line to get the value from the DHT sensor.
pinMode(_pin, INPUT_PULLUP);
Donde mantiene 40us el pin en alto, que supuestamente son 20 a 40 us, si es que el DHT11 se le ocurre a los 30us poner la salida a 0 es un cortocircito!. Esto no tiene explicacion realmente.
Finalmente:Pero si queres agregarle el BSF y ver si funciona, pero para mi seria lo mismo (5V serian lo mismo desde donde vengan), hagamos la del articulo que paso PalitroqueZ. Aca le agrego el BSF y que sea momentaneo, es decir un pequeño pulsito nada mas. Tal y cual esta la otra libreria funcionando.
list p=16F877 ;Se indica el modo de procesador
radix hex
W EQU 0
F EQU 1
STATUS EQU 0x03
C EQU 0
Z EQU 2
RP0 EQU 5
PORTA EQU 0x05
PORTB EQU 0x06
PORTC EQU 0x07
PORTD EQU 0x08
TRISA EQU 0x85
TRISB EQU 0x86
TRISC EQU 0x87
TRISD EQU 0x88
ADCON1 EQU 0X9F
d1 equ 0x20
d2 equ 0x21
d3 equ 0x22
reg1 equ 0x23
reg2 equ 0x24
Checksum equ 0x25
TempDecimal equ 0x26
TempEntero equ 0x27
HumEntero equ 0x28
HumDecimal equ 0x29
CantidadBits equ 0x30
;----------------------------------------------------------------------------
ORG 0x00 ;vector de inicio
GOTO Setup
ORG 0x04
RETURN
Setup:
BSF STATUS, RP0
MOVLW 0x06 ;Puerto A en modo digital
MOVWF ADCON1
MOVLW b'000001' ; RA0 entrada
MOVWF TRISA
CLRF TRISB
CLRF TRISC
CLRF TRISD ;
CLRF TRISE
BCF STATUS, RP0
CLRF PORTA
CLRF PORTB
CLRF PORTC
CLRF PORTD
CLRF PORTE
Main:
CALL Delay_1s
CALL Leer_DHT
CALL Checkear_datos
ANDLW 0xFF
BTFSS STATUS, Z
GOTO Mal_dato
BCF PORTB, 0
MOVF TempEntero, W
MOVWF PORTD
MOVF HumEntero, W
MOVWF PORTC
GOTO Main
Mal_dato:
BSF PORTB, 0
GOTO Main
Leer_DHT:
CLRF TempEntero
CLRF TempDecimal
CLRF HumEntero
CLRF HumDecimal
CLRF Checksum
MOVLW .40
MOVWF CantidadBits
; Aca enviar pulso inicial ( poner como salida, y luego a 0 por un tiempo, luego pasarlo a entrada )
BSF STATUS, RP0
BCF TRISA, 0 ; Salida
BCF STATUS, RP0
BCF PORTA, 0 ; Pongo un 0 en caso que no lo hubiera tenido
CALL Delay_80us ; Espero los 80us necesarios
BSF PORTA, 0
BSF STATUS, RP0
BSF TRISA, 0 ; Entrada nuevamente
BCF STATUS, RP0
; Agregar aca la espera del primer pulso de respuesta que no forma parte de los bits.
BTFSC PORTA, 0 ; Espero que llegue el 0, desde el DHT11
GOTO $-1
BTFSS PORTA, 0 ; Estoy en 0, Espero que se ponga en 1 el DHT11
GOTO $-1
; Ahora comienzo a recibir bit a bit
Loop:
BTFSC PORTA, 0 ; Espero que llegue el 0
GOTO $-1
BTFSS PORTA, 0 ; Estoy en 0, Espero que se ponga en 1
GOTO $-1
CALL Delay35us ; Luego del delay pasan como maximo 17 ciclos hasta que vuelve a preguntar de nuevo, lo cual estaria dentro del rango de las 20 instrucciones para 4Mhz
BTFSS PORTA, 0
GOTO Es_cero
Es_uno:
; Si llego aca es 1
BSF Checksum, 0 ; Observa que no uso INCF, sino que directamente pongo a 1 o 0 el bit
GOTO Rotar
Es_cero:
; Si llego aca es 0
BCF Checksum, 0
Rotar:
DECF CantidadBits, F ; Decremento la cantidad de bits restantes, cuando llega a 0 salgo, sino roto el valor, al rotar lo trato como un numero completo de 40 bits
BTFSC STATUS,Z
RETURN
RLF Checksum, F ; Cuando roto por primera vez (en Checksum) el carry puede tener cualquier valor
RLF TempDecimal, F ; pero no importa por que en la proxima pasada sobreescribo ese bit con BSF y BCF, los demas carrys son necesarios
RLF TempEntero, F
RLF HumDecimal, F
RLF HumEntero, F
GOTO Loop
; Si W = 0 indica que esta todo bien, sino borra todo por que el dato es malo.
; Esto es para comprobar con el que llama
Checkear_datos:
MOVF HumEntero, W
ADDWF HumDecimal, W
ADDWF TempEntero, W
ADDWF TempDecimal, W
XORWF Checksum, W
BTFSC STATUS, Z
RETURN ;W = 0
Mal_Checksum:
CLRF TempEntero
CLRF TempDecimal
CLRF HumEntero
CLRF HumDecimal
CLRF Checksum
RETURN ;W =/= 0
end
; ******************************************************************
;
; Delays
;
; ******************************************************************
; Delay = 1 seconds
; Clock frequency = 4 MHz
; Actual delay = 1 seconds = 1000000 cycles
; Error = 0 %
Delay_1s
;999990 cycles
movlw 0x07
movwf d1
movlw 0x2F
movwf d2
movlw 0x03
movwf d3
Delay_1s_0
decfsz d1, f
goto $+2
decfsz d2, f
goto $+2
decfsz d3, f
goto Delay_1s_0
;6 cycles
goto $+1
goto $+1
goto $+1
;4 cycles (including call)
return
; Delay = 80 instruction cycles
; Clock frequency = 4 MHz
; Actual delay = 8e-005 seconds = 80 cycles
; Error = 0 %
Delay_80us
;76 cycles
movlw 0x19
movwf d1
Delay_80us_0
decfsz d1, f
goto Delay_80us_0
;4 cycles (including call)
return
; Delay = 35 instruction cycles
; Clock frequency = 4 MHz
; Actual delay = 3.5e-005 seconds = 35 cycles
; Error = 0 %
Delay_35us
;31 cycles
movlw 0x0A
movwf d1
Delay_35us_0
decfsz d1, f
goto Delay_35us_0
;4 cycles (including call)
return