/** the bit number being sent (MSb first), up to 40 */
volatileuint8_tsensor_dht11_bit=0;
/** the 40 bits (5 bytes) being sent by the device */
volatileuint8_tsensor_dht11_bits[5]={0};
/** reset all states */
staticvoidsensor_dht11_reset(void)
{
// reset states
sensor_dht11_state=SENSOR_DHT11_OFF;
sensor_dht11_bit=0;
sensor_dht11_measurement_received=false;
gpio_set(TIM_CH_PORT(SENSOR_DHT11_TIMER,SENSOR_DHT11_CHANNEL),TIM_CH_PIN(SENSOR_DHT11_TIMER,SENSOR_DHT11_CHANNEL));// idle is high (using pull-up resistor), pull-up before setting as output else the signal will be low for short
gpio_set_mode(TIM_CH_PORT(SENSOR_DHT11_TIMER,SENSOR_DHT11_CHANNEL),GPIO_MODE_OUTPUT_2_MHZ,GPIO_CNF_OUTPUT_OPENDRAIN,TIM_CH_PIN(SENSOR_DHT11_TIMER,SENSOR_DHT11_CHANNEL));// setup GPIO pin as output (host starts communication before slave replies)
timer_ic_disable(TIM(SENSOR_DHT11_TIMER),TIM_IC(SENSOR_DHT11_CHANNEL));// enable capture interrupt only when receiving data
// setup timer to measure signal timing for bit decoding (use timer channel as input capture)
rcc_periph_clock_enable(RCC_TIM_CH(SENSOR_DHT11_TIMER,SENSOR_DHT11_CHANNEL));// enable clock for GPIO peripheral
rcc_periph_clock_enable(RCC_TIM(SENSOR_DHT11_TIMER));// enable clock for timer peripheral
timer_reset(TIM(SENSOR_DHT11_TIMER));// reset timer state
timer_set_mode(TIM(SENSOR_DHT11_TIMER),TIM_CR1_CKD_CK_INT,TIM_CR1_CMS_EDGE,TIM_CR1_DIR_UP);// set timer mode, use undivided timer clock,edge alignment (simple count), and count up
timer_set_prescaler(TIM(SENSOR_DHT11_TIMER),20-1);// set the prescaler so this 16 bits timer allows to wait for 18 ms for the start signal ( 1/(72E6/20/(2**16))=18.20ms )
timer_ic_set_input(TIM(SENSOR_DHT11_TIMER),TIM_IC(SENSOR_DHT11_CHANNEL),TIM_IC_IN_TI(SENSOR_DHT11_CHANNEL));// configure ICx to use TIn
timer_ic_set_filter(TIM(SENSOR_DHT11_TIMER),TIM_IC(SENSOR_DHT11_CHANNEL),TIM_IC_OFF);// use no filter input (precise timing needed)
timer_ic_set_polarity(TIM(SENSOR_DHT11_TIMER),TIM_IC(SENSOR_DHT11_CHANNEL),TIM_IC_FALLING);// capture on rising edge
timer_ic_set_prescaler(TIM(SENSOR_DHT11_TIMER),TIM_IC(SENSOR_DHT11_CHANNEL),TIM_IC_PSC_OFF);// don't use any prescaler since we want to capture every pulse
timer_clear_flag(TIM(SENSOR_DHT11_TIMER),TIM_SR_UIF);// clear flag
timer_update_on_overflow(TIM(SENSOR_DHT11_TIMER));// only use counter overflow as UEV source (use overflow as start time or timeout)
timer_enable_irq(TIM(SENSOR_DHT11_TIMER),TIM_DIER_UIE);// enable update interrupt for timer
timer_clear_flag(TIM(SENSOR_DHT11_TIMER),TIM_SR_CCIF(SENSOR_DHT11_CHANNEL));// clear input compare flag
nvic_enable_irq(NVIC_TIM_IRQ(SENSOR_DHT11_TIMER));// catch interrupt in service routine
sensor_dht11_reset();// reset state
}
boolsensor_dht11_measurement_request(void)
{
if(sensor_dht11_state!=SENSOR_DHT11_OFF){// not the right state to start (wait up until timeout to reset state)
returnfalse;
}
if(gpio_get(TIM_CH_PORT(SENSOR_DHT11_TIMER,SENSOR_DHT11_CHANNEL),TIM_CH_PIN(SENSOR_DHT11_TIMER,SENSOR_DHT11_CHANNEL))==0){// signal should be high per default
if((uint8_t)(sensor_dht11_bits[0]+sensor_dht11_bits[1]+sensor_dht11_bits[2]+sensor_dht11_bits[3])!=sensor_dht11_bits[4]){// error in checksum (not really parity bit, as mentioned in the datasheet)
timer_clear_flag(TIM(SENSOR_DHT11_TIMER),TIM_SR_UIF);// clear flag
if(sensor_dht11_state==SENSOR_DHT11_HOST_START){// start signal sent
gpio_set_mode(TIM_CH_PORT(SENSOR_DHT11_TIMER,SENSOR_DHT11_CHANNEL),GPIO_MODE_INPUT,GPIO_CNF_INPUT_FLOAT,TIM_CH_PIN(SENSOR_DHT11_TIMER,SENSOR_DHT11_CHANNEL));// switch pin to input (the external pull up with also set the signal high)
sensor_dht11_state=SENSOR_DHT11_HOST_STARTED;// switch to next state
timer_ic_enable(TIM(SENSOR_DHT11_TIMER),TIM_IC(SENSOR_DHT11_CHANNEL));// enable capture interrupt only when receiving data
}else{// timeout occurred
sensor_dht11_reset();// reset states
}
}elseif(timer_get_flag(TIM(SENSOR_DHT11_TIMER),TIM_SR_CCIF(SENSOR_DHT11_CHANNEL))){// edge detected on input capture
uint16_ttime=TIM_CCR(SENSOR_DHT11_TIMER,SENSOR_DHT11_CHANNEL);// save captured bit timing (this clear also the flag)