Setup for UART Transmit

The following procedure is used to transmit a byte of data:

  1. Configure the clock input and baud rate as detailed in Clocking and Baud Rate Configuration.
  2. Configure the data width and parity by writing a selection to the MODE[3:0] bits.
  3. Configure the polarity, Stop bit duration and flow control.
  4. Configure the TX interrupt watermark using the TXWM[2:0] bits (UxSTAT[30:28]).
  5. Configure the address detect if needed as detailed in Address Detect.
  6. Set the ON bit (UxCON[15]).
  7. Set the TXEN bit (UxCON[5]).
  8. Write the data byte value to the UxTXB register.

A TX interrupt will be generated according to the TXWM[2:0] bits’ interrupt watermark setting. The TXWMx bits can be configured to generate a TX interrupt when the buffer has one to eight empty slots.

The UARTx Transmit Buffer (UxTXB) has two associated flags to indicate its contents. The TX Buffer Empty Status bit, TXBE (UxSTAT[21]), indicates that the buffer is empty, and the TX Buffer Full Status bit, TXBF (UxSTAT[20]), indicates that there are no empty slots in the buffer, and it should not be written.

UART1 Transmission with Interrupts

#include <xc.h>

//Clock settings for CPU @8MHz, UART1 clocked from 1/2 speed peripheral bus @4MHz
#define FUART 4000000
#define BAUDRATE 9600
//Baud rate calculation for fractional baud rate divider
#define BRGVAL (FUART/BAUDRATE)

#define TRANSMIT_CHAR_SIZE 16
uint8_t transmitChar[TRANSMIT_CHAR_SIZE] = "ABCDEFGHIJKLMNOP";
uint8_t transmitCount = 0;


int main(void) {    
    
    //Configure I/O
    _RP114R = _RPOUT_U1TX;     //Assign UART1 TX output functionality to RP114 (RH1)
    _TRISH1 = 0;               //Set RH1 as output

    U1CONbits.MODE = 0;       // Asynchronous 8-bit UART
    U1CONbits.CLKSEL = 0;     // FPB/2 as Baud Clock source
    U1CONbits.STP = 0;        // 1 stop bit

    //Use fractional baud rate divider
    U1CONbits.CLKMOD = 1;   
    U1BRG = BRGVAL;          // Baud Rate setting for 9600

    U1STATbits.TXWM = 0;     // Interrupt when TX buffer is empty (8 empty slots)
    IEC3bits.U1TXIE = 1;     // Enable Transmit interrupt
    
    U1CONbits.ON = 1;        // Enable UART
    U1CONbits.TXEN = 1;      // Enable UART TX. This generates TX interrupt.
    
    while(1) {
        //Re-transmit periodically
        if (IEC3bits.U1TXIE == 0) { //Check if TX interrupt was disabled
            //Delay
            for (uint16_t i = 0; i < 0x1234; i++);
            //Re-enable TX interrupt to resume transmission
            IEC3bits.U1TXIE = 1;
        }
    }
    
    return 0;
}

void __attribute__((interrupt)) _U1TXInterrupt(void)
{ 
    IFS3bits.U1TXIF = 0;                   // Clear TX interrupt flag
    U1TXB = transmitChar[transmitCount++]; // Transmit one character
    
    if (transmitCount >= TRANSMIT_CHAR_SIZE) {
        transmitCount = 0;
        //Stop transmitting by disabling the TX interrupt.
        IEC3bits.U1TXIE = 0;
    }
}