102 lines
2.2 KiB
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);
|
|
}
|