UART interfacing with pic microcontroller

In: Project Code: PE000005

In this project we will interface uart with PIC16F877A microcontroller and communicate with the microcontroller from a computer. If you are new to PIC microcontroller programming we suggest you to execute the basic led blinking project before trying this project. If you don't have access to your own hardware for this project, you can and execute it remotely.

If you are new to UART protocol go through article before executing this project.

course thumb

Project Content

Required hardware and software

The required hardware and software for this project is as below:

  • Development board hosting PIC16F877A 8-bit microcontroller
  • TTL - USB converter module
  • MPLAB IDE(v5.05) from Microchip
  • PICKIT3 Programmer, connecting cable from PICKIT3 to your computer.
  • Power supply for the development board
  • Teraterm emulator software
  • Hookup wires

  • Project connections

    Make sure that development board housing PIC16F877A microcontroller is NOT powered on. You should connect the GND pin, pin 26(Rx) pin, pin 25(Tx) to the Tx pin, Rx pin, GND pin of TTL to USB converter module. Connect other end of the TTL to USB converter module to one of the USB port port in your computer. Go to windows start -> device manager and check that the converter module is recongnized. If it is not recognized, right click on the device and follow the direction to get the driver for the module from internet. Once all the three connections are made between Microcontroller and TTL - USB converter module, you power on the development board and develop the uart program as explained in the next section.

    PIC16f877A UART description

    Lets discuss about the registers in PIC16F877A PIC microcontroller and its programming. The USART is one of the two serial I/O modules in PIC16F877A.

    PIC16F877A USART has both synchronous and asynchronous features. The USART can be configured as a full-duplex asynchronous system that can communicate with peripheral devices, such as CRT terminals and personal computers, or it can be configured as a half-duplex synchronous system that can communicate with peripheral devices, such as A/D or D/A integrated circuits, serial EEPROMs, etc.

    There are 6 registers that are associated with UART in PIC16F877A microcontroller.

    UART pins, Description

    No Description
    1 SPBRG(Serial Port baud rate generator)
    2 TXREG(Transfer Register)
    3 RXREG(Receive Register)
    4 TXSTA(Transmit control and status register)
    5 RXSTA(Receive control and status register)
    6 PIR1(Peripheripheral interrupt request register 1)
    SPBRG(Serial Port baud rate generator)

    Some of the baud rates generated out of the computer are 1200,2400,4800,9600,19200,38400,57600,115200. PIC16F877A transfers and receives data serially at many different baud rates. The baud rate in PIC16F877A is programmable. This is done with the help of the SPBRG register. For a give crystal frequency the value loaded into the SPREG register decides the baud rate. In asynchronous mode BRGH in TXSTA bit 2 also controls the baud rate.

    Given the desired baud rate and FOSC, the nearest integer value for the SPBRG register can be calculated using the formula in figure shown below. From this, the error in baud rate can be determined.

    course thumb
    Baud rate calculation formula.

    Example: With a crystal frequency of 10MHz the instruction cycle time frequency is 2.5MHz. PICs UART circuitry divides the instruction cycle frequency by 16 once more before it is used by an internal timer to set the baud rate. So 2.5GHz is divided by 16 gives 156250Hz. So for getting a baud rate of 9600 the value of SPBRG is set to: (156250/9600)-1 which is 15 in decimal or F in hexadecimal. The default value of 16 can be reduced to get higher baud rate with the same crystal by which UART's internal circuitry divides can be changed using BRGH value to 1. When BRGH is set to 0 it does not do any increase in baud rate. But when it is set to 1 it increases the baud rate by 4 i.e. division by 4 happens instead of 16.

    Example: Baud Rate(9600) = (11.0592*1000000)/(16 * (71 + 1)) with BRGH =1 in TXSTA register. So SPBRG = 71 i.e. in hex SPBRG = 0x47.

    TXREG Register

    TXREG Register is another 8-bit register used for serial communication in the PIC16F877A. For a byte of data to be transferred via the TX pin it must be placed in the TXREG register. TXREG is a special function register and can be accessed like any other register in the PIC16F877A.

    Once a byte is written into the TXREG, it is fetched into a register called TSR(Transmit shift register). The TSR frames the 8-bit data with the start and stop bits and the 10-bit data is serially transferred serially via the TX pin. While TXREG is accessible by the programmer, TSR is not accessible and strictly for internal purpose.

    RXREG Register

    When bits are received internally serially via the RX pin, the PIC16F877A deframes them by eliminating the stop and start bits, making a byte out of the data received and then placing it in the RCREG register.

    TXSTA Register

    The TXSTA register is an 8-bit register used to select the synchronous /asynchronous modes and data framing size, among the other things. We use the asynchronous mode with data size of 8-bits. The BRGH bit is used to select a higher speed of transmission. The default is lower baud rate transmission. D6 bit determines the framing of data by specifying the number of bits per character. We use 8-bit data size. There are some applications where nineth bit is used as an address.

    The D1 bit checks the status of the TSR register which cannot be accessed.Once a byte is written into the TXREG, it is fetched into a register called TSR(Transmit shift register). The TSR frames the 8-bit data with the start and stop bits and the 10-bit data is serially transferred serially via the TX pin. While TXREG is accessible by the programmer, TSR is not accessible and strictly for internal purpose. When the last bit which is the stop bit is transmitted the TRMT flag is raised to indicate that it is empty and ready for next byte. When TSR fetches the data from TXREG, it clears the TRMT flag to indicate it is full. When TSR is empty it gets its data from TXREG register and clears the TXREG register immediately, so it does not send the same data twice.

    The Transmit status and control register is shown in figure below.

    course thumb
    Transmit status and control register
    RXSTA Register

    The RXREG register is an 8-bit register used to enable the serial port to receive data. The Receive status and control register is shown in figure below.

    course thumb
    Receive status and control register
    PIR1 Register

    Two bits of the PIR1 register are used for UART. They are TXIF(Transmit Interrupt Flag) and RCIF(Receive Interrupt Flag). We monitor the TXIF flag bit and RCIF flag bit to make sure that all the bits of the last byte are transmitted before we write another byte into the TXREG. By the same logic, we monitor the RCIF flag to see if a byte of data has come in yet.

    Prepare source code, building program source code, creating binary

    Prepare source code
    #include "xc.h"
    #include "string.h"
    #include "stdlib.h"
    #include "pic16f877a.h"
    #include "htc.h"
    #define _XTAL_FREQ 11059200  //Device Crystal Frequency
    void SerialInit(); 
    #pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
    #pragma config WDTE = OFF        // Watchdog Timer Enable bit (WDT enabled)
    #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
    #pragma config CP = OFF         // FLASH Program Memory Code Protection bits (Code protection off)
    #pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
    #pragma config LVP = OFF        // Low Voltage In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
    #pragma config CPD = OFF        // Data EE Memory Code Protection (Code Protection off)
    #pragma config WRT = OFF        // FLASH Program Memory Write Enable (Unprotected program memory may not be written to by EECON control)
    #define TMR2PRESCALE 4
    unsigned int count = 0;
    #define BAUDRATE 9600   //Set BaudRate
    void SendString(char *);
    char getCharacter (void);
    void delay(unsigned int ); //Function prototype for delay function
    unsigned char i,j;
    int main()
      char str[15],mtr[15];
        unsigned int i = 0;
        char ct;
        unsigned char a;
      unsigned char msg[]="Welcome Message\r\n";  //To Send the Data Serial
        i = 0,j;
        str[0] = 0;
          while(1 == 1)
            ct = getCharacter();
            if(ct == '\r')
              str[i] = ct;
              str[i+1] = '\0';
      return 0;
    void SerialInit()
      TRISC6=0;         //Configure RC6/TX Pin as Output
      TXSTA=0x24;         //Set Transmit Enable Bit and High Speed Baudrate in Asynchronous Mode      ////////  SPBRG = [((_XTAL_FREQ/16)/BAUDRATE)-1]  //////////
      RCSTA=0x24;         //Set Transmit Enable Bit and High Speed Baudrate in Asynchronous Mode      ////////  SPBRG = [((_XTAL_FREQ/16)/BAUDRATE)-1]  //////////
      SPBRG=0x47;         //Load the Value of Baud Rate Generator Register for 11.0592MHz crystal to generate 9600 baud               ////////  SPBRG = [((20000000/16)/9600)-1]    //////////
      //TXEN=1;           //Set Transmit Enable Bit                           ////////  SPBRG = 129 = 0x81            //////////
      SYNC = 0;
      SPEN=1;           //Set Serial Port Enable Bit                          //////////////////////////////////////////////////////////////
      CREN = 1;
    * getCharacter - Waits for a new character to arrive in the serial port,
    *  then reads it.
    * INPUT: N/A
    * RETURNS: newly received character
    char getCharacter (void)
      char chr;        /* variable to hold the new character */
      * Wait until the serial port signals a new character has arrived.
      * It does so by setting the Received interrupt flag, RI, which
      * this routine loops on until it is set to 1.  This is known
      * as polling.
      while (RCIF != 1) {;}
      /* now read the value in the serial buffer into the local variable */
      chr = RCREG;
      * Once the character is read, the serial port must be told that it is
      * free to receive a new character.  This is done by clearing the
      * Received Interrupt flag.
      /* the character is then returned to the calling function. */
    void SendString(char *s)
      unsigned int a;
      for(a = 0;s[a] != '\0';a++)
        while(TXIF==0);       //Wait for the last char is sent completely
        TXREG = s[a];

    Download and install teraterm on your computer if not yet installed. Open teraterm and go to file -> new connection -> serial and click ok. Go to Setup -> serial port and configure baud rate to 9600.

    Follow the procedure as followed in to load the .hex file in the microcontroller. Once programmed the microcontroller, you should see string "Welcome message" displayed on the teraterm console.

    Looking for a new project? Write and upload your project information .


    C Programming

    More Articles Categories

    Technical articles

    Prepare for software jobs

    Test your skills