I was making a circuit transmitting data over RS485. I couldn’t get the transmissions to be complete – the best I could get was the last character would always be chopped. I was checking for when both TXC and UDRE bits are 1’s, and I could see on the scope, the TX/RX switch would always be thrown before the last character. I compiled the code into assembly, to make sure the optimization wasn’t cutting corners, and it wasn’t. The datasheet says:
This flag bit is set when the entire frame in the Transmit Shift Register has been shifted
out and there are no new data currently present in the transmit buffer (UDR).
But it was still not working properly. I finally googled up what was the problem. User snarflemike in an avrfreaks post suggested that:
You have to reset TXC0 manually unless you have a TXCIE0 interrupt, which will reset TXC0 automatically. If you don’t reset TXC0 at the end of your transmission (and I don’t see your code doing that), on the next transmission it will still be set and your loop that tests it will immediately fall through, not waiting for the last character to be sent.
And, well, turns out if you actually read past the first sentence in the datasheet, it says so clearly enough:
The TXC Flag bit is automatically cleared when a transmit complete interrupt is executed, or it can be cleared by writing a one to its bit location.
Oh well, if you run into this yourself, perhaps you’ll find it sooner here than it took me to find it there.
So, basically, it’s enough to check the TXC bit (not the UDRE, kids!) after you reset it (writing a 1 into it) before the transmission starts.