ak-kr-project/Core/Src/dht11.c

102 lines
2.2 KiB
C

#include "main.h"
#include "generic_macros.h"
#include "dht11.h"
static struct SysTickConfig stc;
static uint32_t *systick_base = (uint32_t *) SysTick_BASE;
static void wait(uint32_t wait_us)
{
int target_time = *(systick_base+8);
target_time -= wait_us << 4;
while (*(systick_base+8) > target_time) {}
}
static void dht11_save_systick_state(void)
{
stc.ctrl = *(systick_base + 0);
stc.load = *(systick_base + 4);
stc.val = *(systick_base + 8);
}
static void dht11_load_systick_state(void)
{
*(systick_base + 4) = stc.load;
*(systick_base + 8) = stc.val;
*(systick_base + 0) = stc.ctrl;
}
static void dht11_init_systick(void)
{
dht11_save_systick_state();
*(systick_base + 0) = 0x5; // disable /8 prescaler, no interrupts, enable counting
*(systick_base + 4) = 0xFFFFFF; // load largest possible value
// verify value load
if (*(systick_base + 8) == 0)
PANIC(0x4000);
}
static size_t dht11_measure_high_duration(void)
{
int current_time = *(systick_base+8);
SKIP_HIGH;
// elapsed_time > 49us ? 1 : 0
return (current_time - *(systick_base+8)) > (49 << 4);
}
static void dht11_read_value(struct DHT11_Data *data)
{
dht11_init_systick();
register uint8_t read_register = 0;
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
// switch GPIOD 11 to input mode
GPIOD->MODER &= 0xFF3FFFFF;
// read transmission start sequence from DHT11
SKIP_HIGH;
SKIP_LOW;
SKIP_HIGH;
// read humidity integral
FILL_REGISTER;
data->humid_integral = read_register;
// read humidity decimal
FILL_REGISTER;
data->humid_decimal = read_register;
// read temperature integral
FILL_REGISTER;
data->temp_integral = read_register;
// read temperature decimal
FILL_REGISTER;
data->temp_decimal = read_register;
// read crc
FILL_REGISTER;
data->crc = read_register;
// switch GPIOD 11 back to output mode
GPIOD->MODER |= 0x00900000;
dht11_load_systick_state();
}
void dht11_show_both(void)
{
struct DHT11_Data data;
dht11_read_value(&data);
}