Reading + Writing over Serial1

Hi, I don’t know much about hardware programming so bear with me :slight_smile:


I have some code that is communicating with an external ATMega8. I got this code from another programmer so I don’t understand it all (especially what the high/low does on the pin).

I’m seeing a weird issue (which is hard to reproduce). It seems like the code to read the incoming data is actually reading the data I sent out.

This makes me think of two possible reasons

  1. It is actually reading the data before it can be flushed
  2. The RX/TX buffers aren’t cleared after sending. When it starts reading some of the response bytes (I have some code that checks the format), the buffer looks like a complete.

My code basically looks like this:

// Pin on a P1
#define EXPANSION_BOX_PIN A0

void setup(void) {
    Serial.begin(115200);
    Serial1.begin(19200);

    /*RS485 direction pin*/
	pinMode(EXPANSION_BOX_PIN, OUTPUT);
	/*set RS485 direction pin LOW: receiver*/
	digitalWrite(EXPANSION_BOX_PIN, LOW);
}

void loop(void) {
  // My timer class that tells things to be re-sent
  myTimer.Tick();
  if (myTimer.ShouldReset()) {
    isWaitingForResponse = false;
  }

  if (isWaitingForResponse) {
    isWaitingForResponse = true;
    digitalWrite(EXPANSION_BOX_PIN, HIGH);
    Serial1.write(1); // I actually write out a full packet here with a specific format
    Serial1.flush();
    digitalWrite(EXPANSION_BOX_PIN, LOW);

  }
}

void serialEvent1()
{
  if (!isWaitingForResponse) {
    return;
  }

  while(Serial1.available()) {
  	Serial1.read(); // Read the response packet.
  }

  isWaitingForResponse false;
}


// Including this just in case it matters...
#define SERIA1_BUFFER_SIZE 129
HAL_USB_USART_Config acquireUSBSerial1Buffer()
{
  HAL_USB_USART_Config conf = {0};

  // The usable buffer size will be 128
  static uint8_t usbserial1_rx_buffer[SERIA1_BUFFER_SIZE];
  static uint8_t usbserial1_tx_buffer[SERIA1_BUFFER_SIZE];

  conf.rx_buffer = usbserial1_rx_buffer;
  conf.tx_buffer = usbserial1_tx_buffer;
  conf.rx_buffer_size = SERIA1_BUFFER_SIZE;
  conf.tx_buffer_size = SERIA1_BUFFER_SIZE;

  return conf;
}

What I’m wondering is if I could use halfDuplex and get rid of all this logic I’ve added to make sure I’m never reading/writing at the same time?

By the looks of things the HIGH/LOW pin is an output on your that is being used (in theory) by the code on the ATmega so it knows its about to get some data. This would make it work a little like I2C - something you could read up on and copy.

If you are indeed using RS485 as indicated by the code comments half-duplex and a clear master-slave relationship between the two devices is indeed much simpler.

Of course there are all sorts of other things that could be going on depending on how the hardware is setup and what the code really looks like rather than this highly edited version.

Thanks. As I’ve been working through this code, it really seemed like the two-way communication should already be a solved problem. That’s why I was thinking about using the half-duplex.

Yes, this is a master/slave scenario and I’m pretty sure it’s using RS485.
If I do use that, would I need to still set the HIGH/LOW pins?


In case you’re interested in the real code…

main/loop setup code
Packet writing code
Packet reading code
Logic for switching from read/write modes