Unit 6 - Notes

ECE227 12 min read

Unit 6: Serial Port Programming

1. Basics of Serial Communication

1.1 What is Serial Communication?

Serial communication is a process of sending data one bit at a time, sequentially, over a single communication channel or computer bus. This is in contrast to parallel communication, where multiple bits are sent simultaneously on multiple channels. While slower than parallel communication, serial communication is simpler, requires fewer wires, reduces cost, and is more reliable over long distances.

  • Advantages: Fewer wires, lower cost, less crosstalk, effective over long distances.
  • Disadvantages: Slower data transmission rate compared to parallel.
  • Applications: Connecting peripherals like GPS modules, modems, sensors, and for debugging microcontrollers.

1.2 Framing

In asynchronous serial communication, data is sent in packets called "frames". Synchronization between the transmitter and receiver is achieved for each frame using start and stop bits. This means the receiver can start listening at any time and will be able to synchronize with the next frame it receives.

A typical serial frame consists of:

  1. Start Bit: A single bit that transitions the line from high (idle) to low. It signals the receiver that a new frame of data is about to begin.
  2. Data Bits: The actual data payload. This is typically 5 to 8 bits, sent with the Least Significant Bit (LSB) first.
  3. Parity Bit (Optional): Used for basic error checking. It is set to make the total number of '1's in the data either even (even parity) or odd (odd parity). If no parity is used, this bit is omitted.
  4. Stop Bit(s): One or two bits that transition the line back to high (idle state). This marks the end of the frame and provides a buffer before the next frame can start.

Diagram of a Serial Frame (8-N-1: 8 data bits, No parity, 1 stop bit):

TEXT
Idle (High) ___   +-----+-----+-----+-----+-----+-----+-----+-----+----------+
               |  D0 |  D1 |  D2 |  D3 |  D4 |  D5 |  D6 |  D7 |          |   ___ Idle (High)
               +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+----------+
                  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |          |
                  v  v  v  v  v  v  v  v  v  v  v  v  v  v  v  v          v
Line Level     ___| S | D0| D1| D2| D3| D4| D5| D6| D7| P | Stop |_________
                  t
                  a
                  r
                  t

1.3 Key Parameters

For two devices to communicate serially, they must be configured with the same parameters:

  • Baud Rate: The speed of data transmission, measured in bits per second (bps). Common baud rates are 1200, 2400, 4800, 9600, 19200, 115200. Both devices must operate at the same baud rate.
  • Parity: The method of error detection.
    • None: No parity bit is used.
    • Even: The parity bit is set to '1' if the number of '1's in the data is odd, making the total number of '1's even.
    • Odd: The parity bit is set to '1' if the number of '1's in the data is even, making the total number of '1's odd.
  • Data Bits: The number of bits in the data payload (usually 8).
  • Stop Bits: The number of bits to signal the end of the frame (usually 1).

1.4 Communication Modes

  • Simplex: Communication is unidirectional (one-way only). Example: A radio broadcast.
  • Half-Duplex: Communication is bi-directional, but not simultaneous. Only one device can transmit at a time. Example: A walkie-talkie.
  • Full-Duplex: Communication is bi-directional and simultaneous. Both devices can transmit and receive at the same time. This requires two separate communication lines (Transmit - TX, Receive - RX).

1.5 The RS-232 Standard

RS-232 (Recommended Standard 232) is a widely used standard for serial communication. It defines the electrical characteristics and timing of signals, the meaning of signals, and the physical size and pinout of connectors.

  • Voltage Levels: RS-232 uses different voltage levels than the TTL/CMOS logic used by microcontrollers.
    • Logic '1' (Mark): -3V to -25V
    • Logic '0' (Space): +3V to +25V
    • Undefined Region: -3V to +3V
  • Microcontroller TTL/CMOS Levels:
    • Logic '1': +2.0V to +5V (typically VDD)
    • Logic '0': 0V to +0.8V (typically GND)

This voltage mismatch means a microcontroller cannot be directly connected to an RS-232 device. A level converter IC is required.

2. PIC18 Connection to RS232

2.1 The Voltage Level Mismatch Problem

As noted above, PIC18 microcontrollers operate on TTL logic levels (0V for logic 0, +5V for logic 1), while the RS-232 standard uses higher, bipolar voltages (-12V for logic 1, +12V for logic 0). Connecting a PIC's TX/RX pins directly to an RS-232 port will damage the microcontroller.

2.2 The MAX232 Level Converter IC

The MAX232 is a popular integrated circuit that solves the voltage level mismatch problem. It acts as a bridge between the two standards.

  • Function:
    1. TTL/CMOS to RS-232 Conversion: Takes 0V/+5V signals from the PIC's TX pin and converts them to corresponding +12V/-12V signals for the RS-232 port.
    2. RS-232 to TTL/CMOS Conversion: Takes +12V/-12V signals from the RS-232 port and converts them to 0V/+5V signals for the PIC's RX pin.
  • Operation: The MAX232 uses an internal "charge pump" with four external capacitors to generate the required positive (+10V) and negative (-10V) voltages from a single +5V supply.

2.3 Hardware Connection Diagram

The following diagram shows a typical connection between a PIC18F4550, a MAX232 IC, and a DB9 (RS-232) female connector.

PIC18F4550 Pins:

  • RC6/TX: Transmit pin
  • RC7/RX: Receive pin

MAX232 Connections:

  • The chip has two sets of drivers/receivers. We will use one set.
  • T1IN (Pin 11): Connects to the PIC's TX pin (RC6).
  • R1OUT (Pin 12): Connects to the PIC's RX pin (RC7).
  • T1OUT (Pin 14): Connects to the DB9 RX pin (Pin 2).
  • R1IN (Pin 13): Connects to the DB9 TX pin (Pin 3).
  • VCC (Pin 16): Connects to +5V.
  • GND (Pin 15): Connects to Ground.
  • Capacitors: Typically, 1µF or 10µF capacitors are used as per the datasheet (C1-C4).

DB9 Female Connector:

  • Pin 2 (RXD): Receives data.
  • Pin 3 (TXD): Transmits data.
  • Pin 5 (GND): Signal Ground.

3. Serial Port Programming in C (PIC18 - XC8 Compiler)

PIC18 microcontrollers feature a built-in EUSART (Enhanced Universal Synchronous Asynchronous Receiver Transmitter) module for handling serial communication. Programming it involves configuring several Special Function Registers (SFRs).

3.1 Key Special Function Registers (SFRs)

TXSTA: Transmit Status and Control Register
This register controls the transmission process.

Bit Name Function
7 CSRC Clock Source Select (not used in async mode)
6 TX9 9-bit Transmit Enable (0 = 8-bit transmission)
5 TXEN Transmit Enable (1 = Enable)
4 SYNC EUSART Mode Select (0 = Asynchronous, 1 = Synchronous)
3 SENDB Send Break Character (not commonly used)
2 BRGH High Baud Rate Select (1 = High speed, 0 = Low speed)
1 TRMT Transmit Shift Register Status (1 = TSR empty)
0 TX9D 9th bit of transmit data

RCSTA: Receive Status and Control Register
This register controls the reception process.

Bit Name Function
7 SPEN Serial Port Enable (1 = Enable serial port)
6 RX9 9-bit Receive Enable (0 = 8-bit reception)
5 SREN Single Receive Enable (not used in async mode)
4 CREN Continuous Receive Enable (1 = Enable receiver)
3 ADDEN Address Detect Enable (for 9-bit mode)
2 FERR Framing Error bit (1 = error occurred)
1 OERR Overrun Error bit (1 = buffer was full, data lost)
0 RX9D 9th bit of received data

BAUDCON: Baud Rate Control Register
Used for advanced settings, particularly enabling 16-bit baud rate generation.

  • BAUDCONbits.BRG16 = 1; // Enables 16-bit Baud Rate Generator

SPBRG & SPBRGH: Baud Rate Generator Registers
These registers (SPBRG is the low byte, SPBRGH is the high byte) hold a value that determines the baud rate based on the system clock frequency (Fosc).

Data Registers:

  • TXREG: Transmit Buffer Register. You write the byte you want to send to this register.
  • RCREG: Receive Buffer Register. You read the received byte from this register.

Interrupt Registers (PIR1, PIE1, IPR1):

  • TXIF (PIR1<4>): Transmit Interrupt Flag. Set when the TXREG buffer is empty and ready for new data.
  • RCIF (PIR1<5>): Receive Interrupt Flag. Set when the RCREG buffer has received a full byte of data and is ready to be read.
  • TXIE (PIE1<4>): Transmit Interrupt Enable.
  • RCIE (PIE1<5>): Receive Interrupt Enable.

3.2 Calculating the Baud Rate

The value to load into the SPBRG/SPBRGH registers is calculated using a formula from the datasheet. The formula depends on the SYNC, BRGH, and BRG16 bits. For Asynchronous Mode:

Formula: Baud Rate = Fosc / (Multiplier * (X + 1))
where X is the value in SPBRGH:SPBRG.

This can be rearranged to find X:
X = (Fosc / (Multiplier * Baud Rate)) - 1

The Multiplier depends on BRGH and BRG16 settings:

  • BRG16=0 (8-bit), BRGH=0 (low speed): Multiplier = 64
  • BRG16=0 (8-bit), BRGH=1 (high speed): Multiplier = 16
  • BRG16=1 (16-bit), BRGH=0 (low speed): Multiplier = 16
  • BRG16=1 (16-bit), BRGH=1 (high speed): Multiplier = 4

Example: Calculate SPBRG for 9600 baud with Fosc = 20MHz, using High Speed (BRGH=1) and 8-bit mode (BRG16=0).

X = (20,000,000 / (16 * 9600)) - 1
X = (20,000,000 / 153,600) - 1
X = 130.208 - 1
X = 129.208

Round to the nearest integer: X = 129. So, SPBRG = 129.

3.3 C Code Implementation (using XC8)

Here are example functions for serial communication on a PIC18F4550 with a 20MHz crystal.

3.3.1 Initialization Function

C
#include <xc.h>

#define _XTAL_FREQ 20000000 // System clock frequency for delay functions

void UART_Init(long baud_rate) {
    // Calculate SPBRG value
    // Using Asynchronous High Speed Mode (BRGH=1, BRG16=0)
    // SPBRG = (Fosc / (16 * Baud Rate)) - 1
    int spbrg_value = (_XTAL_FREQ / (16 * baud_rate)) - 1;

    // 1. Configure I/O pins
    TRISCbits.TRISC6 = 0; // TX pin as output
    TRISCbits.TRISC7 = 1; // RX pin as input

    // 2. Configure TXSTA register
    TXSTAbits.TXEN = 1;   // Enable transmitter
    TXSTAbits.SYNC = 0;   // Asynchronous mode
    TXSTAbits.BRGH = 1;   // High speed baud rate

    // 3. Configure RCSTA register
    RCSTAbits.SPEN = 1;   // Enable serial port
    RCSTAbits.CREN = 1;   // Enable continuous receiver

    // 4. Configure BAUDCON for 8-bit mode
    BAUDCONbits.BRG16 = 0; // Use 8-bit baud rate generator

    // 5. Set the baud rate by loading SPBRG
    SPBRG = spbrg_value;
}

3.3.2 Transmitting a Character (Polling)

This function waits until the transmit buffer is empty before sending the next character.

C
void UART_Write(char data) {
    while(!TXSTAbits.TRMT); // Wait until the Transmit Shift Register is empty
    TXREG = data;          // Load the data to be transmitted
}

3.3.3 Transmitting a String

This function iterates through a string and sends it character by character.

C
void UART_Write_String(const char *text) {
    for(int i = 0; text[i] != '\0'; i++) {
        UART_Write(text[i]);
    }
}

3.3.4 Receiving a Character (Polling)

This function waits until a character has been received.

C
char UART_Read() {
    while(!PIR1bits.RCIF); // Wait for data to be received
    
    // Check for framing or overrun errors (optional but good practice)
    if(RCSTAbits.OERR) {
        // Overrun error, clear the flag by resetting CREN
        RCSTAbits.CREN = 0;
        RCSTAbits.CREN = 1;
    }
    
    return RCREG; // Return the received character
}

3.3.5 Example main.c

C
void main(void) {
    UART_Init(9600); // Initialize UART at 9600 baud

    __delay_ms(100); // Wait for UART to stabilize

    UART_Write_String("Serial Communication Initialized.\r\n");
    UART_Write_String("Type a character to echo it back:\r\n");

    while(1) {
        char received_char = UART_Read(); // Wait and read a character
        
        UART_Write_String("You typed: ");
        UART_Write(received_char); // Echo the character back
        UART_Write_String("\r\n");
    }
}

4. Proteus Simulation for Serial Communication

Proteus is an excellent tool for simulating serial communication without needing physical hardware.

4.1 Required Components

  1. Microcontroller: PIC18F4550 (or your target PIC)
  2. Level Converter: MAX232
  3. Virtual Serial Port: COMPIM (This component models a physical COM port on your PC).
  4. Virtual Terminal: From the "Virtual Instruments" menu. This acts as a serial monitor.

4.2 Circuit Schematic in Proteus

  1. Place the PIC18F4550, MAX232, and COMPIM components on the schematic.
  2. Connect the PIC's RC6/TX pin to T1IN of the MAX232.
  3. Connect the PIC's RC7/RX pin to R1OUT of the MAX232.
  4. Connect T1OUT of the MAX232 to the RXD pin of the COMPIM.
  5. Connect R1IN of the MAX232 to the TXD pin of the COMPIM.
  6. Connect power (+5V) and ground to both the PIC and MAX232. You do not need to add capacitors for the MAX232 in the simulation.

Alternatively, for simple TTL-level simulation, you can connect the PIC's TX/RX pins directly to the RXD/TXD pins of the Virtual Terminal instrument, bypassing the MAX232 and COMPIM.

Proteus Schematic (using COMPIM):

4.3 Configuring the Components

  1. PIC18F4550:

    • Double-click the PIC.
    • Under "Program File", browse and select the .hex file generated by your MPLAB X project.
    • Set the "Processor Clock Frequency" to match your code (e.g., 20MHz).
  2. COMPIM (Virtual Serial Port):

    • Double-click the COMPIM component.
    • Physical Port: Set to an available COM port on your PC (e.g., COM1).
    • Physical Baud Rate: Set to the baud rate used in your code (e.g., 9600).
    • Virtual Baud Rate: Also set to the same baud rate (9600).
    • The other settings (Data bits, Parity, Stop bits) should match your PIC's configuration (e.g., 8, None, 1).

4.4 Simulation Steps

  1. Build the Circuit: Create the schematic in Proteus as described above.
  2. Compile Code: Write and compile your C code in MPLAB X to generate the .hex file.
  3. Configure Proteus: Load the .hex file into the PIC and configure the COMPIM component.
  4. Open a Terminal Program:
    • Open a PC terminal application like PuTTY, Tera Term, or the Arduino Serial Monitor.
    • Configure it to connect to the same COM port you set in the COMPIM (e.g., COM1).
    • Set the baud rate and other parameters to match your simulation (9600, 8-N-1).
  5. Run Simulation: Click the "Play" button in Proteus to start the simulation.
  6. Test Communication:
    • You should see the initialization messages from your PIC appear in the PC terminal window.
    • Type a character in the PC terminal window. It will be sent through the virtual COM port to the COMPIM, through the simulated MAX232, to the PIC's RX pin. The PIC's code will then echo it back, and it will appear in your terminal.