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

Revision:
0:da29cdc50643
diff -r 000000000000 -r da29cdc50643 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Nov 16 13:22:00 2016 +0000
@@ -0,0 +1,285 @@
+/*
+ * mbed Application program / Frequency Counter using GPS 1PPS gate puls
+ *      Only for ST DISCO-F746NG and Nucleo-F411RE + F446RE
+ *
+ * Copyright (c) 2014,'15,'16 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  http://mbed.org/users/kenjiArai/
+ *      Created:    October   18th, 2014
+ *      Revised:    January    2nd, 2015
+ *      Re-started: June      25th, 2016    ported from F411 to F746
+ *      Re-started: October    5th, 2016    Change board -> DISCO-F746NG
+ *      Re-started: October   10th, 2016    back to F411
+ *      Revised:    Nobember  15th, 2016
+ *
+ * Base program: Frequency_counter_w_GPS_1PPS (only for Nucleo-F411RE board)
+ * https://developer.mbed.org/users/kenjiArai/code/Frequency_Counter_w_GPS_1PPS/
+ *
+ * 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 AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define     USE_COM         // use Communication with PC(UART)
+#define     USE_DEBUG
+
+//  Include --------------------------------------------------------------------
+#include    "mbed.h"
+#include    "GPSrcvr.h"
+#include    "fc_GPS1PPS.h"
+
+//  Definition -----------------------------------------------------------------
+#ifdef  USE_COM
+#define BAUD(x)             pc.baud(x)
+#define GETC(x)             pc.getc(x)
+#define PUTC(x)             pc.putc(x)
+#define PRINTF(...)         pc.printf(__VA_ARGS__)
+#define READABLE(x)         pc.readable(x)
+#else
+#define BAUD(x)             {;}
+#define GETC(x)             {;}
+#define PUTC(x)             {;}
+#define PRINTF(...)         {;}
+#define READABLE(x)         {;}
+#endif
+
+#ifdef  USE_DEBUG
+#define U_DEBUGBAUD(x)      pc.baud(x)
+#define U_DEBUG(...)        pc.printf(__VA_ARGS__)
+#define DBG(c)              pc.putc(c)
+#else
+#define U_DEBUGBAUD(x)      {;}
+#define U_DEBUG(...)        {;}
+#define DBG(c)              {;}
+#endif
+
+#if defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F446RE)
+#define RECIPRO_LMT         4500
+#define RECIPRO_10KHZ       5000
+#elif defined(TARGET_STM32F746NG)
+#define RECIPRO_LMT         9000
+#define RECIPRO_10KHZ       10000
+#else
+#error "Target is only Nucleo-F411RE + F446RE or DISCO-F746NG!!!"
+#endif
+#define GSP_BUF_B           (128 * 3)
+#define GPS_BUF_S           (128 * 2)
+
+enum input_select {
+         BNC_NORMAL = 1,
+         RECIPRO_AC,
+         RECIPRO_DC,
+         SMA_10,
+         SMA_20
+};
+
+using namespace Frequency_counter;
+
+//  Object ---------------------------------------------------------------------
+#if defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F446RE)
+DigitalOut  input_frq_select(PA_4);
+DigitalInOut  prescaler10or20(PA_7);
+DigitalOut  recipro_select(PB_6);
+#elif defined(TARGET_STM32F746NG)
+DigitalOut  input_frq_select(PF_9);
+DigitalInOut  prescaler10or20(PB_15);
+DigitalOut  recipro_select(PA_8);
+#endif
+DigitalOut  led1(LED1);
+Serial      pc(USBTX, USBRX);
+Timer       tmr;
+
+//**** Req. Counter
+FRQ_CUNTR   fc;
+
+//  RAM ------------------------------------------------------------------------
+// Freq.
+double      new_frequency;
+double      f_10sec;
+double      f_100sec;
+double      f_1000sec;
+double      freq_recipro;
+// Operation mode
+uint8_t     input_mode;
+
+//  ROM / Constant data --------------------------------------------------------
+//                               12345678901234567890
+static char *const msg_msg0   = "Frequency Counter by JH1PJL K.Arai";
+#if   defined(TARGET_NUCLEO_F411RE)
+static char *const msg_msg1   = "on Nucleo-F411RE System";
+#elif defined(TARGET_NUCLEO_F446RE)
+static char *const msg_msg1   = "on Nucleo-F446RE System";
+#elif defined(TARGET_STM32F746NG)
+static char *const msg_msg1   = "on DISCO-F746NG System";
+#endif
+static char *const msg_msg2   = "    "__DATE__" ";
+static char *const msg_mode1  = "  BNC none-prescaler              ";
+static char *const msg_mode2  = "  BNC recipro(BNC none-prescaler) ";
+static char *const msg_mode3  = "  BNC recipro(dedicated BNC input)";
+static char *const msg_mode4  = "  SMA prescaler 1/10              ";
+static char *const msg_mode5  = "  SMA prescaler 1/20              ";
+
+//  Function prototypes --------------------------------------------------------
+void gps_data_rcv(void);
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+void freq_measurement(uint8_t mode)
+{
+    uint16_t    n = 0;
+    char        buf[48];
+    time_t      seconds;
+    double      scale;
+
+    if (mode == SMA_20){
+        scale = 20.0f;
+    } else if(mode == SMA_10){
+        scale = 10.0f;
+    } else {
+        scale = 1.0f;
+    }
+    while(true){
+        tmr.reset();
+        tmr.start();
+        if (fc.status_freq_update() != 0) {
+            new_frequency = fc.read_freq_data() * scale;
+            f_10sec   = fc.read_freq_w_gate_time(10) * scale;
+            f_100sec  = fc.read_freq_w_gate_time(100) * scale;
+            f_1000sec = fc.read_freq_w_gate_time(1000) * scale;
+            PRINTF("%8d, Freq: %9.0f,", ++n, new_frequency);
+            PRINTF(" F10s: %10.1f, F100s: %11.2f,", f_10sec, f_100sec);
+            PRINTF(" F1000s: %12.3f,", f_1000sec);
+        } else {
+            PRINTF("%8d, No data,,,,", ++n);
+        }
+        if (mode == SMA_20){
+            PRINTF(" Div: 1/20,");
+        } else if(mode == SMA_10){
+            PRINTF(" Div: 1/10,");
+        } else {
+            PRINTF(" Div: 1/1 ,");
+        }             
+        seconds = time(NULL) + 32400; // Adjust UTC to JST
+        strftime(buf, 40, " %I:%M:%S %p JST (%m/%d)", localtime(&seconds));
+        PRINTF("%s\r\n", buf);
+        wait_ms(1000 - tmr.read_ms());      // 1sec interval
+    }
+}
+
+void recipro()
+{
+    uint16_t    n = 0;
+    char        buf[48];
+    time_t      seconds;
+    double      freq_recipro;
+    uint32_t    interval_recipro;
+    uint32_t    base_clk;
+    int32_t     run2stop;
+
+    while(true){
+        fc.recipro_start_measure();
+        PRINTF("Start measurement\r");
+        while (fc.recipro_check_trigger() == 0){
+            run2stop = tmr.read_ms();
+            if (run2stop >= 100000){ // 100sec 0.001Hz
+                break;
+            }
+        }
+        if (run2stop >= 1000000){ // 100sec 0.001Hz
+            freq_recipro = 0;
+        } else {
+            interval_recipro = fc.recipro_read_data();
+            base_clk = fc.recipro_base_clk_data(1);
+            if (interval_recipro >= 9000){// Measure less than 10KHz frequency
+                freq_recipro = (double)base_clk / (double)interval_recipro;
+                PRINTF("%8d, Freq: %11.5f [Hz] , ", n++, freq_recipro);
+                PRINTF("Raw:  %11u [cnt] , ", interval_recipro);
+                PRINTF("Base: %11u [Hz], ", base_clk);
+                seconds = time(NULL) + 32400;   // Adjust UTC to JST
+                strftime(buf, 40,
+                            " %I:%M:%S %p JST (%m/%d)", localtime(&seconds));
+                PRINTF("%s\r\n", buf);
+                run2stop = tmr.read_ms();
+                if (run2stop < 1000){ 
+                    run2stop = 1000 - run2stop;
+                    wait_ms(run2stop);          // 1sec interval
+                }
+            } else {
+                freq_recipro = 0;
+            }
+        }
+    }
+}
+
+int main()
+{
+    PRINTF("\r\n%s%s\r\n", msg_msg0, msg_msg2);
+    PRINTF("%s\r\n", msg_msg1);
+    PRINTF("Wait GPS 1PPS signal\r\n");
+    gps_data_rcv();
+    PRINTF("\r\nPlease select measurement mode.\r\n");
+    PRINTF("%s-> 1\r\n", msg_mode1);
+    PRINTF("%s-> 2\r\n", msg_mode2);
+    PRINTF("%s-> 3\r\n", msg_mode3);
+    PRINTF("%s-> 4\r\n", msg_mode4);
+    PRINTF("%s-> 5\r\n", msg_mode5);
+    PRINTF("Enter 1 to 5 (other input then 1)\r\n");
+    // Select operation mode
+    char c = GETC() - '0';
+    if ((c > 5) || (c <= 0)){   c = 1;}
+    input_mode = c;
+    PRINTF("If you want to change the input signal,");
+    PRINTF(" please restart the system (Enter Alt+B from your PC)\r\n");
+    PRINTF("\r\nStart measuring\r\nMeasureing mode = ");
+    switch(input_mode){
+        case RECIPRO_AC:
+            PRINTF("%s\r\n", msg_mode2);
+            input_frq_select = 1;
+            prescaler10or20.output();
+            prescaler10or20 = 0;
+            recipro_select = 0;
+            recipro();
+            break;
+        case RECIPRO_DC:
+            PRINTF("%s\r\n", msg_mode3);
+            input_frq_select = 1;
+            prescaler10or20.output();
+            prescaler10or20 = 0;
+            recipro_select = 1;
+            recipro();
+            break;
+        case SMA_10:
+            PRINTF("%s\r\n", msg_mode4);
+            input_frq_select = 0;
+            prescaler10or20.output();
+            prescaler10or20 = 0;
+            recipro_select = 0;
+            freq_measurement(input_mode);
+            break;
+        case SMA_20:
+            PRINTF("%s\r\n", msg_mode5);
+            input_frq_select = 0;
+            prescaler10or20.input();
+            recipro_select = 0;
+            freq_measurement(input_mode);
+            break;
+        case BNC_NORMAL:
+        default:
+            input_mode = BNC_NORMAL;
+            PRINTF("%s\r\n", msg_mode1);
+            input_frq_select = 1;
+            prescaler10or20.output();
+            prescaler10or20 = 0;
+            recipro_select = 0;
+            freq_measurement(input_mode);
+            break;
+    }
+    while(true){;}  // Just in case
+}
+
+