Difficulty turning around RS485 half duplex from TX to RX | Cypress Semiconductor
Difficulty turning around RS485 half duplex from TX to RX
(((QUICK TAKE HOME: Always do "rxStatus = UART_1_RXSTATUS_REG" after calling UART_LoadRxConfig() function.)))
I'm using a PSoC5, RS485 TX/RX interface chip (ST1480ABDR), and UART component version 2.10 configured in half duplex mode.
In general, I can transmit and receive just fine. Also, note that the UART component tx_en output goes to a PSoC5 chip pin and to my RS485 TX/RX chip, *properly* controlling the physical direction of the lines. So physical line turnaround works correctly.
However, I have a turnaround problem inside the PSoC5. On power up, I configure for transmit and send out a version number to let my host PC know the target is alive. Then I turn the channel around for receive. I'm typing slow by hand on the host, but regardless I *miss* the first char. I type a CR/LF and my software recognizes a "command" from the host. My software turns the channel around and echoes out the command. This is one way I know I missed the first char. I then turn the channel around yet again to start receiving. Yet again, I miss the first character typed. In general, every time I turn around from TX to RX, I miss the first character in RX. I can see the char on the scope, so I know my physical line is working. Also, I'm should be using UART_LoadTxConfig() and UART_LoadRxConfig() properly.
Debugging, I discover the following. I do indeed get an interrupt for that first character. I trace inside UART_GetChar() and discover that I really do get the character itself as well. However, immediately after this, this UART_GetChar() code checks rxstatus. It turns out that rxstatus has the UART_RX_STS_BREAK bit set. Seeing this, the code replaces the properly recieved char with a zero, and my code then thinks UART_GetChar() had nothing to return.
So it appears that I'm getting a "break" status after turning the line around from TX to RX. I tried two things. The second worked, but I would prefer the first to work. The second thing I tried was to do "rxStatus = UART_1_RXSTATUS_REG" *inside* the interrupt routine immediately before my call to UART_GetChar(). This effectively cleared the break condition prior to UART_GetChar(), so that UART_GetChar() followed through with returning that first char to me. In fact, I set a one-time flag so that I only do this "rxStatus = UART_1_RXSTATUS_REG" during the first interrupt after I turn the line around. So this works.
But the first thing I tried should be more appropriate. I tried many things when I turned the line around, but none worked. In detail, I tried UART_1_ClearRxBuffer(), UART_1_ReadRxStatus(), and UART_1_GetChar().
CONFUSING SUCCESS: While writing up to this point right here, the above was the case. But I thought of a third thing to do. I was trying my first thing immediately *before* the UART_LoadRxConfig(). Instead, I tried "rxStatus = UART_1_RXSTATUS_REG" immediately *after* the UART_LoadRxConfig(). This is now working properly and it's in a code location that makes sense. That it, it's immediately after turning the line around rather than upon the first receipt of a character interrupt.
So it turns out I've got things working to my satisfaction. But I still want to "know", and I'll still post in case this helps others in the future. What I want to know is this: Why am I getting a break after turning the line around from TX to RX? I'm pretty sure that no actual break is occurring. Should UART_LoadRxConfig() be modified to clean up this little snafu? Or is there something ELSE I should be doing to keep this from happening?
Thanks very much.