Very simple but enough accuracy "Frequency Counter". Using GPS 1PPS signal for 1sec gate. CPU is F746, F446 and F411.

Dependencies:   fc_GPS1PPS_f746_f4xx iSerial mbed

Please refer following.
/users/kenjiArai/notebook/frequency-counters/

Concept block are follows.
F746
/media/uploads/kenjiArai/block_diagram_fc_f746_wo_oven.pdf
F411&F446
/media/uploads/kenjiArai/block_diagram_fc_f411_wo_oven.pdf
Hardware Circuit(common F746,F446 and F411)
/media/uploads/kenjiArai/fc_f746ng_circuit.pdf
/media/uploads/kenjiArai/f746_fc_1.jpg

Committer:
kenjiArai
Date:
Wed Nov 16 13:22:00 2016 +0000
Revision:
0:da29cdc50643
Frequency counter program. Using GPS 1PPS signal. ; Frequency measurement range 0.01 Hz to Over 1.5GHz (F746 & F446)  or 0.8GHz.; This is very simple way but enough accuracy.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:da29cdc50643 1 /*
kenjiArai 0:da29cdc50643 2 * mbed Application program / Frequency Counter using GPS 1PPS gate puls
kenjiArai 0:da29cdc50643 3 * Only for ST DISCO-F746NG and Nucleo-F411RE + F446RE
kenjiArai 0:da29cdc50643 4 *
kenjiArai 0:da29cdc50643 5 * Copyright (c) 2014,'15,'16 Kenji Arai / JH1PJL
kenjiArai 0:da29cdc50643 6 * http://www.page.sannet.ne.jp/kenjia/index.html
kenjiArai 0:da29cdc50643 7 * http://mbed.org/users/kenjiArai/
kenjiArai 0:da29cdc50643 8 * Created: October 18th, 2014
kenjiArai 0:da29cdc50643 9 * Revised: January 2nd, 2015
kenjiArai 0:da29cdc50643 10 * Re-started: June 25th, 2016 ported from F411 to F746
kenjiArai 0:da29cdc50643 11 * Re-started: October 5th, 2016 Change board -> DISCO-F746NG
kenjiArai 0:da29cdc50643 12 * Re-started: October 10th, 2016 back to F411
kenjiArai 0:da29cdc50643 13 * Revised: Nobember 15th, 2016
kenjiArai 0:da29cdc50643 14 *
kenjiArai 0:da29cdc50643 15 * Base program: Frequency_counter_w_GPS_1PPS (only for Nucleo-F411RE board)
kenjiArai 0:da29cdc50643 16 * https://developer.mbed.org/users/kenjiArai/code/Frequency_Counter_w_GPS_1PPS/
kenjiArai 0:da29cdc50643 17 *
kenjiArai 0:da29cdc50643 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
kenjiArai 0:da29cdc50643 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
kenjiArai 0:da29cdc50643 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
kenjiArai 0:da29cdc50643 21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
kenjiArai 0:da29cdc50643 22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
kenjiArai 0:da29cdc50643 23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
kenjiArai 0:da29cdc50643 24 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
kenjiArai 0:da29cdc50643 25 */
kenjiArai 0:da29cdc50643 26
kenjiArai 0:da29cdc50643 27 #define USE_COM // use Communication with PC(UART)
kenjiArai 0:da29cdc50643 28 #define USE_DEBUG
kenjiArai 0:da29cdc50643 29
kenjiArai 0:da29cdc50643 30 // Include --------------------------------------------------------------------
kenjiArai 0:da29cdc50643 31 #include "mbed.h"
kenjiArai 0:da29cdc50643 32 #include "GPSrcvr.h"
kenjiArai 0:da29cdc50643 33 #include "fc_GPS1PPS.h"
kenjiArai 0:da29cdc50643 34
kenjiArai 0:da29cdc50643 35 // Definition -----------------------------------------------------------------
kenjiArai 0:da29cdc50643 36 #ifdef USE_COM
kenjiArai 0:da29cdc50643 37 #define BAUD(x) pc.baud(x)
kenjiArai 0:da29cdc50643 38 #define GETC(x) pc.getc(x)
kenjiArai 0:da29cdc50643 39 #define PUTC(x) pc.putc(x)
kenjiArai 0:da29cdc50643 40 #define PRINTF(...) pc.printf(__VA_ARGS__)
kenjiArai 0:da29cdc50643 41 #define READABLE(x) pc.readable(x)
kenjiArai 0:da29cdc50643 42 #else
kenjiArai 0:da29cdc50643 43 #define BAUD(x) {;}
kenjiArai 0:da29cdc50643 44 #define GETC(x) {;}
kenjiArai 0:da29cdc50643 45 #define PUTC(x) {;}
kenjiArai 0:da29cdc50643 46 #define PRINTF(...) {;}
kenjiArai 0:da29cdc50643 47 #define READABLE(x) {;}
kenjiArai 0:da29cdc50643 48 #endif
kenjiArai 0:da29cdc50643 49
kenjiArai 0:da29cdc50643 50 #ifdef USE_DEBUG
kenjiArai 0:da29cdc50643 51 #define U_DEBUGBAUD(x) pc.baud(x)
kenjiArai 0:da29cdc50643 52 #define U_DEBUG(...) pc.printf(__VA_ARGS__)
kenjiArai 0:da29cdc50643 53 #define DBG(c) pc.putc(c)
kenjiArai 0:da29cdc50643 54 #else
kenjiArai 0:da29cdc50643 55 #define U_DEBUGBAUD(x) {;}
kenjiArai 0:da29cdc50643 56 #define U_DEBUG(...) {;}
kenjiArai 0:da29cdc50643 57 #define DBG(c) {;}
kenjiArai 0:da29cdc50643 58 #endif
kenjiArai 0:da29cdc50643 59
kenjiArai 0:da29cdc50643 60 #if defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F446RE)
kenjiArai 0:da29cdc50643 61 #define RECIPRO_LMT 4500
kenjiArai 0:da29cdc50643 62 #define RECIPRO_10KHZ 5000
kenjiArai 0:da29cdc50643 63 #elif defined(TARGET_STM32F746NG)
kenjiArai 0:da29cdc50643 64 #define RECIPRO_LMT 9000
kenjiArai 0:da29cdc50643 65 #define RECIPRO_10KHZ 10000
kenjiArai 0:da29cdc50643 66 #else
kenjiArai 0:da29cdc50643 67 #error "Target is only Nucleo-F411RE + F446RE or DISCO-F746NG!!!"
kenjiArai 0:da29cdc50643 68 #endif
kenjiArai 0:da29cdc50643 69 #define GSP_BUF_B (128 * 3)
kenjiArai 0:da29cdc50643 70 #define GPS_BUF_S (128 * 2)
kenjiArai 0:da29cdc50643 71
kenjiArai 0:da29cdc50643 72 enum input_select {
kenjiArai 0:da29cdc50643 73 BNC_NORMAL = 1,
kenjiArai 0:da29cdc50643 74 RECIPRO_AC,
kenjiArai 0:da29cdc50643 75 RECIPRO_DC,
kenjiArai 0:da29cdc50643 76 SMA_10,
kenjiArai 0:da29cdc50643 77 SMA_20
kenjiArai 0:da29cdc50643 78 };
kenjiArai 0:da29cdc50643 79
kenjiArai 0:da29cdc50643 80 using namespace Frequency_counter;
kenjiArai 0:da29cdc50643 81
kenjiArai 0:da29cdc50643 82 // Object ---------------------------------------------------------------------
kenjiArai 0:da29cdc50643 83 #if defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F446RE)
kenjiArai 0:da29cdc50643 84 DigitalOut input_frq_select(PA_4);
kenjiArai 0:da29cdc50643 85 DigitalInOut prescaler10or20(PA_7);
kenjiArai 0:da29cdc50643 86 DigitalOut recipro_select(PB_6);
kenjiArai 0:da29cdc50643 87 #elif defined(TARGET_STM32F746NG)
kenjiArai 0:da29cdc50643 88 DigitalOut input_frq_select(PF_9);
kenjiArai 0:da29cdc50643 89 DigitalInOut prescaler10or20(PB_15);
kenjiArai 0:da29cdc50643 90 DigitalOut recipro_select(PA_8);
kenjiArai 0:da29cdc50643 91 #endif
kenjiArai 0:da29cdc50643 92 DigitalOut led1(LED1);
kenjiArai 0:da29cdc50643 93 Serial pc(USBTX, USBRX);
kenjiArai 0:da29cdc50643 94 Timer tmr;
kenjiArai 0:da29cdc50643 95
kenjiArai 0:da29cdc50643 96 //**** Req. Counter
kenjiArai 0:da29cdc50643 97 FRQ_CUNTR fc;
kenjiArai 0:da29cdc50643 98
kenjiArai 0:da29cdc50643 99 // RAM ------------------------------------------------------------------------
kenjiArai 0:da29cdc50643 100 // Freq.
kenjiArai 0:da29cdc50643 101 double new_frequency;
kenjiArai 0:da29cdc50643 102 double f_10sec;
kenjiArai 0:da29cdc50643 103 double f_100sec;
kenjiArai 0:da29cdc50643 104 double f_1000sec;
kenjiArai 0:da29cdc50643 105 double freq_recipro;
kenjiArai 0:da29cdc50643 106 // Operation mode
kenjiArai 0:da29cdc50643 107 uint8_t input_mode;
kenjiArai 0:da29cdc50643 108
kenjiArai 0:da29cdc50643 109 // ROM / Constant data --------------------------------------------------------
kenjiArai 0:da29cdc50643 110 // 12345678901234567890
kenjiArai 0:da29cdc50643 111 static char *const msg_msg0 = "Frequency Counter by JH1PJL K.Arai";
kenjiArai 0:da29cdc50643 112 #if defined(TARGET_NUCLEO_F411RE)
kenjiArai 0:da29cdc50643 113 static char *const msg_msg1 = "on Nucleo-F411RE System";
kenjiArai 0:da29cdc50643 114 #elif defined(TARGET_NUCLEO_F446RE)
kenjiArai 0:da29cdc50643 115 static char *const msg_msg1 = "on Nucleo-F446RE System";
kenjiArai 0:da29cdc50643 116 #elif defined(TARGET_STM32F746NG)
kenjiArai 0:da29cdc50643 117 static char *const msg_msg1 = "on DISCO-F746NG System";
kenjiArai 0:da29cdc50643 118 #endif
kenjiArai 0:da29cdc50643 119 static char *const msg_msg2 = " "__DATE__" ";
kenjiArai 0:da29cdc50643 120 static char *const msg_mode1 = " BNC none-prescaler ";
kenjiArai 0:da29cdc50643 121 static char *const msg_mode2 = " BNC recipro(BNC none-prescaler) ";
kenjiArai 0:da29cdc50643 122 static char *const msg_mode3 = " BNC recipro(dedicated BNC input)";
kenjiArai 0:da29cdc50643 123 static char *const msg_mode4 = " SMA prescaler 1/10 ";
kenjiArai 0:da29cdc50643 124 static char *const msg_mode5 = " SMA prescaler 1/20 ";
kenjiArai 0:da29cdc50643 125
kenjiArai 0:da29cdc50643 126 // Function prototypes --------------------------------------------------------
kenjiArai 0:da29cdc50643 127 void gps_data_rcv(void);
kenjiArai 0:da29cdc50643 128
kenjiArai 0:da29cdc50643 129 //------------------------------------------------------------------------------
kenjiArai 0:da29cdc50643 130 // Control Program
kenjiArai 0:da29cdc50643 131 //------------------------------------------------------------------------------
kenjiArai 0:da29cdc50643 132 void freq_measurement(uint8_t mode)
kenjiArai 0:da29cdc50643 133 {
kenjiArai 0:da29cdc50643 134 uint16_t n = 0;
kenjiArai 0:da29cdc50643 135 char buf[48];
kenjiArai 0:da29cdc50643 136 time_t seconds;
kenjiArai 0:da29cdc50643 137 double scale;
kenjiArai 0:da29cdc50643 138
kenjiArai 0:da29cdc50643 139 if (mode == SMA_20){
kenjiArai 0:da29cdc50643 140 scale = 20.0f;
kenjiArai 0:da29cdc50643 141 } else if(mode == SMA_10){
kenjiArai 0:da29cdc50643 142 scale = 10.0f;
kenjiArai 0:da29cdc50643 143 } else {
kenjiArai 0:da29cdc50643 144 scale = 1.0f;
kenjiArai 0:da29cdc50643 145 }
kenjiArai 0:da29cdc50643 146 while(true){
kenjiArai 0:da29cdc50643 147 tmr.reset();
kenjiArai 0:da29cdc50643 148 tmr.start();
kenjiArai 0:da29cdc50643 149 if (fc.status_freq_update() != 0) {
kenjiArai 0:da29cdc50643 150 new_frequency = fc.read_freq_data() * scale;
kenjiArai 0:da29cdc50643 151 f_10sec = fc.read_freq_w_gate_time(10) * scale;
kenjiArai 0:da29cdc50643 152 f_100sec = fc.read_freq_w_gate_time(100) * scale;
kenjiArai 0:da29cdc50643 153 f_1000sec = fc.read_freq_w_gate_time(1000) * scale;
kenjiArai 0:da29cdc50643 154 PRINTF("%8d, Freq: %9.0f,", ++n, new_frequency);
kenjiArai 0:da29cdc50643 155 PRINTF(" F10s: %10.1f, F100s: %11.2f,", f_10sec, f_100sec);
kenjiArai 0:da29cdc50643 156 PRINTF(" F1000s: %12.3f,", f_1000sec);
kenjiArai 0:da29cdc50643 157 } else {
kenjiArai 0:da29cdc50643 158 PRINTF("%8d, No data,,,,", ++n);
kenjiArai 0:da29cdc50643 159 }
kenjiArai 0:da29cdc50643 160 if (mode == SMA_20){
kenjiArai 0:da29cdc50643 161 PRINTF(" Div: 1/20,");
kenjiArai 0:da29cdc50643 162 } else if(mode == SMA_10){
kenjiArai 0:da29cdc50643 163 PRINTF(" Div: 1/10,");
kenjiArai 0:da29cdc50643 164 } else {
kenjiArai 0:da29cdc50643 165 PRINTF(" Div: 1/1 ,");
kenjiArai 0:da29cdc50643 166 }
kenjiArai 0:da29cdc50643 167 seconds = time(NULL) + 32400; // Adjust UTC to JST
kenjiArai 0:da29cdc50643 168 strftime(buf, 40, " %I:%M:%S %p JST (%m/%d)", localtime(&seconds));
kenjiArai 0:da29cdc50643 169 PRINTF("%s\r\n", buf);
kenjiArai 0:da29cdc50643 170 wait_ms(1000 - tmr.read_ms()); // 1sec interval
kenjiArai 0:da29cdc50643 171 }
kenjiArai 0:da29cdc50643 172 }
kenjiArai 0:da29cdc50643 173
kenjiArai 0:da29cdc50643 174 void recipro()
kenjiArai 0:da29cdc50643 175 {
kenjiArai 0:da29cdc50643 176 uint16_t n = 0;
kenjiArai 0:da29cdc50643 177 char buf[48];
kenjiArai 0:da29cdc50643 178 time_t seconds;
kenjiArai 0:da29cdc50643 179 double freq_recipro;
kenjiArai 0:da29cdc50643 180 uint32_t interval_recipro;
kenjiArai 0:da29cdc50643 181 uint32_t base_clk;
kenjiArai 0:da29cdc50643 182 int32_t run2stop;
kenjiArai 0:da29cdc50643 183
kenjiArai 0:da29cdc50643 184 while(true){
kenjiArai 0:da29cdc50643 185 fc.recipro_start_measure();
kenjiArai 0:da29cdc50643 186 PRINTF("Start measurement\r");
kenjiArai 0:da29cdc50643 187 while (fc.recipro_check_trigger() == 0){
kenjiArai 0:da29cdc50643 188 run2stop = tmr.read_ms();
kenjiArai 0:da29cdc50643 189 if (run2stop >= 100000){ // 100sec 0.001Hz
kenjiArai 0:da29cdc50643 190 break;
kenjiArai 0:da29cdc50643 191 }
kenjiArai 0:da29cdc50643 192 }
kenjiArai 0:da29cdc50643 193 if (run2stop >= 1000000){ // 100sec 0.001Hz
kenjiArai 0:da29cdc50643 194 freq_recipro = 0;
kenjiArai 0:da29cdc50643 195 } else {
kenjiArai 0:da29cdc50643 196 interval_recipro = fc.recipro_read_data();
kenjiArai 0:da29cdc50643 197 base_clk = fc.recipro_base_clk_data(1);
kenjiArai 0:da29cdc50643 198 if (interval_recipro >= 9000){// Measure less than 10KHz frequency
kenjiArai 0:da29cdc50643 199 freq_recipro = (double)base_clk / (double)interval_recipro;
kenjiArai 0:da29cdc50643 200 PRINTF("%8d, Freq: %11.5f [Hz] , ", n++, freq_recipro);
kenjiArai 0:da29cdc50643 201 PRINTF("Raw: %11u [cnt] , ", interval_recipro);
kenjiArai 0:da29cdc50643 202 PRINTF("Base: %11u [Hz], ", base_clk);
kenjiArai 0:da29cdc50643 203 seconds = time(NULL) + 32400; // Adjust UTC to JST
kenjiArai 0:da29cdc50643 204 strftime(buf, 40,
kenjiArai 0:da29cdc50643 205 " %I:%M:%S %p JST (%m/%d)", localtime(&seconds));
kenjiArai 0:da29cdc50643 206 PRINTF("%s\r\n", buf);
kenjiArai 0:da29cdc50643 207 run2stop = tmr.read_ms();
kenjiArai 0:da29cdc50643 208 if (run2stop < 1000){
kenjiArai 0:da29cdc50643 209 run2stop = 1000 - run2stop;
kenjiArai 0:da29cdc50643 210 wait_ms(run2stop); // 1sec interval
kenjiArai 0:da29cdc50643 211 }
kenjiArai 0:da29cdc50643 212 } else {
kenjiArai 0:da29cdc50643 213 freq_recipro = 0;
kenjiArai 0:da29cdc50643 214 }
kenjiArai 0:da29cdc50643 215 }
kenjiArai 0:da29cdc50643 216 }
kenjiArai 0:da29cdc50643 217 }
kenjiArai 0:da29cdc50643 218
kenjiArai 0:da29cdc50643 219 int main()
kenjiArai 0:da29cdc50643 220 {
kenjiArai 0:da29cdc50643 221 PRINTF("\r\n%s%s\r\n", msg_msg0, msg_msg2);
kenjiArai 0:da29cdc50643 222 PRINTF("%s\r\n", msg_msg1);
kenjiArai 0:da29cdc50643 223 PRINTF("Wait GPS 1PPS signal\r\n");
kenjiArai 0:da29cdc50643 224 gps_data_rcv();
kenjiArai 0:da29cdc50643 225 PRINTF("\r\nPlease select measurement mode.\r\n");
kenjiArai 0:da29cdc50643 226 PRINTF("%s-> 1\r\n", msg_mode1);
kenjiArai 0:da29cdc50643 227 PRINTF("%s-> 2\r\n", msg_mode2);
kenjiArai 0:da29cdc50643 228 PRINTF("%s-> 3\r\n", msg_mode3);
kenjiArai 0:da29cdc50643 229 PRINTF("%s-> 4\r\n", msg_mode4);
kenjiArai 0:da29cdc50643 230 PRINTF("%s-> 5\r\n", msg_mode5);
kenjiArai 0:da29cdc50643 231 PRINTF("Enter 1 to 5 (other input then 1)\r\n");
kenjiArai 0:da29cdc50643 232 // Select operation mode
kenjiArai 0:da29cdc50643 233 char c = GETC() - '0';
kenjiArai 0:da29cdc50643 234 if ((c > 5) || (c <= 0)){ c = 1;}
kenjiArai 0:da29cdc50643 235 input_mode = c;
kenjiArai 0:da29cdc50643 236 PRINTF("If you want to change the input signal,");
kenjiArai 0:da29cdc50643 237 PRINTF(" please restart the system (Enter Alt+B from your PC)\r\n");
kenjiArai 0:da29cdc50643 238 PRINTF("\r\nStart measuring\r\nMeasureing mode = ");
kenjiArai 0:da29cdc50643 239 switch(input_mode){
kenjiArai 0:da29cdc50643 240 case RECIPRO_AC:
kenjiArai 0:da29cdc50643 241 PRINTF("%s\r\n", msg_mode2);
kenjiArai 0:da29cdc50643 242 input_frq_select = 1;
kenjiArai 0:da29cdc50643 243 prescaler10or20.output();
kenjiArai 0:da29cdc50643 244 prescaler10or20 = 0;
kenjiArai 0:da29cdc50643 245 recipro_select = 0;
kenjiArai 0:da29cdc50643 246 recipro();
kenjiArai 0:da29cdc50643 247 break;
kenjiArai 0:da29cdc50643 248 case RECIPRO_DC:
kenjiArai 0:da29cdc50643 249 PRINTF("%s\r\n", msg_mode3);
kenjiArai 0:da29cdc50643 250 input_frq_select = 1;
kenjiArai 0:da29cdc50643 251 prescaler10or20.output();
kenjiArai 0:da29cdc50643 252 prescaler10or20 = 0;
kenjiArai 0:da29cdc50643 253 recipro_select = 1;
kenjiArai 0:da29cdc50643 254 recipro();
kenjiArai 0:da29cdc50643 255 break;
kenjiArai 0:da29cdc50643 256 case SMA_10:
kenjiArai 0:da29cdc50643 257 PRINTF("%s\r\n", msg_mode4);
kenjiArai 0:da29cdc50643 258 input_frq_select = 0;
kenjiArai 0:da29cdc50643 259 prescaler10or20.output();
kenjiArai 0:da29cdc50643 260 prescaler10or20 = 0;
kenjiArai 0:da29cdc50643 261 recipro_select = 0;
kenjiArai 0:da29cdc50643 262 freq_measurement(input_mode);
kenjiArai 0:da29cdc50643 263 break;
kenjiArai 0:da29cdc50643 264 case SMA_20:
kenjiArai 0:da29cdc50643 265 PRINTF("%s\r\n", msg_mode5);
kenjiArai 0:da29cdc50643 266 input_frq_select = 0;
kenjiArai 0:da29cdc50643 267 prescaler10or20.input();
kenjiArai 0:da29cdc50643 268 recipro_select = 0;
kenjiArai 0:da29cdc50643 269 freq_measurement(input_mode);
kenjiArai 0:da29cdc50643 270 break;
kenjiArai 0:da29cdc50643 271 case BNC_NORMAL:
kenjiArai 0:da29cdc50643 272 default:
kenjiArai 0:da29cdc50643 273 input_mode = BNC_NORMAL;
kenjiArai 0:da29cdc50643 274 PRINTF("%s\r\n", msg_mode1);
kenjiArai 0:da29cdc50643 275 input_frq_select = 1;
kenjiArai 0:da29cdc50643 276 prescaler10or20.output();
kenjiArai 0:da29cdc50643 277 prescaler10or20 = 0;
kenjiArai 0:da29cdc50643 278 recipro_select = 0;
kenjiArai 0:da29cdc50643 279 freq_measurement(input_mode);
kenjiArai 0:da29cdc50643 280 break;
kenjiArai 0:da29cdc50643 281 }
kenjiArai 0:da29cdc50643 282 while(true){;} // Just in case
kenjiArai 0:da29cdc50643 283 }
kenjiArai 0:da29cdc50643 284
kenjiArai 0:da29cdc50643 285