0

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.

Hannes
  • 3
  • 1

1 Answers1

0

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

timemage
  • 5,639
  • 1
  • 14
  • 25