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/

Committer:
kenjiArai
Date:
Tue Oct 21 11:19:54 2014 +0000
Revision:
2:54c05b0a117a
Parent:
1:fd2e1c853ab6
Child:
3:61bea8bfe404
Added Nucleo-F411RE Board

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:83661d0d09c0 1 /*
kenjiArai 0:83661d0d09c0 2 * mbed Library program
kenjiArai 0:83661d0d09c0 3 * Frequency Counter Hardware relataed program
kenjiArai 0:83661d0d09c0 4 *
kenjiArai 0:83661d0d09c0 5 * Copyright (c) 2014 Kenji Arai / JH1PJL
kenjiArai 0:83661d0d09c0 6 * http://www.page.sannet.ne.jp/kenjia/index.html
kenjiArai 0:83661d0d09c0 7 * http://mbed.org/users/kenjiArai/
kenjiArai 2:54c05b0a117a 8 * Additional functions and modification
kenjiArai 0:83661d0d09c0 9 * started: October 18th, 2014
kenjiArai 1:fd2e1c853ab6 10 * Revised: October 21st, 2014
kenjiArai 0:83661d0d09c0 11 *
kenjiArai 0:83661d0d09c0 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
kenjiArai 0:83661d0d09c0 13 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
kenjiArai 0:83661d0d09c0 14 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
kenjiArai 0:83661d0d09c0 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
kenjiArai 0:83661d0d09c0 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
kenjiArai 0:83661d0d09c0 17 */
kenjiArai 2:54c05b0a117a 18 //-------------------------------------------------------------------------------------------------
kenjiArai 2:54c05b0a117a 19 // Reference program
kenjiArai 2:54c05b0a117a 20 //-------------------------------------------------------------------------------------------------
kenjiArai 2:54c05b0a117a 21 // 5MHzOSC
kenjiArai 2:54c05b0a117a 22 // http://developer.mbed.org/users/mio/code/5MHzOSC/
kenjiArai 2:54c05b0a117a 23 // by fuyono sakura
kenjiArai 2:54c05b0a117a 24 // http://developer.mbed.org/users/mio/
kenjiArai 0:83661d0d09c0 25
kenjiArai 0:83661d0d09c0 26 #include "mbed.h"
kenjiArai 0:83661d0d09c0 27 #include "freq_counter.h"
kenjiArai 0:83661d0d09c0 28
kenjiArai 0:83661d0d09c0 29 F_COUNTER::F_COUNTER(PinName f_in): _pin(f_in)
kenjiArai 0:83661d0d09c0 30 {
kenjiArai 0:83661d0d09c0 31 initialize();
kenjiArai 0:83661d0d09c0 32 }
kenjiArai 0:83661d0d09c0 33
kenjiArai 0:83661d0d09c0 34 void F_COUNTER::initialize(void)
kenjiArai 0:83661d0d09c0 35 {
kenjiArai 0:83661d0d09c0 36 #if defined(TARGET_LPC1768)
kenjiArai 0:83661d0d09c0 37 LPC_SC->PCONP |= 1 << 22; // 1)Power up TimerCounter3 (bit23)
kenjiArai 0:83661d0d09c0 38 LPC_PINCON->PINSEL0 |= 3 << 8; // 2)Set P0[23] to CAP3[0]
kenjiArai 0:83661d0d09c0 39 LPC_TIM2->TCR = 2; // 3)Counter Reset (bit1<=1,bit0<=0)
kenjiArai 0:83661d0d09c0 40 LPC_TIM2->CTCR = 1; // 4)Count on riging edge Cap3[0]
kenjiArai 0:83661d0d09c0 41 LPC_TIM2->CCR = 0; // 5)Input Capture Disabled
kenjiArai 0:83661d0d09c0 42 LPC_TIM2->TCR = 1; // 6)Counter Start (bit1<=0,bit0<=1)
kenjiArai 2:54c05b0a117a 43 #elif defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
kenjiArai 1:fd2e1c853ab6 44 // PA0 -> Counter frequency input pin as Timer2 TI1
kenjiArai 1:fd2e1c853ab6 45 GPIOA->AFR[0] &= 0xfffffff0;
kenjiArai 1:fd2e1c853ab6 46 GPIOA->AFR[0] |= GPIO_AF1_TIM2;
kenjiArai 1:fd2e1c853ab6 47 GPIOA->MODER &= ~(GPIO_MODER_MODER0);
kenjiArai 1:fd2e1c853ab6 48 GPIOA->MODER |= 0x2;
kenjiArai 1:fd2e1c853ab6 49 // Initialize Timer2(32bit) for an external up counter mode
kenjiArai 1:fd2e1c853ab6 50 RCC->APB1ENR |= ((uint32_t)0x00000001);
kenjiArai 1:fd2e1c853ab6 51 TIM2->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD)); // count_up + div by 1
kenjiArai 1:fd2e1c853ab6 52 TIM2->ARR = 0xFFFFFFFF;
kenjiArai 1:fd2e1c853ab6 53 TIM2->PSC = 0x0000;
kenjiArai 1:fd2e1c853ab6 54 TIM2->CCMR1 &= (uint16_t)~TIM_CCMR1_IC1F; // input filter
kenjiArai 1:fd2e1c853ab6 55 TIM2->CCER = TIM_CCER_CC1P; // positive edge
kenjiArai 1:fd2e1c853ab6 56 TIM2->SMCR &= (uint16_t)~(TIM_SMCR_SMS | TIM_SMCR_TS | TIM_SMCR_ECE);
kenjiArai 1:fd2e1c853ab6 57 TIM2->SMCR |= (uint16_t)(TIM_TS_TI1FP1 | TIM_SMCR_SMS); // external mode 1
kenjiArai 1:fd2e1c853ab6 58 TIM2->CR1 |= TIM_CR1_CEN; //Enable the TIM Counter
kenjiArai 0:83661d0d09c0 59 #else
kenjiArai 0:83661d0d09c0 60 #error "No support for this CPU"
kenjiArai 0:83661d0d09c0 61 #endif
kenjiArai 0:83661d0d09c0 62 }
kenjiArai 0:83661d0d09c0 63
kenjiArai 0:83661d0d09c0 64 uint32_t F_COUNTER::read_frequency(float gate_time)
kenjiArai 0:83661d0d09c0 65 {
kenjiArai 0:83661d0d09c0 66 #if defined(TARGET_LPC1768)
kenjiArai 0:83661d0d09c0 67 LPC_TIM2->TCR = 2; // Reset the counter (bit1<=1,bit0<=0)
kenjiArai 0:83661d0d09c0 68 LPC_TIM2->TCR = 1; // UnReset counter (bit1<=0,bit0<=1)
kenjiArai 0:83661d0d09c0 69 wait(gate_time); // Gate time for count
kenjiArai 0:83661d0d09c0 70 freq = LPC_TIM2->TC;
kenjiArai 0:83661d0d09c0 71 return freq;
kenjiArai 2:54c05b0a117a 72 #elif defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
kenjiArai 1:fd2e1c853ab6 73 TIM2->CNT = 0;
kenjiArai 1:fd2e1c853ab6 74 wait(gate_time); // Gate time for count
kenjiArai 1:fd2e1c853ab6 75 freq = TIM2->CNT;
kenjiArai 1:fd2e1c853ab6 76 return freq;
kenjiArai 0:83661d0d09c0 77 #else
kenjiArai 0:83661d0d09c0 78 #error "No support for this CPU"
kenjiArai 0:83661d0d09c0 79 #endif
kenjiArai 0:83661d0d09c0 80 }
kenjiArai 0:83661d0d09c0 81
kenjiArai 0:83661d0d09c0 82 #if 0
kenjiArai 0:83661d0d09c0 83 //
kenjiArai 0:83661d0d09c0 84 // CLOCK OUT to PWM1[6] Sample with Freq Counter using Cap2.0
kenjiArai 0:83661d0d09c0 85 // For LPC1768-mbed
kenjiArai 0:83661d0d09c0 86 //
kenjiArai 0:83661d0d09c0 87 // Reference: 5MHz Clock Out Code and Comment - http://mbed.org/forum/mbed/topic/733/
kenjiArai 0:83661d0d09c0 88 //
kenjiArai 0:83661d0d09c0 89 // !! To Self Measurement Output Clock, Connect p21 <-> p30 with jumper wire.
kenjiArai 0:83661d0d09c0 90 // 2013.6.18 : Wrong comment about MR6 and Duty fix.
kenjiArai 0:83661d0d09c0 91 //
kenjiArai 0:83661d0d09c0 92
kenjiArai 0:83661d0d09c0 93 #include "mbed.h"
kenjiArai 0:83661d0d09c0 94
kenjiArai 0:83661d0d09c0 95 PwmOut fmclck(p21); // for RESERVE pin21 as PWM1[6]
kenjiArai 0:83661d0d09c0 96 DigitalIn clkin(p30); // for RESERVE pin30 as CAP2[0]
kenjiArai 0:83661d0d09c0 97
kenjiArai 0:83661d0d09c0 98 // Reset Counter and Count Start
kenjiArai 0:83661d0d09c0 99 void P30_RESET_CTR(void)
kenjiArai 0:83661d0d09c0 100 {
kenjiArai 0:83661d0d09c0 101 LPC_TIM2->TCR = 2; // Reset the counter (bit1<=1,bit0<=0)
kenjiArai 0:83661d0d09c0 102 LPC_TIM2->TCR = 1; // UnReset counter (bit1<=0,bit0<=1)
kenjiArai 0:83661d0d09c0 103 }
kenjiArai 0:83661d0d09c0 104
kenjiArai 0:83661d0d09c0 105 // Get Counter Value
kenjiArai 0:83661d0d09c0 106 int P30_GET_CTR(void)
kenjiArai 0:83661d0d09c0 107 {
kenjiArai 0:83661d0d09c0 108 return LPC_TIM2->TC; // Read the counter value
kenjiArai 0:83661d0d09c0 109 }
kenjiArai 0:83661d0d09c0 110
kenjiArai 0:83661d0d09c0 111 // Setting p30 to Cap2.0
kenjiArai 0:83661d0d09c0 112 void P30_INIT_CTR(void)
kenjiArai 0:83661d0d09c0 113 {
kenjiArai 0:83661d0d09c0 114 LPC_SC->PCONP |= 1 << 22; // 1)Power up TimerCounter2 (bit22)
kenjiArai 0:83661d0d09c0 115 LPC_PINCON->PINSEL0 |= 3 << 8; // 2)Set P0[4] to CAP2[0]
kenjiArai 0:83661d0d09c0 116 LPC_TIM2->TCR = 2; // 3)Counter Reset (bit1<=1,bit0<=0)
kenjiArai 0:83661d0d09c0 117 LPC_TIM2->CTCR = 1; // 4)Count on riging edge Cap2[0]
kenjiArai 0:83661d0d09c0 118 LPC_TIM2->CCR = 0; // 5)Input Capture Disabled
kenjiArai 0:83661d0d09c0 119 LPC_TIM2->TCR = 1; // 6)Counter Start (bit1<=0,bit0<=1)
kenjiArai 0:83661d0d09c0 120 }
kenjiArai 0:83661d0d09c0 121
kenjiArai 0:83661d0d09c0 122 // Clock Output From pin21(PWM6)
kenjiArai 0:83661d0d09c0 123 // Set Clock Freq with div.
kenjiArai 0:83661d0d09c0 124 // if mbed is running at 96MHz, div is set 96 to Get 1MHz.
kenjiArai 0:83661d0d09c0 125 void PWM6_SETCLK(int div)
kenjiArai 0:83661d0d09c0 126 {
kenjiArai 0:83661d0d09c0 127 LPC_PWM1->TCR = (1 << 1); // 1)Reset counter, disable PWM
kenjiArai 0:83661d0d09c0 128 LPC_SC->PCLKSEL0 &= ~(0x3 << 12);
kenjiArai 0:83661d0d09c0 129 LPC_SC->PCLKSEL0 |= (1 << 12); // 2)Set peripheral clock divider to /1, i.e. system clock
kenjiArai 0:83661d0d09c0 130 LPC_PWM1->MR0 = div - 1; // 3)Match Register 0 is shared period counter for all PWM1
kenjiArai 0:83661d0d09c0 131 LPC_PWM1->MR6 = (div + 1)>> 1; //
kenjiArai 0:83661d0d09c0 132 LPC_PWM1->LER |= 1; // 4)Start updating at next period start
kenjiArai 0:83661d0d09c0 133 LPC_PWM1->TCR = (1 << 0) || (1 << 3); // 5)Enable counter and PWM
kenjiArai 0:83661d0d09c0 134 }
kenjiArai 0:83661d0d09c0 135
kenjiArai 0:83661d0d09c0 136 int main()
kenjiArai 0:83661d0d09c0 137 {
kenjiArai 0:83661d0d09c0 138 PWM6_SETCLK(19) ; // Outout mbed's "PWM6" pin to 96MHZ/19 = 5.052MHz (Approx)
kenjiArai 0:83661d0d09c0 139 // PWM6_SETCLK(96) ; // Outout mbed's "PWM6" pin to 96MHZ/96 = 1.000MHz (Approx)
kenjiArai 0:83661d0d09c0 140 P30_INIT_CTR();
kenjiArai 0:83661d0d09c0 141 while(1) {
kenjiArai 0:83661d0d09c0 142 P30_RESET_CTR();
kenjiArai 0:83661d0d09c0 143 wait(1.0); // Gate time for count
kenjiArai 0:83661d0d09c0 144 printf("pin30 Freq = %d (Hz)\r\n",P30_GET_CTR());
kenjiArai 0:83661d0d09c0 145 }
kenjiArai 0:83661d0d09c0 146 }
kenjiArai 0:83661d0d09c0 147
kenjiArai 0:83661d0d09c0 148 #endif