Unit 4: PIC Interfacing - II
CCP Modes
CCP stands for Capture/Compare/PWM, and it is one of the core features of PIC microcontrollers used to measure time events, compare signals, and generate pulse-width modulation (PWM) signals. PIC microcontrollers include dedicated CCP modules that enable various time-based and control functions.
Capture Mode
The Capture mode is used to capture the value of a timer at the exact moment an external event occurs. The CCP module waits for a trigger (an edge on a specific pin) and captures the current timer value at that instant. This allows us to measure external events such as the time between two pulses or the frequency of a signal.
Key Features:
- Can detect rising, falling, or both edges of an incoming signal.
- The captured value can be stored in the CCP register and then processed by the microcontroller.
Example Code (Capture Mode):
#include <xc.h>
void capture_init() {
TRISCbits.TRISC2 = 1; // Set CCP1 pin as input
CCP1CON = 0x05; // Configure CCP1 module in Capture mode (rising edge)
T1CON = 0x01; // Timer1 ON with prescaler 1:1
}
void main() {
capture_init();
while (1) {
if (PIR1bits.CCP1IF) { // Check if Capture has occurred
unsigned int captured_value = (CCPR1H << 8) + CCPR1L; // Get captured value
PIR1bits.CCP1IF = 0; // Clear the interrupt flag
}
}
}
Compare Mode
In Compare mode, the CCP module compares the value of a timer with a preset value and triggers an event when the two values match. This can be used to trigger an action, like toggling a pin or generating a pulse when the timer reaches the desired count.
Key Features:
- Can generate an interrupt when the timer value matches the comparison value.
- Useful for creating precise time delays.
Example Code (Compare Mode):
#include <xc.h>
void compare_init() {
CCP1CON = 0x0B; // Compare mode: Toggle output on match
T1CON = 0x01; // Timer1 ON with prescaler 1:1
CCPR1 = 5000; // Set the compare value
}
void main() {
compare_init();
while (1) {
// Wait for compare event (handled by hardware)
}
}
PWM Mode
Pulse Width Modulation (PWM) is a technique used to control the power delivered to a load by varying the width of the pulse while keeping the frequency constant. PWM is widely used in controlling motor speeds, LED brightness, and other power control applications.
Key Features:
- Duty cycle determines how much time the signal stays HIGH in one cycle.
- Frequency of PWM remains constant, while the duty cycle varies.
Example Code (PWM Mode):
#include <xc.h>
void pwm_init() {
PR2 = 255; // Set PWM period
CCPR1L = 128; // Set initial duty cycle
CCP1CON = 0x0C; // Configure CCP1 module in PWM mode
T2CON = 0x04; // Timer2 ON with prescaler 1:1
}
void main() {
pwm_init();
while (1) {
// Adjust the PWM duty cycle as needed
}
}
DC Motor Speed Control Using CCP
Using the PWM mode of the CCP module, we can control the speed of a DC motor. By varying the duty cycle of the PWM signal, the effective voltage applied to the motor changes, thus controlling its speed.
How PWM Controls Motor Speed:
- Low Duty Cycle: Less power is delivered to the motor, making it run slower.
- High Duty Cycle: More power is delivered to the motor, making it run faster.
Example Code (DC Motor Speed Control):
#include <xc.h>
void pwm_init() {
PR2 = 255; // Set PWM period
CCPR1L = 128; // Set initial duty cycle (50%)
CCP1CON = 0x0C; // Configure CCP1 module in PWM mode
T2CON = 0x04; // Timer2 ON with prescaler 1:1
}
void set_motor_speed(unsigned char duty_cycle) {
CCPR1L = duty_cycle; // Adjust duty cycle to control motor speed
}
void main() {
pwm_init();
while (1) {
set_motor_speed(192); // Set motor speed (75% duty cycle)
}
}
Stepper Motor Interfacing with PIC
A Stepper motor is a brushless DC motor that divides a full rotation into equal steps. Each step corresponds to a specific angular movement, making it ideal for precise positioning applications like CNC machines and 3D printers.
Interfacing Steps:
- Half-Step or Full-Step Mode: Choose between these modes depending on the required resolution.
- Driving the Coils: Use transistors or a dedicated driver circuit to supply current to the motor coils.
- Control Sequence: Send a specific sequence of HIGH and LOW signals to the motor coils to make the motor rotate.
Example Code (Stepper Motor Control):
#include <xc.h>
void stepper_init() {
TRISB = 0x00; // Set PORTB as output
}
void rotate_stepper(unsigned char steps) {
const unsigned char sequence[] = {0x09, 0x0A, 0x06, 0x05}; // Full-step sequence
for (unsigned char i = 0; i < steps; i++) {
for (unsigned char j = 0; j < 4; j++) {
PORTB = sequence[j]; // Apply step sequence
__delay_ms(100); // Delay between steps
}
}
}
void main() {
stepper_init();
while (1) {
rotate_stepper(100); // Rotate motor 100 steps
}
}
Serial Communication Protocols
RS232
RS232 is a serial communication protocol used for short-distance communication. It involves a transmit and receive pin, and data is transmitted in bits (one bit at a time).
- Voltage levels: RS232 uses +12V and -12V for signaling.
- Baud rate: Defines how fast data is transmitted (e.g., 9600 baud).
I2C
I2C (Inter-Integrated Circuit) is a two-wire protocol used for communication between multiple ICs. The two wires are:
- SCL (Serial Clock): Used to synchronize the communication.
- SDA (Serial Data): Used to transmit and receive data.
I2C allows communication between multiple devices, where each device has a unique address.
SPI
SPI (Serial Peripheral Interface) is a four-wire communication protocol commonly used to interface sensors, SD cards, and display modules with microcontrollers. The wires are:
- MOSI (Master Out Slave In): Data sent from master to slave.
- MISO (Master In Slave Out): Data sent from slave to master.
- SCLK (Serial Clock): Clock signal for synchronization.
- SS (Slave Select): Selects which slave device to communicate with.
UART
UART (Universal Asynchronous Receiver-Transmitter) is a widely used protocol for serial communication. It involves only two data lines:
- TX (Transmit): Sends data from the microcontroller.
- RX (Receive): Receives data into the microcontroller.
Serial Communication Programming using Embedded C
RS232 Example:
#include <xc.h>
void uart_init() {
TXSTAbits.TXEN = 1; // Enable UART transmission
RCSTAbits.SPEN = 1; // Enable UART module
SPBRG = 25; // Set baud rate to 9600
}
void uart_write(char data) {
while (!TXSTAbits.TRMT); // Wait until buffer is empty
TXREG = data; // Transmit data
}
void main() {
uart_init();
uart_write('A'); // Send character 'A'
while (1);
}
I2C Example:
char i2c_read_ack() {
SSPCON2bits.RCEN = 1; // Enable receive mode
while (!SSPSTATbits.BF); // Wait for data
return SSPBUF; // Return received data
}
char i2c_read_nack() {
SSPCON2bits.RCEN = 1; // Enable receive mode
while (!SSPSTATbits.BF); // Wait for data
SSPCON2bits.ACKDT = 1; // Send NACK
SSPCON2bits.ACKEN = 1; // Send ACK
return SSPBUF; // Return received data
}
void main() {
i2c_init();
i2c_start();
i2c_write(0xA0); // Device address
char data = i2c_read_nack(); // Read data with NACK
while (1);
}
SPI Example:
char spi_read() {
SSPBUF = 0xFF; // Send dummy byte to generate clock
while (!SSPSTATbits.BF); // Wait for transmission to complete
return SSPBUF; // Read received data
}
void main() {
spi_init();
while (1) {
char data = spi_read(); // Read data from SPI
}
}