Phase Shifting the Square wave using Due-TC

Hello friends....

I have read the Timer/counter chapter in ATSAM3X8E datasheet. It is mentioned that using the Timer/counter, we can perform the interval measurement between the instants.

My doubt is, can we do the phase shifting of the square wave pulse coming from other signal source. If possible please Let me know. :)

chamarthi: can we do the phase shifting of the square wave pulse coming from other signal source

Can you explain exactly what you mean ?

Sorry I couldn’t explained neatly.

I have attached the file tooo.

I want to give the Vin signal to due pin. The arduino due should produce the phase shifted input signal.

1/So you want to decipher frequency and duty cycle of an PWM input signal----> A Timer Counter with an Input capture will do that nicely. Of course, the input frequency should be within an acceptable range....

An example sketch for this part:

/*************************************************************************************************/
/*  a jumper needs to be installed between pin 2 (TIOA0) and pin A7 (TC0 channel 1 TIOA pin)     */
/*************************************************************************************************/
//#define Serial SerialUSB
volatile uint32_t CaptureCountA, CaptureCountB, Period, Duty;
volatile boolean CaptureFlag;

void setup() {
  Serial.begin(250000);

  /*************  Timer Counter 0 Channel 0 to generate PWM pulses thru TIOA0  ************/
  PMC->PMC_PCER0 |= PMC_PCER0_PID27;                      // Timer Counter 0 channel 0 IS TC0
  PIOB->PIO_PDR |= PIO_PDR_P25 | PIO_PDR_P27;
  PIOB->PIO_ABSR |= PIO_ABSR_P25 | PIO_ABSR_P27;

  TC0->TC_CHANNEL[0].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1   // MCK/2, clk on rising edge
                              | TC_CMR_WAVE                // Waveform mode
                              | TC_CMR_WAVSEL_UP_RC        // UP mode with automatic trigger on RC Compare
                              | TC_CMR_ACPA_CLEAR          // Clear TIOA0 on RA compare match
                              | TC_CMR_ACPC_SET;           // Set TIOA0 on RC compare match

  TC0->TC_CHANNEL[0].TC_RC = 42000;                          // Frequency of PWM pulses = MCK/2/TC_RC
  TC0->TC_CHANNEL[0].TC_RA = 21000;                          // Duty cycle of PWM pulses = (TC_RA/TC_RC) * 100 %

  TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger and enable

  /*************  Timer Counter 0 Channel 1 to capture PWM pulses thru TIOA1  ************/
  PMC->PMC_PCER0 |= PMC_PCER0_PID28;                       // Timer Counter 0 channel 1 IS TC1

  TC0->TC_CHANNEL[1].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1   // capture mode, MCK/2, clk on rising edge
                              | TC_CMR_ABETRG              // TIOA is used as the external trigger
                              | TC_CMR_LDRA_RISING         // load RA on rising edge of trigger input
                              | TC_CMR_LDRB_FALLING;       // load RB on falling edge of trigger input

  TC0->TC_CHANNEL[1].TC_IER |= TC_IER_LDRAS | TC_IER_LDRBS; // Trigger interruption on Load RA and load RB
  TC0->TC_CHANNEL[1].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN;  // Software trigger and enable

  NVIC_DisableIRQ(TC1_IRQn);
  NVIC_ClearPendingIRQ(TC1_IRQn);
  NVIC_SetPriority(TC1_IRQn, 0);                      // Give TC1 interrupt the highest urgency
  NVIC_SetPriority(SysTick_IRQn, 15);                 // SysTick interrupt will not interrupt TC1 interrupt
  NVIC_SetPriority(UART_IRQn, 14);                    // UART interrupt will not interrupt TC1 interrupt
  NVIC_EnableIRQ(TC1_IRQn);                           // Enable TC1 interrupts
}

void loop() {
  const uint32_t _F_CPU = F_CPU / 2;
  static uint32_t counter;
  float Frequency;
  float _Duty;

  if (counter++ > 100000) { // to be adjusted....do not print too often

    if ( CaptureFlag == true) {
      Frequency = _F_CPU / Period  ; //  (Mck/2 is TC1 clock) F Hz
      _Duty = (Duty * 100.00) / Period;
      printf(" F = %d  Hz , Duty = %d per cent\n", (uint32_t)Frequency, (uint32_t)_Duty);
      counter = 0;
      CaptureFlag = false;
    }
  }
}

void TC1_Handler() {

  static uint32_t _CaptureCountA;
  uint32_t status = TC0->TC_CHANNEL[1].TC_SR;       // Read and Clear status register

  //if (status & TC_SR_LOVRS) abort();  // We are loosing some edges

  if (status & TC_SR_LDRAS) {  // If ISR is triggered by LDRAS then ....
    CaptureCountA = (uint32_t) TC0->TC_CHANNEL[1].TC_RA;        // get data from capture register A for TC0 channel 1
    Period = CaptureCountA - _CaptureCountA;
    _CaptureCountA = CaptureCountA;
  }
  else { /*if ((status & TC_SR_LDRBS) == TC_SR_LDRBS)*/  // If ISR is triggered by LDRBS then ....
    CaptureCountB = (uint32_t) TC0->TC_CHANNEL[1].TC_RB;         // get data from caputre register B for TC0 channel 1
    Duty = CaptureCountB - _CaptureCountA;
    CaptureFlag = true;                      // set flag indicating a new capture value is present
  }
}

2/Then you want to output the same PWM signal, phase shifted of a fraction of the input PWM signal period----> Do the math to calculate the delay to trigger the ouptut PWM signal once you have results from 1/, program a new PWM signal and start this signal accordingly.

Thanks for the response ard_newbie.

I will learn what you have posted. :)

I will test the code