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

nRF51: Timer Capture Task

Hello,

I want to measure a frequency of a PWM signal like this:

GPIOTE-Event --> PPI --> Timer1-Capture-Task

So every time the event occurs, the counter value is copied into the respective CC-Register (in my case channel 0).

Question: Where is the ideal place to copy the content of the CC-Register into, lets say a data array? Normally, I would assume, that the Timer gererates an interrupt as soon as it has finished the capture. So my first idea is to use the timer ISR to copy the value. BUT: What is the advantage of that technique compared to a normal GPIO-Interrupt-ISR and reading/capturing the timer value manually in that ISR? (without using GPIOTE and PPI)?

Second question: How can I achive a timer clear as soon as the capture is done?

This is my code so far:

  uint32_t err_code;
  
  err_code = nrf_drv_ppi_init();
  APP_ERROR_CHECK(err_code);
  
  err_code = nrf_drv_gpiote_init();
  APP_ERROR_CHECK(err_code);
  
  nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
  err_code = nrf_drv_timer_init(&timer, &timer_cfg, timer_dummy_handler);
  APP_ERROR_CHECK(err_code);
  
  
  #ifdef NRF51
    //Workaround for PAN-73.
    *(uint32_t *)0x40008C0C = 1;
  #endif
  
  
  uint32_t gpiote_evt_addr;
  uint32_t capture_task_addr;
  nrf_ppi_channel_t ppi_channel;
  nrf_drv_gpiote_in_config_t config;
  
  config.sense = NRF_GPIOTE_POLARITY_LOTOHI;
  config.pull = NRF_GPIO_PIN_NOPULL;
  config.is_watcher = false;
  config.hi_accuracy = true;
  
  nrf_drv_gpiote_in_init(SIG_PIN,&config, gpiote_evt_handler);
  APP_ERROR_CHECK(err_code);
  
  err_code = nrf_drv_ppi_channel_alloc(&ppi_channel);
  APP_ERROR_CHECK(err_code);
  
  capture_task_addr = nrf_drv_timer_task_address_get(&timer, NRF_TIMER_TASK_CAPTURE0);
  gpiote_evt_addr = nrf_drv_gpiote_in_event_addr_get(SIG_PIN);
  
  err_code = nrf_drv_ppi_channel_assign(ppi_channel, gpiote_evt_addr, capture_task_addr);
  APP_ERROR_CHECK(err_code);
  
  err_code = nrf_drv_ppi_channel_enable(ppi_channel);
  APP_ERROR_CHECK(err_code);
  
  nrf_drv_gpiote_in_event_enable(SIG_PIN, true);
  
  nrf_drv_timer_enable(&timer);
  
  while(1)
  {
    
  };

Thank you very much in advance!

Parents
  • FormerMember
    0 FormerMember

    There is no specific ideal place to copy the content of the CC register, typically, the content in the CC register can be copied to a variable, a data array should work fine.

    The benefit of using PPI instead of normal GPIO interrupt handling is that when using PPI, the CPU is not being used:

    The Programmable Peripheral Interconnect (PPI) enables different peripherals to interact autonomously with each other using tasks and events without use of the CPU. The PPI provides a mechanism to automatically trigger a task in one peripheral as a result of an event occurring in another. A task is connected to an event through a PPI channel.

    (nRF51 series reference manual chapter 3.3.4)

    Clearing timer as soon as the capture is done:

    1. Capture value (will be copied to the CC register).

    2. Clear timer

    3. Read captured value from the CC register.

    This should work as long as every reading of captured values is finished before the next captured value.

  • Thank you very much for your support. In order to get that working accurately, it seems necessary to clear the timer immediately after the capture is done. Is the timer generating an interrupt after finishing the capture?

Reply Children
No Data
Related