Reciprocal Frequency counter only for STM32F401、F411 and F466. Reciprocal Mode -> Pulse width measurement
Dependents: Frequency_Counter_Recipro_for_STM32F4xx
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
Generated on Tue Jul 19 2022 04:30:27 by 1.7.2