Zliczanie czasu trwania impulsu (STM32)

0

Mam przebieg prostokątny pochodzący z detektora przejścia przez 0, potrzebuje zmierzyć czas trwania stanu wysokiego. Wiem, że w przypadku liczników w STM-ie jest opcja „capture”. Próbowałem skonfigurować licznik z wykorzystaniem biblioteki SPL, na początku chciałem rozwiązać to za pomocą przerwania. W przypadku wykrycia zbocza narastającego uruchamiane jest przerwanie a w obsłudze tego przerwania uruchamiany jest licznik. Gdy pojawi się zbocze opadające generowane jest kolejne przerwanie w wyniku, którego licznik jest zatrzymywany, jego wartość jest przekazywana do jakiejś zmiennej a sam licznik jest resetowany i cykl się powtarza. Jednak tu pojawia się problem, ponieważ potrzebuje zsumować czasy trwania 12 stanów wysokich i na postawie tych danych wykonywać dalsze obliczenia, dlatego też nie chciałbym, aby procesor cały czas pracował nad obsługą przerwań. Natomiast wyczytałem, że licznik w trybie "capture" wykonuje całą opisaną przeze mnie operację i wartość licznika zapisuje do odpowiedniego rejestru. Tylko nie wiem jak poprawnie skonfigurować licznik do działania w tym trybie.

przebieg

    int main(void)
    {
            TIM5_Config();
            NVIC_Config ();
            IWDG_ReloadCounter();
     
            RCC_Config();
            RCC_APB1PeriphClockCmd(RCC_APB1PeriphClockCmd, ENABLE);
           
    while(1){      
     
           
    }
    }
    RCC_Config()
    {
            BKP_DeInit();
            // Reset RCC
            RCC_DeInit ();
            // HSI ON
            RCC_HSICmd(ENABLE);
            // Wait for HSI
            while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET){};
     
            FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
            FLASH_SetLatency(FLASH_Latency_2);
       
            RCC_HCLKConfig(RCC_SYSCLK_Div1);
            RCC_PCLK2Config(RCC_HCLK_Div1);
            RCC_PCLK1Config(RCC_HCLK_Div1);
            RCC_HCLKConfig(RCC_SYSCLK_Div1);
            RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
           
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
            RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    }
     
    void IWDG_Config (void) {
            // watchdoga IWGD
            IWDG_WriteAccessCmd (IWDG_WriteAccess_Enable);
            IWDG_SetPrescaler(IWDG_Prescaler_4);            // 40kHz/4 = 10kHz
            IWDG_SetReload(0x28A);                          // 65ms
            IWDG_Enable();                                 
    }
    void TIM5_IRQHandler(void)
                    {
                            TIM_Cmd(TIM5, ENABLE); 
                    }
    void TIM5_Config (void)
    {
            RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
           
            // Ustawienia podstawy czasu TIM5
            TIM_TimeBaseStructure.TIM_Period= 0xFFFF;       //65535
            TIM_TimeBaseStructure.TIM_Prescaler = 23;       // fclk = 72MHz/24 =okolo 3MHz
            TIM_TimeBaseStructure.TIM_ClockDivision = 1;
            TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
            TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
           
                           
            // Zrodlo przerwania kanal 1
            TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);
            TIM_Cmd(TIM5,ENABLE);
                   
            // TIM5_CH1, Rising edge, no filter
            TIM_TIxExternalClockConfig(TIM5, TIM_TIxExternalCLK1Source_TI1, TIM_ICPolarity_Rising, 0x00);
            TIM5_ICInitStructure.TIM_Channel=TIM_Channel_1;
            TIM5_ICInitStructure.TIM_ICFilter=0;                           
            TIM5_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
            TIM5_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;   
            TIM5_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;
           
            TIM_ICInit(TIM5, &TIM5_ICInitStructure);
    }
     
    void NVIC_Config (void)
    {
            NVIC_InitStructure.NVIC_IRQChannel=TIM5_IRQn;
            NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
            NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1;                      
            NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
            NVIC_Init(&NVIC_InitStructure);
    }
0
  1. To co wkleiłeś, to chyba jakiś zlepek przypadkowego kodu znalezionego w sieci, skoro najpierw konfigurujesz peryferia, a potem zegar do nich;
  2. SPL jest bardzo starym API bez aktualnego wsparcia ze strony ST, więc proponuję poczytać o HAL, oraz narzędziu STM32CubeMX;
  3. Nie napisałeś jaki dokładnie to procesor, a nawet w przypadku timerów są różnice pomiędzy poszczególnymi rodzinami;
  4. Nie wiemy nic o sygnale, który chcesz mierzyć, jaki jest zakres jego częstotliwości, jakie jest wypełnienie? Czy jest zmienne?
  5. Czy możesz wybrać dowolny pin, timer do realizacji tego zadania?
0

Procesor to STM32F103F103RET, jeżeli chodzi o timer, to mogę wykorzystać dowolny. Z określeniem parametrów sygnału wejściowego dla procesora będzie problem póki, co (może uda mi się odszukać jakąś dokumentację), ponieważ (nie wiem, w jaki sposób lub w jakim celu) ktoś zdarł spory fragment naklejki z obudowy detektora przejścia przez zero. Został jedynie niewielki kawałek takiej złotawej folii z częścią jednego znaku, ale to nie jest nijak pomocna informacja. Sygnał z detektora trafia na wejście zewnętrznego licznika (D71054 C-10), z podłączonym zewnętrznym zegarem 3 MHz. W momencie pojawienia na jednym z wejść sygnału - „GC” uruchamiany jest pierwszy licznik. Równolegle do drugiego wejścia licznika podawany jest inny sygnał - „GB”. W monecie, gdy GB=1 uruchamiany jest drugi licznik, który działa do czasu aż GB =0 i na podstawie ilości zliczonych impulsów obliczany jest czas „t”. Natomiast pierwszy licznik (uruchomiony, gdy GC=1), zlicza do czasu zebrania 12 wyników „t”. Tak, więc na początku tematu źle napisałem, że wartość „T” to jest sumą 12 czasów „t”, gdzie „t” jest czasem trwania pojedynczej logicznej „1” pochodzącej z detektora. „T” jest to całkowitym czasem potrzebnym do uzyskania 12 wyników „t”.

0

Teraz to już nie rozumiem co właściwie masz mierzyć. W każdym razie wydaje mi się, że w Twoim przypadku powinieneś skorzystać z trybu PWM input mode.

1 użytkowników online, w tym zalogowanych: 0, gości: 1