Arduino Due TXD3 & RXD3 to use as serial ports

Hi,

I have a question about the USART ports on the Arduino Due (ATSAM3X8E). According to the ATSAM datasheet, there are two pins (PB20 and PB21, pin number 91 and 92) that are USART pins. I have an XBEE module that I need to connect to these two pins (I know there are other TXDs available on the board, they're being used already) to send and receive data to the MCU. Is there a way to access these pins and use them for serial comms?

Thanks

Hi,

Don't have much experience with the Deu, but to mee it looks like:
On the Due's page it says:
"Serial: 0 (RX) and 1 (TX)
Serial 1: 19 (RX) and 18 (TX)
Serial 2: 17 (RX) and 16 (TX)
Serial 3: 15 (RX) and 14 (TX) "
So my guess is:

#include <SoftwareSerial.h>

SoftwareSerial mySerial(15, 14); // RX, TX

But not sure how to use it in combo with the other 2 UART signals.

Good luck

I don't think there is a version of SoftwareSerial for Due, is there?

To use the fifth hardware serial port, you would have to create one, I think this is possible in user code:

I'll call it Serial4, it actually uses USART2 in the Due.

// Create a new Serial port on pins 91 & 92
// Note : SerialEvent will not be called for Serial4.

RingBuffer rx_buffer5;

USARTClass Serial4 (USART2, USART2_IRQn, ID_USART2, &rx_buffer5);

// IT handlers
extern "C" void USART2_Handler(void)
{
  Serial4.IrqHandler();
}

void setup () {
  // Initialize USART pins for Serial4

  PIO_Configure(PIOB, PIO_PERIPH_A, PIO_PB20A_TXD2 | PIO_PB21A_RXD2, PIO_DEFAULT);

}

I haven't tried it :slight_smile: Hopefully the core does enough initialisation to allow this to work, there may need to be some other stuff to set up.

Let us know if it works or not...

ETA: there was other stuff, maybe still some more...? At least it builds.

bobcousins:
I don't think there is a version of SoftwareSerial for Due, is there?

To use the fifth hardware serial port, you would have to create one, I think this is possible in user code:

I'll call it Serial4, it actually uses USART2 in the Due.

// Create a new Serial port on pins 91 & 92

// Note : SerialEvent will not be called for Serial4.

RingBuffer rx_buffer5;

USARTClass Serial4 (USART2, USART2_IRQn, ID_USART2, &rx_buffer5);

// IT handlers
extern "C" void USART2_Handler(void)
{
  Serial4.IrqHandler();
}

void setup () {
  // Initialize USART pins for Serial4

PIO_Configure(PIOB, PIO_PERIPH_A, PIO_PB20A_TXD2 | PIO_PB21A_RXD2, PIO_DEFAULT);

}




I haven't tried it :) Hopefully the core does enough initialisation to allow this to work, there may need to be some other stuff to set up.

Let us know if it works or not...

ETA: there was other stuff, maybe still some more...? At least it builds.

That actually worked, thanks a lot. Well, by worked I mean I have managed to access those pins and send something to it with Serial4.print().
Now one question, when you say SerialEvent won't be called, do you mean when Serial4 receives data nothing would happen? As in I won't be able to use Serial4.available()?

mhmani21:
That actually worked, thanks a lot. Well, by worked I mean I have managed to access those pins and send something to it with Serial4.print().
Now one question, when you say SerialEvent won't be called, do you mean when Serial4 receives data nothing would happen? As in I won't be able to use Serial4.available()?

Glad to know it worked :slight_smile:

serialEventx is an optional feature. It is a call back function provided by the user, it is called when a serial port has data available. But you don't need to use it; all the other functions like Serial4.available() should still work.

The Due core code only calls serialEventx for the Serial objects it has created. I think this could be overridden by the user, but it seems this feature only saves half a line of code and is only supported on a couple of platforms.

bobcousins:
Glad to know it worked :slight_smile:

serialEventx is an optional feature. It is a call back function provided by the user, it is called when a serial port has data available. But you don't need to use it; all the other functions like Serial4.available() should still work.

The Due core code only calls serialEventx for the Serial objects it has created. I think this could be overridden by the user, but it seems this feature only saves half a line of code and is only supported on a couple of platforms.

Dude, you have no idea how much trouble you saved me from XD

It seems like everything is working and well; so thank you :slight_smile:
By the looks of it, I don't need the serialEventx at all as everything is working now, so I'm not even gonna bother with that :wink:

Hi,

as this old topic provided a great support to my problem, I would like to share necessary modifications to make Serial4 on the Due work in the year 2019.

It seams like the USARTClass has been modified and now the constructor requires more inputs. So the orignal code from bobcousins doesn't compile without errors.

However, fixing is easy:

  • add a second RingBuffer for TxD
  • add this new buffer to the argument list at the USARTClass constructor

Here is my code that I used to test the Serial4:

#include <Arduino.h>

// Create a new Serial port on pins 91 & 92
// Note : SerialEvent will not be called for Serial4.
RingBuffer rx_buffer5, tx_buffer5;
USARTClass Serial4 (USART2, USART2_IRQn, ID_USART2, &rx_buffer5, &tx_buffer5);

// IT handlers
extern "C" void USART2_Handler(void)
{
  Serial4.IrqHandler();
}

void setup () {
	// Initializing Serial for debug information and bi-directional communication tests.
	Serial.begin(115200);
	Serial.println("--- Here we go! (on Serial) ---");

  // Initialize USART pins for Serial4
  PIO_Configure(PIOB, PIO_PERIPH_A, PIO_PB20A_TXD2 | PIO_PB21A_RXD2, PIO_DEFAULT);
	Serial4.begin(115200);
	Serial4.println("--- Here we go! (on Serial4) ---");
	
}

void loop() {
	static uint32_t loopCounter = 0;
	static uint32_t timeStamp = millis();
	
	// Bi-directional communication that sends each byte received by one serial port to the other
	if (Serial.available()) {
		int inByte = Serial.read();
		Serial4.write(inByte);
	}
	if (Serial4.available()) {
		int inByte = Serial4.read();
		Serial.write(inByte);
	}
	
	if ( ( millis() - timeStamp ) >= 1000 ) {
	  timeStamp  = millis();
	  Serial.println("- Serial: run #" + String(loopCounter) );
		Serial4.println("- Serial4:  run #" + String(loopCounter) );
		loopCounter++;
	}
}

The Serial Console for the classic Serial (TxD0 at Pin1 and RxD0 at Pin0 via USB cable per Arduino Due Programming Port) looks like this:

--- Here we go! (on Serial) ---
- Serial: run #0
Hello from Serial4
- Serial: run #1
- Serial: run #2
- Serial: run #3
- Serial: run #4
- Serial: run #5
- Serial: run #6
- Serial: run #7
- Serial: run #8
- Serial: run #9

The prints at the new Serial4 (TxD4 on Pin65 (A11) and RxD4 on Pin52) looks like this:

--- Here we go! (on Serial4) ---
- Serial4:  run #0
- Serial4:  run #1
- Serial4:  run #2
- Serial4:  run #3
- Serial4:  run #4
Hello from Serial
- Serial4:  run #5
- Serial4:  run #6
- Serial4:  run #7
- Serial4:  run #8
- Serial4:  run #9

The "Hello from SerialX" messages has been send manually from the other port.

Hope it helps.. Marco