MCU Examples.com
PIC Microcontroller Project Examples, free source codes and resources collection.


 

PIC RS232 Serial Communication example with computer

Serial communication is one of easiest communication protocol available. This example demonstrates how to use serial communication to send and receive data through serial port (RS232C) available in computer.

Some new computers don’t come with serial port on back panel. But most of them has header to connect serial port on mother board. Also USB to serial converter cables available for really cheap price as 5USD.

PIC microcontroller has serial communication module (USART) which operates using CMOS logic levels which changes between +5V and 0V to represent logic 1 and 0. However computer serial port (RS232C) operates in different voltage levels. It represents logic 0 with -10V and logic 1 with +10V. So obliviously we can’t directly connect PIC MCUs USART pins to computer. We need to convert voltage levels. For this task there is specially designed serial level converter ICs available in most common one is MAX232 which is used here. This IC receives signals from -10 to +10V from computer side and converts them into 0 and 5V which can be used with microcontrollers.

When using MAX232 IC it is essential to connect C2 capacitor as close as possible to MAX232 chip. Otherwise your circuit may not work. Also it is good idea to keep serial cable from computer to MAX232 reasonably short. (Don’t take it in meters)

This example utilize hardware EUSART module available in PIC18F4520 (and most other pics.)  However you can easily port this code to other PICs with minor header file change. This hardware serial communication use standard NRZ (Non Return to Zero) format also known as 8 (9)-N-1, or 8 or 9 data bits, without parity bit and with one stop bit. Free line in this format is defined as status of logic one. Start of transmission has the status of logic zero (start bit). Data bits sent after start bit and least significant bit sent immediately after start bit. After data bits stop bits sent with logic 1. The duration of the stop bit 'T' depends on the transmission baud rate. It is adjusted according to the needs of the transmission. For the transmission speed of 9600 baud, T is 104 uS.

In this example we utilize receive interrupt. When data byte received through PIC MCUs RX line interrupt generated by hardware and we will get received data byte in to a variable and enable a flag so that in main program we can identify reception of valid data byte. In side main programs infinite loop will constantly look for new data reception flag and if that flag is set, that means new data available. So main program will send bat received data through PIC MCUs TX line to Computer via MAX232 IC. To test this example use Hyper-terminal (type “hypertrm” in Start->run of windows XP) and configure it to 9600bps baud, 8 data bits, one stop bit, no parity and no flow control. Then once you type character on computer it will be sent to PIC via serial port and PIC will echo same data back to computer and displayed on hyper terminals window.

PIC MCUs only has one receive buffer. So since we are not using flow control, it is our responsibility to read received data from PICs receive buffer (RCREG) as soon as data arrives. If new data arrived before you read data in RCREG, overrun error will occur and pervious data will be lost.

This example project uses 20MHz crystal oscillator.

MPLAB project source available at end of the page and OrCAD project is available upon request. (USE forum)











//
// Designed by www.MCUExamples.com
// rasika0612@gmail.com
// Serial communications example. Echo data comes to serial port
// using serial receive interrupt.
//

#include <p18f4520.h>

#pragma config OSC         =    HS     // 20MHz Crystal, (HS oscillator)
#pragma config PBADEN   =    OFF // PORTB<4:0> pins are configured as digital I/O on Reset)
#pragma config WDT         =    OFF // watch dog timer off
#pragma config LVP         =    OFF // Low voltage program off

unsigned char cUART_char;
unsigned char cUART_data_flg;

void init_uart(void);
void UART_putc(unsigned char c);
void InterruptHandlerLow ();

void main()
{

    init_uart(); // init UART module
    while (1) // infinite loop which handles ncoming data as they arrive
    {
        if (cUART_data_flg==1)// if new data available, send it back through USART tx line (echo it)
        {
            UART_putc(cUART_char); 
            cUART_data_flg=0; // clear new data flag so one charactor will echoed once
        }
    }
}

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

#pragma code InterruptVectorLow = 0x18
void InterruptVectorLow (void)
{
  _asm
    goto InterruptHandlerLow //jump to interrupt routine
  _endasm
}

//----------------------------------------------------------------------------
// Low priority interrupt routine

#pragma code
#pragma interrupt InterruptHandlerLow

void InterruptHandlerLow ()
{
  if (PIR1bits.RCIF==1)//is interrupt occured by EUSART receive?, 
                        //then RCREG is full we have new data (cleared when RCREG is read)
  {  
    if(RCSTA&0x06) //more efficient way than following commented method to check for reception error 
    //if(RCSTAbits.FERR==1 || RCSTAbits.OERR==1 )
    {
      RCSTAbits.CREN=0;    //Overrun error (can be cleared by clearing bit CREN)
      cUART_char=RCREG;    //clear Framing error 
      RCSTAbits.CREN=1;
    }
    else
    {
       cUART_char = RCREG; // read new data into variable
       cUART_data_flg = 1; // new data received. so enable flg
    }
  }
}

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

void init_uart(void) // init UART module for 9600bps boud, start bit 1, stopbit 1, parity NONE
{
    cUART_data_flg=0;   // init data receive flag to zero (no data)
    TRISCbits.TRISC7=1; //Make UART RX pin input
    TRISCbits.TRISC6=0; //Make UART TX pin output
    SPBRGH  = 0x02;     //9600bps 20MHz Osc
    SPBRG   = 0x08;        

    RCSTAbits.CREN=1;   //1 = Enables receiver
    RCSTAbits.SPEN=1;   //1 = Serial port enabled (configures RX/DT and TX/CK pins as serial port pins)
    BAUDCONbits.BRG16=1;//1 = 16-bit Baud Rate Generator – SPBRGH and SPBRG

    TXSTAbits.SYNC=0;  //0 = Asynchronous mode
    TXSTAbits.BRGH=1;  //1 = High speed 
    TXSTAbits.TXEN=1;  //1 = Transmit enabled

    RCONbits.IPEN = 1;  //enable Interrupt priority levels
    IPR1bits.RCIP=0;     // EUSART Receive Interrupt Priority 0 = Low priority
    PIE1bits.RCIE=1;     // 1 = Enables the EUSART receive interrupt
    INTCONbits.GIEL = 1;//enable interrupts
    INTCONbits.GIEH = 1;      
}

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

void UART_putc(unsigned char c)
{
  TXSTAbits.TXEN=0;// disable transmission
  TXREG=c;            // load txreg with data
  TXSTAbits.TXEN=1;    // enable transmission
  while(TXSTAbits.TRMT==0) // wait here till transmit complete
  {
    Nop();
  }
}

 

You can download MPLAB project files here

 

Custom Search