Kolejna sprawa

dwa dni się męczę już

Chcę zrobić komunikację z czujnikiem DTH11. I mam problem.
Czujnik podpięty do GPIO2. Po tych 18ms GPIO konfiguruję jako wejście i przerwanie od zboczy (obojętnie jakiego), w callbacku z przerwania sprawdzam jakie zbocze i zliczam czas od poprzedniego wystąpienia zbocza, wówczas mam dwa czasy l_time i h_time odpowiadające czasom trwania poszczególnych poziomów.
Za zliczanie czasu odpowiada "wewnętrzny" zegar a odczytuję go funkcją system_get_time();
Poniżej nieco kodu, przepraszam za bałagan ale już próbowałem tylko na zboczach opadających lub tylko rosnących i kod może być nieco chaotyczny ale zależało mi żeby odebrać dane a potem się dopisuje

Kod: Zaznacz cały
// struktura na dane wykorzystywane w funkcji
typedef struct
{
uint8 temp_H;
uint8 temp_L;
uint8 humi_H;
uint8 humi_L;
uint8 pos;
uint32 buff;
} T_dht11;
// Funkcja wyzwaljąca odczyt
void ICACHE_FLASH_ATTR
get_dth11(void)
{
dht11Data.pos = 0;
os_timer_disarm( &timer_dth11 );
os_timer_setfn( &timer_dth11, dht11_timer, 0 );
os_timer_arm( &timer_dth11, 18, 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);
GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 0);
}
// Callback do timera programowego
void ICACHE_FLASH_ATTR
dht11_timer(void* arg)
{
// GPIO jako wejscie
GPIO_DIS_OUTPUT( GPIO_ID_PIN(2) );
// przerwanie od przerwania (callback)
ETS_GPIO_INTR_DISABLE();
ETS_GPIO_INTR_ATTACH( gpio_interrupt_handle, 0 );
gpio_pin_intr_state_set( GPIO_ID_PIN(2), GPIO_PIN_INTR_ANYEDGE);
ETS_GPIO_INTR_ENABLE();
}
// Callback przerwania czyli odbieranie danych
void ICACHE_FLASH_ATTR
gpio_interrupt_handle(void)
{
uint8 h_time, l_time;
static uint32 lasttime;
uint32 tmptime;
uint16 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status);
if( gpio_status & BIT(2) )
{
tmptime = system_get_time();
if( GPIO_INPUT_GET( BIT(2) ))
{
// narastające
l_time = tmptime - lasttime;
} else {
// opadające
h_time = tmptime - lasttime;
}
lasttime = tmptime;
// poczatek bitu (stan niski około 50us)
if ( l_time > 40 && l_time < 60 )
{
dht11Data.pos++;
dht11Data.buff = (dht11Data.buff << 1);
os_printf(" NB ");
}
if( dht11Data.pos )
{
// bit 0 (jesli stan wysoki około 20us)
if( h_time > 18 && h_time < 30 )
{
os_printf("0:[%d] ", dht11Data.pos);
}
// bit 1 (jeśli stan wysoki około 70us)
if ( h_time > 62 && h_time < 78 )
{
dht11Data.buff |= 1;
os_printf("1:[%d] ", dht11Data.pos);
}
}
// odebranie "sygnału startowego" około 80 us po nim lecą już bity z danymi
if( !dht11Data.pos && h_time > 80 && h_time < 93)
{
dht11Data.pos = 1;
dht11Data.buff = 0;
os_printf("\n\rSYNC: ");
}
}Teraz to dostaję, problem w tym że nie to co bym chciał

Kod powyżej generuje w terminalu coś podobnego do tego:
SYNC: 0:[1] 0:[1] 1:[1] 0:[1] 0:[1] 1:[1] 0:[1] 0:[1] 0:[1] 0:[1] 0:[1] 0:[1] 0:[1] 0:[1] 0:[1] 0:[1] 0:[1] 0:[1] 0:[1] 1:[1] 1:[1] 0:[1] 0:[1] 0:[1] 0:[1] 0:[1] 1:[1]
W nawiasie klamrowym [] jest 1 czyli wartość dht11Data.pos która powinna się zwiększać po każdym bicie, to co jest przed nawiasem to odczytany stan 0 lub 1 jak widać coś tam zlatuje ale zamiast 40 bitów jest 27 czasami 30. Czyli część danych wysyłanych przez czujnik"przepada".
Na funkcje udostępniane przez SDK nie mam wpływu a w dokumentacji też nie znalazłem informacji czy system_get_time() jest "atomowe" tzn może jakieś "wewnętrzne" procesy ESP mają wpływ na wynik tej funkcji albo na przebieg przerwań.
W necie szukałem ale większość dostępnych materiałów dla ESP8266 to Arduino albo LUA, czyste C czyli NONOS albo RTOS jest stosunkowo mało

PS. pozwoliłem sobie edytować post i dodać więcej światła (kodu).