Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SoftwareSerial sends illegal characters after initialization #132

Open
thorv opened this issue Nov 10, 2023 · 0 comments
Open

SoftwareSerial sends illegal characters after initialization #132

thorv opened this issue Nov 10, 2023 · 0 comments

Comments

@thorv
Copy link

thorv commented Nov 10, 2023

I am using Arduino nano every, Board lib: Arduino megaAVR Boards 1.8.8.

I tried the following program:

#include <SoftwareSerial.h>

SoftwareSerial ser(4,5);

void setup() {
  Serial.begin(9600);
  Serial.println("START");
  Serial1.begin(9600);
  ser.begin(9600);
  ser.println("ABC");
  delay(10);
  ser.println("DEF");
}

void loop() {
  while(Serial1.available()){
    Serial.write(Serial1.read());
  }
}

The expectation is that "START(CR)ABC(CR)DEF(CR)" will be displayed, but what I actually got was the following:

START
P��H�DEF

This works fine:

void setup() {
  Serial.begin(9600);
  Serial.println("START");
  Serial1.begin(9600);
  pinMode(5,OUTPUT); //add
  digitalWrite(5,HIGH); //add
  ser.begin(9600);
  ser.println("ABC");
  delay(10);
  ser.println("DEF");
}

Looking inside SoftwareSerial.cpp, it looks like the following.

void SoftwareSerial::setTX(uint8_t tx)
{
  // comments omitted
  digitalWrite(tx, _inverse_logic ? LOW : HIGH);
  pinMode(tx, OUTPUT);
  _transmitBitMask = digitalPinToBitMask(tx);
  uint8_t port = digitalPinToPort(tx);
  _transmitPortRegister = portOutputRegister(port);
}

and in wiring_digital.c

void digitalWrite(uint8_t pin, PinStatus val)
{
	// omitted
	if(port->DIR & bit_mask){

		/* Set output to value */
		// omitted

	/* Input direction */
	} else {
		/* Old implementation has side effect when pin set as input -
		pull up is enabled if this function is called.
		Should we purposely implement this side effect?
		*/

		/* Get bit position for getting pin ctrl reg */
		uint8_t bit_pos = digitalPinToBitPosition(pin);

		/* Calculate where pin control register is */
		volatile uint8_t* pin_ctrl_reg = getPINnCTRLregister(port, bit_pos);

		/* Save system status and disable interrupts */
		uint8_t status = SREG;
		cli();

		if(val == LOW){
			/* Disable pullup */
			*pin_ctrl_reg &= ~PORT_PULLUPEN_bm;

		} else {
			/* Enable pull-up */
			*pin_ctrl_reg |= PORT_PULLUPEN_bm;
		}

		/* Restore system status */
		SREG = status;
	}

}

MegaAVR's digitalWrite() does not change the OUT register of PORT when pinMode is not OUTPUT (operation is different from UNO r3 etc.).
However, SoftwareSerial's setTx() function is written to set the OUT register to H level using digitalWrite() before setting pinMode to OUTPUT. As a result, the OUT register is not set, the output becomes L, and it seems that the appropriate output for the UART is not obtained.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant