#include "main.h" #include "generic_macros.h" #include "lcd.h" #include "DHT11.h" extern TIM_HandleTypeDef htim2; static inline void wait(uint32_t wait_us) { uint32_t target_time = TIM2->CNT; target_time += wait_us << 4; while (TIM2->CNT < target_time) {} } static inline size_t dht11_measure_high_duration(void) { SKIP_LOW; uint32_t start_time = TIM2->CNT; SKIP_HIGH; uint32_t end_time = TIM2->CNT; // elapsed_time > 49us ? 1 : 0 return (end_time - start_time) > (49 << 4); } static size_t dht11_read_value(struct DHT11_Data *data) { // treat data as a normal array to simplify read loop uint8_t *buffer = (uint8_t *) data; register uint32_t read_register = 0; TIM2->CNT = 0; HAL_TIM_Base_Start(&htim2); GPIOD->MODER |= 0x00400000; // enable output mode on GPIOD 11 GPIOD->BSRR = GPIO_PIN_11; // enable DHT11 wait(50000); // hold HIGH for 50 ms GPIOD->BSRR = GPIO_PIN_11 << 16; // start signal wait(30000); // hold it for 30 ms GPIOD->BSRR = GPIO_PIN_11; // pull up, DHT will now take control over the connection wait(100); GPIOD->MODER &= 0xFF3FFFFF; // switch GPIOD 11 to input mode // reading pull down from DHT11 SKIP_LOW; // waiting for 500ms max for (size_t i = TIM2->CNT + (500000 << 4); TIM2->CNT <= i; ) if (!(GPIOD->IDR & 0x0800)) goto reading_data; // if didn't exit through goto, then DHT11 awaiting has timed out return 1; reading_data: // read 5 bytes of data for (size_t i = 0; i < 5; i++) { for (register size_t j = 0; j < 8; j++) { read_register <<= 1; read_register |= dht11_measure_high_duration(); } buffer[i] = (uint8_t) read_register; } HAL_TIM_Base_Stop(&htim2); return 0; } int DHT11_run_test(void) { DISPLAY_CLEAR; display_write_data_seq("DHT11 Temp+Humid"); struct DHT11_Data data; size_t result = dht11_read_value(&data); size_t checksum_mismatch = (( data.humid_decimal + data.humid_integral + data.temp_decimal + data.temp_integral ) & 0xFF) != data.crc; if (result) { DISPLAY_SET_CURSOR(1, 4); display_write_data_seq("StartTimeout"); } else if (checksum_mismatch) { DISPLAY_SET_CURSOR(1, 4); display_write_data_seq("CRC Fault"); } else { DISPLAY_SET_CURSOR(1, 4); display_write_data_seq("OK"); DISPLAY_SET_CURSOR(1, 7); display_write_data_byte('0' + (data.humid_integral/10)%10); display_write_data_byte('0' + (data.humid_integral)%10); display_write_data_seq("% "); display_write_data_byte('0' + (data.temp_integral/10)%10); display_write_data_byte('0' + (data.temp_integral)%10); display_write_data_byte('.'); display_write_data_byte('0' + data.temp_decimal); display_write_data_seq("C"); } return (result || checksum_mismatch); }