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?