Go Down

Topic: ARDUINO DUE - Multi timer with internal and external clocks (Read 444 times) previous topic - next topic

Algorafun

Hello,

In first, i want to apology because my English is not good, so please don't tease me...
My project is base on the use of internal and external clocks and command 3 digital output pins to command a sequence in a multiplexer 8 to 1. I create PWM signal with a frequency max 2,5 Mhz and min 217 KHz. With another interruption timer, i change the output on the multiplexer every 10 KHz.

______________________________________________________________________________________

In the beginning, i choose the DUE card because of the 9 timers. But after some tests and research, i think this card it's not really good for this job. And the first reason is this table :
InstanceTCXChannelExternal ClockInput pinInternal clockoutput pin
T0TC0
0
XC0pin 22TCLK0Pin 2
T1TC0
1
XC0Ana In5TCLK1Ana In7
T2TC0
2
XC0pin 31TCLK2/
T3TC1
0
XC1Ana In3TCLK3/
T4TC1
1
XC1Ana In2TCLK4/
T5TC1
2
XC1DAC1TCLK5/
T6TC2
0
XC2/TCLK6pin 5
T7TC2
1
XC2LED "RX"TCLK7Pin 3
T8TC2
2
XC2pin 30TCLK8Pin 11


Like i understand this, if you want to use an external clock to create a PWM signal, you can use only the timer0 and timer8. All the other have not hardware connection for a external clock (timer6 and timer7) or a hardware output (timer1, timer2, timer3, timer4 and timer5). So, in first you have 9 timers and in the end you can use only 2 ! (or 4 with internal clock)

In the first place, when i want to comprehend the DUE board, i create 4 PWM signals with internal clock only (timer0, timer6, timer7 and timer8) because they have hardware connection output.

Code: [Select]



void setup()
{
  //Declaration des sorties PWM
  pinMode (2, OUTPUT);
  pinMode (3, OUTPUT);
  pinMode (5, OUTPUT);
  pinMode (11, OUTPUT);
 

 
  /*Initialisation périfiques du timers 0, 6, 7, 8 */
  pmc_set_writeprotect(false);  //Turn off write protection on Power Management Controller
  pmc_enable_periph_clk(TC0_IRQn);  // Enable the  peripheral clock by IRQ for Timer 0 channel 0
  pmc_enable_periph_clk(TC6_IRQn);  // Enable the  peripheral clock by IRQ for Timer 2 channel 0
  pmc_enable_periph_clk(TC7_IRQn);  // Enable the  peripheral clock by IRQ for Timer 2 channel 1
  pmc_enable_periph_clk(TC8_IRQn);  // Enable the  peripheral clock by IRQ for Timer 2 channel 2

 
  /* Configuration du timer TC2 channel 0 => timer 6 */
  TcChannel * t6 = &(TC2->TC_CHANNEL)[0] ;    // creation du pointeur sur le registre TC0 channel 0
                                             
  t6->TC_CCR = TC_CCR_CLKDIS ;  // désactivation des horloges le temps des reglages
  t6->TC_IDR = 0xFFFFFFFF ;     // desactivation des interruptions
  t6->TC_SR ;                   // lecture status pour reinitialisation du timer
  t6->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 |   // utilisation TCLK1 (division par 2, F = 42MHz)
              TC_CMR_WAVE |         // mode courbe
              TC_CMR_WAVSEL_UP_RC | // compteur PWM utilisant le registre RC
              TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR |
              TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR ;
 
  t6->TC_RC = 42;     // Definition de la fréquence : 42 MHz / TC_RC
  t6->TC_RA = 21;      // Definition du rapport cyclique, avec RA = 1/2 RC
 
  t6->TC_CMR = (t6->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET ; // set et reset des flags pour la comparaison des registres RA et RC                     
  t6->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ;  // reactivation de l horloge.
  /* Configuration des I/O : */
  int ulPin6 = 5; // Timer6 -> PWM Pin 5
  PIO_Configure(g_APinDescription[ulPin6].pPort,
  g_APinDescription[ulPin6].ulPinType,
  g_APinDescription[ulPin6].ulPin,
  g_APinDescription[ulPin6].ulPinConfiguration);

  /* Configuration du timer TC0 channel 0 => timer 0 */
  TcChannel * t0 = &(TC0->TC_CHANNEL)[0] ;    // creation du pointeur sur le registre TC0 channel 0
                                             
  t0->TC_CCR = TC_CCR_CLKDIS ;  // désactivation des horloges le temps des reglages
  t0->TC_IDR = 0xFFFFFFFF ;     // desactivation des interruptions
  t0->TC_SR ;                   // lecture status pour reinitialisation du timer
  t0->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 |   // utilisation TCLK1 (division par 2, F = 42MHz)
              TC_CMR_WAVE |         // mode courbe
              TC_CMR_WAVSEL_UP_RC | // compteur PWM utilisant le registre RC
              TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR |
              TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR ;
             
  t0->TC_RC = 17;     // Definition de la fréquence : 42 MHz / TC_RC
  t0->TC_RA = 8;      // Definition du rapport cyclique, avec RA = 1/2 RC
 
  t0->TC_CMR = (t0->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET ; // set et reset des flags pour la comparaison des registres RA et RC
                       
  t0->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ;  // reactivation de l horloge.

  int ulPin0 = 2; // Timer0 -> PWM Pin 2
  PIO_Configure(g_APinDescription[ulPin0].pPort,
  g_APinDescription[ulPin0].ulPinType,
  g_APinDescription[ulPin0].ulPin,
  g_APinDescription[ulPin0].ulPinConfiguration);


 
}

void loop()
{
 

}


With this code, i have my 4 signals with the correct frequency i set.


Algorafun

After, i want to use the external clock to generate a PWM signal. For this task, i use a 5 MHz clock connected to the pin22 (timer0) on DUE board .

Code: [Select]

void setup()
{
  //Declaration des sorties PWM
  pinMode (2, OUTPUT);  // timer0 - OUT
  pinMode (22, INPUT);  // timer0 - IN
 
 
 
  /*Initialisation périfiques du timers 0, 6, 7, 8 */
  pmc_set_writeprotect(false);  //Turn off write protection on Power Management Controller
  pmc_enable_periph_clk(TC0_IRQn);  // Enable the  peripheral clock by IRQ for Timer 0 channel 0


  /* Configuration du timer TC0 channel 0 => timer 0 */
  TcChannel * t0 = &(TC0->TC_CHANNEL)[0] ;    // creation du pointeur sur le registre TC0 channel 0
                                             
  t0->TC_CCR = TC_CCR_CLKDIS ;  // désactivation des horloges le temps des reglages
  t0->TC_IDR = 0xFFFFFFFF ;     // desactivation des interruptions
  t0->TC_SR ;                   // lecture status pour reinitialisation du timer
  t0->TC_CMR = TC_CMR_TCCLKS_XC0 |   // utilisation horloge externe (F = 5 MHz) - pin 22
              TC_CMR_WAVE |         // mode courbe
              TC_CMR_WAVSEL_UP_RC;  // compteur PWM utilisant le registre RC
                 
  t0->TC_RC = 5;     // Definition de la fréquence : 5 MHz / TC_RC
  t0->TC_RA = 2;      // Definition du rapport cyclique, avec RA = 1/2 RC
 
  t0->TC_CMR = (t0->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_SET | TC_CMR_ACPC_CLEAR ; // set et reset des flags pour la comparaison des registres RA et RC
                       
  t0->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ;  // reactivation de l horloge.

  int ulPin0 = 2; // Timer0 -> PWM Pin 2
  PIO_Configure(g_APinDescription[ulPin0].pPort,
  g_APinDescription[ulPin0].ulPinType,
  g_APinDescription[ulPin0].ulPin,
  g_APinDescription[ulPin0].ulPinConfiguration);
}

void loop()
{
}


This code work fine.
But my problem is when i change / adapt this code for the timer8.

Code: [Select]

void setup()
{
  //Declaration des sorties PWM
  pinMode (11, OUTPUT);  // timer0 - OUT
  pinMode (30, INPUT);  // timer0 - IN
 
 
 
  /*Initialisation périfiques du timers 0, 6, 7, 8 */
  pmc_set_writeprotect(false);  //Turn off write protection on Power Management Controller
  pmc_enable_periph_clk(TC8_IRQn);  // Enable the  peripheral clock by IRQ for Timer 0 channel 0


  /* Configuration du timer TC2 channel 2 => timer 8 */
  TcChannel * t8 = &(TC2->TC_CHANNEL)[2] ;    // creation du pointeur sur le registre TC2 channel 2
                                             
  t8->TC_CCR = TC_CCR_CLKDIS ;  // désactivation des horloges le temps des reglages
  t8->TC_IDR = 0xFFFFFFFF ;     // desactivation des interruptions
  t8->TC_SR ;                   // lecture status pour reinitialisation du timer
  t8->TC_CMR = TC_CMR_TCCLKS_XC2 |   // utilisation horloge externe (F = 5 MHz) - pin 30
              TC_CMR_WAVE |         // mode courbe
              TC_CMR_WAVSEL_UP_RC;  // compteur PWM utilisant le registre RC
                 
  t8->TC_RC = 5;     // Definition de la fréquence : 5 MHz / TC_RC
  t8->TC_RA = 2;      // Definition du rapport cyclique, avec RA = 1/2 RC
 
  t8->TC_CMR = (t8->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_SET | TC_CMR_ACPC_CLEAR ; // set et reset des flags pour la comparaison des registres RA et RC
                       
  t8->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ;  // reactivation de l horloge.

  int ulPin0 = 11; // Timer8 -> PWM Pin 11
  PIO_Configure(g_APinDescription[ulPin0].pPort,
  g_APinDescription[ulPin0].ulPinType,
  g_APinDescription[ulPin0].ulPin,
  g_APinDescription[ulPin0].ulPinConfiguration);
}

void loop()
{
}



I put the external clock in pin 30, but i have nothing in the output pin 11.
Can i have some help please ? where is my problem in the code or in the understanding of the DUE board ?

ard_newbie

To avoid confusion, see  "Timer Pins routed to the Arduino Due Board" here :


https://github.com/ivanseidel/DueTimer/issues/11





Algorafun

To avoid confusion, see  "Timer Pins routed to the Arduino Due Board" here :


https://github.com/ivanseidel/DueTimer/issues/11


I have already check this. My table is a quick summary of the content of the link.

ard_newbie



Did you activate PWM controller : PMC->PMC_PCER1 |= PMC_PCER1_PID36; ?

Algorafun

I don't know. I will check that.

I add the "TC_CMR_BURST_XC2" instruction in my code for the CMR register and it work.

Thank for this point.

Now, i will code a timer interruption for the multiplexer command with a frequency of 10 KHz.

Algorafun

With an adaptation, i make a timer with an interruption for the multiplexer command :

Code: [Select]


// Initialisation des variables
volatile int sequence = 0;
//Creation du tableau contenant l'ordre des fréquences à afficher
int table[16][3] = {{0,1,0},//F4 - 0
                    {1,0,1},//F6
                    {0,0,0},//F1
                    {0,0,1},//F2
                    {0,1,0},//F4
                    {1,0,1},//F5
                    {1,0,0},//F6
                    {0,1,1},//F3
                    {1,0,0},//F6
                    {1,1,1},//F7
                    {0,0,0},//F1
                    {0,1,1},//F3
                    {0,1,0},//F4
                    {0,0,1},//F1
                    {1,0,0},//F5
                    {0,0,1}};//F2 - 15

//TC1 ch 0
void TC3_Handler()
{
        TC_GetStatus(TC1, 0);
        digitalWrite(8, table[sequence][0]);
        digitalWrite(9, table[sequence][1]);
        digitalWrite(10, table[sequence][2]);
       
     //   Serial.print(sequence);
     //   Serial.print(" ; ");
     //   Serial.println(table[sequence][2]);
       
        sequence++;
}

void startTimer(Tc *tc, uint32_t channel, IRQn_Type irq) {
        pmc_set_writeprotect(false);
        pmc_enable_periph_clk((uint32_t)irq);

        /* Configuration du timer TC0 channel 2 => timer 2 */
        TcChannel * t3 = &(TC1->TC_CHANNEL)[0] ;    // creation du pointeur sur le registre TC1 channel 0
                                             
        t3->TC_CCR = TC_CCR_CLKDIS ;  // désactivation des horloges le temps des reglages
        t3->TC_SR ;                   // lecture status pour reinitialisation du timer
        t3->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 |   // utilisation TCLK1 (division par 2, F = 42MHz)
              TC_CMR_WAVE |         // mode courbe
              TC_CMR_WAVSEL_UP_RC; // compteur PWM utilisant le registre RC
             
        t3->TC_RC = 4200;     // Definition de la fréquence : 5 MHz / TC_RC
        t3->TC_RA = 2100;      // Definition du rapport cyclique, avec RA = 1/2 RC
        TC_Start(tc, channel);
        tc->TC_CHANNEL[channel].TC_IER=TC_IER_CPCS;
        tc->TC_CHANNEL[channel].TC_IDR=~TC_IER_CPCS;
        NVIC_EnableIRQ(irq);
}

void setup()
{
        pinMode(8,OUTPUT);
        pinMode(9,OUTPUT);
        pinMode(10,OUTPUT);
        startTimer(TC1, 0, TC3_IRQn); //TC1 channel 0, the IRQ for that channel and the desired frequency
        Serial.begin(250000);
        delay(500);
}

void loop()
{
        if (sequence > 15)
        {
          sequence = 0;
        }
}

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy