Does there exist (any user developed etc.) version of the Hardware UART serial library that has support for RTS/CTS based flow control? More interested in the Tx side (Arduino sends data, while the peripheral can back-pressure). The library should enable the Arduino to stop transmitting within 1 character of seeing a 'not ready' indication from the peripheral.
Thank you.
-
This library may help for the AVR-based Arduinos: github.com/i-am-bigmike/HardwareSerial_flow_controlMV.– MV.2021年05月31日 10:48:06 +00:00Commented May 31, 2021 at 10:48
3 Answers 3
I am not aware of any such library. You could try to implement one yourself, and maybe share it with the community. :-)
If you take this route, you will have to copy the file HardwareSerial.cpp from the Arduino core, make your changes there, and have your version replace the one from the core. Here are some ideas that may help to get you started:
- Wire the 'ready' signal from the device to an interrupt-capable pin of the Arduino.
- Inside the interrupt handler:
- when 'ready' is deasserted, disable the UDRE interrupt by issuing
cbi(*_ucsrb, UDRIE0)
- when ready is asserted, enable it again, but only if the output
buffer is not empty:
if (_tx_buffer_head != _tx_buffer_tail) sbi(*_ucsrb, UDRIE0);
- when 'ready' is deasserted, disable the UDRE interrupt by issuing
- Patch
HardwareSerial::write()
to enable the interrupt only if 'ready' is asserted. - Note that the UDRE IRQ can be explicitly called
by
HardwareSerial::flush()
and byHardwareSerial::write()
if interrupts are globally disabled. You will have to condition this on the 'ready' signal. - Note also that
HardwareSerial::write()
can write directly to the UART if the buffer is empty. This also has to be conditioned on the 'ready' signal.
I believe that CTS would be fairly easy to implement:
void loop() {
uint8_t clear_to_send = digitalRead(CTS);
volatile char data;
if (clear_to_send) {
Serial.write(data);
}
}
I'm not sure about RTS.
-
2This wont work to stop the transmission within a one (or even a few) characters, because although you stopped the Serial.write, there may already be data in the serial buffer (default 64bytes I think in Arduino lib) that could continue to go out (and potentially lost). Anyways, I shifted to Teensy, which has hardware based RTS/CTS flow control, so it is capable of stopping as soon as (i believe 1 character) CTS is deassertedO.K.– O.K.2016年08月02日 03:39:24 +00:00Commented Aug 2, 2016 at 3:39
-
Hardware USART is better for sure. Though, you could flush the buffer Serial.flush() after every write and store the last sent byte to be sent later.woo2– woo22016年08月02日 03:46:27 +00:00Commented Aug 2, 2016 at 3:46
-
I'd be surprised if there is no Arduino implementation. Usually, the (hardware) send buffer on an UNO is, I believe, 1 byte. The Arduino serial wrapper has it's own software buffer implemented. You could change it there. But you may have to retrigger the sending manually (since I think they use the "tx complete interrupt" to wait for the next possible send, which won't happen if you stop the sending)aaa– aaa2016年11月30日 07:04:00 +00:00Commented Nov 30, 2016 at 7:04
I have I discovered that RTS/CTS may be implemented in genuine Arduinos, but is not supported by Arduinos that use the CH340 USB to serial chip. I found this when my JAVA program could talk with a genuine Uno ok, but didn't send any data to several Arduino compatibles that use the CH340 chip (but did receive from them). I had RTS/CTS set on the JAVA program. When I changed it to FLOWCONTROL_NONE it started working just fine.