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

  • means by calling timer start and ppi_enable for first gpio 10ms interrupt. Now i am not getting toggle output. But with BLE i am facing fallowing issue.

    1. I cant able to use ppi_enable call in gpio interrupt handler.

    2. Always i need to call in BLE interrupt as fallows.

      ppi_enable(); NVIC_EnableIRQ(GPIOTE_IRQn); __enable_irq();

      __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) | (PPI_CHEN_CH3_Msk)| (PPI_CHEN_CH4_Msk));
      
       APP_ERROR_CHECK(err_code);
      

      }

    Kindly let me know why i am not able to call ppi_enable in GPIOTE_IRQHandler. if i call i am not getting any PWM.

  • can you try not using sd_ppi function and enable ppi directly using PPI registers. If it works then something is wrong in softdevice. I am sorry for my late response, i am on vacation and wont be back to work until Monday.

  • Yes i tried by using PPI register directly but that is also not working, for that what i did as fallows.

    1. For each ble interuppt i just first_event flag and i set one more flag in gpiote_interrupt handler.
    2. i enabled the ppi in main while loop by checking gpio interrupt flag.

    Here is my code in BLE.

       for (;;)
        {
    				if(pwm_flag == true)
    				{
    					peripheral_init();
    					pwm_flag = false;
    				}
    				if(nrf_gpio_pin_read(M_BUTTON_PIN) == 0)
    				{
    					button_config();
    					//nrf_delay_ms(50);
    				}
            app_sched_execute();
            power_manage();
        }
    }
    
    static void peripheral_init()
    {
            nrf_gpio_pin_toggle(19);
    				gpiote0_timer_dis();
            gpiote_channel_0_set();
            nrf_gpio_pin_clear(AC_OUT_PIN);
    				NRF_TIMER2->TASKS_CLEAR=1;
    				//pwm_set(2);
    				pwm_set(load.slide_value);
    				NRF_TIMER2->TASKS_START=1;
    			  ppi_enable(); 
    }
    

    in BLE interrupt i added fallowing lines.

    gpiote_channel_0_set();

    										ppi_disable();
    										NRF_TIMER2->TASKS_STOP = 1;
    										//ppi_enable();
    										load.on_off = 1;
    										load.slide_value = p_evt_write->data[1];
    										OneTime_gpiote_IRQ_f = true;
    										NVIC_EnableIRQ(GPIOTE_IRQn);
    									__enable_irq();
    

    In gpiote_interrupt handler has fallowing code:

    void GPIOTE_IRQHandler(void)
    {
    		uint32_t             err_code;
        // Event causing the interrupt must be cleared.
         if (NRF_GPIOTE->EVENTS_IN[2] == 1)
        {
    			
    			if(OneTime_gpiote_IRQ_f == true)
    			{
    				nrf_gpio_pin_toggle(18);
    				pwm_flag=true; 
    				OneTime_gpiote_IRQ_f = false;
      			}
    			
    			NRF_GPIOTE->EVENTS_IN[2] = 0;	
        }
    }
    

    I did same logic which is did without BLE, only change is i called pheripheral_init from main in BLE but that i called from GPIOTE_IRQhandler in without BLE.

    WIthout BLE if i keep on press the button i am getting constant PWM , there is no invert output.

    But with BLE getting inverted ouput some times, and Once you came from vacation , could you tell me what may the issue.

  • please give me your main.c file Punith, I want to replicate your problem here.

  • Hi Aryan.

    You meant to say with BLE main.c right?.

Related