Arduino due interrupt changing value problem

hello, I've adapted my arduino mega SPWM.inoto the arduino Due.

The ino was well working with mega but give eratic result with Due.

I cannot find the reason why, it was well working with arduino mega. i've tested with oscilloscope the timmer TC0 and TC6 are good and perfectly frequenced respectively to 1 seconde and 2,56 khz but tc6 instead of changing value every 1 seconde is changing eraticly every rc trigger ( 1/2560) second

/* this ino give a sinusoidal PWM on digital 5 and a 50% PWM on digital 4
 *  timer TC0 is 1 hz frequency and give an interrupt to change the value of 
the register TC2_RA0 of timer TC6 with the new value sample0 from 
sinusoide tab
 */
const int sinewave_length=256;

const unsigned char sinewave_data[] PROGMEM = {
0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,
0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8,
0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf5,
0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,
0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe2,0xe0,0xde,0xdc,
0xda,0xd8,0xd5,0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb3,
0xb0,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x98,0x95,0x92,0x8f,0x8c,0x89,0x86,0x83,
0x80,0x7c,0x79,0x76,0x73,0x70,0x6d,0x6a,0x67,0x63,0x60,0x5d,0x5a,0x57,0x54,0x51,
0x4f,0x4c,0x49,0x46,0x43,0x40,0x3e,0x3b,0x38,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27,
0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x12,0x10,0x0f,0x0d,0x0c,0x0a,
0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08,
0x09,0x0a,0x0c,0x0d,0x0f,0x10,0x12,0x13,0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23,
0x25,0x27,0x2a,0x2c,0x2e,0x31,0x33,0x36,0x38,0x3b,0x3e,0x40,0x43,0x46,0x49,0x4c,
0x4f,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,0x67,0x6a,0x6d,0x70,0x73,0x76,0x79,0x7c};


volatile uint16_t sample0;

void tc0_setup()
{
  REG_PMC_PCER0 |= PMC_PCER0_PID27;                 // Enable peripheral TC0 (TC0 Channel 0)
  
  REG_TC0_CMR0 = TC_CMR_WAVE |                      // Enable wave mode
                 TC_CMR_WAVSEL_UP_RC |              // Count up with automatic trigger on RC compare
                 TC_CMR_TCCLKS_TIMER_CLOCK4;        // Set the timer clock to TCLK4 (MCK/2 = 84MHz/128 = 328125 Hz) 1/2 2/8 3/32 4/128

  REG_TC0_RC0 = 656250;                               // Load the RC0 register give 1 hz frequency
 
  REG_TC0_CCR0 = TC_CCR_SWTRG | TC_CCR_CLKEN;       // Enable the timer TC0 and software trigger
  REG_TC0_IER0=0b00010000; // enable interrupt on counter=rc
  REG_TC0_IDR0=0b11101111; // disable other interrupts

  NVIC_EnableIRQ(TC0_IRQn); // enable TC0 interrupts
}


void tc6_setup()
{
  REG_PMC_PCER1 |= PMC_PCER1_PID33;                 // Enable peripheral TC6 (TC2 Channel 0)
  REG_PIOC_ABSR |= PIO_ABSR_P26 | PIO_ABSR_P25;     // Switch the multiplexer to peripheral B for TIOA6 and TIOB6 => led output on digital 4 and 5
  REG_PIOC_PDR |= PIO_PDR_P26 | PIO_PDR_P25;        // Disable the GPIO on the corresponding pins

  REG_TC2_CMR0 = TC_CMR_BCPC_SET |                  // Set TIOB on counter match with RC0
                 TC_CMR_ACPC_SET |                  // Set TIOA on counter match with RC0
                 TC_CMR_BCPB_CLEAR |                // Clear TIOB on counter match with RB0
                 TC_CMR_ACPA_CLEAR |                // Clear TIOA on counter match with RA0
                 TC_CMR_WAVE |                      // Enable wave mode
                 TC_CMR_WAVSEL_UP_RC |              // Count up with automatic trigger on RC compare
                 TC_CMR_EEVT_XC0 |                  // Set event selection to XC0 to make TIOB an output
                 TC_CMR_TCCLKS_TIMER_CLOCK4;        // Set the timer clock to TCLK1 (MCK/2 = 84MHz/2 = 48MHz)

  REG_TC2_RA0 = 1;                               // Load the RA0 register
  REG_TC2_RB0 = 128;                               // Load the RB0 register
  REG_TC2_RC0 = 256;                               // Load the RC0 register
 
  REG_TC2_CCR0 = TC_CCR_SWTRG | TC_CCR_CLKEN;       // Enable the timer TC6 and software trigger
  //REG_TC2_IER0=0b00010000; // enable interrupt on counter=rc
  //REG_TC2_IDR0=0b11101111; // disable other interrupts

  //NVIC_EnableIRQ(TC6_IRQn); // enable TC0 interrupts
}


void TC0_Handler()
{
  
  REG_TC2_RA0 = pgm_read_byte(&sinewave_data[sample0]);
  if (sample0 >= sinewave_length) { sample0 = -1;}
  ++sample0;
}

void setup()
{
  tc0_setup();
  tc6_setup();
}

void loop() {}


Your TC0_Handler() needs this line:
TC_GetStatus(TC0, 0); // reading this clears pending interrupt status
You also need a similar one for timer 6 (use: TC3, 0).
I didn't test your code, but without reading the status, your interrupt never clears, and gets called again and again, not just at the expected time.

  • Wes
1 Like

it's ok now I have a spwm at the output but I've had to change 0x00 values to 0x01 in the sinewave_data[]for the compare value RA of TC6 timmer because without this at 0x00 it put the output on instead of off... it wasn't the case withe the arduino mega

thanks a lot for your help it's cool :slight_smile: I'm wondering where we can find this TC_GetStatus(TC0, 0);because I've not seen it in datasheet, just seen the satus register but as I'm not used to programm I've certainly missed it ...
I don't use interrupt for tc6 so I think I don't have to use TC_GetStatus(TC2, 0);

It's in the Arduino libraries, but not sure which one.
I believe it just reads a register and the hardware clears the pending interrupt so it doesn't continue to trigger, but I never delved any deeper. I do know that without it my Due was 500KHz square waves instead of the 2KHz ones I was looking for.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.