Arduino DUE pulseIn() ,This function does not work properly

I tried to compile a program currently running on the UNO board and run it on the DUE board. However, the time returned by the pulseIn instruction is not the same on a DUE board, and the error is large, which is a problem.What is required for the pulseIn instruction to work properly on a DUE board?

Arduino IDE windows 1.8.12

--code--
int pin = 2;
unsigned long duration;

void setup() {
Serial.begin(9600);
pinMode(pin, INPUT);
}

void loop() {
duration = pulseIn(pin, HIGH);
Serial.println(duration);
}

-- result 500Hz pulse input
UNO
986
985
985
985
985
985
985
985
985
986
985
986
986
986

DUE
929
953
962
962
897
929
897
963
963
897
929
897
963
963

m-miyake:
What is required for the pulseIn instruction to work properly on a DUE board?

A clean 3.3V signal I guess.

Probably a version that doesn't try to guess instruction timing on a CPU with non-deterministic flash memory timing :frowning:

pulseln() is not designed for the DUE. You need a timer set in Capture Mode.

An example sketch to capture frequency and duty cycle of an input pulse provided by the board itself:

/*************************************************************************************************/
/*  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) { 

    if ( CaptureFlag == true) {

      Frequency = _F_CPU / Period  ; //  (Mck/2 is TC1 clock) F in 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
  }

}

Do you know which timers on Due are available?
I was thinking that the SAM3X might get away with the same micros()-based pulsein() that I did for the Adafruit SAMD51 boards

Thank you everyone for advice.
I understand that the pulseIn instruction cannot be used with the DUE board.
The following method was used.

--- code ---
volatile unsigned long duration=0;
volatile unsigned long prevMicros=0;
float freq;

void setup()
{
Serial.begin(9600);
attachInterrupt(2, periodIrq, RISING);
}

void loop()
{
freq = 1000000/duration;
Serial.println(freq);
delay(200);
}

void periodIrq() // interrupt handler
{
unsigned long currentMicros = micros();
duration = currentMicros - prevMicros;
prevMicros = currentMicros;
}

The loop access to the variable duration has to be atomic.

See Gammon Forum : Electronics : Microprocessors : Interrupts

The loop access to the variable duration has to be atomic.

Isn't it always? Remember this is a 32bit chip...

westfw:
Isn't it always? Remember this is a 32bit chip...

Probably. I forgot about the 32 bit architecture.