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.h
- Revision:
- 1:102230f2879d
- Parent:
- 0:bfdc6ed58a06
- Child:
- 2:194f82ad3041
--- a/frq_cuntr_full.h Sat Nov 22 04:01:41 2014 +0000 +++ b/frq_cuntr_full.h Sat Nov 22 23:02:39 2014 +0000 @@ -1,13 +1,14 @@ /* - * mbed Application program / Frequency Counter with GPS 1PPS Compensation + * 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: Nobember 22nd, 2014 + * Revised: Nobember 23rd, 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 @@ -21,105 +22,163 @@ #include "mbed.h" +#define DEBUG // use Communication with PC(UART) +/* + CAUTION: + If you select internal clock (100MHz), you need consider PLL clock behavior. + PLL clock drifts over 60Hz (increase frequency) within 30 to 40 second + then suddenly back to low frequency and increase again. + Even you prepare precision external clock, this frequency drift cannot avoid. + */ +#define BASE_EXTERNAL_CLOCK + namespace Frequency_counter { - #define DEBUG // use Communication with PC(UART) - #define IRQ_DRIVE - //#define BASE_EXTERNAL_CLOCK - - #if defined(BASE_EXTERNAL_CLOCK) - #define CNT_UPPER (0xffffffff - 100) - #define CNT_LOWER (0 + 100) - //#define CNT_UPPER (30000000 + 1000000) - //#define CNT_LOWER (30000000 - 1000000) - #else - #define CNT_UPPER (0xffffffff - 100) - #define CNT_LOWER (0 + 100) - //#define CNT_UPPER (100000000 - 100000) - //#define CNT_LOWER (100000000 + 100000) - #endif - - #if defined(BASE_EXTERNAL_CLOCK) - #define ONE_SECOND_COUNT 0xe4e1c0 - #else - #define ONE_SECOND_COUNT 0x2faf080 - #endif - - #define CNT_BF_SIZE 120 - - //#if defined(IRQ_DRIVE) - // 1PPS data - extern uint32_t onepps_cnt[CNT_BF_SIZE]; - extern uint32_t onepps_num; - extern uint64_t onepps_cnt_avarage; - extern uint8_t onepps_buf_full; - extern uint8_t onepps_ready_flg; - // TIM2 - extern uint8_t tim2_ready_flg; - extern uint32_t tim2_cnt_data; - extern uint32_t tim2_old_cnt_data; - // TIM3+4 - extern uint8_t tim3p4_ready_flg; - extern uint32_t tim3p4_cnt_data; - extern uint32_t tim3p4_old_cnt_data; - - // TIM2 IC2 Interrupt control - void irq_ic2_TIM2(void); - // TIM3 IC2 Interrupt control (same signal connected to TIM4 IC1) - void irq_ic2_TIM3P4(void); +#define CNT_BASE 29999978 // 30MHz +#define CNT_FIX_BASE 600000 // 0.03sec + +#if defined(BASE_EXTERNAL_CLOCK) +#define CNT_UPPER (CNT_BASE + 20) +#define CNT_LOWER (CNT_BASE - 20) +#else +#define CNT_UPPER (0xffffffff - 100) +#define CNT_LOWER (0 + 100) +#endif + +#if defined(BASE_EXTERNAL_CLOCK) +#define ONE_SECOND_COUNT (CNT_BASE - CNT_FIX_BASE) +#else +#define ONE_SECOND_COUNT 0x2faf080 // 50MHz +#endif + +#define CNT_BF_SIZE 120 // 1PPS data save size + +/** Frequency Counter program + * Only for ST Nucleo F411RE Board + * + * @code + * #include "mbed.h" + * + * // PC_6,PC_7 & PB6 use for Timer3 & 4(16+16bit) + * // PA_0,PA_1 & PB10 use for Timer2(32bit) + * FRQ_CUNTR fc(PC_6, 1.0); // Input port(Fixed) & gate time[sec] + * + * int main() { + * // This is for test purpose + * fc.port_mco1_mco2_set(2); // Clk/2 ->1/1(100MHz) cannot measure!! + * fc.read_frequency_TIM2(1.0); // read TIM2 source frequency (test) + * fc.read_frequency_TIM3P4(1.0); // read TIM3 source frequency (test) + * while(true) { + * while (fc.status_1pps() == 0) {;} + * counter_1pps = fc.read_avarage_1pps(); + * while (fc.status_freq_update() == 0) {;} + * new_frequency = fc.read_freq_data(); + * print("1PPS/ave = %9d , FREQUENCY = %9d\r\n", counter_1pps, new_frequency); + * } + * } + * @endcode + */ + +class FRQ_CUNTR +{ +public: + /** Configure data pin (Not changeable) + * @param Freq. input pin + */ + FRQ_CUNTR(PinName f_in, double gt); + + /** Set gate time + * @param gate time [sec] + * @return !=0: new data is avairable, 0: not yet + */ + double set_gate_time(double gt); + + /** Read status (new frequency data is available or not) + * @param none + * @return !=0: new data is avairable, 0: not yet + */ + uint32_t status_freq_update(void); + + /** Read new frequency data + * @param none + * @return frequency data + */ + uint32_t read_freq_data(void); - class FRQ_CUNTR - { - public: - - FRQ_CUNTR(PinName f_in); - - void initialize_Freq_counter(void); - - // Read TIM2 captured counter value - uint32_t read_ic2_counter_TIM2(void); - - // Check TIM2 IC2 status - uint32_t check_ic2_status_TIM2(void); - - // Read TIM3+4(as 32bit) captured counter value - uint32_t read_ic2_counter_TIM3P4(void); - - // Check TIM3 IC2 & TIM4 IC1 status - uint32_t check_ic2_status_TIM3P4(void); - - // Avarage measued data GPS 1PPS by 50MHz Internal Clock - void avarage_1pps(void); - - // Frequency check for test purpose - uint32_t read_frequency_TIM2(float gate_time); - uint32_t read_frequency_TIM3P4(float gate_time); - - // Clock output for test purpose - void port_mco1_mco2_set(uint8_t select); - - protected: - DigitalIn _pin; - - // Initialize TIM2 - // Internal clock (50MHz) and IC2 for GPS 1pps signal measurement - void initialize_TIM2(void); - - // 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 initialize_TIM3P4(void); - - private: - #if defined(IRQ_DRIVE) - // 1PPS data - uint32_t onepps_cnt[CNT_BF_SIZE]; - uint32_t onepps_num; - uint64_t onepps_cnt_avarage; - uint8_t onepps_buf_full; - uint8_t onepps_ready_flg; - #endif - }; + /** Read avarage measued data GPS 1PPS + * @param none + * @return Frequency + */ + uint32_t read_avarage_1pps(void); + + /** Read status (new 1PPS data is available or not) + * @param none + * @return !=0: new data is avairable, 0: not yet + */ + uint32_t status_1pps(void); + + /** This is a test purpose function + * Check PA0 pin input or internal clock frequency + * @param none + * @return Frequency + */ + uint32_t read_frequency_TIM2(float gate_time); + + /** This is a test purpose function + * Check PC6 pin input frequency + * @param none + * @return Frequency + */ + uint32_t read_frequency_TIM3P4(float gate_time); + + /** This is a test purpose function + * Output clock from pin PA8 & PC9 uses for MCO_1 & MCO_2 + * @param none + * @return none + */ + void port_mco1_mco2_set(uint8_t select); + +protected: + DigitalIn _pin; + + void initialize_Freq_counter(void); // Initialize timers + // Internal clock (50MHz) and IC2 for GPS 1pps signal measurement + void initialize_TIM2(void); + // Initialize TIM3 and TIM4 as 32bit counter (TIM3(16bit) + TIM4(16bit)) + void initialize_TIM3P4(void); + uint32_t set_1PPS_data(void); // Set GPS 1PPS counter value + uint32_t read_ic2_counter_TIM2(void); // Read TIM2 captured counter value + uint32_t check_ic2_status_TIM2(void); // Check TIM2 IC2 status + uint32_t read_ic2_counter_TIM3P4(void); // Read TIM3+4(as 32bit) captured counter value + uint32_t check_ic2_status_TIM3P4(void); // Check TIM3 IC2 & TIM4 IC1 status + uint8_t read_oc_port_status(void); // Check TIM2 OC port + +private: + // TIM2 + double gate_time; + uint32_t counter_tim2; + uint32_t old_cntr_tim2; + // TIM3+4 + uint32_t counter_tim3p4; + uint32_t old_cntr_tim3p4; + // 1PPS data + uint32_t onepps_newest; + uint32_t onepps_cnt[CNT_BF_SIZE]; + uint32_t onepps_num; + uint64_t onepps_cnt_avarage; + uint8_t onepps_buf_full; + uint8_t onepps_ready_flg; +}; + +/* + Interrupt handler does NOT work following code + NVIC_SetVector(TIM2_IRQn, (uint32_t)FRQ_CUNTR::irq_ic2_TIM2); + From this reason, I wrote below code and set interrupt handler out side "FRQ_CUNTR" class + NVIC_SetVector(TIM2_IRQn, (uint32_t)irq_ic2_TIM2); + */ +void irq_ic2_TIM2(void); // TIM2 IC2 Interrupt control +void irq_ic2_TIM3P4(void); // TIM3 IC2 Interrupt control (same signal connected to TIM4 IC1) + } // Frequency_counter -#endif // MBED_FRQ_CUNTR +#endif // MBED_FRQ_CUNTR