Hi Daniel,
First, I do need to run my Tx and Rx on the same board.
That depends on what you're planning to do for your transmitter, but the PWM runs independently of the CPU, so isn't processor intensive. The PWM duty-cycle/frequency can be changed by just loading a register.
For Tx I am using your PWM code, which generate 40 kHz on Pin 7 thanks to timers based on GCLK4 clock , TCC0 and TCC1 etc...
For Rx (our last exchanges above), I use Pin 12 and attached interuption, and timers based on GCLK5 , TCC0 and TCC1 etc...
The TCC0 and TCC1 timers share the same generic clock (GCLK), but have separate timer prescalers. As you're running the timers at high speed the generic clock will be set to the maximum of 48MHz anyway, so this isn't an issue. I imagine you'll also be setting the timer prescalers to 1.
If you're using timer TCC0 for timer capture on the receiver, then it will be necessary to use TCC1 for PWM generation on the transmitter. This is because the TCC0 timer is reset at the end of a capture cycle (timer period), whereas for PWM generation the timer runs until its count (COUNT) value matches the value in its period (PER) register. If you were to run them on the same timer, they'd interfere with each other.
Did I well understand that both timers / interruptions can work at the same time ?
Yes, both timers can work at the same time. Each timer has it's own interrupt service routine and can be triggered by overflow (OVF) and counter compare match (MCx) for each timer channel.
Here's an example of the TCC0 interrupt service routine:
void TCC0_Handler() // Interrupt Service Routine (ISR) for timer TCC0
{
// Check for overflow (OVF) interrupt
if (TCC0->INTFLAG.bit.OVF && TCC0->INTENSET.bit.OVF)
{
// Put your timer overflow (OVF) code here...
// ...
REG_TCC0_INTFLAG = TCC_INTFLAG_OVF; // Clear the OVF interrupt flag
}
// Check for match counter 0 (MC0) interrupt
if (TCC0->INTFLAG.bit.MC0 && TCC0->INTENSET.bit.MC0)
{
// Put your counter compare 0 (CC0) code here...
// ...
REG_TCC0_INTFLAG = TCC_INTFLAG_MC0; // Clear the MC0 interrupt flag
}
// Check for match counter 1 (MC1) interrupt
if (TCC0->INTFLAG.bit.MC1 && TCC0->INTENSET.bit.MC1)
{
// Put your counter compare 1 (CC1) code here...
// ...
REG_TCC0_INTFLAG = TCC_INTFLAG_MC1; // Clear the MC1 interrupt flag
}
// TCC0 has 4 channels, so has MC2 and MC3 as well...
}
How to STOP / START timers individualy ?
To stop the timer:
REG_TCC0_CTRLBSET = TCC_CTRLBSET_CMD_STOP;
while(TCC0->SYNCBUSY.bit.CTRLB);
To re-start the timer again:
REG_TCC0_CTRLBSET = TCC_CTRLBSET_CMD_RETRIGGER;
while(TCC0->SYNCBUSY.bit.CTRLB);
For the external interruption linked to Pin 12, can we use "Nointerrupts() / Interrupts() instructions to stop it ? I mean, does other interruptions in the system will be affected ? and if yes how to manage it selectively ?
To manage the interrupts it's possible to use the timer's interrupt enable set (INTENSET) and interrupt enable clear registers (INTENCLR):
REG_TCC0_INTENSET = TCC_INTENSET_MC1 | // Enable compare channel 1 (CC1) interrupts
TCC_INTENSET_MC0 | // Enable compare channel 0 (CC0) interrupts
TCC_INTENSET_OVF; // Enable overflow (OVF) interupts
REG_TCC0_INTENCLR = TCC_INTENSET_MC1 | // Disable compare channel 1 (CC1) interrupts
TCC_INTENSET_MC0 | // Disable compare channel 0 (CC0) interrupts
TCC_INTENSET_OVF; // Disable overflow (OVF) interupts
Kind regards,
Martin