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
Please refer following.
/users/kenjiArai/notebook/frequency-counters/
Diff: frq_cuntr_full.cpp
- Revision:
- 2:194f82ad3041
- Parent:
- 1:102230f2879d
- Child:
- 3:339307e1dc0d
diff -r 102230f2879d -r 194f82ad3041 frq_cuntr_full.cpp --- a/frq_cuntr_full.cpp Sat Nov 22 23:02:39 2014 +0000 +++ b/frq_cuntr_full.cpp Sun Dec 21 12:14:46 2014 +0000 @@ -8,7 +8,7 @@ * http://mbed.org/users/kenjiArai/ * Additional functions and modification * started: October 18th, 2014 - * Revised: Nobember 23rd, 2014 + * Revised: December 21st, 2014 * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE @@ -41,11 +41,11 @@ namespace Frequency_counter { // TIM2 OC -uint32_t oc_set_time0; -uint32_t oc_set_time1; -uint8_t new_gt_value; -uint32_t oc_hi_time; -uint32_t oc_lo_time; +static uint32_t oc_set_time0; +static uint32_t oc_set_time1; +static uint8_t new_gt_value; +static uint32_t oc_hi_time; +static uint32_t oc_lo_time; // TIM2 IC static uint8_t tim2_ready_flg; static uint32_t tim2_cnt_data; @@ -55,7 +55,7 @@ static uint32_t tim3p4_cnt_data; //------------------------------------------------------------------------------------------------- -// Control Program +// Interrupt Handlers //------------------------------------------------------------------------------------------------- // TIM2 IC2 Interrupt control void irq_ic2_TIM2(void) @@ -67,9 +67,12 @@ tim2_old_cnt_data = tim2_cnt_data; tim2_cnt_data = TIM2->CCR2; tim2_ready_flg = 1; - } else if (reg & TIM_SR_CC3IF) { +#if defined(DEBUG) + debug_led = !debug_led; +#endif + } else if (reg & TIM_SR_CC3IF) { // Output Compare TIM2->SR &= ~TIM_SR_CC3IF; // clear IC flag - if (GPIOB->IDR & 0x0400) { // Check PB10 status + if (GPIOB->IDR & 0x0400) { // Check PB10 status TIM2->CCR3 = TIM2->CCR3 + oc_hi_time; } else { TIM2->CCR3 = TIM2->CCR3 + oc_lo_time; @@ -80,7 +83,7 @@ } } #if defined(DEBUG) - debug_led = !debug_led; +// debug_led = !debug_led; #endif } } @@ -93,17 +96,19 @@ tim3p4_cnt_data = (TIM4->CCR1 << 16) + TIM3->CCR2; tim3p4_ready_flg = 1; #if defined(DEBUG) - debug_led = !debug_led; +// debug_led = !debug_led; #endif } //--------------------------------------------------------------------------------------- // Frequency Counter //--------------------------------------------------------------------------------------- -FRQ_CUNTR::FRQ_CUNTR(PinName f_in, double gt): _pin(f_in) +FRQ_CUNTR::FRQ_CUNTR(PinName f_in, double gt, double ex_clock): _pin(f_in) { - set_gate_time(gt); - initialize_Freq_counter(); + // Don't change calling sequence!! + set_external_clock(ex_clock); // 1st + set_gate_time(gt); // 2nd + initialize_Freq_counter(); // 3rd } // Set gate time @@ -116,23 +121,52 @@ } else { gate_time = gt; } - oc_set_time0 = CNT_FIX_BASE; - double gt_tmp0 = CNT_BASE * gate_time; + oc_set_time0 = clk_hi_const; + double gt_tmp0 = ex_clk_base * gate_time; uint32_t gt_tmp1 = (uint32_t)gt_tmp0; if ((gt_tmp0 - (double)gt_tmp1) >= 0.5) { ++gt_tmp1; } - oc_set_time1 = gt_tmp1 - CNT_FIX_BASE; + oc_set_time1 = gt_tmp1 - clk_hi_const; new_gt_value = 1; return gate_time; } +// Read gate time +double FRQ_CUNTR::read_gate_time(void) +{ + return gate_time; +} + +// Set External Clock Frequency +void FRQ_CUNTR::set_external_clock(double ex_clock) +{ +#if defined(BASE_EXTERNAL_CLOCK) + ex_clock_freq = ex_clock; + ex_clk_base = (uint32_t)(ex_clock_freq * 1000000); // MHz->Hz + clk_hi_const = (uint32_t)(ex_clock_freq * 1000000 * 0.04); // 40mS +// uint32_t err = (uint32_t)(ex_clock_freq * 1000000 * 0.00001); // 10ppm error range + uint32_t err = (uint32_t)(ex_clock_freq * 1000000 * 0.1); + clk_upper_limit = ex_clk_base + err; + clk_lower_limit = ex_clk_base - err; +#else + ex_clock_freq = 100; // Internal 100MHz + ex_clk_base = 100000000; // MHz->Hz + clk_hi_const = 4000000; // 40mS + uint32_t err = 100; // 10ppm error range + clk_upper_limit = ex_clk_base + err; + clk_lower_limit = ex_clk_base - err; +#endif +} + // Read new frequency data -uint32_t FRQ_CUNTR::read_freq_data(void) +double FRQ_CUNTR::read_freq_data(void) { old_cntr_tim3p4 = counter_tim3p4; counter_tim3p4 = read_ic2_counter_TIM3P4(); - return (counter_tim3p4 - old_cntr_tim3p4); + double freq0 = (double)(counter_tim3p4 - old_cntr_tim3p4); + newest_frequency = freq0 / gate_time; + return newest_frequency; } // Read status (new frequency data is available or not) @@ -151,9 +185,12 @@ uint32_t FRQ_CUNTR::set_1PPS_data(void) { uint32_t diff = tim2_cnt_data - tim2_old_cnt_data; - if ((diff > CNT_UPPER) || (diff < CNT_LOWER)) { + if ((diff > clk_upper_limit) || (diff < clk_lower_limit)) { +// PRINTF("IC0 %d %d %d \r\n", diff, clk_upper_limit, clk_lower_limit); + gps_ready = 0; return 0; } else { + gps_ready = 1; onepps_cnt[onepps_num] = diff; if (++onepps_num >= CNT_BF_SIZE) { onepps_num = 0; @@ -173,16 +210,26 @@ total += (uint64_t)onepps_cnt[i]; } onepps_cnt_avarage = total / CNT_BF_SIZE; - PRINTF("buf"); +// PRINTF("buf"); } else { for (uint32_t i = 0; i < onepps_num; i++) { total += (uint64_t)onepps_cnt[i]; } onepps_cnt_avarage = total / onepps_num; - PRINTF("not"); +// PRINTF("not"); } - PRINTF(" full, num= %3d , 1PPS/new= %9d , ", onepps_num, onepps_newest); +// PRINTF(" full, num= %3d , 1PPS/new= %9d\r\n", onepps_num, onepps_newest); +#if defined(ONEPPS_AVE) return onepps_cnt_avarage; +#else + return onepps_newest; +#endif +} + +// Check GPS condition +uint8_t FRQ_CUNTR::gps_status(void) +{ + return gps_ready; } //--------------------------------------------------------------------------------------- @@ -247,7 +294,7 @@ TIM2->CNT = 0; wait(gate_time); // Gate time for count freq = TIM2->CNT; // read counter - PRINTF("Clock freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq, gate_time); +// PRINTF("Clock freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq, gate_time); return freq; // return counter data } @@ -263,7 +310,7 @@ freq0 = TIM3->CNT; freq1 = TIM4->CNT; freq0 = (freq1 << 16) + freq0; - PRINTF("Input freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq0, gate_time); +// PRINTF("Input freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq0, gate_time); return freq0; // read counter } @@ -297,17 +344,17 @@ // MC01 output HSE 1/1, MCO2 output SYSCLK 1/1 // MCO2 MCO2PRE MCO1PRE MCO1 RCC->CFGR |= (0x0 << 30) + (0x0 << 27) + (0x0 << 24) + (0x2 << 21); - PRINTF("Set MCO1(PA8):HSE/1, MCO2(PC9):SYSCLK/1\r\n"); +// PRINTF("Set MCO1(PA8):HSE/1, MCO2(PC9):SYSCLK/1\r\n"); } else if (select == 2) { // MC01 output HSE 1/2, MCO2 output SYSCLK 1/2 // MCO2 MCO2PRE MCO1PRE MCO1 RCC->CFGR |= (0x0 << 30) + (0x4 << 27) + (0x4 << 24) + (0x2 << 21); - PRINTF("Set MCO1(PA8):HSE/2, MCO2(PC9):SYSCLK/2\r\n"); +// PRINTF("Set MCO1(PA8):HSE/2, MCO2(PC9):SYSCLK/2\r\n"); } else { // select = 4 and other wrong order // MC01 output HSE 1/4, MCO2 output SYSCLK 1/4 // MCO2 MCO2PRE MCO1PRE MCO1 RCC->CFGR |= (0x0 << 30) + (0x6 << 27) + (0x6 << 24) + (0x2 << 21); - PRINTF("Set MCO1(PA8):HSE/4, MCO2(PC9):SYSCLK/4\r\n"); +// PRINTF("Set MCO1(PA8):HSE/4, MCO2(PC9):SYSCLK/4\r\n"); } } @@ -347,7 +394,7 @@ TIM2->SMCR |= (uint16_t)( TIM_TS_TI1FP1 | TIM_SLAVEMODE_EXTERNAL1); // ECE must be ZERO!!!! TIM2->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter #else - // Initialize Timer2(32bit) for an external up counter mode + // Initialize Timer2(32bit) for an internal up counter mode RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; TIM2->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD)); // count_up + div by 1 TIM2->CR1 |= TIM_CR1_URS; @@ -391,6 +438,7 @@ oc_hi_time = oc_set_time0; oc_lo_time = oc_set_time1; TIM2->CCR3 = TIM2->CNT + oc_hi_time;// Set the Capture Compare Register value +#if 0 // Only for Debug purpose BAUD(9600); // PA @@ -417,6 +465,7 @@ PRINTF("TIM2->CCER 0x%08x:0x%08x\r\n",&TIM2->CCER, TIM2->CCER); PRINTF("TIM2->SMCR 0x%08x:0x%08x\r\n",&TIM2->SMCR, TIM2->SMCR); PRINTF("TIM2->CCR3 0x%08x:0x%08x\r\n\r\n",&TIM2->CCR3, TIM2->CCR3); +#endif // Interrupt Timer2 IC2 for (uint32_t i = 0; i < CNT_BF_SIZE; i++) { onepps_cnt[i] = 0; @@ -498,6 +547,7 @@ TIM4->CCMR1 |= (uint16_t)TIM_CCMR1_CC1S_0; TIM4->CCER &= (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP); // positive edge TIM4->CCER |= (uint16_t)TIM_CCER_CC1E; // enable capture +#if 0 // Only for Debug purpose // PB PRINTF("// PB6 -> Input Capture pin as Timer4 CH1/TI1\r\n"); @@ -537,6 +587,7 @@ PRINTF("TIM4->CCER 0x%08x:0x%08x\r\n",&TIM4->CCER, TIM4->CCER); PRINTF("TIM4->SMCR 0x%08x:0x%08x\r\n\r\n",&TIM4->SMCR, TIM4->SMCR); PRINTF("RCC->APB1ENR 0x%08x:0x%08x\r\n\r\n",&RCC->APB1ENR, RCC->APB1ENR); +#endif // Interrupt Timer3 IC2 tim3p4_ready_flg = 0; tim3p4_cnt_data = 0; @@ -548,4 +599,21 @@ NVIC_EnableIRQ(TIM3_IRQn); } +//--------------------------------------------------------------------------------------- +// Only for Debug purpose +//--------------------------------------------------------------------------------------- +void FRQ_CUNTR::debug_printf_internal_data(void) +{ +#if 0 + PRINTF("Debug information\r\n"); + PRINTF("gate_time %f\r\n", gate_time); + PRINTF("ex_clock_freq %f\r\n", ex_clock_freq); + PRINTF("ex_clk_base %9d\r\n", ex_clk_base); + PRINTF("clk_hi_const %9d\r\n", clk_hi_const); + PRINTF("clk_upper_limit %9d\r\n", clk_upper_limit); + PRINTF("clk_lower_limit %9d\r\n", clk_lower_limit); + PRINTF("\r\n"); +#endif +} + } // Frequency_counter