Arduino DUE - read serial in interupt

Hello,
I have moved my code from arduino mega to due.

Because I'm handling RS485 communication I need to receive data in interrupts - on arduino mega I used library GitHub - SlashDevin/NeoHWSerial: Arduino HardwareSerial with attachInterrupt for RX chars - which unforutently is not working on DUE.

I know that serial is being handle on interrupts in DUE - but data goes to buffer - I would like to handle data right away instad of polling from buffer.

How can I receive data via interrupts on arduino DUE ?

Thanks in advance.

EDIT:
or eventualy how can I adjust arduino code to make libarary from above working ?
Here are errors I have when I try to use it:

In file included from src/main.cpp:80:0:
/home/xx/xx/modules/home-controller/libraries/common/NeoHWSerial/NeoHWSerial.h:64:0: warning: "SERIAL_5N1" redefined [enabled by default]
#define SERIAL_5N1 0x00
^
In file included from /home/xx/.platformio/packages/framework-arduinosam/variants/arduino_due_x/variant.h:39:0,
from /home/xx/.platformio/packages/framework-arduinosam/cores/sam/Arduino.h:201,

from src/main.cpp:79:
/home/xx/.platformio/packages/framework-arduinosam/cores/sam/USARTClass.h:29:0: note: this is the location of the previous definition
#define SERIAL_5N1 USARTClass::Mode_5N1
^

What would you have this interrupt do with the Serial data? It has to read it into something. I've seen lots of people try to write new serial interrupt code, but all any of them are ever doing is the same thing the serial interrupt was already doing. You have to collect the data into some buffer. What's the difference between collecting it into the serial buffer or collecting it into some other buffer?

lonas:
Because I'm handling RS485 communication I need to receive data in interrupts

Can you explain why?

Then it may be possible to make some useful suggestions.

...R

For an RS485 working code wilth Serial2 (USART1), see this thread:

https://forum.arduino.cc/index.php?topic=451676.0

lonas:
I know that serial is being handle on interrupts in DUE - but data goes to buffer - I would like to handle data right away instad of polling from buffer.

You may want to do it that way, but its not likely to help you.

You have a need to process the serial at a particular time, as indicated by the interrupt happening? Then
just call the relevant handling function from the ISR (making sure its variables are volatile). It can then pull
stuff from the buffer.

If loop() is running often enough (nothing hogs the processor), just poll the buffer there and any other state
you need, no ISR needed, just keep your system from being overloaded and everything progresses nicely.

Maybe you are calling delay() somewhere? That's probably a problem worth solving if so.

I need to receive data with interrupts because I've implemented RS485 multimaster protocol.

When one device start transmission it's sending to all of devices negotiation character - after which no device should send anything till bus will be free - so that negotiation character have to be read as fast as possbile (without poll) - and set lock on device to do not send anything till bus is free.

MarkT:
You may want to do it that way, but its not likely to help you.

You have a need to process the serial at a particular time, as indicated by the interrupt happening? Then
just call the relevant handling function from the ISR (making sure its variables are volatile). It can then pull
stuff from the buffer.

  • so how can I acheive that ?

I tried for example like this - but it seems not work

void UART_Handler(void) __attribute__((weak));
void UART_Handler(void) {
  Serial.IrqHandler();
  Serial.print(Serial.read());
}

Try first the polling mode, as suggested in my reply #3 with USART1 (Serial2), RXD1=PA12, TXD1=PA13, RST1=PA14 (see Greynomad pinaout diagram) :

void setup()
{

  pinMode(23, OUTPUT); //RTS for USART1
  digitalWrite(23, LOW);
  Serial.begin(9600);
  Serial2.begin(9600, SERIAL_8N1);  //SERIAL_8N1

  //USART1->US_WPMR = 0x55534100; //Unlock the USART Mode register, just in case. (mine wasn't locked).
  USART1->US_CR |= US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS;
  USART1->US_MR |= US_MR_USART_MODE_RS485 //USART1 IN RS485 mode
                  | US_MR_PAR_NO          // No parity
                  | US_MR_OVER;           // 8 X oversampling
  USART1->US_CR |= US_CR_TXEN | US_CR_RXEN; //Enable Transmitter and Receiver

}
void loop()
{
  char mydat = 0;
  while (1)
  {
    while (Serial2.available()) // USART1
    {

      mydat =  Serial2.read();
      if (mydat != 0)
      {
        Serial.println(mydat);


      }

      if (mydat == 's') //check if char 's' received if yes then transmit for test
      {

        delay(100);
        digitalWrite(23, HIGH);  //for transmitter RTS HIGH

        Serial2.println("waiting for char");
        Serial2.flush();   //Wait till transmit all char

        digitalWrite(23, LOW);
        delay(100);

        mydat = 0;
      }
    }
  }
}

@ard_newbie, thanks - I saw post You mentioned before I wrote here.

Issue here is I don't want to poll - I want to be notified after someting cames to receiver - to lock transmission.

I believe code You pasted is to manage RTS pin for RS485 transmission, right ?

  USART1->US_CR |= US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS;
  USART1->US_MR |= US_MR_USART_MODE_RS485   // USART1 IN RS485 mode
                   | US_MR_PAR_NO           // No parity
                   | US_MR_OVER;            // 8 X oversampling
  USART1->US_CR |= US_CR_TXEN | US_CR_RXEN; // Enable Transmitter and Receiver

Yes you will have to manage RTS pin.

You don't want to poll, but step 1 would be to be able to receive via RS485, then tune USART1_Handler().

I saw that USART1 have some handling for RS485 - another issue here is I need to use Serial0 - because in near future I will have to upload code via rs485 to DUE

AFAICT RS485 is not available ON UART (Serial = Serial0). You will have to deal with Serial1,2 or 3 (Serial4 has no broken out RTS pin).

I see, thanks - but still I would like to know how to make this work ?

void UART_Handler(void) __attribute__((weak));
void UART_Handler(void) {
  Serial.IrqHandler();
  Serial.print(Serial.read());
}

If you intend to use RS485 protocol without this builtin feature of the Sam3x, you might be interested by this:
https://www.gammon.com.au/forum/?id=11428

Serial.read() is already handled by interrupts. When the handler is called, the status register is cleared and the received data pulled from UART_RHR :

thanks @ard_newbie - I will try to switch to Serial1 with RS485 - but still I can't find how can I handle UART with interrupt :confused:

If you want to make your own UART code (Serial) then you could start from here:

Uncomment UART_IER_TXRDY in UART->UART_IER and return 0 when necessary in uart_putchar