Interrupt service routine for SAMD21G18

I’m using a SAMD21G18 microcontroller with Arduino as the development platform and I want to implement a UART interrupt service routine. Is there a way to achieve this?

Hi there,
Something like this would do.

void setup(){
 Serial.begin(9600);  
  pinMode(7, INPUT);      // Make pin 7 RXD an input
   
    // attach our interrupt pin to it's ISR
    attachInterrupt(0, recISR, CHANGE);
    // we need to call this to enable interrupts
    interrupts();
}

// The interrupt hardware calls this when we hit our left bumper
void recISR(){

  //  rec = 1;
     Serial.println("interrupt!"); 
 
}

Give something like that a try.
HTH
GL :slight_smile: PJ :v:

1 Like

I’ve successfully set up a UART-based interrupt system using the code below. The interrupt is triggered on changes to the RX pin (pin 7), and it correctly prints “interrupt!” to Serial1 when triggered.

void setup() {
  Serial1.begin(115200);
  pinMode(7, INPUT);  // Configure pin 7 as an input

  // Attach interrupt to pin 7 with ISR for CHANGE event
  attachInterrupt(digitalPinToInterrupt(7), recISR, CHANGE);
  // Enable interrupts
  interrupts();
}

// ISR for handling interrupts
void recISR() {
  Serial1.println("interrupt!");
}

I made a small change to the code by adding digitalPinToInterrupt(7) to the attachInterrupt function, which resolved the issue. However, I am still encountering difficulties reading the received UART data from the RX register and transmitting it via the TX line.

Could anyone provide guidance on how to read the incoming data from the RX register and send it through the TX line within the ISR, or suggest a more effective approach for handling UART communication with interrupts?

Hi there,
You almost have it…

HTH
GL :slight_smile: PJ :v:

Don’t forget to mark this as the solution so others may find it. :+1:

goal:

  • I want to use the same UART serial port for both receiving data via interrupts and transmitting data via Serial1.write() or similar.

  • When a character is received on the RX line, I need to trigger an interrupt. In the interrupt handler, I will read the character directly from the RX register and store it in a character array for further processing.
    Details:

  • I don’t want to use another serial port (like SoftwareSerial or Serial2). I just need to work with one UART for both RX and TX.

  • How can I set up an interrupt for the RX event on the XIAO SAMD21G18? And how do I read the character from the RX register after the interrupt is triggered?

Hi there,
You just need to read the data that caused the interrupt . something like this will do it.

#define BUFFER_SIZE 50
char dataBuffer[BUFFER_SIZE];  // Buffer for storing incoming data
int dataIndex = 0;             // Keep track of where to write new data

void setup() {
  Serial.begin(9600);          // Initialize Serial at 9600 baud rate
  pinMode(7, INPUT);           // Pin 7 for any other interrupts you need

  // Attaching interrupt for pin 7 (e.g., for an external signal)
  attachInterrupt(digitalPinToInterrupt(7), recISR, CHANGE);  

  // Enabling global interrupts
  interrupts();
}

void loop() {
  // Check if serial data is available
  if (Serial.available() > 0) {
    char incomingByte = Serial.read();   // Read the incoming byte
    Serial.print("Received: ");
    Serial.println(incomingByte);        // Print it for debugging
    
    // Add incoming byte to buffer (make sure it doesn't overflow)
    if (dataIndex < BUFFER_SIZE - 1) {
      dataBuffer[dataIndex] = incomingByte;
      dataIndex++;
      dataBuffer[dataIndex] = '\0';      // Null-terminate the string
    }

    // For demonstration, you can send the received data back
    Serial.println(dataBuffer);
  }
}

// The ISR for pin 7 (triggered when the pin changes state)
void recISR() {
  Serial.println("External interrupt triggered!");
}

The Serial library already has a built-in way to check when data arrives through the Serial.available() function, and it’s usually better to avoid using hardware interrupts for serial data handling, as Serial interrupts internally when data arrives.

However, if you want to stick with the interrupt approach for another reason (like reading a pin), here’s a general concept you could follow:

  1. Use Serial.available() to check if there is data to read.
  2. Use Serial.read() to grab the incoming data and append it to an array.
  3. Send that data back using Serial.write() or Serial.println().

above is a cleaner implementation without relying on an interrupt for the serial port itself:

Key Points:

  1. Serial Data Handling: The code now checks for serial data in the loop() using Serial.available(). This ensures no data is missed.
  2. Buffering: Data is stored in a dataBuffer[], and it’s printed back when new data arrives.
  3. External Interrupt: An interrupt on pin 7 remains, but it’s for an external signal and won’t interfere with serial data reception.

This should work for your use case, handling serial data and sending it back while also using an interrupt for other purposes on pin 7.

HTH
GL :slight_smile: PJ :v: