PWM individual decoder not working

Hi all, 

I need to generate two 1 MHz signals with opposite phases. However once I configure the decode mode as "Individual" I don't have output signals. In case of "Common" mode, I have two same output signals but this is not what I want. Under debugger I have different register values especially for EVENTS_SEQxxx.

1. Individual mode

2. Common mode

Here is the code:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* PWM for 1 MHz square signal generation */
#define PWM_OUTPUT_PIN_0 11//22//4 // First 1 MHz signal
#define PWM_OUTPUT_PIN_1 12//23//5 // Second 1 MHz signal (inverted)
// Define PWM sequence for complementary 1 MHz signals
// static uint16_t pwm_seq[2] = {8, 8}; // 50% duty cycle for both channels
static uint16_t pwm_seq[4] = {
8, // CH0: Normal (rising edge)
8 | (1 << 15), // CH1: Inverted (falling edge)
};
void io_pwm_init(void) {
nrf_clock_hfclk_t HF_CLk;
/* Check if the high frequency crystal isn't enabled */
HF_CLk = nrf_clock_hf_src_get();
if (HF_CLk != NRF_CLOCK_HFCLK_HIGH_ACCURACY)
{
/* Enable the high frequency clock */
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Thanks for your help.

BR,

Hulu

  • Hello Hulu,

    What SDK are you using? The polarity of the output can be configured for each channel. Have you tried this to achieve what you want?

    BR,

    Hieu

  • For your intended design, don't use Individual, use Grouped which gives the differential waveform you seek.

    Change this:

    Fullscreen
    1
    2
    3
    4
    5
    // Select GPIOs for PWM output
    NRF_PWM0->PSEL.OUT[0] = PWM_OUTPUT_PIN_0 | (PWM_PSEL_OUT_CONNECT_Connected << PWM_PSEL_OUT_CONNECT_Pos);
    NRF_PWM0->PSEL.OUT[1] = PWM_OUTPUT_PIN_1 | (PWM_PSEL_OUT_CONNECT_Connected << PWM_PSEL_OUT_CONNECT_Pos);
    NRF_PWM0->DECODER = PWM_DECODER_LOAD_Individual << PWM_DECODER_LOAD_Pos;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    to this:

    Fullscreen
    1
    2
    3
    4
    5
    // Select GPIOs for PWM output - note channels 0 and 2, not 0 and 1
    NRF_PWM0->PSEL.OUT[0] = PWM_OUTPUT_PIN_0 | (PWM_PSEL_OUT_CONNECT_Connected << PWM_PSEL_OUT_CONNECT_Pos);
    NRF_PWM0->PSEL.OUT[2] = PWM_OUTPUT_PIN_1 | (PWM_PSEL_OUT_CONNECT_Connected << PWM_PSEL_OUT_CONNECT_Pos);
    NRF_PWM0->DECODER = PWM_DECODER_LOAD_Grouped << PWM_DECODER_LOAD_Pos;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Thanks Hieu, we're using SDK 17.0.2. Yes actually I tried to configure the polarity of the second channel by writing the MSB to 1 (bit 15).

    Hulu

  • Thank you for the suggestion. I can try it.

    Finally I succeeded by still using the individual mode, but I needed to configure the whole 4 channels in the sequence table, instead of only configuring two. For the two other non-used channels, I put 0. For the counter, it is finally 4 instead of 2 (NRF_PWM0->SEQ[0].CNT = ((sizeof(pwm_seq) / sizeof(uint16_t)) << PWM_SEQ_CNT_CNT_Pos);).


    )
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // Define PWM sequence for complementary 1 MHz signals
    static uint16_t pwm_seq[4] = {
    8, // CH0: Normal (rising edge)
    8 | (1 << 15), // CH1: Inverted (falling edge)
    0,
    0
    };
    void io_pwm_init(void) {
    nrf_clock_hfclk_t HF_CLk;
    /* Check if the high frequency crystal isn't enabled */
    HF_CLk = nrf_clock_hf_src_get();
    if (HF_CLk != NRF_CLOCK_HFCLK_HIGH_ACCURACY)
    {
    /* Enable the high frequency clock */
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_HFCLKSTART = 1;
    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    BR,
    hulu