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?