Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: FreqCntr_GPS1PPS_F746F4xx_w_recipro Freq_Cntr_GPS1PPS_F746NG_GUI
Fork of Frq_cuntr_full by
Revision 2:194f82ad3041, committed 2014-12-21
- Comitter:
- kenjiArai
- Date:
- Sun Dec 21 12:14:46 2014 +0000
- Parent:
- 1:102230f2879d
- Child:
- 3:339307e1dc0d
- Commit message:
- added new function and fixed bugs
Changed in this revision
| frq_cuntr_full.cpp | Show annotated file Show diff for this revision Revisions of this file |
| frq_cuntr_full.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/frq_cuntr_full.cpp Sat Nov 22 23:02:39 2014 +0000
+++ b/frq_cuntr_full.cpp Sun Dec 21 12:14:46 2014 +0000
@@ -8,7 +8,7 @@
* http://mbed.org/users/kenjiArai/
* Additional functions and modification
* started: October 18th, 2014
- * Revised: Nobember 23rd, 2014
+ * Revised: December 21st, 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
@@ -41,11 +41,11 @@
namespace Frequency_counter
{
// TIM2 OC
-uint32_t oc_set_time0;
-uint32_t oc_set_time1;
-uint8_t new_gt_value;
-uint32_t oc_hi_time;
-uint32_t oc_lo_time;
+static uint32_t oc_set_time0;
+static uint32_t oc_set_time1;
+static uint8_t new_gt_value;
+static uint32_t oc_hi_time;
+static uint32_t oc_lo_time;
// TIM2 IC
static uint8_t tim2_ready_flg;
static uint32_t tim2_cnt_data;
@@ -55,7 +55,7 @@
static uint32_t tim3p4_cnt_data;
//-------------------------------------------------------------------------------------------------
-// Control Program
+// Interrupt Handlers
//-------------------------------------------------------------------------------------------------
// TIM2 IC2 Interrupt control
void irq_ic2_TIM2(void)
@@ -67,9 +67,12 @@
tim2_old_cnt_data = tim2_cnt_data;
tim2_cnt_data = TIM2->CCR2;
tim2_ready_flg = 1;
- } else if (reg & TIM_SR_CC3IF) {
+#if defined(DEBUG)
+ debug_led = !debug_led;
+#endif
+ } else if (reg & TIM_SR_CC3IF) { // Output Compare
TIM2->SR &= ~TIM_SR_CC3IF; // clear IC flag
- if (GPIOB->IDR & 0x0400) { // Check PB10 status
+ if (GPIOB->IDR & 0x0400) { // Check PB10 status
TIM2->CCR3 = TIM2->CCR3 + oc_hi_time;
} else {
TIM2->CCR3 = TIM2->CCR3 + oc_lo_time;
@@ -80,7 +83,7 @@
}
}
#if defined(DEBUG)
- debug_led = !debug_led;
+// debug_led = !debug_led;
#endif
}
}
@@ -93,17 +96,19 @@
tim3p4_cnt_data = (TIM4->CCR1 << 16) + TIM3->CCR2;
tim3p4_ready_flg = 1;
#if defined(DEBUG)
- debug_led = !debug_led;
+// debug_led = !debug_led;
#endif
}
//---------------------------------------------------------------------------------------
// Frequency Counter
//---------------------------------------------------------------------------------------
-FRQ_CUNTR::FRQ_CUNTR(PinName f_in, double gt): _pin(f_in)
+FRQ_CUNTR::FRQ_CUNTR(PinName f_in, double gt, double ex_clock): _pin(f_in)
{
- set_gate_time(gt);
- initialize_Freq_counter();
+ // Don't change calling sequence!!
+ set_external_clock(ex_clock); // 1st
+ set_gate_time(gt); // 2nd
+ initialize_Freq_counter(); // 3rd
}
// Set gate time
@@ -116,23 +121,52 @@
} else {
gate_time = gt;
}
- oc_set_time0 = CNT_FIX_BASE;
- double gt_tmp0 = CNT_BASE * gate_time;
+ oc_set_time0 = clk_hi_const;
+ double gt_tmp0 = ex_clk_base * gate_time;
uint32_t gt_tmp1 = (uint32_t)gt_tmp0;
if ((gt_tmp0 - (double)gt_tmp1) >= 0.5) {
++gt_tmp1;
}
- oc_set_time1 = gt_tmp1 - CNT_FIX_BASE;
+ oc_set_time1 = gt_tmp1 - clk_hi_const;
new_gt_value = 1;
return gate_time;
}
+// Read gate time
+double FRQ_CUNTR::read_gate_time(void)
+{
+ return gate_time;
+}
+
+// Set External Clock Frequency
+void FRQ_CUNTR::set_external_clock(double ex_clock)
+{
+#if defined(BASE_EXTERNAL_CLOCK)
+ ex_clock_freq = ex_clock;
+ ex_clk_base = (uint32_t)(ex_clock_freq * 1000000); // MHz->Hz
+ clk_hi_const = (uint32_t)(ex_clock_freq * 1000000 * 0.04); // 40mS
+// uint32_t err = (uint32_t)(ex_clock_freq * 1000000 * 0.00001); // 10ppm error range
+ uint32_t err = (uint32_t)(ex_clock_freq * 1000000 * 0.1);
+ clk_upper_limit = ex_clk_base + err;
+ clk_lower_limit = ex_clk_base - err;
+#else
+ ex_clock_freq = 100; // Internal 100MHz
+ ex_clk_base = 100000000; // MHz->Hz
+ clk_hi_const = 4000000; // 40mS
+ uint32_t err = 100; // 10ppm error range
+ clk_upper_limit = ex_clk_base + err;
+ clk_lower_limit = ex_clk_base - err;
+#endif
+}
+
// Read new frequency data
-uint32_t FRQ_CUNTR::read_freq_data(void)
+double FRQ_CUNTR::read_freq_data(void)
{
old_cntr_tim3p4 = counter_tim3p4;
counter_tim3p4 = read_ic2_counter_TIM3P4();
- return (counter_tim3p4 - old_cntr_tim3p4);
+ double freq0 = (double)(counter_tim3p4 - old_cntr_tim3p4);
+ newest_frequency = freq0 / gate_time;
+ return newest_frequency;
}
// Read status (new frequency data is available or not)
@@ -151,9 +185,12 @@
uint32_t FRQ_CUNTR::set_1PPS_data(void)
{
uint32_t diff = tim2_cnt_data - tim2_old_cnt_data;
- if ((diff > CNT_UPPER) || (diff < CNT_LOWER)) {
+ if ((diff > clk_upper_limit) || (diff < clk_lower_limit)) {
+// PRINTF("IC0 %d %d %d \r\n", diff, clk_upper_limit, clk_lower_limit);
+ gps_ready = 0;
return 0;
} else {
+ gps_ready = 1;
onepps_cnt[onepps_num] = diff;
if (++onepps_num >= CNT_BF_SIZE) {
onepps_num = 0;
@@ -173,16 +210,26 @@
total += (uint64_t)onepps_cnt[i];
}
onepps_cnt_avarage = total / CNT_BF_SIZE;
- PRINTF("buf");
+// PRINTF("buf");
} else {
for (uint32_t i = 0; i < onepps_num; i++) {
total += (uint64_t)onepps_cnt[i];
}
onepps_cnt_avarage = total / onepps_num;
- PRINTF("not");
+// PRINTF("not");
}
- PRINTF(" full, num= %3d , 1PPS/new= %9d , ", onepps_num, onepps_newest);
+// PRINTF(" full, num= %3d , 1PPS/new= %9d\r\n", onepps_num, onepps_newest);
+#if defined(ONEPPS_AVE)
return onepps_cnt_avarage;
+#else
+ return onepps_newest;
+#endif
+}
+
+// Check GPS condition
+uint8_t FRQ_CUNTR::gps_status(void)
+{
+ return gps_ready;
}
//---------------------------------------------------------------------------------------
@@ -247,7 +294,7 @@
TIM2->CNT = 0;
wait(gate_time); // Gate time for count
freq = TIM2->CNT; // read counter
- PRINTF("Clock freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq, gate_time);
+// PRINTF("Clock freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq, gate_time);
return freq; // return counter data
}
@@ -263,7 +310,7 @@
freq0 = TIM3->CNT;
freq1 = TIM4->CNT;
freq0 = (freq1 << 16) + freq0;
- PRINTF("Input freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq0, gate_time);
+// PRINTF("Input freq.=%10d [Hz], gate= %4.2f [Sec]\r\n", freq0, gate_time);
return freq0; // read counter
}
@@ -297,17 +344,17 @@
// MC01 output HSE 1/1, MCO2 output SYSCLK 1/1
// MCO2 MCO2PRE MCO1PRE MCO1
RCC->CFGR |= (0x0 << 30) + (0x0 << 27) + (0x0 << 24) + (0x2 << 21);
- PRINTF("Set MCO1(PA8):HSE/1, MCO2(PC9):SYSCLK/1\r\n");
+// PRINTF("Set MCO1(PA8):HSE/1, MCO2(PC9):SYSCLK/1\r\n");
} else if (select == 2) {
// MC01 output HSE 1/2, MCO2 output SYSCLK 1/2
// MCO2 MCO2PRE MCO1PRE MCO1
RCC->CFGR |= (0x0 << 30) + (0x4 << 27) + (0x4 << 24) + (0x2 << 21);
- PRINTF("Set MCO1(PA8):HSE/2, MCO2(PC9):SYSCLK/2\r\n");
+// PRINTF("Set MCO1(PA8):HSE/2, MCO2(PC9):SYSCLK/2\r\n");
} else { // select = 4 and other wrong order
// MC01 output HSE 1/4, MCO2 output SYSCLK 1/4
// MCO2 MCO2PRE MCO1PRE MCO1
RCC->CFGR |= (0x0 << 30) + (0x6 << 27) + (0x6 << 24) + (0x2 << 21);
- PRINTF("Set MCO1(PA8):HSE/4, MCO2(PC9):SYSCLK/4\r\n");
+// PRINTF("Set MCO1(PA8):HSE/4, MCO2(PC9):SYSCLK/4\r\n");
}
}
@@ -347,7 +394,7 @@
TIM2->SMCR |= (uint16_t)( TIM_TS_TI1FP1 | TIM_SLAVEMODE_EXTERNAL1); // ECE must be ZERO!!!!
TIM2->CR1 |= (uint16_t)TIM_CR1_CEN; // Enable the TIM Counter
#else
- // Initialize Timer2(32bit) for an external up counter mode
+ // Initialize Timer2(32bit) for an internal up counter mode
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
TIM2->CR1 &= (uint16_t)(~(TIM_CR1_DIR | TIM_CR1_CMS | TIM_CR1_CKD)); // count_up + div by 1
TIM2->CR1 |= TIM_CR1_URS;
@@ -391,6 +438,7 @@
oc_hi_time = oc_set_time0;
oc_lo_time = oc_set_time1;
TIM2->CCR3 = TIM2->CNT + oc_hi_time;// Set the Capture Compare Register value
+#if 0
// Only for Debug purpose
BAUD(9600);
// PA
@@ -417,6 +465,7 @@
PRINTF("TIM2->CCER 0x%08x:0x%08x\r\n",&TIM2->CCER, TIM2->CCER);
PRINTF("TIM2->SMCR 0x%08x:0x%08x\r\n",&TIM2->SMCR, TIM2->SMCR);
PRINTF("TIM2->CCR3 0x%08x:0x%08x\r\n\r\n",&TIM2->CCR3, TIM2->CCR3);
+#endif
// Interrupt Timer2 IC2
for (uint32_t i = 0; i < CNT_BF_SIZE; i++) {
onepps_cnt[i] = 0;
@@ -498,6 +547,7 @@
TIM4->CCMR1 |= (uint16_t)TIM_CCMR1_CC1S_0;
TIM4->CCER &= (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP); // positive edge
TIM4->CCER |= (uint16_t)TIM_CCER_CC1E; // enable capture
+#if 0
// Only for Debug purpose
// PB
PRINTF("// PB6 -> Input Capture pin as Timer4 CH1/TI1\r\n");
@@ -537,6 +587,7 @@
PRINTF("TIM4->CCER 0x%08x:0x%08x\r\n",&TIM4->CCER, TIM4->CCER);
PRINTF("TIM4->SMCR 0x%08x:0x%08x\r\n\r\n",&TIM4->SMCR, TIM4->SMCR);
PRINTF("RCC->APB1ENR 0x%08x:0x%08x\r\n\r\n",&RCC->APB1ENR, RCC->APB1ENR);
+#endif
// Interrupt Timer3 IC2
tim3p4_ready_flg = 0;
tim3p4_cnt_data = 0;
@@ -548,4 +599,21 @@
NVIC_EnableIRQ(TIM3_IRQn);
}
+//---------------------------------------------------------------------------------------
+// Only for Debug purpose
+//---------------------------------------------------------------------------------------
+void FRQ_CUNTR::debug_printf_internal_data(void)
+{
+#if 0
+ PRINTF("Debug information\r\n");
+ PRINTF("gate_time %f\r\n", gate_time);
+ PRINTF("ex_clock_freq %f\r\n", ex_clock_freq);
+ PRINTF("ex_clk_base %9d\r\n", ex_clk_base);
+ PRINTF("clk_hi_const %9d\r\n", clk_hi_const);
+ PRINTF("clk_upper_limit %9d\r\n", clk_upper_limit);
+ PRINTF("clk_lower_limit %9d\r\n", clk_lower_limit);
+ PRINTF("\r\n");
+#endif
+}
+
} // Frequency_counter
--- a/frq_cuntr_full.h Sat Nov 22 23:02:39 2014 +0000
+++ b/frq_cuntr_full.h Sun Dec 21 12:14:46 2014 +0000
@@ -8,7 +8,7 @@
* http://mbed.org/users/kenjiArai/
* Additional functions and modification
* started: October 18th, 2014
- * Revised: Nobember 23rd, 2014
+ * Revised: December 21st, 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
@@ -22,34 +22,20 @@
#include "mbed.h"
-#define DEBUG // use Communication with PC(UART)
+//#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
+ PLL clock drifts over 70Hz (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.
+ Comment out "BASE_EXTERNAL_CLOCK" is only for checking!!
*/
#define BASE_EXTERNAL_CLOCK
namespace Frequency_counter
{
-#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
@@ -59,11 +45,16 @@
* @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]
+ * using namespace Frequency_counter;
+ *
+ * // PC_6,PC_7 & PB_6 use for Timer3 & 4(16+16bit)
+ * // PA_0,PA_1 & PB_10 use for Timer2(32bit)
+ * // PA_8 & PC_7 use for MCO (Test purpose)
+ * FRQ_CUNTR fc(PC_6, 1.0, 50.000000);// Input port, gate time[sec] and External clock freq.
*
* int main() {
+ * uint32_t counter_1pps = 0;
+ * double new_frequency = 0;
* // 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)
@@ -73,7 +64,7 @@
* 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);
+ * PRINTF("1PPS/ave = %9d , FREQUENCY = %11.3f\r\n", counter_1pps, new_frequency);
* }
* }
* @endcode
@@ -82,17 +73,24 @@
class FRQ_CUNTR
{
public:
+
/** Configure data pin (Not changeable)
- * @param Freq. input pin
+ * @param Freq. input pin + Gate time[sec] + External clock[MHz]
*/
- FRQ_CUNTR(PinName f_in, double gt);
+ FRQ_CUNTR(PinName f_in, double gt, double ex_clock);
/** Set gate time
* @param gate time [sec]
- * @return !=0: new data is avairable, 0: not yet
+ * @return gate time (range 50mS to 1 minute)
*/
double set_gate_time(double gt);
+ /** Read gate time
+ * @param none
+ * @return gate time (range 50mS to 1 minute)
+ */
+ double read_gate_time(void);
+
/** Read status (new frequency data is available or not)
* @param none
* @return !=0: new data is avairable, 0: not yet
@@ -103,7 +101,7 @@
* @param none
* @return frequency data
*/
- uint32_t read_freq_data(void);
+ double read_freq_data(void);
/** Read avarage measued data GPS 1PPS
* @param none
@@ -117,35 +115,49 @@
*/
uint32_t status_1pps(void);
- /** This is a test purpose function
+ /** Read GPS status
+ * @param none
+ * @return 1: GPS is ready
+ */
+ uint8_t gps_status(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
+ /** 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
+ /** 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);
+ /** This is a "DEBUG PURPOSE" function
+ * print internal data (need to define "DEBUG"
+ * @param none
+ * @return none
+ */
+ void debug_printf_internal_data(void);
+
protected:
DigitalIn _pin;
void initialize_Freq_counter(void); // Initialize timers
- // Internal clock (50MHz) and IC2 for GPS 1pps signal measurement
+ // Internal clock (100MHz) or External clock(?MHz) 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);
+ void set_external_clock(double ex_clock); // Set external clock data
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
@@ -154,8 +166,15 @@
uint8_t read_oc_port_status(void); // Check TIM2 OC port
private:
+ double newest_frequency;
+ double gate_time;
+ double ex_clock_freq;
+ uint32_t ex_clk_base;
+ uint32_t clk_hi_const;
+ uint32_t clk_upper_limit;
+ uint32_t clk_lower_limit;
+ uint8_t gps_ready;
// TIM2
- double gate_time;
uint32_t counter_tim2;
uint32_t old_cntr_tim2;
// TIM3+4
@@ -168,6 +187,7 @@
uint64_t onepps_cnt_avarage;
uint8_t onepps_buf_full;
uint8_t onepps_ready_flg;
+
};
/*
