Unit 6 - Notes
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:
- 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.
- Data Bits: The actual data payload. This is typically 5 to 8 bits, sent with the Least Significant Bit (LSB) first.
- 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.
- 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):
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:
- 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.
- 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 = 64BRG16=0(8-bit),BRGH=1(high speed): Multiplier = 16BRG16=1(16-bit),BRGH=0(low speed): Multiplier = 16BRG16=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
#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.
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.
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.
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
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
- Microcontroller:
PIC18F4550(or your target PIC) - Level Converter:
MAX232 - Virtual Serial Port:
COMPIM(This component models a physical COM port on your PC). - Virtual Terminal: From the "Virtual Instruments" menu. This acts as a serial monitor.
4.2 Circuit Schematic in Proteus
- Place the
PIC18F4550,MAX232, andCOMPIMcomponents on the schematic. - Connect the PIC's
RC6/TXpin toT1INof the MAX232. - Connect the PIC's
RC7/RXpin toR1OUTof the MAX232. - Connect
T1OUTof the MAX232 to theRXDpin of theCOMPIM. - Connect
R1INof the MAX232 to theTXDpin of theCOMPIM. - 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
-
PIC18F4550:
- Double-click the PIC.
- Under "Program File", browse and select the
.hexfile generated by your MPLAB X project. - Set the "Processor Clock Frequency" to match your code (e.g.,
20MHz).
-
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
- Build the Circuit: Create the schematic in Proteus as described above.
- Compile Code: Write and compile your C code in MPLAB X to generate the
.hexfile. - Configure Proteus: Load the
.hexfile into the PIC and configure the COMPIM component. - 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).
- Run Simulation: Click the "Play" button in Proteus to start the simulation.
- 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.