Serial Communication Tutorial

Microcontroller Topics
Post Reply
User avatar
Reginald
Sergeant Major
Sergeant Major
Posts: 29
Joined: Mon Aug 03, 2009 9:54 pm
Location: Mount Lavinia

Serial Communication Tutorial

Post by Reginald » Sun Sep 20, 2009 7:06 am

Introduction
UART (Universal Asynchronous Receiver Transmitter) or USART (Universal Synchronous Asynchronous Receiver Transmitter) are one of the basic interface which you will find in almost all the controllers available in the market till date. This interface provide a cost effective simple and reliable communication between one controller to another controller or between a controller and PC.

RS-232 Basics
RS-232 (Recommended Standard 232) is a standard for serial binary data signals connecting between a DTE (Data terminal equipment) and a DCE (Data Circuit-terminating Equipment).
Voltage Levels:
The RS-232 standard defines the voltage levels that correspond to logical one and logical zero levels. Valid signals are plus or minus 3 to 25 volts. The range near zero volts is not a valid RS-232 level; logic one is defined as a negative voltage, the signal condition is called marking, and has the functional significance of OFF. Logic zero is positive, the signal condition is spacing, and has the function ON.
So a Logic Zero represented as +3V to +25V and Logic One represented as -3V to -25V.
voltage.gif
voltage.gif (2.45 KiB) Viewed 3587 times
RS-232 Level Converters
Usually all the digital ICs works on TTL or CMOS voltage levels which cannot be used to communicate over RS-232 protocol. So a voltage or level converter is needed which can convert TTL to RS232 and RS232 to TTL voltage levels.
The most commonly used RS-232 level converter is MAX232. This IC includes charge pump which can generate RS232 voltage levels (-10V and +10V) from 5V power supply. It also includes two receiver and two transmitters and is capable of full-duplex UART/USART communication.
max232.gif
max232.gif (2.19 KiB) Viewed 3587 times
Fig A. - MAX232 Pin Description
max232a.gif
max232a.gif (3.01 KiB) Viewed 3587 times
Fig B. - MAX232 Typical Connection Circuit

MAX232 Interfacing with Microcontrollers
To communicate over UART or USART, we just need three basic signals which are namely, RXD (receive), TXD (transmit), GND (common ground). So to interface MAX232 with any microcontroller (AVR, ARM, 8051, PIC etc..) we just need the basic signals. A simple schematic diagram of connections between a microcontroller and MAX232 is shown below
max232.png
max232.png (7.93 KiB) Viewed 3587 times
In the next part of this tutorial we will discuss programming microcontroller to communicate over UART and software implementation of half duple UART.

AVR Programming for UART
In AVR, following set of registers are used to communicate over USART
  • UCSRA
  • UCSRB
  • UCSRC
  • UBRRH
  • UBRRL
UCSRA: in this register there are flags for various errors that might occure during data transmission, e.g. parity error, frame error etc.

UCSRB: in this register we have a lot of enable bits. For example different interrupt enable bits but also the reciving and transmitting enable bits.

UCSRC: in this register we set the parity mode, stop bits and so on.

UBRRH & UBRRL: in UBRRH register, the higher byte and in UBRRL, lower byte is stored for generating a required Baud rate.

More information on the above registers can be found in the datasheet of the AVR you are using.

ASM Code for Initializing USART in AVR

Code: Select all

.include "m8515def.inc"
.def reg1 = r16
.def reg2 = r17
Serial_Init:
        ;Load UBRRH with 0 and UBRRL with 25
        ;to set a baud rate of 9600 at 4MHz
        ldi reg1,00
        out UBRRH,reg1
        ldi reg2,25
        out UBRRL,reg1
        ;Clear all error flags
        ldi reg1,00
        out UCSRA,reg1
        ;Enable Transmission and Reception
        ldi reg1,(1<<RXEN)+(1<<TXEN)
        out UCSRB,reg1
        ;Set Frame format
        ;8,N,1
        ldi reg1,(1<<URSEL)|(3<<UCSZ0)
        out UCSRC,reg1
        ret
C Code

Code: Select all

#include <avr/io.h>.
void serial_init(){
        UCSRA=0x00;
        UCSRB=0x18;
        UCSRC=0x86;
        UBRRH=0x00;
        UBRRL=0x19;
}
To transmit data serial we need to put the data to send in 8-bit UDR (UART Data Register) and poll the empty transmit buffer to set. While receiving data we wait for the receive flag, when its set the data recieved can be read from the UDR register. This can be done as follows...

ASM Code

Code: Select all

Serial_Send:
        ;wait for empty transmit buffer flag
        sbis UCSRA, UDRE
        rjmp Serial_Send
        ;If the flag is set
        ;Then move the data to send in UDR
        out UDR,reg2
        ret
       
Serial_Read:
        ;Wait for Receive flag
        sbis UCSRA,RXC
        rjmp Serial_Read
        ;If falg is set
        ;Then read data from UDR
        in reg2,UDR
        ret
C Code

Code: Select all

void serial_send(unsigned char dat){
        while(!(UCSRA & (1<<UDRE)));
        UDR = dat;
}
unsigned char serial_read(){
        while(!(UCSRA & (1<<RXC)));
        return UDR;
}
8051 Programming for UART
In 8051, we make use of Timer 1 to generate the required baud rate. Following are the registers that are need to be configured to communicate over UART.
  • TMOD
  • SCON
  • TH1
  • TL1
  • TCON
TMOD: This register is used to set the mode of Timer0 and Timer1. It is also used to select whether the timers are used as Timer or Counter.

SCON: Serial Control register has various functions like.. it has flags for Framing error, Transmit interrup and receive interrupt. Its used to select the serial port mode, to enable or disable the reception etc.

TCON: This register has varios flag and control bits e.g. Timer overflow flags, interrupt edge flags, timer control bits to start/stop the timer.

TH1 & TL1: Timer registers for Timer 1 determines the baudrate of UART.

More information on the above registers can be found in the 8051 Hardware manual.

ASM Code for Initializing USART in 8051

Code: Select all

Serial_Init:
        ;Set timer 1 mode to 8-bit Auto-Reload
        mov TMOD,#20H
        ;Enable reception
        ;Set Serial port mode to 8-bit UART
        mov SCON,#50H
        ;Set baudrate to 9600 at 11.0592MHz
        mov TH1,#0FDH
        mov TL1,#0FDH
        ;Start Timer
        setb TR1
        ret
C Code

Code: Select all

#include <reg51.h>.
void serial_init(){
        TMOD = 0x20;
        SCON = 0x50;
        TH1  = 0xFD;
        TL1  = 0xFD;
        TR1  = 1;
}
To Send data to the serial port we just have to move the data in SBUF (serial buffer register) and wait for the Transmit Interrupt flag to be set. While receiving we wait for the Receive interrupt flag to be set and read the data from SBUF register. This can be done as shown below...

ASM Code

Code: Select all

Serial_Send:
        ;wait for last data to be
        ;sent completely
        jnb TI,Serial_Send
        ;clear the transmit interrupt flag
        clr TI
        ;Then move the data to send in SBUF
        mov SBUF,A
        ret
       
Serial_Read:
        ;Wait for Receive interrupt flag
        jnb RI,Serial_Read
        ;If falg is set then clear it
        clr RI
        ;Then read data from SBUF
        mov A,SBUF
        ret
C Code

Code: Select all

void serial_send(unsigned char dat){
        while(!TI);
        TI = 0;
        SBUF = dat;
}
unsigned char serial_read(){
        while(!RI);
        RI = 0;
        return SBUF;
}
Software UART for 8051
To implement UART successfully we first need to know how the protocol works.
serwave1.gif
serwave1.gif (2.35 KiB) Viewed 3587 times
Diagram above shows the waveform in which the bits has to be transferred. First is the start bit.. then 8-bit data and at last a stop bit. There is a secret formula to calculate the delay time which is needed between bits to get correct baudrate.
Below is a software implemented UART, which can be used in C as well as Assembly programs. It is written for Keil software. But with a little modification you can use it in your programs.

ASM Code

Code: Select all

?SU?PUTC SEGMENT CODE
?SU?GETC SEGMENT CODE

PUBLIC _putc
PUBLIC getc

txd_pin EQU     P3.1            ;Transmit on this pin
rxd_pin EQU     P3.0            ;Receive on this pin

;Formula to calculate the bit time delay constant
;This constant is calculated as: (((crystal/baud)/12) - 5) / 2
;crystal is the frequency of crystal in Hz
;baud is required baudrate
;Please try to keep baudrate below 9600
;to get best results :-)

BITTIM  EQU     45;             (((11059200/9600)/12) - 5) / 2

;--------------------------------------------
;To send data serially
;For C programs
;Protype definition:
;               void putc(unsigned char);
;Usage:
;               putc(data);
;Return:
;               This function returns nothing
;
;For Assembly Programs:
;
;Usage:
;       data to be send has to be moved to R7
;       for example:
;               mov R7,#'a'
;               lcall _putc
;--------------------------------------------
RSEG ?SU?PUTC
_putc:
        push ACC
        Push PSW
        mov a,r7
        CLR txd_pin                     ;Drop line for start bit
        MOV R0,#BITTIM          ;Wait full bit-time
        DJNZ R0,$                       ;For START bit
        MOV R1,#8                       ;Send 8 bits
putc1:
        RRC A                           ;Move next bit into carry
        MOV txd_pin,C           ;Write next bit
        MOV R0,#BITTIM          ;Wait full bit-time
        DJNZ R0,$                       ;For DATA bit
        DJNZ R1,putc1           ;write 8 bits
        SETB txd_pin            ;Set line high
        RRC A                           ;Restore ACC contents
        MOV R0,#BITTIM          ;Wait full bit-time
        DJNZ R0,$                       ;For STOP bit
        POP PSW
        pop ACC
        RET

;--------------------------------------------
;To receive data Serially
;If you want to use this routine in your
;C program then define function prototype
; as:
;       unsigned char getc(void);
;
;       Usage:
;               data = getc();
;       Return value:
;               Returns data received
;
;
;If you are using it in assembly program
;       Usage:
;               lcall getc
;       Return:
;               data received is stored in R7
;--------------------------------------------

RSEG ?SU?GETC
getc:  
        Push ACC
        Push PSW
        JB rxd_pin,$            ;Wait for start bit
        MOV R0,#BITTIM/2        ;Wait 1/2 bit-time
        DJNZ R0,$                       ;To sample in middle
        JB rxd_pin,getc         ;Insure valid
        MOV R1,#8                       ;Read 8 bits
getc1:
        MOV R0,#BITTIM          ;Wait full bit-time
        DJNZ R0,$                       ;For DATA bit
        MOV C,rxd_pin           ;Read bit
        RRC A                           ;Shift it into ACC
        DJNZ R1,getc1           ;read 8 bits
        mov r7,a
        POP PSW
        pop ACC
        RET                                     ;go home
Post Reply

Return to “Microcontrollers”