Hi All, I'm trying to capture the TWO pulses at TWO GPIO's by measuring the period of the signal. Im using the following code. This code is perfectly working for 1 Signal at 1 GPIO. After making it for TWO signals at 2 GPIO's - Its working for 1 and not showing for second or showing some values. I checked both by commenting one by one and it seems both programs are working fine but when I try to work for boths its showing one and not responding for other.
The code is attached below,
/** * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form, except as embedded into a Nordic * Semiconductor ASA integrated circuit in a product or a software update for * such product, must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. Neither the name of Nordic Semiconductor ASA nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 4. This software, with or without modification, must only be used with a * Nordic Semiconductor ASA integrated circuit. * * 5. Any software provided in binary form under this license must not be reverse * engineered, decompiled, modified and/or disassembled. * * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** @file * @defgroup temperature_example_main main.c * @{ * @ingroup temperature_example * @brief Temperature Example Application main file. * @details * This file contains the source code for a sample application using the temperature sensor. * This contains workaround for PAN_028 rev2.0A anomalies 28, 29,30 and 31. PAN 43 is not covered. * - PAN_028 rev2.0A anomaly 28 - TEMP: Negative measured values are not represented correctly * - PAN_028 rev2.0A anomaly 29 - TEMP: Stop task clears the TEMP register. * - PAN_028 rev2.0A anomaly 30 - TEMP: Temp module analog front end does not power down when DATARDY event occurs. * - PAN_028 rev2.0A anomaly 31 - TEMP: Temperature offset value has to be manually loaded to the TEMP module * - PAN_028 rev2.0A anomaly 43 - TEMP: Using PPI between DATARDY event and START task is not functional. * */ #include <stdint.h> #include "nrf_delay.h" #include "app_error.h" #include "nrf_drv_ppi.h" #include "nrf_drv_timer.h" #include "nrf_log.h" #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" #include <stdbool.h> //#include <stdint.h> #include "nrf.h" #include "nrf_drv_timer.h" #include "bsp.h" #include "app_error.h" #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include "nrf.h" #include "nrf_delay.h" #include "app_error.h" #include "bsp.h" #include "nrf_drv_ppi.h" #include "nrf_drv_timer.h" #include "nrf_drv_ppi.h" #include "nrf_log.h" #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" const nrf_drv_timer_t capture_timer_1 = NRF_DRV_TIMER_INSTANCE(1); const nrf_drv_timer_t capture_timer = NRF_DRV_TIMER_INSTANCE(3); //#define NRF_LOG_BACKEND_UART_TX_PIN NRF_GPIO_PIN_MAP(1, 7) #define BUTTON_Reset_PIN NRF_GPIO_PIN_MAP(1, 0) // 30 // NRF_GPIO_PIN_MAP(1,12) //////////For 1st Period///// #define SAMPLE_PIN NRF_GPIO_PIN_MAP(1, 6) #define TIMER_PRESCALER NRF_TIMER_FREQ_16MHz #define GPIOTE_CH_CAPTURE 1 #define GPIOTE_CH_RESTART 1 #define GPIOTE_CH_SELFTEST 2 #define SELF_TEST 1 //////////For 2nd Period///// #define SAMPLE_PIN_1 NRF_GPIO_PIN_MAP(1, 5) #define TIMER_PRESCALER_1 NRF_TIMER_FREQ_16MHz #define GPIOTE_CH_CAPTURE_1 1 #define GPIOTE_CH_RESTART_1 1 #define GPIOTE_CH_SELFTEST_1 2 #define SELF_TEST_1 1 //////////////////PWM///////////////////// //#define CMFB_CLK_PIN int16_t buf[] = {(1 << 15) | 5}; // Inverse polarity (bit 15) /////editing pasting from PPI Example #define PPI_EXAMPLE_TIMERS_PHASE_SHIFT_DELAY (1)// (10) // 1s = 10 * 100ms (Timer 0 interrupt) #define PPI_EXAMPLE_TIMER0_INTERVAL (1)//(100) // Timer interval in milliseconds #define PPI_EXAMPLE_TIMER3_INTERVAL (1)//(2000) // Timer interval in milliseconds #define PPI_EXAMPLE_TIMER4_INTERVAL (1)//(2000) // Timer interval in milliseconds #define PPI_EXAMPLE_TIMER1_INTERVAL (1)//(2000) // Timer interval in milliseconds #define PPI_EXAMPLE_TIMER2_INTERVAL (1)//(2000) // Timer interval in milliseconds static nrf_ppi_channel_t n_ppi_channel1; static nrf_ppi_channel_t n_ppi_channel2; static nrf_ppi_channel_t m_ppi_channel1; static nrf_ppi_channel_t m_ppi_channel2; static volatile uint32_t m_counter; static void timer0_event_handler(nrf_timer_event_t event_type, void * p_context) { ++m_counter; } /* Timer event handler. Not used since Timer1 and Timer2 are used only for PPI. */ static void empty_timer_handler(nrf_timer_event_t event_type, void * p_context) { } #if SELF_TEST const nrf_drv_timer_t test_timer = NRF_DRV_TIMER_INSTANCE(4); static void run_self_test_pin(uint32_t pin_no, uint32_t us_on, uint32_t us_off) { uint32_t err_code; static nrf_ppi_channel_t ppi_ch_test_pin_run, ppi_ch_test_pin_run2; nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG; timer_cfg.frequency = NRF_TIMER_FREQ_16MHz; timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32; err_code = nrf_drv_timer_init(&test_timer, &timer_cfg, empty_timer_handler); APP_ERROR_CHECK(err_code); nrf_drv_timer_extended_compare(&test_timer, 0, us_on, 0, false); nrf_drv_timer_extended_compare(&test_timer, 1, us_on + us_off, TIMER_SHORTS_COMPARE1_CLEAR_Msk, false); NRF_GPIOTE->CONFIG[GPIOTE_CH_SELFTEST] = GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos | GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos | pin_no << GPIOTE_CONFIG_PSEL_Pos; nrfx_ppi_channel_alloc(&ppi_ch_test_pin_run); nrfx_ppi_channel_assign(ppi_ch_test_pin_run, nrf_drv_timer_compare_event_address_get(&test_timer, 0), (uint32_t)&NRF_GPIOTE->TASKS_CLR[GPIOTE_CH_SELFTEST]); nrfx_ppi_channel_enable(ppi_ch_test_pin_run); nrfx_ppi_channel_alloc(&ppi_ch_test_pin_run2); nrfx_ppi_channel_assign(ppi_ch_test_pin_run2, nrf_drv_timer_compare_event_address_get(&test_timer, 1), (uint32_t)&NRF_GPIOTE->TASKS_SET[GPIOTE_CH_SELFTEST]); nrfx_ppi_channel_enable(ppi_ch_test_pin_run2); nrf_drv_timer_clear(&test_timer); nrf_drv_timer_resume(&test_timer); } #endif #if SELF_TEST_1 const nrf_drv_timer_t test_timer_1 = NRF_DRV_TIMER_INSTANCE(2); static void run_self_test_1_pin(uint32_t pin_no_1, uint32_t us_on_1, uint32_t us_off_1) { uint32_t err_code; static nrf_ppi_channel_t ppi_ch_test_pin_run_1, ppi_ch_test_pin_run2_1; nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG; timer_cfg.frequency = NRF_TIMER_FREQ_16MHz; timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32; err_code = nrf_drv_timer_init(&test_timer_1, &timer_cfg, empty_timer_handler); APP_ERROR_CHECK(err_code); nrf_drv_timer_extended_compare(&test_timer_1, 0, us_on_1, 0, false); nrf_drv_timer_extended_compare(&test_timer_1, 1, us_on_1 + us_off_1, TIMER_SHORTS_COMPARE1_CLEAR_Msk, false); NRF_GPIOTE->CONFIG[GPIOTE_CH_SELFTEST_1] = GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos | GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos | pin_no_1 << GPIOTE_CONFIG_PSEL_Pos; nrfx_ppi_channel_alloc(&ppi_ch_test_pin_run_1); nrfx_ppi_channel_assign(ppi_ch_test_pin_run_1, nrf_drv_timer_compare_event_address_get(&test_timer_1, 0), (uint32_t)&NRF_GPIOTE->TASKS_CLR[GPIOTE_CH_SELFTEST_1]); nrfx_ppi_channel_enable(ppi_ch_test_pin_run_1); nrfx_ppi_channel_alloc(&ppi_ch_test_pin_run2_1); nrfx_ppi_channel_assign(ppi_ch_test_pin_run2_1, nrf_drv_timer_compare_event_address_get(&test_timer_1, 1), (uint32_t)&NRF_GPIOTE->TASKS_SET[GPIOTE_CH_SELFTEST_1]); nrfx_ppi_channel_enable(ppi_ch_test_pin_run2_1); nrf_drv_timer_clear(&test_timer_1); nrf_drv_timer_resume(&test_timer_1); } #endif static void gpiote_capture_init(void) { uint32_t err_code; static nrf_ppi_channel_t ppi_ch_gpiote_capture; static nrf_ppi_channel_t ppi_ch_gpiote_restart; // Optionally, enable pullup or pulldown on the input pin //nrf_gpio_cfg_input(SAMPLE_PIN, NRF_GPIO_PIN_PULLUP); // Allocate two PPI channels nrfx_ppi_channel_alloc(&ppi_ch_gpiote_capture); nrfx_ppi_channel_alloc(&ppi_ch_gpiote_restart); // Configure the capture timer nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG; timer_cfg.frequency = TIMER_PRESCALER; timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32; err_code = nrf_drv_timer_init(&capture_timer, &timer_cfg, empty_timer_handler); APP_ERROR_CHECK(err_code); // The GPIOTE driver doesn't support two GPIOTE channels on the same pin, so direct register access is necessary NRF_GPIOTE->CONFIG[GPIOTE_CH_CAPTURE] = GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos | GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos | SAMPLE_PIN << GPIOTE_CONFIG_PSEL_Pos; NRF_GPIOTE->CONFIG[GPIOTE_CH_RESTART] = GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos | GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos | SAMPLE_PIN << GPIOTE_CONFIG_PSEL_Pos; // Assign a PPI channel to capture the current timer state and store it in CC register 0 nrfx_ppi_channel_assign(ppi_ch_gpiote_capture, (uint32_t)&NRF_GPIOTE->EVENTS_IN[GPIOTE_CH_CAPTURE], nrf_drv_timer_capture_task_address_get(&capture_timer, 0)); // Assign a second PPI channel to restart the timer when a new pulse is detected nrfx_ppi_channel_assign(ppi_ch_gpiote_restart, (uint32_t)&NRF_GPIOTE->EVENTS_IN[GPIOTE_CH_RESTART], nrf_drv_timer_task_address_get(&capture_timer, NRF_TIMER_TASK_CLEAR)); // Enable both PPI channels nrfx_ppi_channel_enable(ppi_ch_gpiote_capture); nrfx_ppi_channel_enable(ppi_ch_gpiote_restart); // Make sure the GPIOTE capture in event is cleared. This will be used to detect if a capture has occured. NRF_GPIOTE->EVENTS_IN[GPIOTE_CH_CAPTURE] = 0; // Start the timer nrfx_timer_resume(&capture_timer); } static void gpiote_capture_1_init(void) { uint32_t err_code; static nrf_ppi_channel_t ppi_ch_gpiote_capture_1; static nrf_ppi_channel_t ppi_ch_gpiote_restart_1; // Optionally, enable pullup or pulldown on the input pin //nrf_gpio_cfg_input(SAMPLE_PIN, NRF_GPIO_PIN_PULLUP); // Allocate two PPI channels nrfx_ppi_channel_alloc(&ppi_ch_gpiote_capture_1); nrfx_ppi_channel_alloc(&ppi_ch_gpiote_restart_1); // Configure the capture timer nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG; timer_cfg.frequency = TIMER_PRESCALER_1; timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32; err_code = nrf_drv_timer_init(&capture_timer_1, &timer_cfg, empty_timer_handler); APP_ERROR_CHECK(err_code); // The GPIOTE driver doesn't support two GPIOTE channels on the same pin, so direct register access is necessary NRF_GPIOTE->CONFIG[GPIOTE_CH_CAPTURE_1] = GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos | GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos | SAMPLE_PIN_1 << GPIOTE_CONFIG_PSEL_Pos; NRF_GPIOTE->CONFIG[GPIOTE_CH_RESTART_1] = GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos | GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos | SAMPLE_PIN_1 << GPIOTE_CONFIG_PSEL_Pos; // Assign a PPI channel to capture the current timer state and store it in CC register 0 nrfx_ppi_channel_assign(ppi_ch_gpiote_capture_1, (uint32_t)&NRF_GPIOTE->EVENTS_IN[GPIOTE_CH_CAPTURE_1], nrf_drv_timer_capture_task_address_get(&capture_timer_1, 0)); // Assign a second PPI channel to restart the timer when a new pulse is detected nrfx_ppi_channel_assign(ppi_ch_gpiote_restart_1, (uint32_t)&NRF_GPIOTE->EVENTS_IN[GPIOTE_CH_RESTART_1], nrf_drv_timer_task_address_get(&capture_timer_1, NRF_TIMER_TASK_CLEAR)); // Enable both PPI channels nrfx_ppi_channel_enable(ppi_ch_gpiote_capture_1); nrfx_ppi_channel_enable(ppi_ch_gpiote_restart_1); // Make sure the GPIOTE capture in event is cleared. This will be used to detect if a capture has occured. NRF_GPIOTE->EVENTS_IN[GPIOTE_CH_CAPTURE_1] = 0; // Start the timer nrfx_timer_resume(&capture_timer_1); } static uint32_t timer_capture_value_get(void) { // Make sure the capture event occured before checking the capture register if(NRF_GPIOTE->EVENTS_IN[GPIOTE_CH_CAPTURE] != 0) { // Clear the capture event NRF_GPIOTE->EVENTS_IN[GPIOTE_CH_CAPTURE] = 0; // Return the stored capture value in the timer return nrf_drv_timer_capture_get(&capture_timer, 0); } else { // In case no capture occured, return 0 return 0; } } static uint32_t timer_capture_1_value_get(void) { // Make sure the capture event occured before checking the capture register if(NRF_GPIOTE->EVENTS_IN[GPIOTE_CH_CAPTURE_1] != 0) { // Clear the capture event NRF_GPIOTE->EVENTS_IN[GPIOTE_CH_CAPTURE_1] = 0; // Return the stored capture value in the timer return nrf_drv_timer_capture_get(&capture_timer_1, 0); } else { // In case no capture occured, return 0 return 0; } } /** @brief Function for main application entry. */ int main(void) { nrf_gpio_cfg_input(BUTTON_Reset_PIN, NRF_GPIO_PIN_PULLUP); nrf_gpio_cfg_output(ENB_MOD_2_PIN); nrf_gpio_cfg_output(FREQ_CNT_PIN); nrf_gpio_cfg_output(CMFB_CLK_PIN); nrf_gpio_cfg_output(PHI_RST_PIN); nrf_gpio_cfg_output(RST_CMFB_PIN); nrf_gpio_cfg_output(ENB_PWDN1); nrf_gpio_cfg_output(ENB_PWDN2); nrf_gpio_cfg_output(ENB_PWDN3); APP_ERROR_CHECK(NRF_LOG_INIT(NULL)); NRF_LOG_DEFAULT_BACKENDS_INIT(); NRF_LOG_INFO("Pulse capture example started"); //gpiote_capture_init(); gpiote_capture_1_init(); //gpiote_capture_1_init(); // gpiote_capture_1_init(); #if SELF_TEST run_self_test_pin(LED_1, 678, 10); #endif #if SELF_TEST_1 run_self_test_1_pin(LED_2, 678, 10); #endif while (true) { uint32_t captured_pulse_length_1 = timer_capture_1_value_get(); uint32_t captured_pulse_length = timer_capture_value_get(); if(captured_pulse_length > 0) { NRF_LOG_INFO("Period 1: %i us", (captured_pulse_length * (1 << TIMER_PRESCALER) / 16)); } if(captured_pulse_length_1 > 0) { NRF_LOG_INFO("\tPeriod 2: %i us", (captured_pulse_length_1 * (1 << TIMER_PRESCALER_1) / 16)); } // else NRF_LOG_INFO("No capture detected"); // nrf_delay_ms(500); */ NRF_LOG_FLUSH();