This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

PPI CHANNEL USED TO generate pulse wave

Hi All,

I am using NRF51822 chip pca10001 development board.

I flashed ble_app_hrs application to the board.

I configure 3 channel for PPI.

static void ppi_init(void)
{
  
  uint32_t err_code;

	 err_code = sd_ppi_channel_assign(0,
                                     &(NRF_TIMER2->EVENTS_COMPARE[0]),
                                     &(NRF_GPIOTE->TASKS_OUT[0]));
    APP_ERROR_CHECK(err_code);
	
		
		err_code = sd_ppi_channel_assign(1,
                                     &(NRF_TIMER2->EVENTS_COMPARE[1]),
                                     &(NRF_GPIOTE->TASKS_OUT[0]));
    APP_ERROR_CHECK(err_code);
	
		err_code = sd_ppi_channel_assign(2,
                                     &(NRF_TIMER2->EVENTS_COMPARE[1]),
                                     &(NRF_TIMER2->TASKS_CLEAR));
    APP_ERROR_CHECK(err_code);
}

I configure gpiote task for channel 0.

void gpiote_channel_0_set(void)
{
	 nrf_gpiote_task_config(0, AC_OUT_PIN, NRF_GPIOTE_POLARITY_TOGGLE, \
                           NRF_GPIOTE_INITIAL_VALUE_HIGH);
}

Now i enable all 3 channels.

__inline void ppi_enable(void)
{
		uint32_t err_code;
		err_code = sd_ppi_channel_enable_set( (PPI_CHEN_CH0_Msk) |  (PPI_CHEN_CH1_Msk)| (PPI_CHEN_CH2_Msk));
    APP_ERROR_CHECK(err_code)
}

The timer2 is intialised as fallows.

static void timer2_init(void)
{
		
   /* Start 16 MHz crystal oscillator */
    NRF_CLOCK->EVENTS_HFCLKSTARTED    = 0;
    NRF_CLOCK->TASKS_HFCLKSTART       = 1;
    /* Wait for the external oscillator to start up */
    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)       
    {
        // Do nothing.
    }
		NRF_TIMER2->TASKS_CLEAR = 1;
    NRF_TIMER2->MODE        = TIMER_MODE_MODE_Timer;
		NRF_TIMER2->PRESCALER   = 4;

    /* Load initial values to Timer 2 CC registers */
    /* Set initial CC0 value to anything > 1 */
		NRF_TIMER2->BITMODE   = TIMER_BITMODE_BITMODE_16Bit;
	
}

Now i am updating timer2 cc0 value and cc1 value from BLE characteristic interrupt and then i start the timer.

But for constant cc0 and cc1 value its giving two waveform.

ex- cc0=1000(1ms), cc1=10000(9ms);

i am getting two wave

  1. 1ms on and 9ms off.

  2. 1ms off and 9ms on.

I need to get only first wave all the time if i write constant value to ble characteristic

Could any one tell me how to solve this?. ( I need to do this with PPI only).

I tried by reinitialising all ppi and gpiote for every ble characteristic interrupt then also it dont work.

Kindly tell me what is the issue.

Regards Punit

Parents
  • Hi ALL,

    Here i have tried without ble but there also getting inverted ouput .

    I also tried for every power reset of the board , i am getting two output.

    Here is my code :

        #include <stdbool.h>
    #include <stdint.h>
    #include "nrf_delay.h"
    #include "nrf_gpio.h"
    #include "boards.h"
    #include "nrf_gpiote.h"
    
    #define AC_OUT_PIN 5
    /**
     * @brief Function for application main entry.
     */
     void gpiote0_timer_dis(void)
    {
    	NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_MODE_Disabled << GPIOTE_CONFIG_MODE_Pos);
    	NRF_GPIOTE->CONFIG[2] = (GPIOTE_CONFIG_MODE_Disabled << GPIOTE_CONFIG_MODE_Pos);
    	NRF_TIMER2->TASKS_STOP = 1;
    	NVIC_DisableIRQ(GPIOTE_IRQn);
    }
    void gpiote_channel_0_set(void)
    {
    	 nrf_gpiote_task_config(0, AC_OUT_PIN, NRF_GPIOTE_POLARITY_TOGGLE, \
                               NRF_GPIOTE_INITIAL_VALUE_HIGH);
    }
    
    static void timer2_init(void)
    {
    		
    //   /* Start 16 MHz crystal oscillator */
    //    NRF_CLOCK->EVENTS_HFCLKSTARTED    = 0;
    //    NRF_CLOCK->TASKS_HFCLKSTART       = 1;
    //    /* Wait for the external oscillator to start up */
    //    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)       
    //    {
    //        // Do nothing.
    //    }
    		NRF_TIMER2->TASKS_CLEAR = 1;
        NRF_TIMER2->MODE        = TIMER_MODE_MODE_Timer;
    		NRF_TIMER2->PRESCALER   = 4;
    
        /* Load initial values to Timer 2 CC registers */
        /* Set initial CC0 value to anything > 1 */
      
    		NRF_TIMER2->CC[0]       = 8000;//(32);
    		//NRF_TIMER2->CC[1] = 10000;//10ms
    		NRF_TIMER2->BITMODE   = TIMER_BITMODE_BITMODE_16Bit;
    		
       // NRF_TIMER2->SHORTS = (TIMER_SHORTS_COMPARE1_CLEAR_Enabled << TIMER_SHORTS_COMPARE1_CLEAR_Pos);
    }
    static void ppi_init(void)
    {
        // Configure PPI channel 0 to toggle GPIO_OUTPUT_PIN on every TIMER0 COMPARE[0] match (200 ms)
        NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TIMER2->EVENTS_COMPARE[0];
        NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
    	
    //		NRF_PPI->CH[1].EEP = (uint32_t)&NRF_TIMER2->EVENTS_COMPARE[1];
    //    NRF_PPI->CH[1].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
    
    //		NRF_PPI->CH[2].EEP =  (uint32_t)&NRF_TIMER2->EVENTS_COMPARE[1];
    //		NRF_PPI->CH[2].TEP =  (uint32_t)&NRF_TIMER2->TASKS_CLEAR;
    //    
    		NRF_PPI->CH[1].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[2];
        NRF_PPI->CH[1].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
    
    		NRF_PPI->CH[2].EEP =  (uint32_t)&NRF_GPIOTE->EVENTS_IN[2];
    		NRF_PPI->CH[2].TEP =  (uint32_t)&NRF_TIMER2->TASKS_CLEAR;
        
                                         
        // Enable PPI channel 0
        NRF_PPI->CHEN = ((PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos) | (PPI_CHEN_CH1_Enabled << PPI_CHEN_CH1_Pos)|(PPI_CHEN_CH2_Enabled << PPI_CHEN_CH2_Pos));
    }
    
    __inline void ppi_enable(void)
    {
    	NRF_PPI->CHEN = ((PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos) | (PPI_CHEN_CH1_Enabled << PPI_CHEN_CH1_Pos)|(PPI_CHEN_CH2_Enabled << PPI_CHEN_CH2_Pos));
    	
    }
    __inline static void ppi_disable(void)
    {
    	NRF_PPI->CHEN = ((PPI_CHEN_CH0_Disabled << PPI_CHEN_CH0_Pos) | (PPI_CHEN_CH1_Disabled << PPI_CHEN_CH1_Pos)|(PPI_CHEN_CH2_Enabled << PPI_CHEN_CH2_Pos));
    	
    }
    static void gpiote_init(void)
    {
        // Enable interrupt on input 1 event.
        NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN3_Msk |GPIOTE_INTENSET_IN2_Msk;
    		nrf_gpiote_event_config(3, 16, NRF_GPIOTE_POLARITY_HITOLO);
    		nrf_gpiote_event_config(2, 20, NRF_GPIOTE_POLARITY_LOTOHI);
     
        // Configure GPIOTE channel 0 to generate event on input pin low-to-high transition.
        //nrf_gpiote_event_config(4, 16, NRF_GPIOTE_POLARITY_TOGGLE);
    	  NVIC_EnableIRQ(GPIOTE_IRQn);
    }
    
    
    void GPIOTE_IRQHandler(void)
    {
    	if(NRF_GPIOTE->EVENTS_IN[3]==1)
    	{
    		nrf_gpio_pin_toggle(18);
    		NRF_GPIOTE->EVENTS_IN[3]=0;
    		gpiote0_timer_dis();	
    		gpiote_channel_0_set();
    		gpiote_init();
    		timer2_init();
    		ppi_init();
    		nrf_gpio_pin_clear(AC_OUT_PIN);
    		NRF_TIMER2->TASKS_START=1;
    
    	}
    	if(NRF_GPIOTE->EVENTS_IN[2]==1)
    	{
    		nrf_gpio_pin_toggle(19);
    		NRF_GPIOTE->EVENTS_IN[2]=0;
    	}	
    }
    
    
    int main(void)
    {
    	nrf_gpio_pin_set(AC_OUT_PIN);
    		int i=0;
        // Configure LED-pins as outputs
    		nrf_gpio_cfg_input(16,GPIO_PIN_CNF_PULL_Pullup );
    		nrf_gpio_cfg_input(17,GPIO_PIN_CNF_PULL_Disabled);
    		nrf_gpio_cfg_input(20,GPIO_PIN_CNF_PULL_Disabled);
        nrf_gpio_cfg_output(LED_0);
        nrf_gpio_cfg_output(LED_1);
    		nrf_gpio_cfg_output(AC_OUT_PIN);
        nrf_gpio_pin_set(AC_OUT_PIN);
    		gpiote_init();	
        // LED 0 and LED 1 blink alternately.
    		
    	  gpiote_channel_0_set();
    		timer2_init();
    		ppi_init();
    		nrf_gpio_pin_set(AC_OUT_PIN);
    		NRF_TIMER2->TASKS_START=1;
    		
    		while (true)
        {
    	
            
        }
    }
    

    Here my gpio interrupt(pin 20) is coming for every 10ms.

    Since CC0=8000 , i should get always PWM (8ms on and 2ms off). But for every power reset i am getting two PWM. 1.sometime PWM of 2ms on and 8ms off. 2.sometime PWM of 8ms on and 2ms off.

    If any one know what will be the issue , kindly let me know the problem.

    I need to use PPI only instead of interrupt handler.

    Regards Punith

Reply
  • Hi ALL,

    Here i have tried without ble but there also getting inverted ouput .

    I also tried for every power reset of the board , i am getting two output.

    Here is my code :

        #include <stdbool.h>
    #include <stdint.h>
    #include "nrf_delay.h"
    #include "nrf_gpio.h"
    #include "boards.h"
    #include "nrf_gpiote.h"
    
    #define AC_OUT_PIN 5
    /**
     * @brief Function for application main entry.
     */
     void gpiote0_timer_dis(void)
    {
    	NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_MODE_Disabled << GPIOTE_CONFIG_MODE_Pos);
    	NRF_GPIOTE->CONFIG[2] = (GPIOTE_CONFIG_MODE_Disabled << GPIOTE_CONFIG_MODE_Pos);
    	NRF_TIMER2->TASKS_STOP = 1;
    	NVIC_DisableIRQ(GPIOTE_IRQn);
    }
    void gpiote_channel_0_set(void)
    {
    	 nrf_gpiote_task_config(0, AC_OUT_PIN, NRF_GPIOTE_POLARITY_TOGGLE, \
                               NRF_GPIOTE_INITIAL_VALUE_HIGH);
    }
    
    static void timer2_init(void)
    {
    		
    //   /* Start 16 MHz crystal oscillator */
    //    NRF_CLOCK->EVENTS_HFCLKSTARTED    = 0;
    //    NRF_CLOCK->TASKS_HFCLKSTART       = 1;
    //    /* Wait for the external oscillator to start up */
    //    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)       
    //    {
    //        // Do nothing.
    //    }
    		NRF_TIMER2->TASKS_CLEAR = 1;
        NRF_TIMER2->MODE        = TIMER_MODE_MODE_Timer;
    		NRF_TIMER2->PRESCALER   = 4;
    
        /* Load initial values to Timer 2 CC registers */
        /* Set initial CC0 value to anything > 1 */
      
    		NRF_TIMER2->CC[0]       = 8000;//(32);
    		//NRF_TIMER2->CC[1] = 10000;//10ms
    		NRF_TIMER2->BITMODE   = TIMER_BITMODE_BITMODE_16Bit;
    		
       // NRF_TIMER2->SHORTS = (TIMER_SHORTS_COMPARE1_CLEAR_Enabled << TIMER_SHORTS_COMPARE1_CLEAR_Pos);
    }
    static void ppi_init(void)
    {
        // Configure PPI channel 0 to toggle GPIO_OUTPUT_PIN on every TIMER0 COMPARE[0] match (200 ms)
        NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TIMER2->EVENTS_COMPARE[0];
        NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
    	
    //		NRF_PPI->CH[1].EEP = (uint32_t)&NRF_TIMER2->EVENTS_COMPARE[1];
    //    NRF_PPI->CH[1].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
    
    //		NRF_PPI->CH[2].EEP =  (uint32_t)&NRF_TIMER2->EVENTS_COMPARE[1];
    //		NRF_PPI->CH[2].TEP =  (uint32_t)&NRF_TIMER2->TASKS_CLEAR;
    //    
    		NRF_PPI->CH[1].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[2];
        NRF_PPI->CH[1].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
    
    		NRF_PPI->CH[2].EEP =  (uint32_t)&NRF_GPIOTE->EVENTS_IN[2];
    		NRF_PPI->CH[2].TEP =  (uint32_t)&NRF_TIMER2->TASKS_CLEAR;
        
                                         
        // Enable PPI channel 0
        NRF_PPI->CHEN = ((PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos) | (PPI_CHEN_CH1_Enabled << PPI_CHEN_CH1_Pos)|(PPI_CHEN_CH2_Enabled << PPI_CHEN_CH2_Pos));
    }
    
    __inline void ppi_enable(void)
    {
    	NRF_PPI->CHEN = ((PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos) | (PPI_CHEN_CH1_Enabled << PPI_CHEN_CH1_Pos)|(PPI_CHEN_CH2_Enabled << PPI_CHEN_CH2_Pos));
    	
    }
    __inline static void ppi_disable(void)
    {
    	NRF_PPI->CHEN = ((PPI_CHEN_CH0_Disabled << PPI_CHEN_CH0_Pos) | (PPI_CHEN_CH1_Disabled << PPI_CHEN_CH1_Pos)|(PPI_CHEN_CH2_Enabled << PPI_CHEN_CH2_Pos));
    	
    }
    static void gpiote_init(void)
    {
        // Enable interrupt on input 1 event.
        NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN3_Msk |GPIOTE_INTENSET_IN2_Msk;
    		nrf_gpiote_event_config(3, 16, NRF_GPIOTE_POLARITY_HITOLO);
    		nrf_gpiote_event_config(2, 20, NRF_GPIOTE_POLARITY_LOTOHI);
     
        // Configure GPIOTE channel 0 to generate event on input pin low-to-high transition.
        //nrf_gpiote_event_config(4, 16, NRF_GPIOTE_POLARITY_TOGGLE);
    	  NVIC_EnableIRQ(GPIOTE_IRQn);
    }
    
    
    void GPIOTE_IRQHandler(void)
    {
    	if(NRF_GPIOTE->EVENTS_IN[3]==1)
    	{
    		nrf_gpio_pin_toggle(18);
    		NRF_GPIOTE->EVENTS_IN[3]=0;
    		gpiote0_timer_dis();	
    		gpiote_channel_0_set();
    		gpiote_init();
    		timer2_init();
    		ppi_init();
    		nrf_gpio_pin_clear(AC_OUT_PIN);
    		NRF_TIMER2->TASKS_START=1;
    
    	}
    	if(NRF_GPIOTE->EVENTS_IN[2]==1)
    	{
    		nrf_gpio_pin_toggle(19);
    		NRF_GPIOTE->EVENTS_IN[2]=0;
    	}	
    }
    
    
    int main(void)
    {
    	nrf_gpio_pin_set(AC_OUT_PIN);
    		int i=0;
        // Configure LED-pins as outputs
    		nrf_gpio_cfg_input(16,GPIO_PIN_CNF_PULL_Pullup );
    		nrf_gpio_cfg_input(17,GPIO_PIN_CNF_PULL_Disabled);
    		nrf_gpio_cfg_input(20,GPIO_PIN_CNF_PULL_Disabled);
        nrf_gpio_cfg_output(LED_0);
        nrf_gpio_cfg_output(LED_1);
    		nrf_gpio_cfg_output(AC_OUT_PIN);
        nrf_gpio_pin_set(AC_OUT_PIN);
    		gpiote_init();	
        // LED 0 and LED 1 blink alternately.
    		
    	  gpiote_channel_0_set();
    		timer2_init();
    		ppi_init();
    		nrf_gpio_pin_set(AC_OUT_PIN);
    		NRF_TIMER2->TASKS_START=1;
    		
    		while (true)
        {
    	
            
        }
    }
    

    Here my gpio interrupt(pin 20) is coming for every 10ms.

    Since CC0=8000 , i should get always PWM (8ms on and 2ms off). But for every power reset i am getting two PWM. 1.sometime PWM of 2ms on and 8ms off. 2.sometime PWM of 8ms on and 2ms off.

    If any one know what will be the issue , kindly let me know the problem.

    I need to use PPI only instead of interrupt handler.

    Regards Punith

Children
No Data
Related