Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to change a pin between GPIO and PWM

Hi There

My design is basic on nrf52840. I need a pin be controlled alternately by GPIO module and PWM module in my application. The PWM function is realized by setting the PWM hardware module, as in the SDK example (nRF5_SDK_16.0.0_98a08e2\examples\peripheral\pwm_driver).

My question is:

Q1. May I  return the pin to GPIO control by just setting the PSEL.OUT[n]. C to 1?  Or do I have to clear the pin number from A so that the pin will go to GPIO control?

Q2.Is there anything you need to pay attention to when implementing pin control conversion between GPIO and PWM?

Q3. Is there a better way to do it

Thanks,

Di-sheng

Parents
  • Hi SmallerPond,

    Thanks for your reply.

    I want those pins which output PWM signal can be controlled by GPIO for few second and then  go back to PWM agian.

    Right now PWM and GPIO works, I hope when GPIO control the pin which come back from PWM and PWM still keep going .

    Thanks,

    B.Rs,

    Di-sheng

    I think you can just uninit the pwm with nrfx_pwm_uninit and then configure it as gpio, then just init the pwm again when you need it.  No need to worry about turning off the gpio since i think the pwm driver does this automatically.
  • Actually, I thought I'd give it a try and you only have to stop the pwm and the gpio will work:

    #include <stdint.h>
    #include "nrf_gpio.h"
    #include "nrfx_pwm.h"
    #include "nrf_delay.h"
    
    #define PWM_GPIO_PIN                     NRF_GPIO_PIN_MAP(1, 12)
    
    /* Create the PWM instance */
    static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(0);
    
    /* PWM values */
    static nrf_pwm_values_common_t seq_values[] =
    {
        4, 4, 4, 4, 16, 16, 16, 16, 6, 6, 6, 6, 12, 12, 12, 12,
        3, 3, 3, 3, 15, 15, 15, 15, 1, 1, 1, 1, 13, 13, 13, 13,
    };
    
    static nrf_pwm_sequence_t const seq =
    {
        .values.p_common = seq_values,
        .length          = NRF_PWM_VALUES_LENGTH(seq_values),
        .repeats         = 10,
        .end_delay       = 0
    };
    
    /**
     * @brief Function for application main entry.
     */
    int main(void)
    {
        nrfx_err_t error;
        /* Config PWM */
        nrfx_pwm_config_t config =
        {
            .base_clock   = NRF_PWM_CLK_1MHz,
            .irq_priority = APP_IRQ_PRIORITY_LOWEST,
            .count_mode   = NRF_PWM_MODE_UP,
            .top_value    = 20,
            .load_mode    = NRF_PWM_LOAD_COMMON,
            .step_mode    = NRF_PWM_STEP_AUTO,
            .output_pins  =
            {
                PWM_GPIO_PIN,
                NRFX_PWM_PIN_NOT_USED,
                NRFX_PWM_PIN_NOT_USED,
                NRFX_PWM_PIN_NOT_USED,
            }
        };
        error = nrfx_pwm_init(&m_pwm0, &config, NULL);
        APP_ERROR_CHECK(error);
    
        /* Config GPIO */
        nrf_gpio_pin_clear(PWM_GPIO_PIN);
        nrf_gpio_cfg_output(PWM_GPIO_PIN);
    
        /* Kick off PWM */
        APP_ERROR_CHECK(nrfx_pwm_simple_playback(&m_pwm0, &seq, 1, NRFX_PWM_FLAG_LOOP));
    
        /* Loop */
        for (;;)
        {
            /* Obviously this would happen using interrupts or timers or such */
            nrf_delay_ms(1000);
            nrfx_pwm_stop(&m_pwm0, true);
            nrf_gpio_pin_toggle(PWM_GPIO_PIN);
            nrf_delay_ms(1000);
            APP_ERROR_CHECK(nrfx_pwm_simple_playback(&m_pwm0, &seq, 1, NRFX_PWM_FLAG_LOOP));
        }
    }

Reply
  • Actually, I thought I'd give it a try and you only have to stop the pwm and the gpio will work:

    #include <stdint.h>
    #include "nrf_gpio.h"
    #include "nrfx_pwm.h"
    #include "nrf_delay.h"
    
    #define PWM_GPIO_PIN                     NRF_GPIO_PIN_MAP(1, 12)
    
    /* Create the PWM instance */
    static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(0);
    
    /* PWM values */
    static nrf_pwm_values_common_t seq_values[] =
    {
        4, 4, 4, 4, 16, 16, 16, 16, 6, 6, 6, 6, 12, 12, 12, 12,
        3, 3, 3, 3, 15, 15, 15, 15, 1, 1, 1, 1, 13, 13, 13, 13,
    };
    
    static nrf_pwm_sequence_t const seq =
    {
        .values.p_common = seq_values,
        .length          = NRF_PWM_VALUES_LENGTH(seq_values),
        .repeats         = 10,
        .end_delay       = 0
    };
    
    /**
     * @brief Function for application main entry.
     */
    int main(void)
    {
        nrfx_err_t error;
        /* Config PWM */
        nrfx_pwm_config_t config =
        {
            .base_clock   = NRF_PWM_CLK_1MHz,
            .irq_priority = APP_IRQ_PRIORITY_LOWEST,
            .count_mode   = NRF_PWM_MODE_UP,
            .top_value    = 20,
            .load_mode    = NRF_PWM_LOAD_COMMON,
            .step_mode    = NRF_PWM_STEP_AUTO,
            .output_pins  =
            {
                PWM_GPIO_PIN,
                NRFX_PWM_PIN_NOT_USED,
                NRFX_PWM_PIN_NOT_USED,
                NRFX_PWM_PIN_NOT_USED,
            }
        };
        error = nrfx_pwm_init(&m_pwm0, &config, NULL);
        APP_ERROR_CHECK(error);
    
        /* Config GPIO */
        nrf_gpio_pin_clear(PWM_GPIO_PIN);
        nrf_gpio_cfg_output(PWM_GPIO_PIN);
    
        /* Kick off PWM */
        APP_ERROR_CHECK(nrfx_pwm_simple_playback(&m_pwm0, &seq, 1, NRFX_PWM_FLAG_LOOP));
    
        /* Loop */
        for (;;)
        {
            /* Obviously this would happen using interrupts or timers or such */
            nrf_delay_ms(1000);
            nrfx_pwm_stop(&m_pwm0, true);
            nrf_gpio_pin_toggle(PWM_GPIO_PIN);
            nrf_delay_ms(1000);
            APP_ERROR_CHECK(nrfx_pwm_simple_playback(&m_pwm0, &seq, 1, NRFX_PWM_FLAG_LOOP));
        }
    }

Children
  • Hi SmallerPond,

    Thanks  for your replay.

    The code is  great.

    Unfortunately, I can not use this. Because I used all channels of the PWM module and these channels cannot be stopped at the same time, that means some pins assigned to the PWM module need to be converted to be controlled by GPIO, while others still need to continue to output the PWM signal .

    Thank you very much again.

    B,Rs

    Di-sheng

Related