Simple frequency counter, run without modification on Nucleo board, Input pin PA0, PA1, PB3. Only for STM32F4 series (Tested on Nucleo-F401RE,-F411RE and F446RE)
Dependents: Frequency_Counter_for_STM32F4xx
see /users/kenjiArai/notebook/frequency-counters/
freq_counter.cpp
- Committer:
- kenjiArai
- Date:
- 2014-10-22
- Revision:
- 3:61bea8bfe404
- Parent:
- 2:54c05b0a117a
- Child:
- 4:3c589d2aad5c
File content as of revision 3:61bea8bfe404:
/* * mbed Library program * Frequency Counter Hardware relataed program * * 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: October 22nd, 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 * 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. */ //------------------------------------------------------------------------------------------------- // Reference program No.1 (see line 104) //------------------------------------------------------------------------------------------------- // 5MHzOSC // http://developer.mbed.org/users/mio/code/5MHzOSC/ // by fuyono sakura // http://developer.mbed.org/users/mio/ //------------------------------------------------------------------------------------------------- // Reference program No.2 (see line 173) //------------------------------------------------------------------------------------------------- // fc114 // http://developer.mbed.org/users/rutles/code/fc1114/ // by Tetsuya Suzuki // http://developer.mbed.org/users/rutles/ #include "mbed.h" #include "freq_counter.h" F_COUNTER::F_COUNTER(PinName f_in): _pin(f_in) { initialize(); } void F_COUNTER::initialize(void) { #if defined(TARGET_LPC1768) LPC_SC->PCONP |= 1 << 22; // 1)Power up TimerCounter3 (bit23) LPC_PINCON->PINSEL0 |= 3 << 8; // 2)Set P0[23] to CAP3[0] LPC_TIM2->TCR = 2; // 3)Counter Reset (bit1<=1,bit0<=0) LPC_TIM2->CTCR = 1; // 4)Count on riging edge Cap3[0] LPC_TIM2->CCR = 0; // 5)Input Capture Disabled LPC_TIM2->TCR = 1; // 6)Counter Start (bit1<=0,bit0<=1) #elif defined(TARGET_LPC1114) LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 9); //TMR32B0 wakeup LPC_IOCON->PIO1_5 |= (1 << 1); // Set dp14 (pin20) as CT32B0_CAP0 LPC_IOCON->PIO1_5 |= (1 << 5); // Hysteresis enable LPC_TMR32B0->TCR = 2; // reset LPC_TMR32B0->CTCR = 1; // counter mode LPC_TMR32B0->CCR = 0; // Input Capture Disable) LPC_TMR32B0->PR = 0; // no prescale LPC_TMR32B0->TCR = 1; // start #elif defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE) // PA0 -> Counter frequency input pin as Timer2 TI1 GPIOA->AFR[0] &= 0xfffffff0; GPIOA->AFR[0] |= GPIO_AF1_TIM2; GPIOA->MODER &= ~(GPIO_MODER_MODER0); GPIOA->MODER |= 0x2; // Initialize Timer2(32bit) for an external up counter mode RCC->APB1ENR |= ((uint32_t)0x00000001); TIM2->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD)); // count_up + div by 1 TIM2->ARR = 0xFFFFFFFF; TIM2->PSC = 0x0000; TIM2->CCMR1 &= (uint16_t)~TIM_CCMR1_IC1F; // input filter TIM2->CCER = TIM_CCER_CC1P; // positive edge TIM2->SMCR &= (uint16_t)~(TIM_SMCR_SMS | TIM_SMCR_TS | TIM_SMCR_ECE); TIM2->SMCR |= (uint16_t)(TIM_TS_TI1FP1 | TIM_SMCR_SMS); // external mode 1 TIM2->CR1 |= TIM_CR1_CEN; //Enable the TIM Counter #else #error "No support for this CPU" #endif } uint32_t F_COUNTER::read_frequency(float gate_time) { #if defined(TARGET_LPC1768) LPC_TIM2->TCR = 2; // Reset the counter (bit1<=1,bit0<=0) LPC_TIM2->TCR = 1; // UnReset counter (bit1<=0,bit0<=1) wait(gate_time); // Gate time for count freq = LPC_TIM2->TC; // read counter #elif defined(TARGET_LPC1114) LPC_TMR32B0->TCR = 2; // reset LPC_TMR32B0->TCR = 1; // start wait(gate_time); // Gate time for count freq = LPC_TMR32B0->TC; // read counter #elif defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE) TIM2->CNT = 0; wait(gate_time); // Gate time for count freq = TIM2->CNT; // read counter #else #error "No support for this CPU" #endif return freq; } #if 0 // // CLOCK OUT to PWM1[6] Sample with Freq Counter using Cap2.0 // For LPC1768-mbed // // Reference: 5MHz Clock Out Code and Comment - http://mbed.org/forum/mbed/topic/733/ // // !! To Self Measurement Output Clock, Connect p21 <-> p30 with jumper wire. // 2013.6.18 : Wrong comment about MR6 and Duty fix. // #include "mbed.h" PwmOut fmclck(p21); // for RESERVE pin21 as PWM1[6] DigitalIn clkin(p30); // for RESERVE pin30 as CAP2[0] // Reset Counter and Count Start void P30_RESET_CTR(void) { LPC_TIM2->TCR = 2; // Reset the counter (bit1<=1,bit0<=0) LPC_TIM2->TCR = 1; // UnReset counter (bit1<=0,bit0<=1) } // Get Counter Value int P30_GET_CTR(void) { return LPC_TIM2->TC; // Read the counter value } // Setting p30 to Cap2.0 void P30_INIT_CTR(void) { LPC_SC->PCONP |= 1 << 22; // 1)Power up TimerCounter2 (bit22) LPC_PINCON->PINSEL0 |= 3 << 8; // 2)Set P0[4] to CAP2[0] LPC_TIM2->TCR = 2; // 3)Counter Reset (bit1<=1,bit0<=0) LPC_TIM2->CTCR = 1; // 4)Count on riging edge Cap2[0] LPC_TIM2->CCR = 0; // 5)Input Capture Disabled LPC_TIM2->TCR = 1; // 6)Counter Start (bit1<=0,bit0<=1) } // Clock Output From pin21(PWM6) // Set Clock Freq with div. // if mbed is running at 96MHz, div is set 96 to Get 1MHz. void PWM6_SETCLK(int div) { LPC_PWM1->TCR = (1 << 1); // 1)Reset counter, disable PWM LPC_SC->PCLKSEL0 &= ~(0x3 << 12); LPC_SC->PCLKSEL0 |= (1 << 12); // 2)Set peripheral clock divider to /1, i.e. system clock LPC_PWM1->MR0 = div - 1; // 3)Match Register 0 is shared period counter for all PWM1 LPC_PWM1->MR6 = (div + 1)>> 1; // LPC_PWM1->LER |= 1; // 4)Start updating at next period start LPC_PWM1->TCR = (1 << 0) || (1 << 3); // 5)Enable counter and PWM } int main() { PWM6_SETCLK(19) ; // Outout mbed's "PWM6" pin to 96MHZ/19 = 5.052MHz (Approx) // PWM6_SETCLK(96) ; // Outout mbed's "PWM6" pin to 96MHZ/96 = 1.000MHz (Approx) P30_INIT_CTR(); while(1) { P30_RESET_CTR(); wait(1.0); // Gate time for count printf("pin30 Freq = %d (Hz)\r\n",P30_GET_CTR()); } } #endif #if 0 // fc1114 - Frequency counter with i2c slave. // target: LPC1114FN28 #include "mbed.h" #define I2C_ADRS 0x70 DigitalOut led(dp28); I2CSlave slave(dp5, dp27); Ticker tick; volatile uint32_t frq; void isr_tick() { frq = LPC_TMR32B0->TC; LPC_TMR32B0->TC = 0; led = !led; } int main() { union { char b[4]; uint32_t w; } buf; char dummy[4]; led = 1; tick.attach(&isr_tick, 1); LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 9);//TMR32B0 wakeup LPC_IOCON->PIO1_5 |= (1 << 1);// Set PIN14 as CT32B0_CAP0 LPC_IOCON->PIO1_5 |= (1 << 5);// Hysteresis enable LPC_TMR32B0->TCR = 2; // reset LPC_TMR32B0->CTCR = 1; // counter mode LPC_TMR32B0->CCR = 0; // Input Capture Disable) LPC_TMR32B0->PR = 0;// no prescale LPC_TMR32B0->TCR = 1; // start slave.address(I2C_ADRS << 1); while (1) { int i = slave.receive(); switch (i) { case I2CSlave::ReadAddressed: buf.w = frq; slave.write(buf.b, 4); break; case I2CSlave::WriteGeneral: slave.read(dummy, 4); break; case I2CSlave::WriteAddressed: slave.read(dummy, 4); break; } } } #endif