Serial1.flush() Problems

rekcut

Member
Hey guys,

The Serial1.flush() function isn't doing what its supposed to be doing by waiting for the TX buffer to be empty... Any fixes for this?

Best,
rekcut
 
Forum rule: post detail/specifics, code that causes problem, and steps to reproduce it.

As I see the code, the flush() does not truncate the current buffer. It waits for that to empty into the UART's FIFO. And some interrupts from the UART may occur.
 
Last edited:
Steve is right, without more information it's impossible to help you more than by simply saying "it should work".

Serial1.end() seems to do the same thing as flush(), it waits for (transmitting == 0).
 
so basically I'm using an RS485 bi-directional transceiver chip which you have to enable with an external pin. Here is the basic code I am using to see whether or not the flush is working. However, flush is returning early and the RS485 chip is being set to RX mode before it should.

int temp;
int k = 0;
char array[5] = {0x3A,0xD8,0x00,0x01,0xE9};
//char array[8] = {0xD,0x8,0x0,0x0,0x0,0x1,0xE,0x9};
char inchar[5]={0};
void setup()
{
Serial1.begin(19200);
Serial.begin(19200);
pinMode(13,OUTPUT);
}
void loop()
{

if(k==0)
{
delay(3000);
digitalWrite(13,HIGH);
for(int i=0;i<5;i++)
{
Serial1.print(array);
}
digitalWrite(13,LOW);
k++;
}
Serial1.flush();
temp = Serial1.available();
if(temp > 0)
{
digitalWrite(13,HIGH);
Serial1.println("hi");
Serial1.flush();
digitalWrite(13,LOW);
}
}
 
Yes, the flush or end code does not wait for the UART's shift register to finish. The shift register is fed by the UART's FIFO (if FIFO mode is enabled).

What you want can be done, with added code that looks at certain UART status bits to see that the FIFO is empty and the dual-rang shift register is empty and the final stop bit has been sent. Or you can kludge in a time delay after the flush, where the delay is baud-rate dependent
 
Last edited:
Where would I find a datasheet to look at the status control registers to do that? I'm familiar with how to do what i want with the ATmega328p but not with the Teensy's micro-controller.
 
I'd give this a try right now, except I can't see any mention of which Teensy board you're using. I have them all right here, but which one should I hook up to test with your code?


so basically I'm using an RS485 bi-directional transceiver chip which you have to enable with an external pin.

Teensy has an undocumented Serail1.transmitterEnable(pin) which is meant for automatically controlling the pin.

Still, this approach with flush() should work. I'll test it here, but only if you tell me which board you're using!
 
I tried this on a Teensy 3.1.

The problem is with your code. You're calling digitalWrite(13,LOW) before Serial1.flush(), which turns off the transmitter before even the first bit is completed.

Serial1.flush() does work properly. You simply need to mode digitalWrite(13,LOW) after Serial1.flush(), so the transmitter remains on.

Here's a modified program:

Code:
char array[5] = {
  0x3A,0xD8,0x00,0x01,0xE9};
void setup()
{
  Serial1.begin(19200);
  Serial.begin(19200);
  pinMode(13,OUTPUT);
}
void loop()
{
    delay(100);
    digitalWrite(13,HIGH);
    for(int i=0;i<5;i++) {
      Serial1.print(array[i]);
    }
    Serial1.flush();
    digitalWrite(13,LOW);
}

Here are the waveforms on pins 1 and 13:

scope_13.png

You can also get a similar result with this code:

Code:
char array[5] = {
  0x3A,0xD8,0x00,0x01,0xE9};
void setup()
{
  Serial1.begin(19200);
  Serial1.transmitterEnable(13);
  Serial.begin(19200);
}
void loop()
{
    delay(100);
    for(int i=0;i<5;i++) {
      Serial1.print(array[i]);
    }
}
 
I'm using the teensy 3.1, and yes that was a problem in the code. But the greater issue is when checking Serial1.available() right after you use serial flush... Here is the code in part of my big project I'm working on... I get an overflow issue when printing one of the errors because Serial1.flush() doesnt wait for all of the data to send.

int temp;
int k = 0;
char array[5] = {0x3A,0xD8,0x00,0x01,0xE9};
//char array[8] = {0xD,0x8,0x0,0x0,0x0,0x1,0xE,0x9};
char inchar[5]={0};
void setup()
{
Serial1.begin(19200);
pinMode(13,OUTPUT);
}
void loop()
{
char inChar = -1;
byte numBytesAvailable = 0;
int ValidCmd = 0;
numBytesAvailable = Serial1.available();
char cmdword[4]={
0x3,0xA,0xD,0x8 };

if (numBytesAvailable > 0)// if there is something to read
{
int i;
int j = 0;
if(numBytesAvailable == 5)
{

for (i = 0; i < numBytesAvailable; i++)// store everything into "inChar"
{
inChar = Serial1.read();
}
}

else if(numBytesAvailable > 5)
{
// Error Code - Received Command Word is too Long
char temp[5] = {
0x3A,0x79,0x00,0x02,0xEE };
digitalWrite(13,HIGH);
for(int i=0;i<5;i++)
{
Serial1.print(temp,HEX);
Serial1.flush();
}
digitalWrite(13,LOW);
}
else if(numBytesAvailable < 5 && numBytesAvailable > 0)
{
// Error Code - Received Command Word is too Short
char temp[5] = {
0x3A,0x79,0x00,0x01,0xEF };
digitalWrite(13,HIGH);
for(int i=0;i<5;i++)
{
Serial1.print(temp,HEX);
Serial1.flush();
}
digitalWrite(13,LOW);
}
}
}
 
Last edited:
I get an overflow issue when printing one of the errors because Serial1.flush() doesnt wait for all of the data to send.

I believe the oscilloscope waveform proves Serial1.flush() does indeed wait for all of the data to send.

Perhaps the error is due to some other cause?
 
Your program's logic, in reply #10, appears to be flawed.

Each time loop() runs, you're calling Serial1.available(). If any data is available, you're running one of three chunks of code.

In order:

#1: If there's more than 5 bytes, you're considering that an error.

#2: If there's exactly 5 bytes, you consider the input correct.

#3: If there's fewer than 5 bytes, you consider the input to be an error!

This seems like deeply flawed logic. How can condition #1 or #2 occur? Since the data arrives at a fairly slow baud rate, and the odds are almost certain that fewer than 5 bytes will be available for quite some time before all 5 appear. But your code in #3 turns on the transmitter, which will prevent any more data from being received.

I'm certain Serial1.flush() is working correctly.

The error is in your code.
 
Hmm... the logic of the code is fine because I'm using if() else if() statements... when one matches it should automatically jump out of them. It seems that the Bi-directional chip I was using was creating some sort of feedback to the receive pin on the Teensy... just took care of the problem by doing a little Serial.clear() after sending my error code. Thank you for the help guys, especially Paul for sending me the scope pics. :) Here is my fixed code to get rid of the issue.

int temp;
int k = 0;
char array[5] = {0x3A,0xD8,0x00,0x01,0xE9};
//char array[8] = {0xD,0x8,0x0,0x0,0x0,0x1,0xE,0x9};
char inchar[5]={0};
void setup()
{
Serial1.begin(19200);
pinMode(13,OUTPUT);
}
void loop()
{
char inChar = -1;
byte numBytesAvailable = 0;
int ValidCmd = 0;
numBytesAvailable = Serial1.available();
char cmdword[4]={
0x3,0xA,0xD,0x8 };

if (numBytesAvailable > 0)// if there is something to read
{
delay(30);
numBytesAvailable = Serial1.available();
int i;
int j = 0;
if(numBytesAvailable == 5)
{

for (i = 0; i < numBytesAvailable; i++)// store everything into "inChar"
{
inChar = Serial1.read();
}
}

else if(numBytesAvailable > 5)
{
// Error Code - Received Command Word is too Long
char temp[5] = {
0x3A,0x79,0x00,0x02,0xEE };
digitalWrite(13,HIGH);
for(int i=0;i<5;i++)
{
Serial1.print(temp,HEX);
Serial1.flush();
}
Serial1.clear();
digitalWrite(13,LOW);
}
else if(numBytesAvailable < 5 && numBytesAvailable > 0)
{
// Error Code - Received Command Word is too Short
char temp[5] = {
0x3A,0x79,0x00,0x01,0xEF };
digitalWrite(13,HIGH);
for(int i=0;i<5;i++)
{
Serial1.print(temp,HEX);
Serial1.flush();
}
Serial1.clear();
digitalWrite(13,LOW);
}
}
}
 
Back
Top