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/
Revision 4:3c589d2aad5c, committed 2020-01-13
- Comitter:
- kenjiArai
- Date:
- Mon Jan 13 07:41:08 2020 +0000
- Parent:
- 3:61bea8bfe404
- Commit message:
- Modified only for STM32F series (Tested on Nucleo-F401RE,-F411RE and F446RE)
Changed in this revision
freq_counter.cpp | Show annotated file Show diff for this revision Revisions of this file |
freq_counter.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/freq_counter.cpp Wed Oct 22 00:35:23 2014 +0000 +++ b/freq_counter.cpp Mon Jan 13 07:41:08 2020 +0000 @@ -2,104 +2,133 @@ * 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 + * Copyright (c) 2014,'15,'20 Kenji Arai / JH1PJL + * http://www7b.biglobe.ne.jp/~kenjia/ + * https://os.mbed.com/users/kenjiArai/ + * Created: October 18th, 2014 + * Revised: January 13th, 2020 * - * 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/ +//------------------------------------------------------------------------------ +// Reference program +// 5MHzOSC +// https://os.mbed.com/users/mio/code/5MHzOSC/ +// by fuyono sakura +// https://os.mbed.com/users/mio/ #include "mbed.h" #include "freq_counter.h" -F_COUNTER::F_COUNTER(PinName f_in): _pin(f_in) +#define WAIT_US 100 + +F_COUNTER::F_COUNTER(PinName f_in, float gate_time): _pin(f_in) { + pin_num = f_in; + gt = (uint32_t)(gate_time * 1000000.0f); + _t.attach_us(callback(this, &F_COUNTER::irq), gt); + new_input = false; 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; + if(pin_num <= PA_15) { + switch (pin_num) { + case PA_0: + // PA0 -> Counter frequency input pin as Timer2 TI1 + GPIOA->AFR[0] &= 0xfffffff0; // bit 0 + GPIOA->AFR[0] |= GPIO_AF1_TIM2; + GPIOA->MODER &= ~(GPIO_MODER_MODER0); + GPIOA->MODER |= 0x2; + break; + case PA_1: + // PA1 -> Counter frequency input pin as Timer2 TI2 + GPIOA->AFR[0] &= 0xffffff0f; // bit 1 + GPIOA->AFR[0] |= GPIO_AF1_TIM2 << (1 * 4); + GPIOA->MODER &= ~(GPIO_MODER_MODER1); + GPIOA->MODER |= 0x2 << (1 * 2); + break; + default: + return; + } + } else if (pin_num == PB_3) { + // PB3 -> Counter frequency input pin as Timer2 TI2 + GPIOB->AFR[0] &= 0xffff0fff; // bit 3 + GPIOB->AFR[0] |= GPIO_AF1_TIM2 << (3 * 4); + GPIOB->MODER &= ~(GPIO_MODER_MODER3); + GPIOB->MODER |= 0x2 << (3 * 2); + } else { + return; + } // 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 + // count_up + div by 1 + TIM2->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD)); 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 + if (pin_num == PA_0) { + TIM2->CCMR1 &= (uint16_t)~TIM_CCMR1_IC1F; // input filter + TIM2->CCER = TIM_CCER_CC1P; // positive edge + // external mode 1 + TIM2->SMCR |= (uint16_t)(TIM_TS_TI1FP1 | TIM_SMCR_SMS); + } else if ((pin_num == PA_1) || (pin_num == PB_3)) { + TIM2->CCMR1 &= (uint16_t)~TIM_CCMR1_IC2F; // input filter + TIM2->CCER = TIM_CCER_CC2P; // positive edge + // external mode 1 + TIM2->SMCR |= (uint16_t)(TIM_TS_TI2FP2 | TIM_SMCR_SMS); + } 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) +int32_t F_COUNTER::read_frequency() { -#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; + int32_t count = gt * 2 / WAIT_US; + while (new_input == false) { + wait_us(WAIT_US); + if (--count < 0) { + return -1; + } + } + new_input = false; + if ((pin_num == PA_0) || (pin_num == PA_1) || (pin_num == PB_3)) { + return freq_raw; + } else { + return -1; + } } +void F_COUNTER::set_gate_time(float gate_time) +{ + _t.detach(); + gt = (uint32_t)(gate_time * 1000000.0f); + _t.attach_us(callback(this, &F_COUNTER::irq), gt); + // delete transient uncorrect data + new_input = false; + int32_t count = gt / WAIT_US; + while (new_input == false) { + wait_us(WAIT_US); + if (--count < 0) { + break; + } + } + new_input = false; +} + +uint32_t F_COUNTER::read_pin() +{ + return pin_num; +} + +void F_COUNTER::irq() +{ + freq_raw = TIM2->CNT; // read counter + TIM2->CNT = 0; + new_input = true; +} + +//------------------------ Reference Program ----------------------------------- #if 0 // // CLOCK OUT to PWM1[6] Sample with Freq Counter using Cap2.0 @@ -167,67 +196,3 @@ } #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
--- a/freq_counter.h Wed Oct 22 00:35:23 2014 +0000 +++ b/freq_counter.h Mon Jan 13 07:41:08 2020 +0000 @@ -2,17 +2,12 @@ * 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/ - * Created: October 18th, 2014 - * Revised: October 22nd, 2014 + * Copyright (c) 2014,'15,'20 Kenji Arai / JH1PJL + * http://www7b.biglobe.ne.jp/~kenjia/ + * https://os.mbed.com/users/kenjiArai/ + * Created: October 18th, 2014 + * Revised: January 13th, 2020 * - * 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. */ #ifndef MBED_F_COUNTER @@ -20,21 +15,22 @@ #include "mbed.h" +/* + CAUTION: Direct access to the CPU Timer module!! + No way to change pin assign and timer module + Tested on Nucleo F401RE, F411RE & F446RE + Tested on mbed-os5.15.0 & mbed-2.0.165 + + Input pin selection -> Only PA0, PA1, PB3 + */ + /** Frequency Counter * - * CAUTION: Direct access to the CPU Timer module!! - * No way to change pin assign and timer module, - * mbed LPC1768 -> p30, - * mbed LPC1114FN28 -> dp14, - * Nucleo F401RE & Nucleo F411RE -> PA_0/A0 - * * @code * #include "mbed.h" * #include "freq_counter.h" - * - * F_COUNTER fc(p30); // for LPC1768 - * //F_COUNTER fc(dp14); // for LPC1114 - * //F_COUNTER fc(PA_0); // for F401 & F411 + * + * F_COUNTER fc(PA_0); // for F401,F411 & F446 * * int main() { * uint32_t frequency = 0; @@ -52,22 +48,40 @@ public: /** Configure data pin * @param frequency counter input pin + * @param gate time (seconds) */ - F_COUNTER(PinName f_in); + F_COUNTER(PinName f_in, float gate_time = 1.0f); /** Read measured frequency - * @param gate time - * @return measured frequency + * @param none + * @return measured frequency (minus = input pin is incorrect) */ - uint32_t read_frequency(float gate_time); + int32_t read_frequency(void); + + /** Set new gate time + * @param new gate time (seconds) + * @return none + */ + void set_gate_time(float gat_time); + + /** Read input assign number + * @param none + * @return Pin number + */ + uint32_t read_pin(); protected: DigitalIn _pin; + Ticker _t; void initialize(void); + void irq(void); private: - uint32_t freq; + uint32_t pin_num; + float gt; + int32_t freq_raw; + bool new_input; };