Go Down

Topic: Arduino DUE - read serial in interupt  (Read 205 times) previous topic - next topic

lonas

May 23, 2017, 08:51 pm Last Edit: May 23, 2017, 09:15 pm by lonas
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 https://github.com/SlashDevin/NeoHWSerial - 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:

Code: [Select]

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
^

Delta_G

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?
If at first you don't succeed, up - home - sudo - enter.

Robin2

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
Two or three hours spent thinking and reading documentation solves most programming problems.

ard_newbie


MarkT

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 will NOT respond to personal messages, I WILL delete them, use the forum please ]

lonas

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.

lonas

#6
May 24, 2017, 01:51 pm Last Edit: May 24, 2017, 02:12 pm by lonas
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

Code: [Select]

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


ard_newbie


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

Code: [Select]

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;
      }
    }
  }
}






lonas

#8
May 24, 2017, 05:43 pm Last Edit: May 24, 2017, 05:54 pm by lonas
@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 ?

Code: [Select]

  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


ard_newbie


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().


lonas

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


ard_newbie


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).

lonas

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

Code: [Select]
void UART_Handler(void) __attribute__((weak));
void UART_Handler(void) {
  Serial.IrqHandler();
  Serial.print(Serial.read());
}

ard_newbie


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 :
https://github.com/arduino/ArduinoCore-sam/tree/master/cores/arduino

Go Up