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.h@2:194f82ad3041, 2014-12-21 (annotated)
- Committer:
- kenjiArai
- Date:
- Sun Dec 21 12:14:46 2014 +0000
- Revision:
- 2:194f82ad3041
- Parent:
- 1:102230f2879d
- Child:
- 3:339307e1dc0d
added new function and fixed bugs
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kenjiArai | 0:bfdc6ed58a06 | 1 | /* |
kenjiArai | 1:102230f2879d | 2 | * mbed Library / Frequency Counter with GPS 1PPS Compensation |
kenjiArai | 0:bfdc6ed58a06 | 3 | * Frequency Counter Hardware relataed program |
kenjiArai | 1:102230f2879d | 4 | * Only for ST Nucleo F411RE |
kenjiArai | 0:bfdc6ed58a06 | 5 | * |
kenjiArai | 0:bfdc6ed58a06 | 6 | * Copyright (c) 2014 Kenji Arai / JH1PJL |
kenjiArai | 0:bfdc6ed58a06 | 7 | * http://www.page.sannet.ne.jp/kenjia/index.html |
kenjiArai | 0:bfdc6ed58a06 | 8 | * http://mbed.org/users/kenjiArai/ |
kenjiArai | 0:bfdc6ed58a06 | 9 | * Additional functions and modification |
kenjiArai | 0:bfdc6ed58a06 | 10 | * started: October 18th, 2014 |
kenjiArai | 2:194f82ad3041 | 11 | * Revised: December 21st, 2014 |
kenjiArai | 0:bfdc6ed58a06 | 12 | * |
kenjiArai | 0:bfdc6ed58a06 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
kenjiArai | 0:bfdc6ed58a06 | 14 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE |
kenjiArai | 0:bfdc6ed58a06 | 15 | * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
kenjiArai | 0:bfdc6ed58a06 | 16 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
kenjiArai | 0:bfdc6ed58a06 | 17 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
kenjiArai | 0:bfdc6ed58a06 | 18 | */ |
kenjiArai | 0:bfdc6ed58a06 | 19 | |
kenjiArai | 0:bfdc6ed58a06 | 20 | #ifndef MBED_FRQ_CUNTR |
kenjiArai | 0:bfdc6ed58a06 | 21 | #define MBED_FRQ_CUNTR |
kenjiArai | 0:bfdc6ed58a06 | 22 | |
kenjiArai | 0:bfdc6ed58a06 | 23 | #include "mbed.h" |
kenjiArai | 0:bfdc6ed58a06 | 24 | |
kenjiArai | 2:194f82ad3041 | 25 | //#define DEBUG // use Communication with PC(UART) |
kenjiArai | 2:194f82ad3041 | 26 | |
kenjiArai | 1:102230f2879d | 27 | /* |
kenjiArai | 1:102230f2879d | 28 | CAUTION: |
kenjiArai | 1:102230f2879d | 29 | If you select internal clock (100MHz), you need consider PLL clock behavior. |
kenjiArai | 2:194f82ad3041 | 30 | PLL clock drifts over 70Hz (increase frequency) within 30 to 40 second |
kenjiArai | 1:102230f2879d | 31 | then suddenly back to low frequency and increase again. |
kenjiArai | 1:102230f2879d | 32 | Even you prepare precision external clock, this frequency drift cannot avoid. |
kenjiArai | 2:194f82ad3041 | 33 | Comment out "BASE_EXTERNAL_CLOCK" is only for checking!! |
kenjiArai | 1:102230f2879d | 34 | */ |
kenjiArai | 1:102230f2879d | 35 | #define BASE_EXTERNAL_CLOCK |
kenjiArai | 1:102230f2879d | 36 | |
kenjiArai | 0:bfdc6ed58a06 | 37 | namespace Frequency_counter |
kenjiArai | 0:bfdc6ed58a06 | 38 | { |
kenjiArai | 1:102230f2879d | 39 | |
kenjiArai | 1:102230f2879d | 40 | #define CNT_BF_SIZE 120 // 1PPS data save size |
kenjiArai | 1:102230f2879d | 41 | |
kenjiArai | 1:102230f2879d | 42 | /** Frequency Counter program |
kenjiArai | 1:102230f2879d | 43 | * Only for ST Nucleo F411RE Board |
kenjiArai | 1:102230f2879d | 44 | * |
kenjiArai | 1:102230f2879d | 45 | * @code |
kenjiArai | 1:102230f2879d | 46 | * #include "mbed.h" |
kenjiArai | 1:102230f2879d | 47 | * |
kenjiArai | 2:194f82ad3041 | 48 | * using namespace Frequency_counter; |
kenjiArai | 2:194f82ad3041 | 49 | * |
kenjiArai | 2:194f82ad3041 | 50 | * // PC_6,PC_7 & PB_6 use for Timer3 & 4(16+16bit) |
kenjiArai | 2:194f82ad3041 | 51 | * // PA_0,PA_1 & PB_10 use for Timer2(32bit) |
kenjiArai | 2:194f82ad3041 | 52 | * // PA_8 & PC_7 use for MCO (Test purpose) |
kenjiArai | 2:194f82ad3041 | 53 | * FRQ_CUNTR fc(PC_6, 1.0, 50.000000);// Input port, gate time[sec] and External clock freq. |
kenjiArai | 1:102230f2879d | 54 | * |
kenjiArai | 1:102230f2879d | 55 | * int main() { |
kenjiArai | 2:194f82ad3041 | 56 | * uint32_t counter_1pps = 0; |
kenjiArai | 2:194f82ad3041 | 57 | * double new_frequency = 0; |
kenjiArai | 1:102230f2879d | 58 | * // This is for test purpose |
kenjiArai | 1:102230f2879d | 59 | * fc.port_mco1_mco2_set(2); // Clk/2 ->1/1(100MHz) cannot measure!! |
kenjiArai | 1:102230f2879d | 60 | * fc.read_frequency_TIM2(1.0); // read TIM2 source frequency (test) |
kenjiArai | 1:102230f2879d | 61 | * fc.read_frequency_TIM3P4(1.0); // read TIM3 source frequency (test) |
kenjiArai | 1:102230f2879d | 62 | * while(true) { |
kenjiArai | 1:102230f2879d | 63 | * while (fc.status_1pps() == 0) {;} |
kenjiArai | 1:102230f2879d | 64 | * counter_1pps = fc.read_avarage_1pps(); |
kenjiArai | 1:102230f2879d | 65 | * while (fc.status_freq_update() == 0) {;} |
kenjiArai | 1:102230f2879d | 66 | * new_frequency = fc.read_freq_data(); |
kenjiArai | 2:194f82ad3041 | 67 | * PRINTF("1PPS/ave = %9d , FREQUENCY = %11.3f\r\n", counter_1pps, new_frequency); |
kenjiArai | 1:102230f2879d | 68 | * } |
kenjiArai | 1:102230f2879d | 69 | * } |
kenjiArai | 1:102230f2879d | 70 | * @endcode |
kenjiArai | 1:102230f2879d | 71 | */ |
kenjiArai | 1:102230f2879d | 72 | |
kenjiArai | 1:102230f2879d | 73 | class FRQ_CUNTR |
kenjiArai | 1:102230f2879d | 74 | { |
kenjiArai | 1:102230f2879d | 75 | public: |
kenjiArai | 2:194f82ad3041 | 76 | |
kenjiArai | 1:102230f2879d | 77 | /** Configure data pin (Not changeable) |
kenjiArai | 2:194f82ad3041 | 78 | * @param Freq. input pin + Gate time[sec] + External clock[MHz] |
kenjiArai | 1:102230f2879d | 79 | */ |
kenjiArai | 2:194f82ad3041 | 80 | FRQ_CUNTR(PinName f_in, double gt, double ex_clock); |
kenjiArai | 1:102230f2879d | 81 | |
kenjiArai | 1:102230f2879d | 82 | /** Set gate time |
kenjiArai | 1:102230f2879d | 83 | * @param gate time [sec] |
kenjiArai | 2:194f82ad3041 | 84 | * @return gate time (range 50mS to 1 minute) |
kenjiArai | 1:102230f2879d | 85 | */ |
kenjiArai | 1:102230f2879d | 86 | double set_gate_time(double gt); |
kenjiArai | 1:102230f2879d | 87 | |
kenjiArai | 2:194f82ad3041 | 88 | /** Read gate time |
kenjiArai | 2:194f82ad3041 | 89 | * @param none |
kenjiArai | 2:194f82ad3041 | 90 | * @return gate time (range 50mS to 1 minute) |
kenjiArai | 2:194f82ad3041 | 91 | */ |
kenjiArai | 2:194f82ad3041 | 92 | double read_gate_time(void); |
kenjiArai | 2:194f82ad3041 | 93 | |
kenjiArai | 1:102230f2879d | 94 | /** Read status (new frequency data is available or not) |
kenjiArai | 1:102230f2879d | 95 | * @param none |
kenjiArai | 1:102230f2879d | 96 | * @return !=0: new data is avairable, 0: not yet |
kenjiArai | 1:102230f2879d | 97 | */ |
kenjiArai | 1:102230f2879d | 98 | uint32_t status_freq_update(void); |
kenjiArai | 1:102230f2879d | 99 | |
kenjiArai | 1:102230f2879d | 100 | /** Read new frequency data |
kenjiArai | 1:102230f2879d | 101 | * @param none |
kenjiArai | 1:102230f2879d | 102 | * @return frequency data |
kenjiArai | 1:102230f2879d | 103 | */ |
kenjiArai | 2:194f82ad3041 | 104 | double read_freq_data(void); |
kenjiArai | 0:bfdc6ed58a06 | 105 | |
kenjiArai | 1:102230f2879d | 106 | /** Read avarage measued data GPS 1PPS |
kenjiArai | 1:102230f2879d | 107 | * @param none |
kenjiArai | 1:102230f2879d | 108 | * @return Frequency |
kenjiArai | 1:102230f2879d | 109 | */ |
kenjiArai | 1:102230f2879d | 110 | uint32_t read_avarage_1pps(void); |
kenjiArai | 1:102230f2879d | 111 | |
kenjiArai | 1:102230f2879d | 112 | /** Read status (new 1PPS data is available or not) |
kenjiArai | 1:102230f2879d | 113 | * @param none |
kenjiArai | 1:102230f2879d | 114 | * @return !=0: new data is avairable, 0: not yet |
kenjiArai | 1:102230f2879d | 115 | */ |
kenjiArai | 1:102230f2879d | 116 | uint32_t status_1pps(void); |
kenjiArai | 1:102230f2879d | 117 | |
kenjiArai | 2:194f82ad3041 | 118 | /** Read GPS status |
kenjiArai | 2:194f82ad3041 | 119 | * @param none |
kenjiArai | 2:194f82ad3041 | 120 | * @return 1: GPS is ready |
kenjiArai | 2:194f82ad3041 | 121 | */ |
kenjiArai | 2:194f82ad3041 | 122 | uint8_t gps_status(void); |
kenjiArai | 2:194f82ad3041 | 123 | |
kenjiArai | 2:194f82ad3041 | 124 | /** This is a "TEST PURPOSE" function |
kenjiArai | 1:102230f2879d | 125 | * Check PA0 pin input or internal clock frequency |
kenjiArai | 1:102230f2879d | 126 | * @param none |
kenjiArai | 1:102230f2879d | 127 | * @return Frequency |
kenjiArai | 1:102230f2879d | 128 | */ |
kenjiArai | 1:102230f2879d | 129 | uint32_t read_frequency_TIM2(float gate_time); |
kenjiArai | 1:102230f2879d | 130 | |
kenjiArai | 2:194f82ad3041 | 131 | /** This is a "TEST PURPOSE" function |
kenjiArai | 1:102230f2879d | 132 | * Check PC6 pin input frequency |
kenjiArai | 1:102230f2879d | 133 | * @param none |
kenjiArai | 1:102230f2879d | 134 | * @return Frequency |
kenjiArai | 1:102230f2879d | 135 | */ |
kenjiArai | 1:102230f2879d | 136 | uint32_t read_frequency_TIM3P4(float gate_time); |
kenjiArai | 1:102230f2879d | 137 | |
kenjiArai | 2:194f82ad3041 | 138 | /** This is a "TEST PURPOSE" function |
kenjiArai | 1:102230f2879d | 139 | * Output clock from pin PA8 & PC9 uses for MCO_1 & MCO_2 |
kenjiArai | 1:102230f2879d | 140 | * @param none |
kenjiArai | 1:102230f2879d | 141 | * @return none |
kenjiArai | 1:102230f2879d | 142 | */ |
kenjiArai | 1:102230f2879d | 143 | void port_mco1_mco2_set(uint8_t select); |
kenjiArai | 1:102230f2879d | 144 | |
kenjiArai | 2:194f82ad3041 | 145 | /** This is a "DEBUG PURPOSE" function |
kenjiArai | 2:194f82ad3041 | 146 | * print internal data (need to define "DEBUG" |
kenjiArai | 2:194f82ad3041 | 147 | * @param none |
kenjiArai | 2:194f82ad3041 | 148 | * @return none |
kenjiArai | 2:194f82ad3041 | 149 | */ |
kenjiArai | 2:194f82ad3041 | 150 | void debug_printf_internal_data(void); |
kenjiArai | 2:194f82ad3041 | 151 | |
kenjiArai | 1:102230f2879d | 152 | protected: |
kenjiArai | 1:102230f2879d | 153 | DigitalIn _pin; |
kenjiArai | 1:102230f2879d | 154 | |
kenjiArai | 1:102230f2879d | 155 | void initialize_Freq_counter(void); // Initialize timers |
kenjiArai | 2:194f82ad3041 | 156 | // Internal clock (100MHz) or External clock(?MHz) and IC2 for GPS 1pps signal measurement |
kenjiArai | 1:102230f2879d | 157 | void initialize_TIM2(void); |
kenjiArai | 1:102230f2879d | 158 | // Initialize TIM3 and TIM4 as 32bit counter (TIM3(16bit) + TIM4(16bit)) |
kenjiArai | 1:102230f2879d | 159 | void initialize_TIM3P4(void); |
kenjiArai | 2:194f82ad3041 | 160 | void set_external_clock(double ex_clock); // Set external clock data |
kenjiArai | 1:102230f2879d | 161 | uint32_t set_1PPS_data(void); // Set GPS 1PPS counter value |
kenjiArai | 1:102230f2879d | 162 | uint32_t read_ic2_counter_TIM2(void); // Read TIM2 captured counter value |
kenjiArai | 1:102230f2879d | 163 | uint32_t check_ic2_status_TIM2(void); // Check TIM2 IC2 status |
kenjiArai | 1:102230f2879d | 164 | uint32_t read_ic2_counter_TIM3P4(void); // Read TIM3+4(as 32bit) captured counter value |
kenjiArai | 1:102230f2879d | 165 | uint32_t check_ic2_status_TIM3P4(void); // Check TIM3 IC2 & TIM4 IC1 status |
kenjiArai | 1:102230f2879d | 166 | uint8_t read_oc_port_status(void); // Check TIM2 OC port |
kenjiArai | 1:102230f2879d | 167 | |
kenjiArai | 1:102230f2879d | 168 | private: |
kenjiArai | 2:194f82ad3041 | 169 | double newest_frequency; |
kenjiArai | 2:194f82ad3041 | 170 | double gate_time; |
kenjiArai | 2:194f82ad3041 | 171 | double ex_clock_freq; |
kenjiArai | 2:194f82ad3041 | 172 | uint32_t ex_clk_base; |
kenjiArai | 2:194f82ad3041 | 173 | uint32_t clk_hi_const; |
kenjiArai | 2:194f82ad3041 | 174 | uint32_t clk_upper_limit; |
kenjiArai | 2:194f82ad3041 | 175 | uint32_t clk_lower_limit; |
kenjiArai | 2:194f82ad3041 | 176 | uint8_t gps_ready; |
kenjiArai | 1:102230f2879d | 177 | // TIM2 |
kenjiArai | 1:102230f2879d | 178 | uint32_t counter_tim2; |
kenjiArai | 1:102230f2879d | 179 | uint32_t old_cntr_tim2; |
kenjiArai | 1:102230f2879d | 180 | // TIM3+4 |
kenjiArai | 1:102230f2879d | 181 | uint32_t counter_tim3p4; |
kenjiArai | 1:102230f2879d | 182 | uint32_t old_cntr_tim3p4; |
kenjiArai | 1:102230f2879d | 183 | // 1PPS data |
kenjiArai | 1:102230f2879d | 184 | uint32_t onepps_newest; |
kenjiArai | 1:102230f2879d | 185 | uint32_t onepps_cnt[CNT_BF_SIZE]; |
kenjiArai | 1:102230f2879d | 186 | uint32_t onepps_num; |
kenjiArai | 1:102230f2879d | 187 | uint64_t onepps_cnt_avarage; |
kenjiArai | 1:102230f2879d | 188 | uint8_t onepps_buf_full; |
kenjiArai | 1:102230f2879d | 189 | uint8_t onepps_ready_flg; |
kenjiArai | 2:194f82ad3041 | 190 | |
kenjiArai | 1:102230f2879d | 191 | }; |
kenjiArai | 1:102230f2879d | 192 | |
kenjiArai | 1:102230f2879d | 193 | /* |
kenjiArai | 1:102230f2879d | 194 | Interrupt handler does NOT work following code |
kenjiArai | 1:102230f2879d | 195 | NVIC_SetVector(TIM2_IRQn, (uint32_t)FRQ_CUNTR::irq_ic2_TIM2); |
kenjiArai | 1:102230f2879d | 196 | From this reason, I wrote below code and set interrupt handler out side "FRQ_CUNTR" class |
kenjiArai | 1:102230f2879d | 197 | NVIC_SetVector(TIM2_IRQn, (uint32_t)irq_ic2_TIM2); |
kenjiArai | 1:102230f2879d | 198 | */ |
kenjiArai | 1:102230f2879d | 199 | void irq_ic2_TIM2(void); // TIM2 IC2 Interrupt control |
kenjiArai | 1:102230f2879d | 200 | void irq_ic2_TIM3P4(void); // TIM3 IC2 Interrupt control (same signal connected to TIM4 IC1) |
kenjiArai | 1:102230f2879d | 201 | |
kenjiArai | 0:bfdc6ed58a06 | 202 | } // Frequency_counter |
kenjiArai | 0:bfdc6ed58a06 | 203 | |
kenjiArai | 1:102230f2879d | 204 | #endif // MBED_FRQ_CUNTR |