Frequency counter library using GPS 1PPS signal and temperature controlled 50MHz Base clock. Ported from F411 Frequency Counter.
Dependents: Frequency_Cntr_1PPS_F746ZG
Fork of Frq_cuntr_full by
frq_cuntr_f746.cpp
00001 /* 00002 * mbed Library / Frequency Counter with GPS 1PPS Compensation 00003 * Frequency Counter Hardware relataed program 00004 * Only for ST Nucleo-F746ZG 00005 * 00006 * Copyright (c) 2014,'15,'16 Kenji Arai / JH1PJL 00007 * http://www.page.sannet.ne.jp/kenjia/index.html 00008 * http://mbed.org/users/kenjiArai/ 00009 * Started: October 18th, 2014 00010 * Revised: January 1st, 2015 00011 * Re-started: June 25th, 2016 ported from F411 board 00012 * Revised: Novemeber 23rd, 2016 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00015 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00017 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00018 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 00019 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 00020 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00021 */ 00022 00023 #if !defined(TARGET_STM32F746ZG) 00024 #error "This function works only on F746ZG!!" 00025 #endif // !defined(TARGET_STM32F746ZG) 00026 00027 #include "frq_cuntr_f746.h" 00028 #include "RingBuff.h" 00029 00030 #define ACTIVE_LED 1 00031 00032 #if ACTIVE_LED 00033 DigitalOut irq_led1(LED1); 00034 DigitalOut irq_led2(LED2); 00035 DigitalOut irq_led3(LED3); 00036 #endif 00037 00038 #if DEBUG 00039 #define PRINTF(...) printf(__VA_ARGS__) 00040 #else 00041 #define PRINTF(...) {;} 00042 #endif 00043 00044 namespace Frequency_counter 00045 { 00046 00047 // Following ring buffers are very big!! 4096 x 8(bytes) x 2(buff) = 64KB 00048 RingBuff<uint64_t> onepps_buf; // RinBuffer for 1PPS (TIM2) 00049 freq_one onepps_dt; // frequency data in pack (interrupt) 00050 RingBuff<uint64_t> fdt_buffer; // RinBuffer for TIM8+4 00051 freq_one fdt; // frequency data in pack (interrupt) 00052 00053 // TIM2 IC2 + OverFlow 00054 static uint8_t tim2_ready_flg; 00055 static uint32_t tim2_cnt_data; 00056 static uint16_t time_count_onepps; 00057 static uint16_t sw_ovrflw_tim2; 00058 // TIM2 IC4 (Reciprocal) 00059 static uint8_t recipro_step; 00060 static uint32_t recipro_start; 00061 static uint32_t recipro_stop; 00062 // TIM2 OC 00063 static uint32_t oc_hi_time; 00064 static uint32_t oc_lo_time; 00065 // TIM4(TIM8) IC + OverFlow 00066 static uint8_t tim8p4_ready_flg; 00067 static uint32_t tim8p4_cnt_data; 00068 static uint16_t time_count; 00069 static uint16_t sw_ovrflw_tim8p4; 00070 00071 //------------------------------------------------------------------------------ 00072 // Frequency Counter 00073 //------------------------------------------------------------------------------ 00074 FRQ_CUNTR::FRQ_CUNTR(double ex_clock) 00075 { 00076 // Don't change calling sequence!! 00077 set_external_clock(ex_clock); // 1st 00078 set_1sec_gate_time(); // 2nd 00079 initialize_Freq_counter(); // 3rd 00080 } 00081 00082 // Set External Clock Frequency 00083 void FRQ_CUNTR::set_external_clock(double ex_clock) 00084 { 00085 ex_clock_freq = ex_clock; 00086 ex_clk_base = (uint32_t)(ex_clock_freq * 1000000.0f); // MHz->Hz 00087 clk_hi_const = (uint32_t)(ex_clock_freq * 1000000.0f * 0.2f);// Count=200mS 00088 // 100ppm error range 00089 uint32_t err = (uint32_t)(ex_clock_freq * 1000000.0f * 0.0001f); 00090 clk_upper_limit = ex_clk_base + err; 00091 clk_lower_limit = ex_clk_base - err; 00092 PRINTF("\r\nSet EXTERNAL Clock mode\r\n"); 00093 } 00094 00095 // Set real gate time 00096 void FRQ_CUNTR::set_1sec_gate_time(void) 00097 { 00098 oc_hi_time = clk_hi_const; // 200mS 00099 double gt_tmp0 = ex_clk_base * 1.0f; // one sec 00100 uint32_t gt_tmp1 = (uint32_t)gt_tmp0; 00101 if ((gt_tmp0 - (double)gt_tmp1) >= 0.5f){ 00102 ++gt_tmp1; 00103 if ((gt_tmp0 - (double)gt_tmp1) >= 0.5f){ 00104 ++gt_tmp1; 00105 } 00106 } 00107 oc_lo_time = gt_tmp1 - clk_hi_const; 00108 } 00109 00110 void FRQ_CUNTR::initialize_Freq_counter(void) 00111 { 00112 initialize_TIM2(); 00113 initialize_TIM8P4(); 00114 } 00115 00116 // Read new frequency data 00117 double FRQ_CUNTR::read_freq_data(void) 00118 { 00119 return read_freq_w_gate_time(1); 00120 } 00121 00122 // Read compensated frequency data with suitable gate time 00123 /* 00124 yr: Measured 1PPS 00125 yi: Ideal 1PPS (expected value) 00126 xr: Measued unkown frequency data 00127 ---> xi: Compesated data 00128 comp = (yr-yi)/yi 00129 -> delta = comp * xr 00130 -> xi = xr + delta = compensated data 00131 */ 00132 double FRQ_CUNTR::read_compensated_freq_data_w_gt(uint16_t gt) 00133 { 00134 freq_one f_new, f_old; 00135 freq_one one_new, one_old; 00136 uint32_t new_cnt, old_cnt; 00137 uint64_t temp0; 00138 double temp1, temp2; 00139 00140 f_new.f_1sec_dt = fdt_buffer.ring_get_newest_dt(); // newest data 00141 f_old.f_1sec_dt = fdt_buffer.ring_get_pointed_dt(gt);// gt[sec] before data 00142 one_new.f_1sec_dt = onepps_buf.ring_get_newest_dt(); 00143 one_old.f_1sec_dt = onepps_buf.ring_get_pointed_dt(gt); 00144 new_cnt = (uint32_t)f_new.t_cnt; 00145 old_cnt = (uint32_t)f_old.t_cnt; 00146 if (old_cnt > new_cnt){ 00147 new_cnt += 0x10000; 00148 } 00149 if ((new_cnt - old_cnt) != gt){ 00150 return 0.0f; 00151 } 00152 new_cnt = (uint32_t)one_new.t_cnt; 00153 old_cnt = (uint32_t)one_old.t_cnt; 00154 if (old_cnt > new_cnt){ 00155 new_cnt += 0x10000; 00156 } 00157 if ((new_cnt - old_cnt) != gt){ 00158 return 0.0f; 00159 } 00160 // comp = (yr-yi)/yi 00161 temp0 = get_diff(one_new.f_1sec_dt, one_old.f_1sec_dt); 00162 temp1 = (double)temp0 - ex_clock_freq * 1000000.0f * (double)gt; 00163 temp2 = temp1 / (ex_clock_freq * 1000000.0f * (double)gt); 00164 // delta = comp * xr 00165 temp0 = get_diff(f_new.f_1sec_dt, f_old.f_1sec_dt); 00166 temp1 = temp2 * (double)temp0; 00167 // xi = xr + delta 00168 temp2 = (double)temp0 + temp1; 00169 return temp2 / (double)gt; 00170 } 00171 00172 // Read new frequency data with specific gate time 00173 double FRQ_CUNTR::read_freq_w_gate_time(uint16_t gt) 00174 { 00175 freq_one f_new, f_old; 00176 00177 if (gt == 0){ return 0.0f;} 00178 f_new.f_1sec_dt = fdt_buffer.ring_get_newest_dt(); // newest data 00179 f_old.f_1sec_dt = fdt_buffer.ring_get_pointed_dt(gt);// gt[sec] before data 00180 uint32_t new_cnt = (uint32_t)f_new.t_cnt; 00181 uint32_t old_cnt = (uint32_t)f_old.t_cnt; 00182 if (old_cnt > new_cnt){ 00183 new_cnt += 0x10000; 00184 } 00185 if ((new_cnt - old_cnt) == gt){ // make sure gt[sec] 00186 uint64_t dt = get_diff(f_new.f_1sec_dt, f_old.f_1sec_dt); 00187 return (double)dt / (double)gt; 00188 } else { 00189 return 0.0f; 00190 } 00191 } 00192 00193 // Read status (new frequency data is available or not) 00194 uint32_t FRQ_CUNTR::status_freq_update(void) 00195 { 00196 return check_ic1_status_TIM8P4(); 00197 } 00198 00199 // Read status (new 1PPS data is available or not) 00200 uint32_t FRQ_CUNTR::status_1pps(void) 00201 { 00202 return check_ic2_status_TIM2(); 00203 } 00204 00205 // Read GPS 1PPS counter value 00206 uint32_t FRQ_CUNTR::calc_1PPS_newest(void) 00207 { 00208 freq_one f_new, f_old; 00209 uint64_t diff = 0; 00210 00211 f_new.f_1sec_dt = onepps_buf.ring_get_newest_dt(); // newest data 00212 f_old.f_1sec_dt = onepps_buf.ring_get_pointed_dt(1); 00213 uint32_t new_cnt = (uint32_t)f_new.t_cnt; 00214 uint32_t old_cnt = (uint32_t)f_old.t_cnt; 00215 if (old_cnt > new_cnt){ 00216 new_cnt += 0x10000; 00217 } 00218 if ((new_cnt - old_cnt) == 1){ // make sure gt[sec] 00219 diff = get_diff(f_new.f_1sec_dt, f_old.f_1sec_dt); 00220 } 00221 if ((diff > clk_upper_limit) || (diff < clk_lower_limit)){ 00222 // Missing 1PPS signal or Base clock is out of range 00223 gps_ready = 0; 00224 onepps_buf.ring_clear_buf(); // Clear ring buffer 00225 return 0; 00226 } else { // GPS 1pps is in good range 00227 gps_ready = 1; 00228 onepps_ready_flg = 0; 00229 onepps_newest = diff; 00230 return diff; 00231 } 00232 } 00233 00234 // Avarage measured data GPS 1PPS by External Base Clock 00235 double FRQ_CUNTR::read_avarage_1pps(void) 00236 { 00237 freq_one f_new, f_old; 00238 int16_t size = 0; 00239 00240 f_new.f_1sec_dt = onepps_buf.ring_get_newest_dt(); // newest data 00241 size = onepps_buf.ring_get_buf_size(); 00242 if (size >= 1500){ // Not use old 500 data 00243 gate_time = 1000; // Gate Time = 16min40sec 00244 } else if (size >= 200){// Not use old 100 data 00245 gate_time = 100; // Gate Time = 1min40sec 00246 } else if (size >= 20){ // Not use old 10 data 00247 gate_time = 10; // Gate Time = 10sec 00248 } else if (size >= 10){ // Not use old 9 data 00249 gate_time = 1; // Gate Time = 1sec 00250 } else { 00251 gate_time = 1; 00252 return 0.0f; // data is not avairable 00253 } 00254 f_old.f_1sec_dt = onepps_buf.ring_get_pointed_dt(gate_time); 00255 uint32_t new_cnt = (uint32_t)f_new.t_cnt; 00256 uint32_t old_cnt = (uint32_t)f_old.t_cnt; 00257 if (old_cnt > new_cnt){ 00258 new_cnt += 0x10000; 00259 } 00260 if ((new_cnt - old_cnt) == gate_time){ // make sure gt[sec] 00261 uint64_t dt = get_diff(f_new.f_1sec_dt, f_old.f_1sec_dt); 00262 return (double)dt / (double)gate_time; 00263 } else { 00264 return 0.0f; 00265 } 00266 } 00267 00268 // Read number of buffered data 00269 uint32_t FRQ_CUNTR::read_num_in_buffer(void) 00270 { 00271 return onepps_buf.ring_get_buf_size(); 00272 } 00273 00274 // Newest measued data GPS 1PPS 00275 uint32_t FRQ_CUNTR::read_newest_1pps(void) 00276 { 00277 calc_1PPS_newest(); 00278 return onepps_newest; 00279 } 00280 00281 // Check GPS condition 00282 uint32_t FRQ_CUNTR::status_gps(void) 00283 { 00284 if (gps_ready){ 00285 return gate_time; 00286 } else { 00287 return 0; // 1PPS signal is not avarable 00288 } 00289 } 00290 00291 uint64_t FRQ_CUNTR::get_diff(uint64_t new_dt, uint64_t old_dt){ 00292 uint64_t nw,od; 00293 00294 nw = new_dt & 0x0000ffffffffffff; // select 48bit data 00295 od = old_dt & 0x0000ffffffffffff; 00296 if (nw < od){ // 48bits counter overflow! 00297 nw += 0x0001000000000000; 00298 } 00299 return (nw - od); 00300 } 00301 00302 //------------------------------------------------------------------------------ 00303 // Frequency Counter / Reciprocal measurement 00304 //------------------------------------------------------------------------------ 00305 void FRQ_CUNTR::recipro_start_measure(void) 00306 { 00307 recipro_step = 0; // initialize step 00308 __disable_irq(); 00309 TIM2->SR &= ~TIM_SR_CC4IF; // clear IC flag 00310 TIM2->DIER |= TIM_DIER_CC4IE; // Enable IC4 00311 __enable_irq(); 00312 } 00313 00314 uint32_t FRQ_CUNTR::recipro_check_trigger(void) 00315 { 00316 if (recipro_step == 2){ // check IC event happan or not 00317 return 1; // happen 00318 } else { 00319 return 0; // not yet 00320 } 00321 } 00322 00323 uint32_t FRQ_CUNTR::recipro_read_data(void) 00324 { 00325 uint64_t dt; 00326 if (recipro_stop < recipro_start){ // 32bit counter overflow 00327 dt = 0x100000000 + recipro_stop; 00328 dt -= recipro_stop; 00329 } else { 00330 dt = recipro_stop - recipro_start; 00331 } 00332 return (uint32_t)dt; 00333 } 00334 00335 //------------------------------------------------------------------------------ 00336 // TIM2 (32bit Counter + IC + OC) 00337 //------------------------------------------------------------------------------ 00338 // Read TIM2 captured counter value 00339 uint32_t FRQ_CUNTR::read_ic2_counter_TIM2(void) 00340 { 00341 return tim2_cnt_data; // return TIM2->CCR2; 00342 } 00343 00344 // Check TIM2 IC2 status 00345 uint32_t FRQ_CUNTR::check_ic2_status_TIM2(void) 00346 { 00347 if (tim2_ready_flg == 0){ 00348 return 0; 00349 } else { // GPS 1PPS is comming 00350 tim2_ready_flg = 0; 00351 return 1; 00352 } 00353 } 00354 00355 // Check OC port status 00356 uint8_t FRQ_CUNTR::read_oc_port_status(void) 00357 { 00358 uint32_t p = GPIOB->IDR; 00359 if (p & 0x0400){ // Check PB10 status 00360 return 1; // H level 00361 } else { 00362 return 0; // L level 00363 } 00364 } 00365 00366 //------------------------------------------------------------------------------ 00367 // TIM8+TIM4 (32bit Counter + IC) 00368 //------------------------------------------------------------------------------ 00369 // Read TIM8+4(as 32bit) captured counter value 00370 uint32_t FRQ_CUNTR::read_counter_TIM8P4(void) 00371 { 00372 return tim8p4_cnt_data; 00373 } 00374 00375 // Check TIM8 IC2 & TIM4 IC1 status 00376 uint32_t FRQ_CUNTR::check_ic1_status_TIM8P4(void) 00377 { 00378 if (tim8p4_ready_flg == 0){ 00379 return 0; 00380 } else { // Gate signal is comming 00381 tim8p4_ready_flg = 0; 00382 return 1; 00383 } 00384 } 00385 00386 //------------------------------------------------------------------------------ 00387 // Initialize TIM2 and TIM8+4 00388 //------------------------------------------------------------------------------ 00389 // Initialize TIM2 00390 // External clock(50MHz)->PA_5 and 00391 // IC2->PA_1 for GPS 1pps signal measurement 00392 // IC4->PA_3 for Reciprocal frequency counting mode 00393 // OC3->PB_10 for Base gate time output(1 Second and other gate time) 00394 /* 00395 ????? Strange behavior : 00396 TIM2_ETR is assigned AF2 but following is assigned AF1! 00397 */ 00398 void FRQ_CUNTR::initialize_TIM2(void) 00399 { 00400 // PA5 -> Counter frequency input pin as Timer2 ETR(CH1?) 00401 RCC->AHB1ENR |= (RCC_AHB1ENR_GPIOAEN); 00402 GPIOA->AFR[0] &= 0xff0fffff; 00403 GPIOA->AFR[0] |= GPIO_AF1_TIM2 << 20; // 5(PA5) x 4bits = AFSEL5 00404 // ??? AF3(TIM2_ETR) does NOT works!! 00405 //GPIOA->AFR[0] |= ((uint8_t)0x02) << 20; 00406 GPIOA->MODER &= ~(GPIO_MODER_MODER5); // AF 00407 GPIOA->MODER |= GPIO_MODER_MODER5_1; // alternate function mode 00408 GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR5); // PU 00409 GPIOA->PUPDR |= GPIO_PUPDR_PUPDR5_0; // Pull-up mode 00410 // Initialize Timer2(32bit) for an external(ECE bit = 1) up counter mode 00411 RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; 00412 // count_up + div by 1 00413 TIM2->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD)); 00414 // only counter overflow for interrupt 00415 TIM2->CR1 |= (uint16_t)TIM_CR1_URS; 00416 // Up counter uses from 0 to max(32bit) 00417 TIM2->ARR = 0xffffffff; 00418 TIM2->PSC = 0x0000; // 1/1 00419 TIM2->CCER &= (uint16_t)~TIM_CCER_CC1E; // Disable the CC1 00420 // input filter + input select 00421 TIM2->CCMR1 &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S); 00422 TIM2->CCMR1 |= TIM_CCMR1_CC1S_0; 00423 TIM2->SMCR = 00424 (TIM_SMCR_ECE| TIM_ETRPRESCALER_DIV1 | TIM_CLOCKSOURCE_ETRMODE1); 00425 TIM2->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter 00426 // PA1 -> Input Capture pin as Timer2 IC2 00427 GPIOA->AFR[0] &= 0xffffff0f; 00428 GPIOA->AFR[0] |= GPIO_AF1_TIM2 << 4; // 1bit x 4 00429 GPIOA->MODER &= ~(GPIO_MODER_MODER1); // AF 00430 GPIOA->MODER |= GPIO_MODER_MODER1_1; // alternate function mode 00431 GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR1); // PU 00432 GPIOA->PUPDR |= GPIO_PUPDR_PUPDR1_0; // Pull-up mode 00433 // Initialize Timer2 IC2 00434 TIM2->CCER &= (uint16_t)~TIM_CCER_CC2E; // Disable the CC2 00435 // input filter + input select 00436 TIM2->CCMR1 &= ~(TIM_CCMR1_IC2F | TIM_CCMR1_CC2S); 00437 TIM2->CCMR1 |= TIM_CCMR1_CC2S_0; 00438 // positive edge 00439 TIM2->CCER &= (uint16_t)~(TIM_CCER_CC2P | TIM_CCER_CC2NP); 00440 TIM2->CCER |= (uint16_t)TIM_CCER_CC2E; // enable capture 00441 // PA3 -> Input Capture pin as Timer2 IC4 for Reciprocal 00442 GPIOA->AFR[0] &= 0xffff0fff; 00443 GPIOA->AFR[0] |= GPIO_AF1_TIM2 << 12; // 3bit x 4 00444 GPIOA->MODER &= ~(GPIO_MODER_MODER3); // AF 00445 GPIOA->MODER |= GPIO_MODER_MODER3_1; // alternate function mode 00446 GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR3); // PU 00447 GPIOA->PUPDR |= GPIO_PUPDR_PUPDR3_0; // Pull-up mode 00448 // Initialize Timer2 IC4 00449 TIM2->CCER &= (uint16_t)~TIM_CCER_CC4E; // Disable the CC 00450 TIM2->CCMR2 &= ~(TIM_CCMR2_IC4F | TIM_CCMR2_CC4S); 00451 TIM2->CCMR2 |= (TIM_CCMR2_CC4S_0 + TIM_CCMR2_IC4F_1); // filter = fCLK/4 00452 // positive edge 00453 TIM2->CCER &= (uint16_t)~(TIM_CCER_CC4P | TIM_CCER_CC4NP); 00454 TIM2->CCER |= (uint16_t)TIM_CCER_CC4E; // enable capture 00455 // PB10 -> Output Compare pin as Timer2 OC3 00456 GPIOB->AFR[1] &= 0xfffff0ff; 00457 GPIOB->AFR[1] |= GPIO_AF1_TIM2 << 8; // 10bit x 4 -> 2bit x 4(AFR[1]) 00458 GPIOB->MODER &= ~(GPIO_MODER_MODER10); // AF 00459 GPIOB->MODER |= GPIO_MODER_MODER10_1; // alternate function mode 00460 GPIOB->OTYPER &= ~(GPIO_OTYPER_OT_10); // Output Push-Pull=0 00461 GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR10; // Speed full=11 00462 GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPDR10); // No Pull-up&down = 0 00463 // Initialize Timer2 OC3 00464 // Reset the CC3E Bit (Disable output) 00465 TIM2->CCER &= (uint16_t)~TIM_CCER_CC3E; 00466 TIM2->CCMR2 &= ~(TIM_CCMR2_OC3M | TIM_CCMR2_CC3S | 00467 TIM_CCMR2_OC3PE | TIM_CCMR2_OC3CE | TIM_CCMR2_OC3FE); 00468 TIM2->CCMR2 |= TIM_CCMR2_OC3M_2; // force to low level 00469 // Reset the Output Polarity level (active H) 00470 TIM2->CCER &= (uint16_t)~TIM_CCER_CC3P; 00471 // Set the CC3E Bit (Enable output) 00472 TIM2->CCER |= (uint16_t)TIM_CCER_CC3E; 00473 // Set the Capture Compare Register value 00474 TIM2->CCR3 = TIM2->CNT + oc_lo_time; 00475 // Up counter based on gate time period 00476 time_count_onepps = 0; 00477 // Only for Debug purpose 00478 // PA 00479 PRINTF("\r\n// Timer2(32bit) for an internal up counter mode\r\n"); 00480 PRINTF("// Set GPIO for Timer2\r\n"); 00481 PRINTF("// PA1 -> Input Capture pin as Timer2 CH2/TI2\r\n"); 00482 PRINTF("// PA3 -> Input Capture pin as Timer2 CH4/TI4\r\n"); 00483 PRINTF("GPIOA->AFRL 0x%08x:0x%08x\r\n",&GPIOA->AFR[0], GPIOA->AFR[0]); 00484 PRINTF("GPIOA->AFRH 0x%08x:0x%08x\r\n",&GPIOA->AFR[1], GPIOA->AFR[1]); 00485 PRINTF("GPIOA->MODER 0x%08x:0x%08x\r\n",&GPIOA->MODER, GPIOA->MODER); 00486 PRINTF("GPIOA->PUPDR 0x%08x:0x%08x\r\n",&GPIOA->PUPDR, GPIOA->PUPDR); 00487 // PB 00488 PRINTF("// PB10 -> Output Compare pin as Timer2 CH3/TI3\r\n"); 00489 PRINTF("GPIOB->AFRL 0x%08x:0x%08x\r\n",&GPIOB->AFR[0], GPIOB->AFR[0]); 00490 PRINTF("GPIOB->AFRH 0x%08x:0x%08x\r\n",&GPIOB->AFR[1], GPIOB->AFR[1]); 00491 PRINTF("GPIOB->MODER 0x%08x:0x%08x\r\n",&GPIOB->MODER, GPIOB->MODER); 00492 PRINTF("GPIOB->PUPDR 0x%08x:0x%08x\r\n",&GPIOB->PUPDR, GPIOB->PUPDR); 00493 // TIM2 00494 PRINTF("// PA1 -> Timer2 IC2\r\n"); 00495 PRINTF("// PA3 -> Timer2 IC4\r\n"); 00496 PRINTF("// PB10-> Timer2 OC3\r\n"); 00497 PRINTF("TIM2->CR1 0x%08x:0x%08x\r\n",&TIM2->CR1, TIM2->CR1); 00498 PRINTF("TIM2->ARR 0x%08x:0x%08x\r\n",&TIM2->ARR, TIM2->ARR); 00499 PRINTF("TIM2->PSC 0x%08x:0x%08x\r\n",&TIM2->PSC, TIM2->PSC); 00500 PRINTF("TIM2->CCMR1 0x%08x:0x%08x\r\n",&TIM2->CCMR1, TIM2->CCMR1); 00501 PRINTF("TIM2->CCMR2 0x%08x:0x%08x\r\n",&TIM2->CCMR2, TIM2->CCMR2); 00502 PRINTF("TIM2->CCER 0x%08x:0x%08x\r\n",&TIM2->CCER, TIM2->CCER); 00503 PRINTF("TIM2->SMCR 0x%08x:0x%08x\r\n",&TIM2->SMCR, TIM2->SMCR); 00504 PRINTF("TIM2->CCR3 0x%08x:0x%08x\r\n",&TIM2->CCR3, TIM2->CCR3); 00505 // Interrupt Timer2 IC2,OC3 & Overflow 00506 tim2_ready_flg = 0; 00507 tim2_cnt_data = 0; 00508 sw_ovrflw_tim2 = 0; 00509 TIM2->SR = 0; // clear all IC/OC flag 00510 TIM2->DIER = 0; // Reset all interrupt flag 00511 TIM2->DIER = TIM_DIER_CC2IE + TIM_DIER_CC3IE + TIM_DIER_UIE; 00512 NVIC_SetVector(TIM2_IRQn, (uint32_t)irq_ic2_TIM2); 00513 NVIC_ClearPendingIRQ(TIM2_IRQn); 00514 NVIC_EnableIRQ(TIM2_IRQn); 00515 PRINTF("TIM2->DIER 0x%08x:0x%08x\r\n\r\n",&TIM2->DIER, TIM2->DIER); 00516 } 00517 00518 // Initialize TIM8 & TIM4 as 32bit counter (TIM8(Low 16bit) + TIM4(High 16bit)) 00519 // TIM8 clock input is unkown freq.(measuring freq.) and TIM4 is slave counter 00520 // 1sec gate signal connected both TIM8 IC2, TIM4 IC1 with TIM2 OC3 00521 void FRQ_CUNTR::initialize_TIM8P4(void) 00522 { 00523 // Timer8 input max freq.= 108MHz (@SystemCoreClock = 216MHz) 00524 // PC6 -> Unkown frequency input pin as Timer8 CH1/TI1 00525 RCC->AHB1ENR |= (RCC_AHB1ENR_GPIOCEN); 00526 GPIOC->AFR[0] &= 0xf0ffffff; 00527 GPIOC->AFR[0] |= GPIO_AF3_TIM8 << 24; // 6bit x 4 00528 GPIOC->MODER &= ~(GPIO_MODER_MODER6); // AF 00529 GPIOC->MODER |= GPIO_MODER_MODER6_1; // alternate function mode 00530 GPIOC->PUPDR &= ~(GPIO_PUPDR_PUPDR6); // PU 00531 GPIOC->PUPDR |= GPIO_PUPDR_PUPDR6_0; // Pull-up mode 00532 // Initialize Timer8(16bit) for an external up counter mode 00533 RCC->APB2ENR |= RCC_APB2ENR_TIM8EN; 00534 // count_up + div by 1 00535 TIM8->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD)); 00536 // update request only by overflow 00537 TIM8->CR1 |= (uint16_t)TIM_CR1_URS; 00538 TIM8->ARR = 0xffff; // Use 16bit full 00539 TIM8->CCER &= (uint16_t)~TIM_CCER_CC1E; // Disable the CC1 00540 // input filter + input select 00541 TIM8->CCMR1 &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S); 00542 TIM8->CCMR1 |= TIM_CCMR1_CC1S_0;// CC1 channel = TI1 00543 // Not use IC1 00544 TIM8->CCER &= 00545 (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NE | TIM_CCER_CC1NP); 00546 // external mode 1 00547 TIM8->SMCR &= ~(TIM_SMCR_ECE | TIM_SMCR_TS | TIM_SMCR_SMS); 00548 // ECE must be ZERO!!!! 00549 TIM8->SMCR |= ( TIM_TS_TI1FP1 | TIM_SLAVEMODE_EXTERNAL1); 00550 TIM8->CR2 &= (uint16_t)~(TIM_CR2_TI1S | TIM_CR2_MMS); 00551 TIM8->CR2 |= (uint16_t)TIM_CR2_MMS_1; // TRGO update 00552 TIM8->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter 00553 // PC7 -> Input Capture pin as Timer8 IC2 00554 GPIOC->AFR[0] &= 0x0fffffff; 00555 GPIOC->AFR[0] |= GPIO_AF3_TIM8 << 28; // 7bit x 4 00556 GPIOC->MODER &= ~(GPIO_MODER_MODER7); // AF 00557 GPIOC->MODER |= GPIO_MODER_MODER7_1; // alternate function mode 00558 GPIOC->PUPDR &= ~(GPIO_PUPDR_PUPDR7); // PU 00559 GPIOC->PUPDR |= GPIO_PUPDR_PUPDR7_0; // Pull-up mode 00560 // Initialize Timer8 IC2 00561 TIM8->CCER &= (uint16_t)~TIM_CCER_CC2E; // Disable the CC2 00562 // input filter + input select 00563 TIM8->CCMR1 &= ~(TIM_CCMR1_IC2F | TIM_CCMR1_CC2S); 00564 TIM8->CCMR1 |= TIM_CCMR1_CC2S_0; 00565 // positive edge 00566 TIM8->CCER &= (uint16_t)~(TIM_CCER_CC2P | TIM_CCER_CC2NP); 00567 TIM8->CCER |= (uint16_t)TIM_CCER_CC2E; // enable capture 00568 // Initialize Timer4(16bit) as slave counter of TIM8 00569 // TIM8 overflow event -> ITR3 as Timer4 clock 00570 RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; 00571 TIM4->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD)); 00572 // only counter overflow for interrupt 00573 TIM4->CR1 |= (uint16_t)TIM_CR1_URS; 00574 // Up counter uses from 0 to max(32bit) 00575 TIM4->ARR = 0xffff; // Use 16bit full 00576 TIM4->CCER &= (uint16_t)~TIM_CCER_CC1E; // Disable the CC1 00577 // input filter + input select 00578 TIM4->CCMR1 &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S); 00579 TIM4->CCMR1 |= TIM_CCMR1_CC1S_0; // CC1 channel = TI1 00580 // Not use IC1 00581 TIM4->CCER &= 00582 (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NE | TIM_CCER_CC1NP); 00583 // external mode 1 00584 TIM4->SMCR &= ~(TIM_SMCR_ECE | TIM_SMCR_TS | TIM_SMCR_SMS); 00585 TIM4->SMCR |= (TIM_TS_ITR3); // Set Internal Triger 3 (ITR3) 00586 TIM4->SMCR |= (TIM_SLAVEMODE_EXTERNAL1); // ECE must be ZERO!!!! 00587 TIM4->CR2 &= (uint16_t)~(TIM_CR2_TI1S | TIM_CR2_MMS); 00588 TIM4->CR2 |= (uint16_t)TIM_CR2_MMS_1; // TRGO update 00589 TIM4->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter 00590 // PB6 -> Input Capture pin as Timer4 IC1 00591 GPIOB->AFR[0] &= 0xf0ffffff; 00592 GPIOB->AFR[0] |= GPIO_AF2_TIM4 << 24; // 6bit x 4 00593 GPIOB->MODER &= ~(GPIO_MODER_MODER6); // AF 00594 GPIOB->MODER |= GPIO_MODER_MODER6_1; // alternate function mode 00595 GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPDR6); // PU 00596 GPIOB->PUPDR |= GPIO_PUPDR_PUPDR6_0; // Pull-up mode 00597 // Initialize Timer4 IC1 00598 TIM4->CCER &= (uint16_t)~TIM_CCER_CC1E; 00599 TIM4->CCMR1 &= ~(TIM_CCMR1_CC1S | TIM_CCMR1_IC1F); 00600 TIM4->CCMR1 |= TIM_CCMR1_CC1S_0; 00601 // positive edge 00602 TIM4->CCER &= (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP); 00603 TIM4->CCER |= (uint16_t)TIM_CCER_CC1E; // enable capture 00604 // Up counter based on gate time period 00605 time_count = 0; 00606 // Only for Debug purpose 00607 PRINTF("\r\n// Timer8(16bit high(max106MHz) clock)\r\n"); 00608 PRINTF("// and Timer4(16bit low clock) combined up counter\r\n"); 00609 PRINTF("// Set GPIO for Timer8&4\r\n"); 00610 // PB 00611 PRINTF("// PB6 -> Input Capture pin as Timer4 CH1/TI1\r\n"); 00612 PRINTF("GPIOB->AFRL 0x%08x:0x%08x\r\n",&GPIOB->AFR[0], GPIOB->AFR[0]); 00613 PRINTF("GPIOB->AFRH 0x%08x:0x%08x\r\n",&GPIOB->AFR[1], GPIOB->AFR[1]); 00614 PRINTF("GPIOB->MODER 0x%08x:0x%08x\r\n",&GPIOB->MODER, GPIOB->MODER); 00615 PRINTF("GPIOB->PUPDR 0x%08x:0x%08x\r\n",&GPIOB->PUPDR, GPIOB->PUPDR); 00616 PRINTF("GPIOB->OTYPER 0x%08x:0x%08x\r\n",&GPIOB->OTYPER, GPIOB->OTYPER); 00617 PRINTF("GPIOB->OSPEEDR 0x%08x:0x%08x\r\n",&GPIOB->OSPEEDR, GPIOB->OSPEEDR); 00618 // PC 00619 PRINTF("// PC6 -> unkown frequency input pin as Timer8 CH1/TI1\r\n"); 00620 PRINTF("// PC7 -> Input Capture pin as Timer8 CH2/TI2\r\n"); 00621 PRINTF("GPIOC->AFRL 0x%08x:0x%08x\r\n",&GPIOC->AFR[0], GPIOC->AFR[0]); 00622 PRINTF("GPIOC->AFRH 0x%08x:0x%08x\r\n",&GPIOC->AFR[1], GPIOC->AFR[1]); 00623 PRINTF("GPIOC->MODER 0x%08x:0x%08x\r\n",&GPIOC->MODER, GPIOC->MODER); 00624 PRINTF("GPIOC->PUPDR 0x%08x:0x%08x\r\n",&GPIOC->PUPDR, GPIOC->PUPDR); 00625 PRINTF("GPIOC->OTYPER 0x%08x:0x%08x\r\n",&GPIOC->OTYPER, GPIOC->OTYPER); 00626 PRINTF("GPIOC->OSPEEDR 0x%08x:0x%08x\r\n",&GPIOC->OSPEEDR, GPIOC->OSPEEDR); 00627 // TIM8 00628 PRINTF("// PC6 -> Timer8(16bit) for an external up counter mode\r\n"); 00629 PRINTF("// PC7 -> Timer8 IC2\r\n"); 00630 PRINTF("TIM8->CR1 0x%08x:0x%08x\r\n",&TIM8->CR1, TIM8->CR1); 00631 PRINTF("TIM8->CR2 0x%08x:0x%08x\r\n",&TIM8->CR2, TIM8->CR2); 00632 PRINTF("TIM8->ARR 0x%08x:0x%08x\r\n",&TIM8->ARR, TIM8->ARR); 00633 PRINTF("TIM8->PSC 0x%08x:0x%08x\r\n",&TIM8->PSC, TIM8->PSC); 00634 PRINTF("TIM8->CCMR1 0x%08x:0x%08x\r\n",&TIM8->CCMR1, TIM8->CCMR1); 00635 PRINTF("TIM8->CCMR2 0x%08x:0x%08x\r\n",&TIM8->CCMR2, TIM8->CCMR2); 00636 PRINTF("TIM8->CCER 0x%08x:0x%08x\r\n",&TIM8->CCER, TIM8->CCER); 00637 PRINTF("TIM8->SMCR 0x%08x:0x%08x\r\n",&TIM8->SMCR, TIM8->SMCR); 00638 // TIM4 00639 PRINTF("// PB6 -> Timer4 IC1\r\n"); 00640 PRINTF("TIM4->CR1 0x%08x:0x%08x\r\n",&TIM4->CR1, TIM4->CR1); 00641 PRINTF("TIM4->ARR 0x%08x:0x%08x\r\n",&TIM4->ARR, TIM4->ARR); 00642 PRINTF("TIM4->PSC 0x%08x:0x%08x\r\n",&TIM4->PSC, TIM4->PSC); 00643 PRINTF("TIM4->CCMR1 0x%08x:0x%08x\r\n",&TIM4->CCMR1, TIM4->CCMR1); 00644 PRINTF("TIM4->CCMR2 0x%08x:0x%08x\r\n",&TIM4->CCMR2, TIM4->CCMR2); 00645 PRINTF("TIM4->CCER 0x%08x:0x%08x\r\n",&TIM4->CCER, TIM4->CCER); 00646 PRINTF("TIM4->SMCR 0x%08x:0x%08x\r\n",&TIM4->SMCR, TIM4->SMCR); 00647 // Interrupt Timer4 IC1 (NOT Timer8 IC2) & Overflow 00648 tim8p4_ready_flg = 0; 00649 tim8p4_cnt_data = 0; 00650 sw_ovrflw_tim8p4 = 0; 00651 TIM8->SR = 0; // clear all IC/OC flag 00652 TIM4->SR = 0; // clear all IC/OC flag 00653 TIM4->DIER = 0; // Reset all interrupt flag 00654 TIM4->DIER = TIM_DIER_CC1IE + TIM_DIER_UIE; 00655 NVIC_SetVector(TIM4_IRQn, (uint32_t)irq_ic1_TIM8P4); 00656 NVIC_ClearPendingIRQ(TIM4_IRQn); 00657 NVIC_EnableIRQ(TIM4_IRQn); 00658 PRINTF("TIM4->DIER 0x%08x:0x%08x\r\n\r\n",&TIM4->DIER, TIM4->DIER); 00659 PRINTF("RCC->APB1ENR 0x%08x:0x%08x\r\n\r\n",&RCC->APB1ENR, RCC->APB1ENR); 00660 } 00661 00662 //------------------------------------------------------------------------------ 00663 // Frequency check for test & debug purpose 00664 //------------------------------------------------------------------------------ 00665 // Read TIM2 Clock frequency 00666 uint32_t FRQ_CUNTR::read_base_clock_frequency(double gatetime) 00667 { 00668 TIM2->CNT = 0; 00669 wait(gatetime); // Gate time for count 00670 uint32_t freq = TIM2->CNT; // read counter 00671 PRINTF("Clock freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq, gatetime); 00672 return freq; // return counter data 00673 } 00674 00675 // Read TIM8(+TIM4) Input frequency 00676 uint32_t FRQ_CUNTR::read_input_frequency(double gatetime) 00677 { 00678 TIM8->CR1 &= ~(uint16_t)TIM_CR1_CEN; // disable the TIM8 Counter 00679 TIM4->CNT = 0; 00680 TIM8->CNT = 0; 00681 TIM8->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM8 Counter 00682 wait(gatetime); // Gate time for count 00683 TIM8->CR1 &= ~(uint16_t)TIM_CR1_CEN; // disable the TIM8 Counter 00684 uint32_t freq = (TIM4->CNT << 16) + TIM8->CNT; 00685 TIM8->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM8 Counter 00686 PRINTF("Input freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq, gatetime); 00687 return freq; // read counter 00688 } 00689 00690 void FRQ_CUNTR::debug_printf_all_buffer(void) 00691 { 00692 fdt_buffer.debug_print_all_buffer(); 00693 } 00694 00695 void FRQ_CUNTR::debug_printf_internal_data(void) 00696 { 00697 printf("Debug information\r\n"); 00698 printf("ex_clock_freq %f\r\n", ex_clock_freq); 00699 printf("ex_clk_base %9d\r\n", ex_clk_base); 00700 printf("clk_hi_const %9d\r\n", clk_hi_const); 00701 printf("clk_upper_limit %9d\r\n", clk_upper_limit); 00702 printf("clk_lower_limit %9d\r\n", clk_lower_limit); 00703 printf("oc_hi_time %9d\r\n", oc_hi_time); 00704 printf("oc_lo_time %9d\r\n", oc_lo_time); 00705 printf("\r\n"); 00706 } 00707 00708 //------------------------------------------------------------------------------ 00709 // Interrupt Handlers 00710 //------------------------------------------------------------------------------ 00711 void irq_ic2_TIM2(void) 00712 { 00713 // IC2 (By GPS 1PPS) 00714 if (TIM2->SR & TIM_SR_CC2IF){ 00715 TIM2->SR &= ~TIM_SR_CC2IF; // clear IC flag 00716 tim2_cnt_data = TIM2->CCR2; 00717 tim2_ready_flg = 1; 00718 // data saves intto the ring buffer 00719 onepps_dt.freq_dt = tim2_cnt_data; 00720 onepps_dt.f_sw_dt = sw_ovrflw_tim2; 00721 onepps_dt.t_cnt = ++time_count_onepps; 00722 onepps_buf.ring_put_dt(onepps_dt.f_1sec_dt); 00723 #if ACTIVE_LED 00724 irq_led3 = !irq_led3; 00725 #endif // ACTIVE_LED 00726 } 00727 // Gate signal (every 1Sec) 00728 if (TIM2->SR & TIM_SR_CC3IF){ // Output Compare 00729 TIM2->SR &= ~TIM_SR_CC3IF; // clear OC flag 00730 TIM2->CCMR2 &= ~(TIM_CCMR2_OC3M); // Clear OC mode 00731 // Check PB10 status 00732 if (GPIOB->IDR & 0x0400){ // High level 00733 TIM2->CCR3 = TIM2->CCR3 + oc_hi_time; 00734 TIM2->CCMR2 |= TIM_CCMR2_OC3M_1; // to be low 00735 #if ACTIVE_LED 00736 irq_led2 = 1; 00737 #endif // ACTIVE_LED 00738 } else { // Low level 00739 TIM2->CCR3 = TIM2->CCR3 + oc_lo_time; 00740 TIM2->CCMR2 |= TIM_CCMR2_OC3M_0; // to be high 00741 #if ACTIVE_LED 00742 irq_led2 = 0; 00743 #endif // ACTIVE_LED 00744 } 00745 } 00746 // IC4 (for reciprocal measurement) 00747 if (TIM2->SR & TIM_SR_CC4IF){ 00748 TIM2->SR &= ~TIM_SR_CC4IF; // clear IC flag 00749 uint32_t data = TIM2->CCR4; 00750 if (recipro_step == 0){ 00751 recipro_start = data; 00752 recipro_step = 1; 00753 } else if (recipro_step == 1){ 00754 TIM2->DIER &= ~TIM_DIER_CC4IE; // disable IC4 interrupt 00755 recipro_stop = data; 00756 recipro_step = 2; 00757 } 00758 } 00759 // TIM2 overflow 00760 if (TIM2->SR & TIM_SR_UIF){ 00761 TIM2->SR &= ~TIM_SR_UIF; 00762 ++sw_ovrflw_tim2; 00763 } 00764 } 00765 00766 // TIM4 IC1 Interrupt control (same signal connected to TIM8 IC2) 00767 void irq_ic1_TIM8P4(void) 00768 { 00769 // IC1 (TIM2 Gate signal) 00770 if (TIM4->SR & TIM_SR_CC1IF){ 00771 TIM8->SR &= ~TIM_SR_CC2IF; // clear IC flag 00772 TIM4->SR &= ~TIM_SR_CC1IF; 00773 tim8p4_cnt_data = (TIM4->CCR1 << 16) + TIM8->CCR2; 00774 tim8p4_ready_flg = 1; 00775 // data saves intto the ring buffer 00776 fdt.freq_dt = tim8p4_cnt_data; 00777 fdt.f_sw_dt = sw_ovrflw_tim8p4; 00778 fdt.t_cnt = ++time_count; 00779 fdt_buffer.ring_put_dt(fdt.f_1sec_dt); 00780 #if ACTIVE_LED 00781 irq_led1 = !irq_led1; 00782 #endif // ACTIVE_LED 00783 } 00784 // TIM4 overflow 00785 if (TIM4->SR & TIM_SR_UIF){ 00786 TIM4->SR &= ~TIM_SR_UIF; 00787 ++sw_ovrflw_tim8p4; 00788 } 00789 } 00790 00791 } // Frequency_counter 00792 00793 00794 00795
Generated on Thu Jul 28 2022 09:57:44 by 1.7.2