Serial3.begin() stops to receive data from Serial1

We have an ATMega2560 with the following, rather simple test application:

#define VARIANT_SERIAL_1_ONLY     1
#define VARIANT_SERIAL_3_ONLY     2
#define VARIANT_SERIAL_1_PLUS_3   3
#define VARIANT_TOGGLE_SERIALS    4


unsigned long	g_uLastSendSerial1 = 0;
unsigned long	g_uLastSendSerial3 = 0;

unsigned long	g_uLastDebugOutput = 0;

unsigned long	g_uSerial1Received = 0;
unsigned long	g_uSerial3Received = 0;

unsigned char	g_uToggle = 0;
unsigned char g_uVariant = VARIANT_TOGGLE_SERIALS;


void setup( void )
{
	ConfigurePortC();

	// it does not seem to matter whether UART0 is enabled or not
	Serial.begin( 115200 );

  if( g_uVariant == VARIANT_SERIAL_1_ONLY || g_uVariant == VARIANT_SERIAL_1_PLUS_3 || g_uVariant == VARIANT_TOGGLE_SERIALS )
  {
  	// we need UART1
  	Serial1.begin( 115200 );
  }
  
	// it does not seem to matter whether UART2 is enabled or not
	Serial2.begin( 115200 );

  if( g_uVariant == VARIANT_SERIAL_3_ONLY || g_uVariant == VARIANT_SERIAL_1_PLUS_3 || g_uVariant == VARIANT_TOGGLE_SERIALS )
	{
	  // we need UART3
	  Serial3.begin( 115200 );
  }

} // setup


void loop()
{
	if( (GetMillis() - g_uLastDebugOutput) > 1000 )
	{
		g_uLastDebugOutput = GetMillis();

		Serial.print("Serial 1: ");
		Serial.print(g_uSerial1Received);
		Serial.println();
		Serial.print("Serial 3: ");
		Serial.print(g_uSerial3Received);
		Serial.println();

    if( g_uVariant == VARIANT_TOGGLE_SERIALS )
    {
  		if( g_uToggle )
  		{
  			Serial.print("Serial3 end");
  			Serial.println();
  
  			Serial3.end();
  		}
  		else
  		{
  			Serial.print("Serial3 begin");
  			Serial.println();
  
  			Serial3.begin( 115200 );
  		}
  		g_uToggle = !g_uToggle;
  	}
	}
 
	ReadSerial1();
	ReadSerial3();

	if( (GetMillis() - g_uLastSendSerial1) > 100 )
	{
		unsigned char aCommand[5]      = { 1, 2, 3, 4, 5 };


		g_uLastSendSerial1 = GetMillis();
		Serial1.write( aCommand, 5 );
	}

	if( (GetMillis() - g_uLastSendSerial3) > 250 )
	{
    unsigned char aCommand[5]      = { 1, 2, 3, 4, 5 };


		g_uLastSendSerial3 = GetMillis();

		Serial3.write( aCommand, 5 );
	}

} // loop


void ReadSerial1( void )
{ 
	unsigned char	uByte;


	while( Serial1.available() > 0 )
	{
		g_uSerial1Received ++;

		uByte = Serial1.read();
	}

} // ReadSerial1


void ReadSerial3( void )
{ 
	unsigned char	uByte;


	while( Serial3.available() > 0 )
	{
		g_uSerial3Received ++;

		uByte = Serial3.read();
	}

} // ReadSerial3


unsigned long GetMillis( void )
{
    return millis();
    
} // GetMillis


void ConfigurePortC( void )
{
	DDRC  = 0b00111111;
	PORTC = 0b00000100;

} // ConfigurePortC

Depending to how we set g_uVariant, we receive the following outputs:

unsigned char g_uVariant = VARIANT_SERIAL_1_ONLY;
Serial 1: 92
Serial 3: 0
Serial 1: 322
Serial 3: 0
Serial 1: 552
Serial 3: 0
...
unsigned char g_uVariant = VARIANT_SERIAL_3_ONLY;
Serial 1: 0
Serial 3: 66
Serial 1: 0
Serial 3: 154
Serial 1: 0
Serial 3: 242
...

The above cases are clear and expected ... but the next one is bothering us extremely:

unsigned char g_uVariant = VARIANT_SERIAL_1_PLUS_3;
Serial 1: 0
Serial 3: 66
Serial 1: 0
Serial 3: 154
Serial 1: 0
Serial 3: 242

In fact we do not receive any byte from Serial1 in case Serial3 is active (= between Serial3.begin() and Serial3.end().
The final variant seems to prove clearly that Serial1 is working or not working depending to whether Serial3 is active:

unsigned char g_uVariant = VARIANT_TOGGLE_SERIALS;
Serial 1: 0
Serial 3: 66
Serial3 begin
Serial 1: 0
Serial 3: 154
Serial3 end
Serial 1: 230
Serial 3: 154
Serial3 begin
Serial 1: 230
Serial 3: 242
Serial3 end
Serial 1: 460
Serial 3: 242
Serial3 begin
Serial 1: 460
Serial 3: 330
Serial3 end
...

We do not think that the pins of Serial3 and Serial1 are connected but we are going to check the Tx and Rx pins of Serial1 in a next step (at the board of interest, we do not have good access to these lines). We think to have checked everything else at the board already ... and we think that this simple sketch does not contain anything which should cause this effect.
We are glad about any hint about what could be wrong here ... does anybody have any piece of clue about what we could do wrong here and/or about how we could use Serial1 and Serial3 in parallel here?

Thanks in Advance,
Markus

What is connected to what? Please post a wiring diagram.

What happens to

  while ( Serial3.available() > 0 )
  {
    g_uSerial3Received ++;
    uByte = Serial3.read();
  }

When Serial3.begin() has not been called?(same question for Serial1)
I'd sort of expect undefined behaviour.
Because both are executed in loop() unconditionally.

  ReadSerial1();
  ReadSerial3();

I think I can not post the original schematics ... but under the line, Serial1 is connected to UART1 (PA9/PA10) of a STM32F3 and Serial3 is connected to UART4 (PC10/PC11) of a STM32F4.
The ATMega2560 has a VCC of 5V, the two STM32 have a VCC of 3,3V.

There are level shifters between the STM32F3 and the ATMega2560:

  • ATMega2560 Tx - NC7SZ08M5XCT-ND - STM32F3 Rx
  • STM32F3 Tx - ATMega2560 Rx

As far as I can see, there is no level shifter between the STM32F4 and the ATMega2560 (but remember, we run into the issue with the Serial1 which is connected to the STM32F3).

At the moment, we do not receive anything from the remote counterparts when they do not receive our requests. Thus, we do not receive any byte when we do not call begin() (and/or when we do not send the proper commands). This can be seen also in the VARIANT_SERIAL_1_ONLY and VARIANT_SERIAL_3_ONLY cases ... there, only Serial1 or only Serial3 deliver data.

A level shifter is required when you connect 5V I/O to 3.3V I/O. Otherwise, expect malfunctions to occur anywhere in the system. All bets are off until that is fixed.

OK ... we have condensed this issue to the following:

if( g_uToggle )
{
	Serial.print("Serial3 end");
	Serial.println();
  
	//Serial3.end();
	cbi(UCSR3B, TXEN0); // this brings the level of RxD1 (!) from about 3.5 ... 4 V back to from 0 ... 3.3 V
}
else
{
	Serial.print("Serial3 begin");
	Serial.println();
  
	//Serial3.begin( 115200 );
	sbi(UCSR3B, TXEN0); // this changes the level of RxD1 (!) from 0 ... 3.3 V to about 3.5 ... 4 V
}
g_uToggle = !g_uToggle;

We have no fast option to add the level shifter between our TxD and the RxD (and vice versa) of the two STM32 but we are going to check out this approach in parallel.
However, is there any idea why a change of the TXEn Bit of UART3 can change the level at our RxD1?

:frowning:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.