Buffered UART routines
Posted: Wed Jan 13, 2016 10:59 am
Does anyone have any insight in to how to do a buffered serial transmit routine?
I thought I'd done one but I've just realised that it doesn't in fact work! The crux is the ISR code - I was wondering why my RS485 bus was going back to 0V after each byte. This is my ISR transmit code:
The intention was that I have a PutChar command (and various compound commands using that to write strings etc) which would fill the TXBuf array and the contents of this would be output one byte at a time by the ISR until the buffer was empty. At this stage the ISR would wait for the transmit shift register to empty and would re-enable the receiver.
The PutChar command sets TXIE so as soon as the first character is put in the buffer transmission starts.
Of course the issue is the double-buffering of the PIC UART. As soon as TXIE gets set the ISR code will execute, writing the top byte from the buffer to TXREG. This will get copied in to the transmit shift register at which point TXIF will be set again. The ISR will complete, exit and be called again before the main code has the chance to add anything else to the buffer. In effect you get stuck in the ISR until transmission has completed and TXIE gets cleared.
I guess one way to do this is to only set TXIE once writing to the buffer has completed but it is hard to know when this is the case if you are assembling a message from several bits of information. It also delays transmission.
Any ideas as to a neat way to do this?
I thought I'd done one but I've just realised that it doesn't in fact work! The crux is the ISR code - I was wondering why my RS485 bus was going back to 0V after each byte. This is my ISR transmit code:
Code: Select all
// Transmit interrupt. Output next character from transmit buffer
If TXIF = true And TXIE = true Then
If TXReadPtr = TXWritePtr Then // No more data waiting to be sent, wait for transmission to complete then enable RS485 receiver
If TXComplete Then // TRMT is clear - transmission is complete
TXIE = false // Disable interrupts
RS485REDE = 0 // Enable RS485 receiver
EndIf // Note that we will be stuck in the ISR until TRMT clears but at least other interrupts will be getting serviced
Else
RS485REDE = 1 // Enable transmitter
TXREG = TXBuf(TXReadPtr) // Write the byte at the read pointer to the transmit register
TXBufFull = false // Can't be full as we've just removed a byte
Inc(TXReadPtr) // Increment the pointer
TXReadPtr = TXReadPtr And TXBufMask // Mask pointer so it will loop.
EndIf
EndIf
The PutChar command sets TXIE so as soon as the first character is put in the buffer transmission starts.
Of course the issue is the double-buffering of the PIC UART. As soon as TXIE gets set the ISR code will execute, writing the top byte from the buffer to TXREG. This will get copied in to the transmit shift register at which point TXIF will be set again. The ISR will complete, exit and be called again before the main code has the chance to add anything else to the buffer. In effect you get stuck in the ISR until transmission has completed and TXIE gets cleared.
I guess one way to do this is to only set TXIE once writing to the buffer has completed but it is hard to know when this is the case if you are assembling a message from several bits of information. It also delays transmission.
Any ideas as to a neat way to do this?