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/
frq_cuntr_full.cpp
- Committer:
- kenjiArai
- Date:
- 2015-01-01
- Revision:
- 4:9d3b3f0a3882
- Parent:
- 3:339307e1dc0d
File content as of revision 4:9d3b3f0a3882:
/* * mbed Library / Frequency Counter with GPS 1PPS Compensation * Frequency Counter Hardware relataed program * Only for ST Nucleo F411RE * * Copyright (c) 2014 Kenji Arai / JH1PJL * http://www.page.sannet.ne.jp/kenjia/index.html * http://mbed.org/users/kenjiArai/ * Additional functions and modification * started: October 18th, 2014 * Revised: January 1st, 2015 * * 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 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if defined(TARGET_NUCLEO_F411RE) #include "frq_cuntr_full.h" #ifdef DEBUG Serial pcm(USBTX, USBRX); DigitalOut debug_led(LED1); #endif #ifdef DEBUG #define BAUD(x) pcm.baud(x) #define PRINTF(...) pcm.printf(__VA_ARGS__) #else #define BAUD(x) {;} #define PRINTF(...) {;} #endif namespace Frequency_counter { // TIM2 OC 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; static uint32_t tim2_old_cnt_data; // TIM3+4 IC static uint8_t tim3p4_ready_flg; static uint32_t tim3p4_cnt_data; //------------------------------------------------------------------------------------------------- // Interrupt Handlers //------------------------------------------------------------------------------------------------- // TIM2 IC2 Interrupt control void irq_ic2_TIM2(void) { uint16_t reg; reg = TIM2->SR; if (reg & TIM_SR_CC2IF) { TIM2->SR &= ~TIM_SR_CC2IF; // clear IC flag tim2_old_cnt_data = tim2_cnt_data; tim2_cnt_data = TIM2->CCR2; tim2_ready_flg = 1; #if defined(DEBUG) debug_led = !debug_led; #endif // defined(DEBUG) } else if (reg & TIM_SR_CC3IF) { // Output Compare TIM2->SR &= ~TIM_SR_CC3IF; // clear IC flag if (GPIOB->IDR & 0x0400) { // Check PB10 status TIM2->CCR3 = TIM2->CCR3 + oc_hi_time; } else { TIM2->CCR3 = TIM2->CCR3 + oc_lo_time; if (new_gt_value) { new_gt_value = 0; oc_hi_time = oc_set_time0; oc_lo_time = oc_set_time1; } } #if defined(DEBUG) debug_led = !debug_led; #endif // defined(DEBUG) } } // TIM3 IC2 Interrupt control (same signal connected to TIM4 IC1) void irq_ic2_TIM3P4(void) { TIM3->SR &= ~TIM_SR_CC2IF; // clear IC flag TIM4->SR &= ~TIM_SR_CC1IF; tim3p4_cnt_data = (TIM4->CCR1 << 16) + TIM3->CCR2; tim3p4_ready_flg = 1; #if defined(DEBUG) debug_led = !debug_led; #endif // defined(DEBUG) } //--------------------------------------------------------------------------------------- // Frequency Counter //--------------------------------------------------------------------------------------- FRQ_CUNTR::FRQ_CUNTR(PinName f_in, double gt, double ex_clock): _pin(f_in) { // Don't change calling sequence!! set_external_clock(ex_clock); // 1st set_gate_time(gt); // 2nd initialize_Freq_counter(); // 3rd } // Set gate time double FRQ_CUNTR::set_gate_time(double gt) { if (gt < 0.05) { gate_time = 0.05; } else if (gt > 60.0) { gate_time = 60.0; } else { gate_time = gt; } 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 - 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 clk_upper_limit = ex_clk_base + err; clk_lower_limit = ex_clk_base - err; PRINTF("EXTERNAL Clock mode\r\n"); #else // defined(BASE_EXTERNAL_CLOCK) ex_clock_freq = 100; // Internal 100MHz ex_clk_base = 100000000; // MHz->Hz clk_hi_const = 4000000; // 40mS uint32_t err = 10000; // error range clk_upper_limit = ex_clk_base + err; clk_lower_limit = ex_clk_base - err; PRINTF("INTERNAL Clock mode\r\n"); #endif // defined(BASE_EXTERNAL_CLOCK) } // Read new frequency data double FRQ_CUNTR::read_freq_data(void) { old_cntr_tim3p4 = counter_tim3p4; counter_tim3p4 = read_ic2_counter_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) uint32_t FRQ_CUNTR::status_freq_update(void) { return check_ic2_status_TIM3P4(); } // Read status (new 1PPS data is available or not) uint32_t FRQ_CUNTR::status_1pps(void) { return check_ic2_status_TIM2(); } // Read GPS 1PPS counter value uint32_t FRQ_CUNTR::set_1PPS_data(void) { uint32_t diff = tim2_cnt_data - tim2_old_cnt_data; 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; onepps_buf_full = 1; } onepps_newest = diff; return diff; } } // Avarage measued data GPS 1PPS by 25MHz External Clock uint32_t FRQ_CUNTR::read_avarage_1pps(void) { uint64_t total = 0; if (onepps_buf_full == 1) { for (uint32_t i = 0; i < CNT_BF_SIZE; i++) { total += (uint64_t)onepps_cnt[i]; } onepps_cnt_avarage = total / CNT_BF_SIZE; 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(" full, num= %3d , 1PPS/new= %9d\r\n", onepps_num, onepps_newest); return onepps_cnt_avarage; } // Newest measued data GPS 1PPS uint32_t FRQ_CUNTR::read_newest_1pps(void) { return onepps_newest; } // Check GPS condition uint8_t FRQ_CUNTR::status_gps(void) { return gps_ready; } //--------------------------------------------------------------------------------------- // TIM2 (32bit Counter + IC + OC) //--------------------------------------------------------------------------------------- // Read TIM2 captured counter value uint32_t FRQ_CUNTR::read_ic2_counter_TIM2(void) { return tim2_cnt_data; // return TIM2->CCR2; } // Check TIM2 IC2 status uint32_t FRQ_CUNTR::check_ic2_status_TIM2(void) { if (tim2_ready_flg == 0) { return 0; } else { tim2_ready_flg = 0; set_1PPS_data(); return 1; } } // Check OC port status uint8_t FRQ_CUNTR::read_oc_port_status(void) { uint32_t p = GPIOB->IDR; if (p & 0x0400) { // Check PB10 status return 1; } else { return 0; } } //--------------------------------------------------------------------------------------- // TIM3+TIM4 (32bit Counter + IC) //--------------------------------------------------------------------------------------- // Read TIM3+4(as 32bit) captured counter value uint32_t FRQ_CUNTR::read_ic2_counter_TIM3P4(void) { return tim3p4_cnt_data; } // Check TIM3 IC2 & TIM4 IC1 status uint32_t FRQ_CUNTR::check_ic2_status_TIM3P4(void) { if (tim3p4_ready_flg == 0) { return 0; } else { tim3p4_ready_flg = 0; return 1; } } //--------------------------------------------------------------------------------------- // Frequency check for test purpose //--------------------------------------------------------------------------------------- // Read TIM2 Clock frequency uint32_t FRQ_CUNTR::read_frequency_TIM2(float gate_time) { uint32_t freq = 0; 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); return freq; // return counter data } // Read TIM3(+TIM4) Input frequency uint32_t FRQ_CUNTR::read_frequency_TIM3P4(float gate_time) { uint32_t freq0 = 0; uint32_t freq1 = 0; TIM3->CNT = 0; TIM4->CNT = 0; TIM3->CNT = 0; wait(gate_time); // Gate time for count freq0 = TIM3->CNT; freq1 = TIM4->CNT; freq0 = (freq1 << 16) + freq0; PRINTF("Input freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq0, gate_time); return freq0; // read counter } //--------------------------------------------------------------------------------------- // Clock output for test purpose //--------------------------------------------------------------------------------------- // Output internal clock void FRQ_CUNTR::port_mco1_mco2_set(uint8_t select) { // PA8 -> MCO_1 GPIOA->AFR[1] &= 0xfffffff0; GPIOA->AFR[1] |= GPIO_AF0_MCO << 0; GPIOA->MODER &= ~(GPIO_MODER_MODER8); // AF GPIOA->MODER |= GPIO_MODER_MODER8_1; GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_8); // Output Push-Pull=0 GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8;// Speed full=11 GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR8); // Pull-up=01 GPIOA->PUPDR |= GPIO_PUPDR_PUPDR8_0; // PC9 -> MCO_2 GPIOC->AFR[1] &= 0xffffff0f; GPIOC->AFR[1] |= GPIO_AF0_MCO << 4; GPIOC->MODER &= ~(GPIO_MODER_MODER9); // AF GPIOC->MODER |= GPIO_MODER_MODER9_1; GPIOC->OTYPER &= ~(GPIO_OTYPER_OT_9); // Output Push-Pull=0 GPIOC->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR9;// Speed full=11 GPIOC->PUPDR &= ~(GPIO_PUPDR_PUPDR9); // Pull-up=01 GPIOC->PUPDR |= GPIO_PUPDR_PUPDR9_0; // Select output clock source RCC->CFGR &= 0x009fffff; if (select == 1) { // 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"); } 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"); } 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"); } } //--------------------------------------------------------------------------------------- // Initialize TIM2 and TIM3+4 //--------------------------------------------------------------------------------------- void FRQ_CUNTR::initialize_Freq_counter(void) { initialize_TIM2(); initialize_TIM3P4(); } // Initialize TIM2 // Internal clock (100MHz) or External clock(?MHz) and IC2 for GPS 1pps signal measurement void FRQ_CUNTR::initialize_TIM2(void) { #if defined(BASE_EXTERNAL_CLOCK) // PA0 -> Counter frequency input pin as Timer2 CH1/ETR RCC->AHB1ENR |= (RCC_AHB1ENR_GPIOAEN); GPIOA->AFR[0] &= 0xfffffff0; GPIOA->AFR[0] |= GPIO_AF1_TIM2; GPIOA->MODER &= ~(GPIO_MODER_MODER0); // AF GPIOA->MODER |= GPIO_MODER_MODER0_1; GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR0); // PU GPIOA->PUPDR |= GPIO_PUPDR_PUPDR0_0; // Initialize Timer2(32bit) for an external 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; TIM2->ARR = 0xffffffff; TIM2->PSC = 0x0000; TIM2->CCER &= (uint16_t)~TIM_CCER_CC1E; // Disable the CC1 TIM2->CCMR1 &= (uint16_t)~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S); // input filter + input select TIM2->CCMR1 |= (uint16_t)TIM_CCMR1_CC1S_0; TIM2->CCER &= (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NE | TIM_CCER_CC1NP); // positive edge TIM2->SMCR = (uint16_t)(TIM_SMCR_ECE| TIM_SMCR_ETPS_0 | TIM_SMCR_TS); // clock/2 !! TIM2->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter #else // defined(BASE_EXTERNAL_CLOCK) // 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; TIM2->ARR = 0xffffffff; TIM2->PSC = 0x0000; TIM2->CCER &= (uint16_t)~TIM_CCER_CC1E; // Disable the CC1 TIM2->SMCR &= (uint16_t)~(TIM_SMCR_ECE | TIM_SMCR_TS | TIM_SMCR_SMS); TIM2->SMCR |= (uint16_t)0; // Internal clock = 100MHz TIM2->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter #endif // defined(BASE_EXTERNAL_CLOCK) // PA1 -> Input Capture pin as Timer2 IC2 GPIOA->AFR[0] &= 0xffffff0f; GPIOA->AFR[0] |= GPIO_AF1_TIM2 << 4; GPIOA->MODER &= ~(GPIO_MODER_MODER1); // AF GPIOA->MODER |= GPIO_MODER_MODER1_1; GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR1); GPIOA->PUPDR |= GPIO_PUPDR_PUPDR1_0; // PU // Initialize Timer2 I.C.2 TIM2->CCER &= (uint16_t)~TIM_CCER_CC2E; // Disable the CC2 TIM2->CCMR1 &= (uint16_t)~(TIM_CCMR1_IC2F | TIM_CCMR1_CC2S);// input filter + input select TIM2->CCMR1 |= (uint16_t)TIM_CCMR1_CC2S_0; TIM2->CCER &= (uint16_t)~(TIM_CCER_CC2P | TIM_CCER_CC2NP); // positive edge TIM2->CCER |= (uint16_t)TIM_CCER_CC2E; // enable capture // PB10 -> Output Compare pin as Timer2 CH3/OC3 GPIOB->AFR[1] &= 0xfffff0ff; GPIOB->AFR[1] |= GPIO_AF1_TIM2 << 8; GPIOB->MODER &= ~(GPIO_MODER_MODER10); // AF GPIOB->MODER |= GPIO_MODER_MODER10_1; GPIOB->OTYPER &= ~(GPIO_OTYPER_OT_10);// Output Push-Pull=0 GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR10;// Speed full=11 GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPDR10); // Pull-up=01 GPIOB->PUPDR |= GPIO_PUPDR_PUPDR10_0; // Initialize Timer2 O.C.3 TIM2->CCER &= (uint16_t)~TIM_CCER_CC3E; // Reset the CC3E Bit TIM2->CCMR2 &= (uint16_t)~(TIM_CCMR2_OC3M | TIM_CCMR2_CC3S | TIM_CCMR2_OC3PE | TIM_CCMR2_OC3CE | TIM_CCMR2_OC3FE); TIM2->CCMR2 |= (TIM_CCMR2_OC3M_0 | TIM_CCMR2_OC3M_1); TIM2->CCER &= (uint16_t)~TIM_CCER_CC3P;// Reset the Output Polarity level TIM2->CCER |= (uint16_t)TIM_CCER_CC3E; // Set the CC3E Bit new_gt_value = 0; 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 // Only for Debug purpose BAUD(9600); // PA PRINTF("\r\n// Timer2(32bit) for an internal up counter mode\r\n"); PRINTF("// PA1 -> Input Capture pin as Timer2 CH2/TI2\r\n"); PRINTF("GPIOA->AFR[0]0x%08x:0x%08x\r\n",&GPIOA->AFR[0], GPIOA->AFR[0]); PRINTF("GPIOA->AFR[1]0x%08x:0x%08x\r\n",&GPIOA->AFR[1], GPIOA->AFR[1]); PRINTF("GPIOA->MODER 0x%08x:0x%08x\r\n",&GPIOA->MODER, GPIOA->MODER); PRINTF("GPIOA->PUPDR 0x%08x:0x%08x\r\n",&GPIOA->PUPDR, GPIOA->PUPDR); // PB PRINTF("// PB10 -> Output Compare pin as Timer2 CH3/TI3\r\n"); PRINTF("GPIOB->AFR[0]0x%08x:0x%08x\r\n",&GPIOB->AFR[0], GPIOB->AFR[0]); PRINTF("GPIOB->AFR[1]0x%08x:0x%08x\r\n",&GPIOB->AFR[1], GPIOB->AFR[1]); PRINTF("GPIOB->MODER 0x%08x:0x%08x\r\n",&GPIOB->MODER, GPIOB->MODER); PRINTF("GPIOB->PUPDR 0x%08x:0x%08x\r\n",&GPIOB->PUPDR, GPIOB->PUPDR); // TIM2 PRINTF("// PA1 -> Timer2 IC2\r\n"); PRINTF("// PB10-> Timer2 OC3\r\n"); PRINTF("TIM2->CR1 0x%08x:0x%08x\r\n",&TIM2->CR1, TIM2->CR1); PRINTF("TIM2->ARR 0x%08x:0x%08x\r\n",&TIM2->ARR, TIM2->ARR); PRINTF("TIM2->PSC 0x%08x:0x%08x\r\n",&TIM2->PSC, TIM2->PSC); PRINTF("TIM2->CCMR1 0x%08x:0x%08x\r\n",&TIM2->CCMR1, TIM2->CCMR1); PRINTF("TIM2->CCMR2 0x%08x:0x%08x\r\n",&TIM2->CCMR2, TIM2->CCMR2); 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); // Interrupt Timer2 IC2 for (uint32_t i = 0; i < CNT_BF_SIZE; i++) { onepps_cnt[i] = 0; } onepps_num = 0; onepps_ready_flg = 0; onepps_buf_full = 0; onepps_cnt_avarage = 0; tim2_ready_flg = 0; tim2_cnt_data = 0; tim2_old_cnt_data = 0; TIM2->SR &= ~(TIM_SR_CC2IF + TIM_SR_CC3IF); // clear IC flag TIM2->DIER |= TIM_DIER_CC2IE + TIM_DIER_CC3IE; NVIC_SetVector(TIM2_IRQn, (uint32_t)irq_ic2_TIM2); NVIC_ClearPendingIRQ(TIM2_IRQn); NVIC_EnableIRQ(TIM2_IRQn); } // Initialize TIM3 and TIM4 as 32bit counter (TIM3(16bit) + TIM4(16bit)) // TIM3 clock input is unkown freq.(measuring freq.) and TIM4 is slave counter // 1sec gate signal connected both TIM3 IC2 and TIM4 IC1 void FRQ_CUNTR::initialize_TIM3P4(void) { // PC6 -> Unkown frequency input pin as Timer3 CH1/TI1 RCC->AHB1ENR |= (RCC_AHB1ENR_GPIOCEN); GPIOC->AFR[0] &= 0xf0ffffff; GPIOC->AFR[0] |= GPIO_AF2_TIM3 << 24; GPIOC->MODER &= ~(GPIO_MODER_MODER6); // AF GPIOC->MODER |= GPIO_MODER_MODER6_1; GPIOC->PUPDR &= ~(GPIO_PUPDR_PUPDR6); GPIOC->PUPDR |= GPIO_PUPDR_PUPDR6_0; // PU // Initialize Timer3(16bit) for an external up counter mode RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; TIM3->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD));// count_up + div by 1 TIM3->CR1 |= (uint16_t)TIM_CR1_URS; TIM3->ARR = 0xffff; TIM3->CCER &= (uint16_t)~TIM_CCER_CC1E; // Disable the CC1 TIM3->CCMR1 &= (uint16_t)~(TIM_CCMR1_IC1F | TIM_CCMR1_CC1S); // input filter + input select TIM3->CCMR1 |= (uint16_t)TIM_CCMR1_CC1S_0; TIM3->CCER &= (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NE | TIM_CCER_CC1NP);// positive edge TIM3->SMCR &= (uint16_t)~(TIM_SMCR_ECE | TIM_SMCR_TS | TIM_SMCR_SMS);// external mode 1 TIM3->SMCR |= (uint16_t)( TIM_TS_TI1FP1 | TIM_SLAVEMODE_EXTERNAL1); // ECE must be ZERO!!!! TIM3->CR2 &= (uint16_t)~(TIM_CR2_TI1S | TIM_CR2_MMS); TIM3->CR2 |= (uint16_t)TIM_CR2_MMS_1; // TRGO update TIM3->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter // Initialize Timer4(16bit) for an slave up counter of TIM3 RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; TIM4->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD));// count_up + div by 1 TIM4->CR1 |= (uint16_t)TIM_CR1_URS; TIM4->ARR = 0xffff; TIM4->CCER &= (uint16_t)TIM_CCER_CC1E; // Capture enable TIM4->SMCR &= (uint16_t)~(TIM_SMCR_ECE | TIM_SMCR_TS | TIM_SMCR_SMS);// external mode 1 TIM4->SMCR |= (uint16_t)( TIM_TS_ITR2 | TIM_SLAVEMODE_EXTERNAL1);// ECE must be ZERO!!!! TIM4->CR2 &= (uint16_t)~(TIM_CR2_TI1S | TIM_CR2_MMS); TIM4->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter // PC7 -> Input Capture pin as Timer3 IC2 GPIOC->AFR[0] &= 0x0fffffff; GPIOC->AFR[0] |= GPIO_AF2_TIM3 << 28; GPIOC->MODER &= ~(GPIO_MODER_MODER7); // AF GPIOC->MODER |= GPIO_MODER_MODER7_1; GPIOC->PUPDR &= ~(GPIO_PUPDR_PUPDR7); GPIOC->PUPDR |= GPIO_PUPDR_PUPDR7_0; // PU // Initialize Timer3 IC2 TIM3->CCER &= (uint16_t)~TIM_CCER_CC2E; // Disable the CC2 TIM3->CCMR1 &= (uint16_t)~(TIM_CCMR1_IC2F | TIM_CCMR1_CC2S);// input filter + input select TIM3->CCMR1 |= (uint16_t)TIM_CCMR1_CC2S_0; TIM3->CCER &= (uint16_t)~(TIM_CCER_CC2P | TIM_CCER_CC2NP); // positive edge TIM3->CCER |= (uint16_t)TIM_CCER_CC2E; // enable capture // PB6 -> Input Capture pin as Timer4 IC1 GPIOB->AFR[0] &= 0xf0ffffff; GPIOB->AFR[0] |= GPIO_AF2_TIM4 << 24; GPIOB->MODER &= ~(GPIO_MODER_MODER6); // AF GPIOB->MODER |= GPIO_MODER_MODER6_1; GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPDR6); GPIOB->PUPDR |= GPIO_PUPDR_PUPDR6_0; // Pull-up=01 // Initialize Timer4 IC1 TIM4->CCER &= (uint16_t)~TIM_CCER_CC1E; TIM4->CCMR1 &= ((uint16_t)~TIM_CCMR1_CC1S) & ((uint16_t)~TIM_CCMR1_IC1F); 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 // Only for Debug purpose // PB PRINTF("// PB6 -> Input Capture pin as Timer4 CH1/TI1\r\n"); PRINTF("GPIOB->AFR[0]0x%08x:0x%08x\r\n",&GPIOB->AFR[0], GPIOB->AFR[0]); PRINTF("GPIOB->AFR[1]0x%08x:0x%08x\r\n",&GPIOB->AFR[1], GPIOB->AFR[1]); PRINTF("GPIOB->MODER 0x%08x:0x%08x\r\n",&GPIOB->MODER, GPIOB->MODER); PRINTF("GPIOB->PUPDR 0x%08x:0x%08x\r\n",&GPIOB->PUPDR, GPIOB->PUPDR); PRINTF("GPIOB->OTYPER 0x%08x:0x%08x\r\n",&GPIOB->OTYPER, GPIOB->OTYPER); PRINTF("GPIOB->OSPEEDR 0x%08x:0x%08x\r\n",&GPIOB->OSPEEDR, GPIOB->OSPEEDR); // PC PRINTF("// PC6 -> unkown frequency input pin as Timer3 CH1/TI1\r\n"); PRINTF("// PC7 -> Input Capture pin as Timer3 CH2/TI2\r\n"); PRINTF("GPIOC->AFR[0]0x%08x:0x%08x\r\n",&GPIOC->AFR[0], GPIOC->AFR[0]); PRINTF("GPIOC->AFR[1]0x%08x:0x%08x\r\n",&GPIOC->AFR[1], GPIOC->AFR[1]); PRINTF("GPIOC->MODER 0x%08x:0x%08x\r\n",&GPIOC->MODER, GPIOC->MODER); PRINTF("GPIOC->PUPDR 0x%08x:0x%08x\r\n",&GPIOC->PUPDR, GPIOC->PUPDR); PRINTF("GPIOC->OTYPER 0x%08x:0x%08x\r\n",&GPIOC->OTYPER, GPIOC->OTYPER); PRINTF("GPIOC->OSPEEDR 0x%08x:0x%08x\r\n",&GPIOC->OSPEEDR, GPIOC->OSPEEDR); // TIM3 PRINTF("// PC6 -> Timer3(16bit) for an external up counter mode\r\n"); PRINTF("// PC7 -> Timer3 IC2\r\n"); PRINTF("TIM3->CR1 0x%08x:0x%08x\r\n",&TIM3->CR1, TIM3->CR1); PRINTF("TIM3->ARR 0x%08x:0x%08x\r\n",&TIM3->ARR, TIM3->ARR); PRINTF("TIM3->PSC 0x%08x:0x%08x\r\n",&TIM3->PSC, TIM3->PSC); PRINTF("TIM3->CCMR1 0x%08x:0x%08x\r\n",&TIM3->CCMR1, TIM3->CCMR1); PRINTF("TIM3->CCMR2 0x%08x:0x%08x\r\n",&TIM3->CCMR2, TIM3->CCMR2); PRINTF("TIM3->CCER 0x%08x:0x%08x\r\n",&TIM3->CCER, TIM3->CCER); PRINTF("TIM3->SMCR 0x%08x:0x%08x\r\n",&TIM3->SMCR, TIM3->SMCR); // TIM4 PRINTF("// none-> Timer4(16bit) for an slave counter\r\n"); PRINTF("// PB6 -> Timer4 IC1\r\n"); PRINTF("TIM4->CR1 0x%08x:0x%08x\r\n",&TIM4->CR1, TIM4->CR1); PRINTF("TIM4->ARR 0x%08x:0x%08x\r\n",&TIM4->ARR, TIM4->ARR); PRINTF("TIM4->PSC 0x%08x:0x%08x\r\n",&TIM4->PSC, TIM4->PSC); PRINTF("TIM4->CCMR1 0x%08x:0x%08x\r\n",&TIM4->CCMR1, TIM4->CCMR1); PRINTF("TIM4->CCMR2 0x%08x:0x%08x\r\n",&TIM4->CCMR2, TIM4->CCMR2); 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); // Interrupt Timer3 IC2 tim3p4_ready_flg = 0; tim3p4_cnt_data = 0; TIM3->SR &= ~TIM_SR_CC2IF; // clear IC flag TIM4->SR &= ~TIM_SR_CC1IF; TIM3->DIER |= TIM_DIER_CC2IE; NVIC_SetVector(TIM3_IRQn, (uint32_t)irq_ic2_TIM3P4); NVIC_ClearPendingIRQ(TIM3_IRQn); NVIC_EnableIRQ(TIM3_IRQn); } //--------------------------------------------------------------------------------------- // Only for Debug purpose //--------------------------------------------------------------------------------------- void FRQ_CUNTR::debug_printf_internal_data(void) { 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"); } } // Frequency_counter #endif // #if defined(TARGET_NUCLEO_F411RE)