Reciprocal Frequency counter only for STM32F401、F411 and F466. Reciprocal Mode -> Pulse width measurement

Dependents:   Frequency_Counter_Recipro_for_STM32F4xx

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fc_recipro.cpp Source File

fc_recipro.cpp

00001 /*
00002  * mbed Library / Frequency Counter / Recipro type
00003  *      Frequency Counter program
00004  *      Only for Nucleo-F401RE,-F411RE,-F446RE
00005  *
00006  * Copyright (c) 2014,'15,'16,'20 Kenji Arai / JH1PJL
00007  *      http://www7b.biglobe.ne.jp/~kenjia/
00008  *      https://os.mbed.com/users/kenjiArai/
00009  *      Started:    October   18th, 2014
00010  *      Revised:    January   19th, 2020
00011  */
00012 
00013 #include    "fc_recipro.h"
00014 
00015 #if (MBED_MAJOR_VERSION == 2)
00016 #   define WAIT(x) wait_ms(x)
00017 #elif (MBED_MAJOR_VERSION == 5)
00018 #   define WAIT(x) ThisThread::sleep_for(x)
00019 #endif
00020 
00021 #if DEBUG
00022 #define PRINTF(...)     printf(__VA_ARGS__)
00023 #define SET0            {tstp0=1;}
00024 #define CLR0            {tstp0=0;}
00025 #define SET1            {tstp1=1;}
00026 #define CLR1            {tstp1=0;}
00027 #define SET2            {tstp2=1;}
00028 #define CLR2            {tstp2=0;}
00029 #else
00030 #define PRINTF(...)     {;}
00031 #define SET0            {;}
00032 #define CLR0            {;}
00033 #define SET1            {;}
00034 #define CLR1            {;}
00035 #define SET2            {;}
00036 #define CLR2            {;}
00037 #endif
00038 
00039 typedef union {
00040     struct {
00041         int64_t    f_64bit_dt;  // not uint but int
00042     };
00043     struct {
00044         uint32_t    freq_dt;
00045         int32_t     f_sw_dt;    // not uint but int
00046     };
00047 } freq_one;
00048 
00049 namespace Frequency_counter
00050 {
00051 
00052 #if DEBUG
00053 // Check interrupt handler processing time
00054 DigitalOut  tstp0(D13, 1);
00055 DigitalOut  tstp1(D12, 1);
00056 DigitalOut  tstp2(D11, 1);
00057 #endif
00058 
00059 // TIM2 IC (Reciprocal) + OverFlow
00060 static int32_t sw_ovrflw_tim2;
00061 static uint8_t rise_cnt;
00062 static uint8_t fall_cnt;
00063 
00064 // buffer for captured data
00065 freq_one captured_dt;               // frequency data in pack (interrupt)
00066 int64_t rise_buf[2];
00067 int64_t fall_buf[2];
00068 uint32_t rise_pointer;
00069 uint32_t fall_pointer;
00070 
00071 //------------------------------------------------------------------------------
00072 //  Frequency Counter Library
00073 //------------------------------------------------------------------------------
00074 FRQ_CUNTR::FRQ_CUNTR(PinName pin) : _input_pin(pin)
00075 {
00076     rise_pointer = 0;
00077     fall_pointer = 0;
00078     initialize_TIM2();      // Use for reciprocal
00079 }
00080 
00081 //------------------------------------------------------------------------------
00082 //  Initialize TIM2
00083 //------------------------------------------------------------------------------
00084 // IC1->PA0 for Reciprocal frequency counting mode (Interrupt) ->Rising Edge
00085 // IC2->PA1 for Reciprocal frequency counting mode (Interrupt) ->Falling Edge
00086 void FRQ_CUNTR::initialize_TIM2(void)
00087 {
00088     // Initialize Timer2(32bit) for an internal(90MHz/F446) up counter mode
00089     RCC->APB1ENR  |= RCC_APB1ENR_TIM2EN;
00090     // count_up + div by 1
00091     TIM2->CR1     &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD));
00092     // only counter overflow for interrupt
00093     TIM2->CR1     |= (uint16_t)TIM_CR1_URS;
00094     // Up counter uses from 0 to max(32bit)
00095     TIM2->ARR      = 0xffffffff;
00096     TIM2->PSC      = 0x0000;                    // 1/1
00097     TIM2->CCER     = 0;                         // Reset all
00098     // PA0 -> Input Capture pin as Timer2 IC1 for Reciprocal
00099     GPIOA->AFR[0] &= 0xfffffff0;
00100     GPIOA->AFR[0] |= GPIO_AF1_TIM2 << 0;        // 0bit x 4
00101     GPIOA->MODER  &= ~(GPIO_MODER_MODER0);      // AF
00102     GPIOA->MODER  |= GPIO_MODER_MODER0_1;       //  alternate function mode
00103     GPIOA->PUPDR  &= ~(GPIO_PUPDR_PUPDR0);      // PU
00104     GPIOA->PUPDR  |= GPIO_PUPDR_PUPDR0_0;       //  Pull-up mode
00105     // Initialize Timer2 IC1
00106     // input filter + input select
00107     TIM2->CCMR1   &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S);
00108     TIM2->CCMR1   |= (TIM_CCMR1_CC1S_0 + TIM_CCMR1_IC1F_0); // filter -> N=2
00109     // Rising Edge   <------------------------------
00110     TIM2->CCER    &= (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
00111     // enable capture + Rising Edge(0)
00112     TIM2->CCER    |= (uint16_t)TIM_CCER_CC1E;
00113     // PA1 -> Input Capture pin as Timer2 IC2
00114     GPIOA->AFR[0] &= 0xffffff0f;
00115     GPIOA->AFR[0] |= GPIO_AF1_TIM2 << 4;        // 1bit x 4
00116     GPIOA->MODER  &= ~(GPIO_MODER_MODER1);      // AF
00117     GPIOA->MODER  |= GPIO_MODER_MODER1_1;       //  alternate function mode
00118     GPIOA->PUPDR  &= ~(GPIO_PUPDR_PUPDR1);      // PU
00119     GPIOA->PUPDR  |= GPIO_PUPDR_PUPDR1_0;       //  Pull-up mode
00120     // Initialize Timer2 IC2
00121     // input filter + input select
00122     TIM2->CCMR1   &= ~(TIM_CCMR1_IC2F | TIM_CCMR1_CC2S);
00123     TIM2->CCMR1   |= (TIM_CCMR1_CC2S_0 + TIM_CCMR1_IC2F_0); // filter -> N=2
00124     // Falling Edge  <------------------------------
00125     TIM2->CCER    &= (uint16_t)~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
00126     // enable capture + Falling Edge(1)
00127     TIM2->CCER    |= (uint16_t)TIM_CCER_CC2E | TIM_CCER_CC2P;
00128     // Only for Debug purpose
00129     //  PA
00130     PRINTF("\r\n// Timer2(32bit) for an internal up counter mode\r\n");
00131     PRINTF("// Set GPIO for Timer2\r\n");
00132     PRINTF("// PA0  -> Input Capture pin as Timer2 CH1/TI1\r\n");
00133     PRINTF("// PA1  -> Input Capture pin as Timer2 CH2/TI2\r\n");
00134     PRINTF("GPIOA->AFRL  0x%08x:0x%08x\r\n",&GPIOA->AFR[0], GPIOA->AFR[0]);
00135     PRINTF("GPIOA->AFRH  0x%08x:0x%08x\r\n",&GPIOA->AFR[1], GPIOA->AFR[1]);
00136     PRINTF("GPIOA->MODER 0x%08x:0x%08x\r\n",&GPIOA->MODER, GPIOA->MODER);
00137     PRINTF("GPIOA->PUPDR 0x%08x:0x%08x\r\n",&GPIOA->PUPDR, GPIOA->PUPDR);
00138     //  TIM2
00139     PRINTF("// PA0 -> Timer2 IC1\r\n");
00140     PRINTF("// PA1 -> Timer2 IC2\r\n");
00141     PRINTF("TIM2->CR1    0x%08x:0x%08x\r\n",&TIM2->CR1, TIM2->CR1);
00142     PRINTF("TIM2->CR2    0x%08x:0x%08x\r\n",&TIM2->CR2, TIM2->CR2);
00143     PRINTF("TIM2->ARR    0x%08x:0x%08x\r\n",&TIM2->ARR, TIM2->ARR);
00144     PRINTF("TIM2->PSC    0x%08x:0x%08x\r\n",&TIM2->PSC, TIM2->PSC);
00145     PRINTF("TIM2->CCMR1  0x%08x:0x%08x\r\n",&TIM2->CCMR1, TIM2->CCMR1);
00146     PRINTF("TIM2->CCMR2  0x%08x:0x%08x\r\n",&TIM2->CCMR2, TIM2->CCMR2);
00147     PRINTF("TIM2->CCER   0x%08x:0x%08x\r\n",&TIM2->CCER, TIM2->CCER);
00148     PRINTF("TIM2->SMCR   0x%08x:0x%08x\r\n",&TIM2->SMCR, TIM2->SMCR);
00149     // Timer2 Overflow
00150     TIM2->DIER = 0;                 // Disable all interrupt
00151     sw_ovrflw_tim2 = 0;
00152     TIM2->CCR1 = 0;
00153     TIM2->CCR2 = 0;
00154     uint32_t dummy = TIM2->CCR1;
00155     dummy = TIM2->CCR1;
00156     dummy = TIM2->CCR2;
00157     dummy = TIM2->CCR2;
00158     TIM2->CNT = 0;
00159     TIM2->SR = 0;                   // clear all IC/OC flag
00160     // set clock source then enable
00161     TIM2->SMCR     = 0;                         // Internal clock
00162     TIM2->CR1     |= (uint16_t)TIM_CR1_CEN;     // Enable the TIM Counter
00163     // interrupt
00164     NVIC_SetVector(TIM2_IRQn, (uint32_t)irq_ic_TIM2);
00165     NVIC_ClearPendingIRQ(TIM2_IRQn);
00166     NVIC_EnableIRQ(TIM2_IRQn);
00167     PRINTF("TIM2->DIER   0x%08x:0x%08x\r\n\r\n",&TIM2->DIER, TIM2->DIER);
00168 }
00169 
00170 //------------------------------------------------------------------------------
00171 //  Reciprocal measuremt
00172 //------------------------------------------------------------------------------
00173 void FRQ_CUNTR::start_action(void)
00174 {
00175     __disable_irq();
00176     TIM2->SR &= ~(TIM_SR_CC1IF | TIM_SR_CC2IF);     // clear IC flag
00177     TIM2->DIER |= TIM_DIER_CC1IE | TIM_DIER_CC2IE;  // Enable IC1+IC2
00178     __enable_irq();
00179 }
00180 
00181 void FRQ_CUNTR::stop_action(void)
00182 {
00183     __disable_irq();
00184     TIM2->SR &= ~(TIM_SR_CC1IF | TIM_SR_CC2IF);     // clear IC flag
00185     __enable_irq();
00186 }
00187 
00188 void FRQ_CUNTR::recipro_start_measurement()
00189 {
00190     SystemCoreClockUpdate();
00191     _base_clock = (float)read_base_clock_frequency();
00192     rise_cnt = 0;
00193     fall_cnt = 0;
00194     _data_ready = false;
00195     rise_buf[0] = 0;
00196     rise_buf[1] = 0;
00197     fall_buf[0] = 0;
00198     fall_buf[1] = 0;
00199     start_action();
00200     _t.reset();
00201     _t.start();
00202 }
00203 
00204 void FRQ_CUNTR::recipro_stop_measurement()
00205 {
00206     _t.reset();
00207     _t.stop();
00208     stop_action();
00209 }
00210 
00211 bool FRQ_CUNTR::recipro_check_status(Recipro_status_TypeDef *status)
00212 {
00213     freq_one _temp;
00214 
00215     bool _ready = false;
00216     _data_buf[0] = rise_buf[0];
00217     _data_buf[1] = rise_buf[1];
00218     _data_buf[2] = fall_buf[0];
00219     _data_buf[3] = fall_buf[1];
00220     uint8_t sum = 0;
00221     if (_data_buf[0] == 0) {   ++sum;}
00222     if (_data_buf[1] == 0) {   ++sum;}
00223     if (_data_buf[2] == 0) {   ++sum;}
00224     if (_data_buf[3] == 0) {   ++sum;}
00225     if (sum != 4) {
00226         _ready = true;
00227         // change order
00228         if (_data_buf[0] > _data_buf[1]){
00229             _temp.f_64bit_dt = _data_buf[0];
00230             _data_buf[0] = _data_buf[1];
00231             _data_buf[1] = _temp.f_64bit_dt;
00232         }
00233         _tp0 = _data_buf[1] - _data_buf[0];
00234         if (_tp0 < 0) {
00235             _tp0 = 0;
00236         }
00237         if (_data_buf[2] > _data_buf[3]){
00238             _temp.f_64bit_dt = _data_buf[2];
00239             _data_buf[2] = _data_buf[3];
00240             _data_buf[3] = _temp.f_64bit_dt;
00241         }
00242         _tp1 = _data_buf[3] - _data_buf[2];
00243         if (_tp1 < 0) {
00244             _tp1 = 0;
00245         }
00246         // calculate diff
00247         if (_data_buf[3] > _data_buf[1]) {
00248             //type A
00249             _tp2 = _data_buf[2] - _data_buf[0];
00250             _tp3 = _data_buf[1] - _data_buf[2];
00251         } else {
00252             //type B
00253             _tp2 = _data_buf[3] - _data_buf[0];
00254             _tp3 = _data_buf[0] - _data_buf[2];
00255         }
00256         if (_tp2 < 0) {
00257             _tp2 = 0;
00258         }
00259         if (_tp3 < 0) {
00260             _tp3 = 0;
00261         }
00262     }
00263     PRINTF("rise_buf[0] = %.0f\r\n", (float)rise_buf[0]);
00264     PRINTF("rise_buf[1] = %.0f\r\n", (float)rise_buf[1]);
00265     PRINTF("fall_buf[0] = %.0f\r\n", (float)fall_buf[0]);
00266     PRINTF("fall_buf[1] = %.0f\r\n", (float)fall_buf[1]);
00267     PRINTF("data_buf0[0]= %.0f\r\n", (float)_data_buf[0]);
00268     PRINTF("data_buf0[1]= %.0f\r\n", (float)_data_buf[1]);
00269     PRINTF("data_buf1[0]= %.0f\r\n", (float)_data_buf[2]);
00270     PRINTF("data_buf1[1]= %.0f\r\n", (float)_data_buf[3]);
00271     PRINTF("tp0= %.0f\r\n", (float)_tp0);
00272     PRINTF("tp1= %.0f\r\n", (float)_tp1);
00273     PRINTF("tp2= %.0f\r\n", (float)_tp2);
00274     PRINTF("tp3= %.0f\r\n", (float)_tp3);
00275     if (_ready == true) {
00276         _freq_rise2rise = _base_clock / (float)_tp0;
00277         _freq_fall2fall = _base_clock / (float)_tp1;
00278         _time_us_rise2fall = (float)_tp2 / _base_clock * 1.0e3;
00279         _time_us_fall2rise = (float)_tp3 / _base_clock * 1.0e3;
00280         _data_ready = true;
00281         PRINTF("freq_rise2rise= %f [Hz]\r\n", _freq_rise2rise);
00282         PRINTF("freq_fall2fall= %f [Hz]\r\n", _freq_fall2fall);
00283         PRINTF("time_us_rise2fall= %f [mS]\r\n", _time_us_rise2fall);
00284         PRINTF("time_us_fall2rise= %f [mS]\r\n", _time_us_fall2rise);
00285     }
00286     status->rise_cnt = rise_cnt;
00287     status->fall_cnt = fall_cnt;
00288     status->input_level = _input_pin.read();
00289     status->passed_time = (float)_t.read_us() / 1.0e6;
00290     return _data_ready;
00291 }
00292 
00293 void FRQ_CUNTR::recipro_get_result(Recipro_result_TypeDef *fq)
00294 {
00295     fq->freq_rise2rise    = _freq_rise2rise;
00296     fq->freq_fall2fall    = _freq_fall2fall;
00297     fq->time_us_rise2fall = _time_us_rise2fall;
00298     fq->time_us_fall2rise = _time_us_fall2rise;
00299 }
00300 
00301 void FRQ_CUNTR::recipro_get_raw_data(int64_t *buf)
00302 {
00303     int64_t *pointer = buf;
00304     *pointer++ = rise_buf[0];
00305     *pointer++ = fall_buf[0];
00306     *pointer++ = rise_buf[1];
00307     *pointer++ = fall_buf[1];
00308     pointer = buf;
00309     for (uint32_t i = 0; i < 4; i++) {
00310         float dt = (float)*pointer++;
00311         PRINTF("%2d = %12.0f \r\n", i, dt);
00312     }
00313 }
00314 
00315 //------------------------------------------------------------------------------
00316 //  Interrupt Handlers
00317 //------------------------------------------------------------------------------
00318 // Reciprocal data (TIM2 IC1+IC2)
00319 void irq_ic_TIM2(void)
00320 {
00321     // IC1 (for reciprocal measurement / Rising edge)
00322     uint32_t reg = TIM2->SR;
00323     if (reg & TIM_SR_CC1IF) {
00324         SET0;
00325         TIM2->SR &= ~TIM_SR_CC1IF;  // clear IC flag
00326         captured_dt.freq_dt = TIM2->CCR1;
00327         captured_dt.f_sw_dt = sw_ovrflw_tim2;
00328         rise_buf[rise_pointer % 2] = captured_dt.f_64bit_dt;
00329         ++rise_pointer;
00330         ++rise_cnt;
00331         CLR0;
00332     }
00333     // IC2 (for reciprocal measurement / Falling edge)
00334     if (reg & TIM_SR_CC2IF) {
00335         SET1;
00336         TIM2->SR &= ~TIM_SR_CC2IF;  // clear IC flag
00337         captured_dt.freq_dt = TIM2->CCR2;
00338         captured_dt.f_sw_dt = sw_ovrflw_tim2;
00339         fall_buf[fall_pointer % 2] = captured_dt.f_64bit_dt;
00340         ++fall_pointer;
00341         ++fall_cnt;
00342         CLR1;
00343     }
00344     // TIM2 overflow
00345     if (reg & TIM_SR_UIF) {            // 32bit counter overflow
00346         SET2;
00347         TIM2->SR &= ~TIM_SR_UIF;  // clear UIF(overflow) flag
00348         ++sw_ovrflw_tim2;
00349         CLR2
00350     }
00351 }
00352 
00353 //------------------------------------------------------------------------------
00354 //  Frequency check for test & debug purpose
00355 //------------------------------------------------------------------------------
00356 // Read TIM2 Clock frequency
00357 uint32_t FRQ_CUNTR::read_base_clock_frequency(void)
00358 {
00359     TIM2->CNT = 0;
00360     wait_us(1000000);           // Gate time = 1seconds
00361     uint32_t freq = TIM2->CNT;  // read counter
00362     PRINTF("Clock Frequency= %10d, gate= %4.2f [Sec]\r\n", freq);
00363     return freq;                // return counter data
00364 }
00365 
00366 //
00367 uint32_t FRQ_CUNTR::read_tm2_overflow(void)
00368 {
00369     return sw_ovrflw_tim2;
00370 }
00371 
00372 }   // Frequency_counter