Below is code that will work to communicate with a DHT11 humidity sensor. The code is only for the humidity integer value. I don't measure the temperature or checksum, but this can easily be done by expanding the number of bits read.

I found that certain routines, like the for/next that some people have used, probably don't run fast enough with a 4MHz clock. 20MHz works well. Using a different scheme I can read the DHT11 with a 4MHz clock.

Also remember that pulsin doesn't measure in usec but rather in increments of microseconds depending on the clock speed. For example, at 4MHz each count on pulsin represents 10usec. So a count of 7 is actually 7 x 10 = 70usec. Likewise for 8MHz it is 8usec/count (7 x 8usec = 56usec) and at 20MHz is is 2usec/count (7 x 2usec = 14usec). Similarly, at 20MHz to read 70usec you need 70/2 = 35 counts, tho I'd look for >=30 counts to give some leeway.




'************************************************* ***************
'* Name : DHT11_test.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2015 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 3/28/2015 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************

'
' PIC16F688
'
' Running at 20MHz but code also shown for 4MHz
'
' The configuration bits for the 16F688 I set in MPLAB manually. Depedning on your processor you will have to
' determine and set your own bits.
'



DEFINE OSC 20 '20 MHz clock frequency, need a fast clock for this to work best
define HSER_RCSTA 90h 'enable the serial port receiver
define HSER_TXSTA 24h 'set up the serial port, enable transmit for fast clock
define HSER_BAUD 9600 'select the baud rate, run slow for the RF xmitter
define HSER_CLROERR 1 'automatically clear the buffer overrun error


i var byte
rhdata var byte
hum var byte[8]
humidity var byte 'humidity data byte
humid var byte

dbit0 var byte
dbit1 var byte
dbit2 var byte
dbit3 var byte
dbit4 var byte
dbit5 var byte
dbit6 var byte
dbit7 var byte

togl var portc.0 'not used except to add delay
rhpin var portc.2 'relativity sensor data bit
TxD var portc.4 'transmitted data
RxD var portc.5 'received data

CMCON0 = %00000111 'comparator off
OSCCON = %01110110 ' external 20 runs at 4 MHz internal clock
ADCON0 = %10000000 'ADC is disabled
ANSEL = %00000000 'all digital
TRISA = %11111111 'set up port A where 1 = input, 0 = output
TRISC = %11101011 'set up port C where 1 = input, 0 = output



'================================================= ================================================== =======================================
'
' This routine below works but needs a clock faster than 4MHz or the For/Next loop isn't fast enough. This might be what is causing
' people consternation if they run at the common 4MHz clock.
'
'
'================================================= ================================================== =======================================

rhpin = 1 'initial condition
pause 2000 'wait for the DHT to start up

mainloop:

trisc.2 = 0 'now set portc.2 (the DHT11 I/O pin) to output mode
rhpin = 0 'set rhpin = portc.2 low
pause 30 'wait 30 msec, must wait at least 18 msec for DHT11 to detect the signal
trisc.2 = 1 'now make portb.2 an input. Since this line is pulled high with an R rhpin becomes high
'rhpin stays high 20-40usec until DHT pulls it low (actually ~13usec measured on scope)

pulsin rhpin, 0, rhdata 'execute an active low pulse measurement
'When the pulse goes back high it stays for 80 usec and goes low followed by data

if rhdata > 50 then goto subloop 'if this takes way over 100 usec then error (50 x 2usec/pulsin count = 100usec)
rhdata = 0 'clear rhdata. Since < 130 usec then get ready for data which will be next low to high

pauseus 30 'delay makes sure the next pulse is a high going data pulse. Probably isn't needed.

For i = 7 To 0 Step -1 '8 bits (1..8)

Pulsin rhpin, 1, rhdata ' receive pulses from sensor. 8 bits of integer part of data come first, ignore rest
If rhdata >= 30 Then ' A "1" is defined for a bit width of 70usec, a "0" for bit width <30 usec.
'Remember, Pulsin counts increments depending on the clock frequency. At 20MHz clock
' frequency 30 rhdata counts => 30 x 2usec = 60usec. Rhdata >= 30 counts == data = 1
hum[i] = 1 ' if >50 usec then logic 1
Else
hum[i] = 0 ' if not >=50 usec then is a 0
endif

next i

pause 500 'not needed, was added during testing for readability of printout

humidity = hum[7]*128+hum[6]*64+ hum[5]*32+hum[4]*16+ hum[3]*8+hum[2]*4+ hum[1]*2+hum[0]*1

hserout ["A", 9, dec3 humidity, 13] 'serial output

pause 2000 ' wait for the rest of the DHT timing



'************************************************* ************************************************** ***************************************
'
'
' The scheme below will work with a 4MHz clock, but the timing number to check dbit is shown for 20MHz. For 4MHz compare dbit
' to 6 not 30.
'
'
'
'************************************************* ************************************************** ***************************************

humid = 0
trisc.2 = 0 'now set portc.2 to output
rhpin = 0 'set rhpin = portc.2 low
pause 30 'wait 30 msec, must wait at least 18 msec for DHT11 to detect the signal
trisc.2 = 1 'make portb.2 an input. Since this line is pulled high with an R rhpin becomes high

toggle togl 'use to add some delay here. Pauseus can't be < 24 usec at 4MHz clock

luupy:
if rhpin = 1 then goto luupy 'wait for the DHT pin to go low then delay until the DHT is ready

pauseus 130 'this delay ignores the first high going DHT pulse for initializaion and instead
' moves ahead to wait for first dat abit high transition.

pulsin rhpin, 1, dbit7 'measure the pulsewidth of the DHT transmitted bit. Low ~ 26-28usec, high ~70usec

pulsin rhpin, 1, dbit6 'measure the pulsewidth of the DHT transmitted bit. Low ~ 26-28usec, high ~70usec

pulsin rhpin, 1, dbit5 'measure the pulsewidth of the DHT transmitted bit. Low ~ 26-28usec, high ~70usec

pulsin rhpin, 1, dbit4 'measure the pulsewidth of the DHT transmitted bit. Low ~ 26-28usec, high ~70usec

pulsin rhpin, 1, dbit3 'measure the pulsewidth of the DHT transmitted bit. Low ~ 26-28usec, high ~70usec

pulsin rhpin, 1, dbit2 'measure the pulsewidth of the DHT transmitted bit. Low ~ 26-28usec, high ~70usec

pulsin rhpin, 1, dbit1 'measure the pulsewidth of the DHT transmitted bit. Low ~ 26-28usec, high ~70usec

pulsin rhpin, 1, dbit0 'measure the pulsewidth of the DHT transmitted bit. Low ~ 26-28usec, high ~70usec



hserout [13] 'the dbits can be printed if desired. This is used to check the data. Not needed.
hserout ["C", 9, dec2 dbit6, 9, dec2 dbit5, 9, dec2 dbit4, 9, dec2 dbit3, 9, dec2 dbit2, 9, dec2 dbit1, 9, dec2 dbit0, 13] 'optional


'100% humidity = 0110 0100. Don't need to add bit 7
if dbit6 >= 30 then 'check each bit to see if greater than 60 usec (30 x 2usec). If so the bit is a 1 so
humid = 64 ' add its decimal equivalent to the humidity byte to get he rh value
endif
if dbit5 >= 30 then
humid = humid + 32 'NOTE: if using 4MHz clock then test dbit for >=6 (6 x 10usec/pulsin count = 60 usec)
endif
if dbit4 >= 30 then
humid = humid + 16
endif
if dbit3 >= 30 then
humid = humid + 8
endif
if dbit2 >= 30 then
humid = humid + 4
endif
if dbit1 >= 30 then
humid = humid + 2
endif
if dbit0 >= 30 then
humid = humid + 1 'at this point the humid value is the humidity value
endif


hserout ["D", 9, dec3 humid, 13] 'serial output
hserout [13] 'linefeed for better output readability. This isn't needed.

pause 2000 'need to wait at least a second before repeating this data read sequence


GoTo mainloop



subloop:
hserout ["Sensor not ready", 13]
GoTo mainloop

end