Serial Communication Using PIC (USART)

Serial communication is very important for micro devices. By using the serial communication one can communicate with computers (via COM port,USB,etc), peripheral devices or some ICs(such as eeprom, A/D converters,etc.).

The process of serial communication can be done by low level coding. You need to have a look at timing specification of the protocol and write a code to meet the requirements.

However, most PIC microcontrollers come with build in serial communication protocols such as USART, I2C, SPI. You only need to configure it and start receiver and/or transmitter.

In this tutorial, we will use PC’s COM port also called as RS-232 (Recommended Standart 232) and built in USART module of PIC micro.

The word USART is the acronym of Universal Synchronous Asynchronous Receive Transmit. Standart COM port uses asynchronous receiver and transmitter. In this mode there are Tx (transmit) and Rx (receive) lines. It can transmit and receive information at the same time from these lines. Because of this, it is called full-duplex communication. (If you have to wait to complete Rx/Tx before Tx/Rx information, it is called as half-duplex.)

Configuration bits

To configure USART module we use TXSTA, RCSTA, SPBRG and interrupt registers.

TXSTA register:


CSRCClock Source Select Bit :
Only works in synchronous mode.
Selects Master(1)(Clock generated internally)/Slave(0)(Clock from external source)mode.
TX99-bit Transmit Enable Bit :
This bit enables(1)/disables(0) the 9-bit transmission
TXENTransmit Enable Bit :
Transmit Enable(1)/Disable(0) bit
BRGHHigh Baud Rate Select Bit :
Only works in Asynchronous mode. High(1)/Low(0) speed
TRMTTransmit Status Bit :
TSR empty(1)/full(0)
TX9D9th bit of transmit data. Can be Parity bit.

RCSTA register:


SPENSerial Port Enable Bit :
Enables(1)/Disables(0) serial port
RX99-bit Receive Enable Bit :
Enables(1)/Disables(0) 9-bit reception
SRENSingle Receive Enable Bit :
Only works in Synchronous Master Mode. Enables(1)/Disables(0)
CRENContinous Receive Enable Bit :
Enables(1)/Disables(0) continous receive
ADENAddress Detect Enable Bit :
Only wokrs in 9-bit Asynchronous mode. Enables(1)/Disables(0) address detection
FERRFraming Error Bit :
Set(1) when framing error occured
OERROverrun Error Bit :
Set(1) when overrun error occured
RX9D – 9th bit of received data. Can be parity bit.


SPBRG register :

This is the register which holds the baud rate generator value. It can be calculated using the below formula :

Baud Rate Calculation :

Desired Baud Rate = Fosc/(64(X+1)) where X is the SPBRG value.
If we choose BRGH (High baud rate bit in the TXSTA register) bit as high, the formula will be :
Desired Baud Rate = Fosc/(16(X+1))
Let’s calculate the SPBRG value for Fosc=4MHz, Baud Rate=9600, BRGH=1 :
9600 = 4000000/(16(X+1))

The error will be :
Baud Rate = 4000000/(16(25,04167+1))=9615
Error = (9615-9600)/9600=0,16%

Try to find smaller error rate by giving 1 or 0 to BRGH bit.

The table for SPBRG can be found in the pic micro controller’s datasheet. I also have created an Open Office Calc (or Microsoft Excel) Table :


Can be downloaded here : Calculator.ods or Calculator.xls

Interrupts :

The USART module has two interrupts; received and transmitted. In our example we will use only received interrupt.

The interrupt registers we need are INTCON and PIE1. We have to enable PEIE(6th) bit (Peripheral Interrupts Enable) of the INTCON register and enable RCIE (5th) bit of the PIE1 registers.

Now, we know everything to configure a PIC microcontroller to receive and transmit serial data.

Follow the steps to receive data :
- Load the SPBRG register for desired Baud Rate.
-Set/Reset BRGH bit of TXSTA for high/low speed baud.
-Enable Asynchronous mode by clearing SYNC bit of the TXSTA register.
-Enable Serial Port by setting SPEN bit of RCSTA register.
-Set the RCIE bit of the PIE1 register to enable Received Interrupt.
-Set the GIE and PEIE bit of INTCON register to enable Peripheral Interrupts and General Interrupts.
-Start to receive CREN bit of RCSTA register.
-Get the received data from RCREG register at Interrupt routine check RCIF flag of PIR1 register to be sure if the interrupt was generated by USART Receiver.

Follow the steps to transmit data :
- Load the SPBRG register for desired Baud Rate.
-Set/Reset BRGH bit of TXSTA for high/low speed baud.
-Enable transmitter by setting TXEN bit of TXSTA register.
-Load the data which will be transmitted, to TXREG register to start transmission.

Example :

The following example demonstrates how to use USART receiver and transmitter. We will use PIC16F628 but other PIC micros with USART module can be used.

In the example, when a data is sent through the PC’s COM Port, the LEDs connected to PORTA shows the received value. And, when the button connected to 4. bit of PORTB is pushed the received value is sent back to the PC’s COM Port.

Download source file.

The assembly code :

LIST P=16F628
#include <>

TMP_TX EQU H’20′ ;Value to hold received value

ORG 0×00 ;Start vector
GOTO main
ORG 0×04 ;Interrupt vector
GOTO interrupt

;—Use PORTA as I/O
MOVLW D’7′ ;Use PORTA as I/O
CLRF TRISA ;Set all pins of PORTA as output
BSF TRISB,4 ;Set PORTB.4 as input

;—Configure peripheral interrupts
MOVLW B’00100000′ ;Disable all peripheral interrupts except receiver
MOVWF PIE1 ;Peripheral interrupt enable/disable

;—Configure general interrupts
MOVLW B’01000000′ ;Disable all interrupts except peripheral
MOVWF INTCON ;Interrupt control register

;—Configure SPBRG for desired baud rate
MOVLW D’25′ ;We will use 9600
MOVWF SPBRG ;baud at 4MHz

;—Configure TXSTA
MOVLW B’00100100′ ;Configure TXSTA as :

;8 bit transmission – 6.bit
;Transmit enabled – 5.bit
;Asynchronous mode – 4.bit
;Enable high speed baud rate – 2.bit

MOVLW B’10000000′ ;Enable serial port
MOVWF RCSTA ;Receive status reg
BSF INTCON,7 ;Enable all unmasked interrupts
BSF RCSTA,4 ;Enable USART receive

MAIN_LOOP: ;Continous loop
BTFSC PORTB,4 ;Check if the button is pressed
GOTO MAIN_LOOP ;If not goto continous loop

;We load TMP_TX on the interrupt routine,
;when an information received from RX.
GOTO MAIN_LOOP ;Continous loop

BCF INTCON,7 ;Disable all interrupts
BTFSS PIR1,5 ;Check if the RCIF flag is set
GOTO quit_int ;If not return back to the main loop
MOVF RCREG,W ;Move the received byte to W



In the circuit, we have used a PIC16F628, RS-232 to 5V logic level converter (MAX232) and a push button and LEDs for user interface.

Click to open image

Why do we need a level translator?

Because, the RS-232 standart works between -15~-3V (for logic 0) and +3~+15V (for logic 1) and micro controllers work between 0 and +5V. So, we need max232 level translator IC.




PORTA<5> cannot be used as output and PORTA<4> can only be used as open drain output. So you won’t see the corresponding bits of the serial value on PORTA<4:5> with the current hardware configuration. But in the end the circuit does what it is supposed to do. The serial communication works well. Thanks for correction.

PC software

You can use any terminal software to test the circuit. Windows has Hyper Terminal for this purpose.

Configure it as 9600 baud, 8 data bit, no parity, 1 stop bit, no flow control.


I have written a small VB 6.0 application to get one byte data from serial port. VB-COM-Application

Unrar it and run COM.exe.


Video Tutorial

You can find a video tutorial below derived from this tutorial prepared by Ian. His setup is better than mine :). Thanks Ian.

Share and Enjoy

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Reddit
  • Add to favorites
  • Email
  • RSS

2 Responses to “Serial Communication”

  1. victor says:

    For communicating with microcontroller programmatically from host PC, scm can be used. It is an alternative library to rxtx/javaxcomm for serial port communication.
    Wiki :
    Repository :
    Video :

  2. johan says:

    Would this work if i connect a pic16f874 to a mitsubishi got940

Leave a Reply