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@3:339307e1dc0d, 2014-12-23 (annotated)
- Committer:
- kenjiArai
- Date:
- Tue Dec 23 23:26:49 2014 +0000
- Revision:
- 3:339307e1dc0d
- Parent:
- 2:194f82ad3041
- Child:
- 4:9d3b3f0a3882
change clock input PA0, CH1 to ETR, change debug functions, add new functions
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 | 3:339307e1dc0d | 11 | * Revised: December 24th, 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 | 3:339307e1dc0d | 25 | // please comment out when normal run mode |
kenjiArai | 2:194f82ad3041 | 26 | //#define DEBUG // use Communication with PC(UART) |
kenjiArai | 2:194f82ad3041 | 27 | |
kenjiArai | 1:102230f2879d | 28 | /* |
kenjiArai | 1:102230f2879d | 29 | CAUTION: |
kenjiArai | 1:102230f2879d | 30 | If you select internal clock (100MHz), you need consider PLL clock behavior. |
kenjiArai | 2:194f82ad3041 | 31 | PLL clock drifts over 70Hz (increase frequency) within 30 to 40 second |
kenjiArai | 1:102230f2879d | 32 | then suddenly back to low frequency and increase again. |
kenjiArai | 1:102230f2879d | 33 | Even you prepare precision external clock, this frequency drift cannot avoid. |
kenjiArai | 2:194f82ad3041 | 34 | Comment out "BASE_EXTERNAL_CLOCK" is only for checking!! |
kenjiArai | 1:102230f2879d | 35 | */ |
kenjiArai | 1:102230f2879d | 36 | #define BASE_EXTERNAL_CLOCK |
kenjiArai | 1:102230f2879d | 37 | |
kenjiArai | 3:339307e1dc0d | 38 | // use avaraged 1pps data |
kenjiArai | 3:339307e1dc0d | 39 | #define ONEPPS_AVE |
kenjiArai | 3:339307e1dc0d | 40 | |
kenjiArai | 3:339307e1dc0d | 41 | // External clock divided by 2 |
kenjiArai | 3:339307e1dc0d | 42 | #define CLOCK_DIVIDED_BY_2 |
kenjiArai | 3:339307e1dc0d | 43 | |
kenjiArai | 0:bfdc6ed58a06 | 44 | namespace Frequency_counter |
kenjiArai | 0:bfdc6ed58a06 | 45 | { |
kenjiArai | 1:102230f2879d | 46 | |
kenjiArai | 1:102230f2879d | 47 | #define CNT_BF_SIZE 120 // 1PPS data save size |
kenjiArai | 1:102230f2879d | 48 | |
kenjiArai | 1:102230f2879d | 49 | /** Frequency Counter program |
kenjiArai | 1:102230f2879d | 50 | * Only for ST Nucleo F411RE Board |
kenjiArai | 1:102230f2879d | 51 | * |
kenjiArai | 1:102230f2879d | 52 | * @code |
kenjiArai | 1:102230f2879d | 53 | * #include "mbed.h" |
kenjiArai | 1:102230f2879d | 54 | * |
kenjiArai | 2:194f82ad3041 | 55 | * using namespace Frequency_counter; |
kenjiArai | 2:194f82ad3041 | 56 | * |
kenjiArai | 2:194f82ad3041 | 57 | * // PC_6,PC_7 & PB_6 use for Timer3 & 4(16+16bit) |
kenjiArai | 2:194f82ad3041 | 58 | * // PA_0,PA_1 & PB_10 use for Timer2(32bit) |
kenjiArai | 2:194f82ad3041 | 59 | * // PA_8 & PC_7 use for MCO (Test purpose) |
kenjiArai | 2:194f82ad3041 | 60 | * FRQ_CUNTR fc(PC_6, 1.0, 50.000000);// Input port, gate time[sec] and External clock freq. |
kenjiArai | 1:102230f2879d | 61 | * |
kenjiArai | 1:102230f2879d | 62 | * int main() { |
kenjiArai | 2:194f82ad3041 | 63 | * uint32_t counter_1pps = 0; |
kenjiArai | 2:194f82ad3041 | 64 | * double new_frequency = 0; |
kenjiArai | 1:102230f2879d | 65 | * // This is for test purpose |
kenjiArai | 1:102230f2879d | 66 | * fc.port_mco1_mco2_set(2); // Clk/2 ->1/1(100MHz) cannot measure!! |
kenjiArai | 1:102230f2879d | 67 | * fc.read_frequency_TIM2(1.0); // read TIM2 source frequency (test) |
kenjiArai | 1:102230f2879d | 68 | * fc.read_frequency_TIM3P4(1.0); // read TIM3 source frequency (test) |
kenjiArai | 1:102230f2879d | 69 | * while(true) { |
kenjiArai | 1:102230f2879d | 70 | * while (fc.status_1pps() == 0) {;} |
kenjiArai | 1:102230f2879d | 71 | * counter_1pps = fc.read_avarage_1pps(); |
kenjiArai | 1:102230f2879d | 72 | * while (fc.status_freq_update() == 0) {;} |
kenjiArai | 1:102230f2879d | 73 | * new_frequency = fc.read_freq_data(); |
kenjiArai | 2:194f82ad3041 | 74 | * PRINTF("1PPS/ave = %9d , FREQUENCY = %11.3f\r\n", counter_1pps, new_frequency); |
kenjiArai | 1:102230f2879d | 75 | * } |
kenjiArai | 1:102230f2879d | 76 | * } |
kenjiArai | 1:102230f2879d | 77 | * @endcode |
kenjiArai | 1:102230f2879d | 78 | */ |
kenjiArai | 1:102230f2879d | 79 | |
kenjiArai | 1:102230f2879d | 80 | class FRQ_CUNTR |
kenjiArai | 1:102230f2879d | 81 | { |
kenjiArai | 1:102230f2879d | 82 | public: |
kenjiArai | 2:194f82ad3041 | 83 | |
kenjiArai | 1:102230f2879d | 84 | /** Configure data pin (Not changeable) |
kenjiArai | 2:194f82ad3041 | 85 | * @param Freq. input pin + Gate time[sec] + External clock[MHz] |
kenjiArai | 1:102230f2879d | 86 | */ |
kenjiArai | 2:194f82ad3041 | 87 | FRQ_CUNTR(PinName f_in, double gt, double ex_clock); |
kenjiArai | 1:102230f2879d | 88 | |
kenjiArai | 1:102230f2879d | 89 | /** Set gate time |
kenjiArai | 1:102230f2879d | 90 | * @param gate time [sec] |
kenjiArai | 2:194f82ad3041 | 91 | * @return gate time (range 50mS to 1 minute) |
kenjiArai | 1:102230f2879d | 92 | */ |
kenjiArai | 1:102230f2879d | 93 | double set_gate_time(double gt); |
kenjiArai | 1:102230f2879d | 94 | |
kenjiArai | 2:194f82ad3041 | 95 | /** Read gate time |
kenjiArai | 2:194f82ad3041 | 96 | * @param none |
kenjiArai | 2:194f82ad3041 | 97 | * @return gate time (range 50mS to 1 minute) |
kenjiArai | 2:194f82ad3041 | 98 | */ |
kenjiArai | 2:194f82ad3041 | 99 | double read_gate_time(void); |
kenjiArai | 2:194f82ad3041 | 100 | |
kenjiArai | 1:102230f2879d | 101 | /** Read status (new frequency data is available or not) |
kenjiArai | 1:102230f2879d | 102 | * @param none |
kenjiArai | 1:102230f2879d | 103 | * @return !=0: new data is avairable, 0: not yet |
kenjiArai | 1:102230f2879d | 104 | */ |
kenjiArai | 1:102230f2879d | 105 | uint32_t status_freq_update(void); |
kenjiArai | 1:102230f2879d | 106 | |
kenjiArai | 1:102230f2879d | 107 | /** Read new frequency data |
kenjiArai | 1:102230f2879d | 108 | * @param none |
kenjiArai | 1:102230f2879d | 109 | * @return frequency data |
kenjiArai | 1:102230f2879d | 110 | */ |
kenjiArai | 2:194f82ad3041 | 111 | double read_freq_data(void); |
kenjiArai | 0:bfdc6ed58a06 | 112 | |
kenjiArai | 1:102230f2879d | 113 | /** Read avarage measued data GPS 1PPS |
kenjiArai | 1:102230f2879d | 114 | * @param none |
kenjiArai | 1:102230f2879d | 115 | * @return Frequency |
kenjiArai | 1:102230f2879d | 116 | */ |
kenjiArai | 1:102230f2879d | 117 | uint32_t read_avarage_1pps(void); |
kenjiArai | 1:102230f2879d | 118 | |
kenjiArai | 1:102230f2879d | 119 | /** Read status (new 1PPS data is available or not) |
kenjiArai | 1:102230f2879d | 120 | * @param none |
kenjiArai | 1:102230f2879d | 121 | * @return !=0: new data is avairable, 0: not yet |
kenjiArai | 1:102230f2879d | 122 | */ |
kenjiArai | 1:102230f2879d | 123 | uint32_t status_1pps(void); |
kenjiArai | 1:102230f2879d | 124 | |
kenjiArai | 2:194f82ad3041 | 125 | /** Read GPS status |
kenjiArai | 2:194f82ad3041 | 126 | * @param none |
kenjiArai | 2:194f82ad3041 | 127 | * @return 1: GPS is ready |
kenjiArai | 2:194f82ad3041 | 128 | */ |
kenjiArai | 3:339307e1dc0d | 129 | uint8_t status_gps(void); |
kenjiArai | 2:194f82ad3041 | 130 | |
kenjiArai | 2:194f82ad3041 | 131 | /** This is a "TEST PURPOSE" function |
kenjiArai | 1:102230f2879d | 132 | * Check PA0 pin input or internal clock 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_TIM2(float gate_time); |
kenjiArai | 1:102230f2879d | 137 | |
kenjiArai | 2:194f82ad3041 | 138 | /** This is a "TEST PURPOSE" function |
kenjiArai | 1:102230f2879d | 139 | * Check PC6 pin input frequency |
kenjiArai | 1:102230f2879d | 140 | * @param none |
kenjiArai | 1:102230f2879d | 141 | * @return Frequency |
kenjiArai | 1:102230f2879d | 142 | */ |
kenjiArai | 1:102230f2879d | 143 | uint32_t read_frequency_TIM3P4(float gate_time); |
kenjiArai | 1:102230f2879d | 144 | |
kenjiArai | 2:194f82ad3041 | 145 | /** This is a "TEST PURPOSE" function |
kenjiArai | 1:102230f2879d | 146 | * Output clock from pin PA8 & PC9 uses for MCO_1 & MCO_2 |
kenjiArai | 1:102230f2879d | 147 | * @param none |
kenjiArai | 1:102230f2879d | 148 | * @return none |
kenjiArai | 1:102230f2879d | 149 | */ |
kenjiArai | 1:102230f2879d | 150 | void port_mco1_mco2_set(uint8_t select); |
kenjiArai | 1:102230f2879d | 151 | |
kenjiArai | 2:194f82ad3041 | 152 | /** This is a "DEBUG PURPOSE" function |
kenjiArai | 2:194f82ad3041 | 153 | * print internal data (need to define "DEBUG" |
kenjiArai | 2:194f82ad3041 | 154 | * @param none |
kenjiArai | 2:194f82ad3041 | 155 | * @return none |
kenjiArai | 2:194f82ad3041 | 156 | */ |
kenjiArai | 2:194f82ad3041 | 157 | void debug_printf_internal_data(void); |
kenjiArai | 2:194f82ad3041 | 158 | |
kenjiArai | 1:102230f2879d | 159 | protected: |
kenjiArai | 1:102230f2879d | 160 | DigitalIn _pin; |
kenjiArai | 1:102230f2879d | 161 | |
kenjiArai | 1:102230f2879d | 162 | void initialize_Freq_counter(void); // Initialize timers |
kenjiArai | 2:194f82ad3041 | 163 | // Internal clock (100MHz) or External clock(?MHz) and IC2 for GPS 1pps signal measurement |
kenjiArai | 1:102230f2879d | 164 | void initialize_TIM2(void); |
kenjiArai | 1:102230f2879d | 165 | // Initialize TIM3 and TIM4 as 32bit counter (TIM3(16bit) + TIM4(16bit)) |
kenjiArai | 1:102230f2879d | 166 | void initialize_TIM3P4(void); |
kenjiArai | 2:194f82ad3041 | 167 | void set_external_clock(double ex_clock); // Set external clock data |
kenjiArai | 1:102230f2879d | 168 | uint32_t set_1PPS_data(void); // Set GPS 1PPS counter value |
kenjiArai | 1:102230f2879d | 169 | uint32_t read_ic2_counter_TIM2(void); // Read TIM2 captured counter value |
kenjiArai | 1:102230f2879d | 170 | uint32_t check_ic2_status_TIM2(void); // Check TIM2 IC2 status |
kenjiArai | 1:102230f2879d | 171 | uint32_t read_ic2_counter_TIM3P4(void); // Read TIM3+4(as 32bit) captured counter value |
kenjiArai | 1:102230f2879d | 172 | uint32_t check_ic2_status_TIM3P4(void); // Check TIM3 IC2 & TIM4 IC1 status |
kenjiArai | 1:102230f2879d | 173 | uint8_t read_oc_port_status(void); // Check TIM2 OC port |
kenjiArai | 1:102230f2879d | 174 | |
kenjiArai | 1:102230f2879d | 175 | private: |
kenjiArai | 2:194f82ad3041 | 176 | double newest_frequency; |
kenjiArai | 2:194f82ad3041 | 177 | double gate_time; |
kenjiArai | 2:194f82ad3041 | 178 | double ex_clock_freq; |
kenjiArai | 2:194f82ad3041 | 179 | uint32_t ex_clk_base; |
kenjiArai | 2:194f82ad3041 | 180 | uint32_t clk_hi_const; |
kenjiArai | 2:194f82ad3041 | 181 | uint32_t clk_upper_limit; |
kenjiArai | 2:194f82ad3041 | 182 | uint32_t clk_lower_limit; |
kenjiArai | 3:339307e1dc0d | 183 | uint8_t gps_ready; |
kenjiArai | 1:102230f2879d | 184 | // TIM2 |
kenjiArai | 1:102230f2879d | 185 | uint32_t counter_tim2; |
kenjiArai | 1:102230f2879d | 186 | uint32_t old_cntr_tim2; |
kenjiArai | 1:102230f2879d | 187 | // TIM3+4 |
kenjiArai | 1:102230f2879d | 188 | uint32_t counter_tim3p4; |
kenjiArai | 1:102230f2879d | 189 | uint32_t old_cntr_tim3p4; |
kenjiArai | 1:102230f2879d | 190 | // 1PPS data |
kenjiArai | 1:102230f2879d | 191 | uint32_t onepps_newest; |
kenjiArai | 1:102230f2879d | 192 | uint32_t onepps_cnt[CNT_BF_SIZE]; |
kenjiArai | 1:102230f2879d | 193 | uint32_t onepps_num; |
kenjiArai | 1:102230f2879d | 194 | uint64_t onepps_cnt_avarage; |
kenjiArai | 1:102230f2879d | 195 | uint8_t onepps_buf_full; |
kenjiArai | 1:102230f2879d | 196 | uint8_t onepps_ready_flg; |
kenjiArai | 2:194f82ad3041 | 197 | |
kenjiArai | 1:102230f2879d | 198 | }; |
kenjiArai | 1:102230f2879d | 199 | |
kenjiArai | 1:102230f2879d | 200 | /* |
kenjiArai | 1:102230f2879d | 201 | Interrupt handler does NOT work following code |
kenjiArai | 1:102230f2879d | 202 | NVIC_SetVector(TIM2_IRQn, (uint32_t)FRQ_CUNTR::irq_ic2_TIM2); |
kenjiArai | 1:102230f2879d | 203 | From this reason, I wrote below code and set interrupt handler out side "FRQ_CUNTR" class |
kenjiArai | 1:102230f2879d | 204 | NVIC_SetVector(TIM2_IRQn, (uint32_t)irq_ic2_TIM2); |
kenjiArai | 1:102230f2879d | 205 | */ |
kenjiArai | 1:102230f2879d | 206 | void irq_ic2_TIM2(void); // TIM2 IC2 Interrupt control |
kenjiArai | 1:102230f2879d | 207 | void irq_ic2_TIM3P4(void); // TIM3 IC2 Interrupt control (same signal connected to TIM4 IC1) |
kenjiArai | 1:102230f2879d | 208 | |
kenjiArai | 0:bfdc6ed58a06 | 209 | } // Frequency_counter |
kenjiArai | 0:bfdc6ed58a06 | 210 | |
kenjiArai | 1:102230f2879d | 211 | #endif // MBED_FRQ_CUNTR |