I designed a circuitboard and need to proof the function.Therefore i have to modify the code to read from Pins D1 instead of D2. Unfourtunatly i am not that familar with the high level programming so im not sure if i got all changes. Basically all PINS on the circuit are used.
Basecode foud here: Seeeduino XIAO write and read PWM duration (period) using timers
Reading short square waves with Seeeduino XIAO pin D2
// Setup TC4 to capture pulse-width and period on digital pin D2 on Seeeduino Xiao
volatile boolean periodComplete;
volatile uint32_t isrPeriod;
volatile uint32_t isrPulsewidth;
uint32_t period;
uint32_t pulsewidth;
void setup() {
SerialUSB.begin(115200); // Initialise the native serial port
while(!SerialUSB); // Wait for the console to open
PM->APBCMASK.reg |= PM_APBCMASK_EVSYS; // Switch on the event system peripheral
GCLK->GENDIV.reg = GCLK_GENDIV_DIV(1) | // Divide the 48MHz system clock by 1 = 48MHz
GCLK_GENDIV_ID(4); // Set division on Generic Clock Generator (GCLK) 4
GCLK->GENCTRL.reg = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW
GCLK_GENCTRL_GENEN | // Enable GCLK 4
GCLK_GENCTRL_SRC_DFLL48M | // Set the clock source to 48MHz
GCLK_GENCTRL_ID(4); // Set clock source on GCLK 4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Route GCLK4 to TC4 and TC5
GCLK_CLKCTRL_GEN_GCLK4 |
GCLK_CLKCTRL_ID_TC4_TC5;
// Enable the port multiplexer on port pin PA10
PORT->Group[PORTA].PINCFG[10].bit.PMUXEN = 1;
// Set-up the pin as an EIC (interrupt) on port pin PA10
PORT->Group[PORTA].PMUX[10 >> 1].reg |= PORT_PMUX_PMUXE_A;
EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO10; // Enable event output on external interrupt 10
EIC->CONFIG[1].reg |= EIC_CONFIG_SENSE2_HIGH; // Set event detecting a HIGH level
EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT10; // Disable interrupts on external interrupt 10
EIC->CTRL.reg |= EIC_CTRL_ENABLE; // Enable EIC peripheral
while (EIC->STATUS.bit.SYNCBUSY); // Wait for synchronization
EVSYS->USER.reg = EVSYS_USER_CHANNEL(1) | // Attach the event user (receiver) to channel 0 (n + 1)
EVSYS_USER_USER(EVSYS_ID_USER_TC4_EVU); // Set the event user (receiver) as timer TC4
EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT | // No event edge detection
EVSYS_CHANNEL_PATH_ASYNCHRONOUS | // Set event path as asynchronous
EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_10) | // Set event generator (sender) as external interrupt 10
EVSYS_CHANNEL_CHANNEL(0); // Attach the generator (sender) to channel 0
TC4->COUNT32.EVCTRL.reg = TC_EVCTRL_TCEI | // Enable the TC event input
//TC_EVCTRL_TCINV | // Invert the event input
TC_EVCTRL_EVACT_PPW; // Set up the timer for capture: CC0 period, CC1 pulsewidth
TC4->COUNT32.CTRLC.reg = TC_CTRLC_CPTEN1 | // Enable capture on CC1
TC_CTRLC_CPTEN0; // Enable capture on CC0
while (TC4->COUNT32.STATUS.bit.SYNCBUSY); // Wait for synchronization
NVIC_SetPriority(TC4_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest)
NVIC_EnableIRQ(TC4_IRQn); // Connect the TC4 timer to the Nested Vector Interrupt Controller (NVIC)
TC4->COUNT32.INTENSET.reg = TC_INTENSET_MC1 | // Enable compare channel 1 (CC1) interrupts
TC_INTENSET_MC0; // Enable compare channel 0 (CC0) interrupts
TC4->COUNT32.CTRLA.reg = //TC_CTRLA_PRESCSYNC_PRESC | // Overflow on precaler clock, (rather than the GCLK)
TC_CTRLA_PRESCALER_DIV1 | // Set prescaler to 1, 48MHz/1 = 48MHz
TC_CTRLA_MODE_COUNT32; // Set TC4/TC5 to 32-bit timer mode
TC4->COUNT32.CTRLA.bit.ENABLE = 1; // Enable TC4
while (TC4->COUNT32.STATUS.bit.SYNCBUSY); // Wait for synchronization
}
void loop() {
if (periodComplete) // Check if the period is complete
{
noInterrupts(); // Read the new period and pulse-width
period = isrPeriod;
pulsewidth = isrPulsewidth;
interrupts();
SerialUSB.print("PW: ");
SerialUSB.print(pulsewidth);
SerialUSB.print(F(" "));
SerialUSB.print("P: ");
SerialUSB.println(period);
periodComplete = false; // Start a new period
}
}
void TC4_Handler() // Interrupt Service Routine (ISR) for timer TC4
{
// Check for match counter 0 (MC0) interrupt
if (TC4->COUNT32.INTFLAG.bit.MC0)
{
TC4->COUNT32.READREQ.reg = TC_READREQ_RREQ | // Enable a read request
TC_READREQ_ADDR(0x18); // Offset address of the CC0 register
while (TC4->COUNT32.STATUS.bit.SYNCBUSY); // Wait for (read) synchronization
isrPeriod = TC4->COUNT32.CC[0].reg; // Copy the period
periodComplete = true; // Indicate that the period is complete
}
// Check for match counter 1 (MC1) interrupt
if (TC4->COUNT32.INTFLAG.bit.MC1)
{
TC4->COUNT32.READREQ.reg = TC_READREQ_RREQ | // Enable a read request
TC_READREQ_ADDR(0x1A); // Offset address of the CC1 register
while (TC4->COUNT32.STATUS.bit.SYNCBUSY); // Wait for (read) synchronization
isrPulsewidth = TC4->COUNT32.CC[1].reg; // Copy the pulse-width
}
}
Do i only have to change the IOs:
from:
PORT->Group[PORTA].PINCFG[10].bit.PMUXEN = 1;
PORT->Group[PORTA].PMUX[10 >> 1].reg |= PORT_PMUX_PMUXE_A;
to:
PORT->Group[PORTA].PINCFG[4].bit.PMUXEN = 1;
PORT->Group[PORTA].PMUX[4 >> 1].reg |= PORT_PMUX_PMUXE_A;
or do i need to mod more code?
Thanks for helping.
1 Answer 1
In addition to the changes you mentioned, your EIC_EVCTRL_EXTINTEO10
, EIC_INTENCLR_EXTINT10
, and EVSYS_ID_GEN_EIC_EXTINT_10
usages will need to be changed to EIC_EVCTRL_EXTINTE4
, EIC_INTENCLR_EXTINT4
and to EVSYS_ID_GEN_EIC_EXTINT_4
, to re-target the event system source, because PORT_PMUX_PMUXE_A
on both these pins routes the signal to the EIC, but not to the exact same interrupt number. The EIC->CONFIG
line needs to change to the first group of 8 ([0]
) and fourth SENSE within that group (EIC_CONFIG_SENSE4_HIGH
) to the change to D1 (PA04) uses EXTINT4. This is something I'd left out of the first edit before I'd been able to test. I did eventually find a XIAO to test with and these modifications seem to make it work just fine on digital pin 1 now instead of digital pin 2.
EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTE4;
EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE4_HIGH;
EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT4;
EIC->CTRL.reg |= EIC_CTRL_ENABLE;
while (EIC->STATUS.bit.SYNCBUSY);
...
EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT |
EVSYS_CHANNEL_PATH_ASYNCHRONOUS |
EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_4) |
EVSYS_CHANNEL_CHANNEL(0);
The changes you'd mentioned and those I've said above as diff:
--- original.ino
+++ modified.ino
@@ -24,14 +24,14 @@
GCLK_CLKCTRL_GEN_GCLK4 |
GCLK_CLKCTRL_ID_TC4_TC5;
- // Enable the port multiplexer on port pin PA10
- PORT->Group[PORTA].PINCFG[10].bit.PMUXEN = 1;
- // Set-up the pin as an EIC (interrupt) on port pin PA10
- PORT->Group[PORTA].PMUX[10 >> 1].reg |= PORT_PMUX_PMUXE_A;
+ // Enable the port multiplexer on port pin PA04
+ PORT->Group[PORTA].PINCFG[4].bit.PMUXEN = 1;
+ // Set-up the pin as an EIC (interrupt) on port pin PA04
+ PORT->Group[PORTA].PMUX[4 >> 1].reg |= PORT_PMUX_PMUXE_A;
- EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO10; // Enable event output on external interrupt 10
- EIC->CONFIG[1].reg |= EIC_CONFIG_SENSE2_HIGH; // Set event detecting a HIGH level
- EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT10; // Disable interrupts on external interrupt 10
+ EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO4; // Enable event output on external interrupt 4
+ EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE4_HIGH; // Set event detecting a HIGH level
+ EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT4; // Disable interrupts on external interrupt 4
EIC->CTRL.reg |= EIC_CTRL_ENABLE; // Enable EIC peripheral
while (EIC->STATUS.bit.SYNCBUSY); // Wait for synchronization
@@ -40,7 +40,7 @@
EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT | // No event edge detection
EVSYS_CHANNEL_PATH_ASYNCHRONOUS | // Set event path as asynchronous
- EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_10) | // Set event generator (sender) as external interrupt 10
+ EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_4) | // Set event generator (sender) as external interrupt 4
EVSYS_CHANNEL_CHANNEL(0); // Attach the generator (sender) to channel 0
TC4->COUNT32.EVCTRL.reg = TC_EVCTRL_TCEI | // Enable the TC event input