When to use:
When to use:
When NOT to use:
The MCHP_OC_SW block provides interrupt-driven software output compare functionality. Unlike hardware OC which operates autonomously, this block uses timer interrupts to precisely time output pin changes, offering greater flexibility at the cost of CPU overhead.
| Parameter | Description | Values |
|---|---|---|
| Channel | OC channel identifiers to use | 1-9 (logical channels, not hardware OC) |
| Channel_UP_Down_Periode | Operation mode per channel | 3 (Up & Down) |
| InputPeriod | Period source | ‘is a block input’ - Dynamic via Simulink |
| PIN_OCx | GPIO pin assignment | Any available GPIO (e.g., ‘RA0’, ‘RB5’) |
| Timer Configuration | Automatic timer allocation | Handled by MCHP_Fun.TimerConfig() |
| Mode | Description | Block Inputs | Use Case |
|---|---|---|---|
| 3 | Up & Down edges | OC1_Up (rising time) | OC1_Down (falling time) |
| 5 | Up edge & Period | OC1_Up (pulse width) | OC1_Per (period, optional) |
| 10 | Down edge & Period | OC1_Down (pulse width) | OC1_Per (period, optional) |
| 32 | Toggle mode | OC1_Toggle (half period) | Square wave generation, clock output |
Typical latency: 10-50 instruction cycles
Jitter sources: Other interrupts, CPU priority, cache misses
Mitigation: Use high interrupt priority, minimize concurrent interrupts
| Mode | Interrupts per Cycle | Overhead @ 10 kHz | Notes |
|---|---|---|---|
| Toggle (32) | 2 | ~0.1% @ 60 MHz | Lowest overhead |
| Up & Down (3) | 2 | ~0.1% @ 60 MHz | Two state transitions |
| Up & Period (5) | 2-3 | ~0.15% @ 60 MHz | Period reload overhead |
Maximum frequency: Limited by interrupt service time
// Optimize ISR for minimal latency
void __attribute__((__interrupt__, no_auto_psv)) _T2Interrupt(void)
__attribute__((section(".critical_code"))); // Place in fast RAM
// Use inline assembly for time-critical sections (dsPIC)
void __attribute__((__interrupt__, no_auto_psv)) _T2Interrupt(void)
### Best Practices
- **Use toggle mode (32)** when possible - simplest and fastest
- **Minimize ISR complexity** - only update timer and output pin
- **Pre-calculate values** - avoid math in interrupt handlers
- **Choose appropriate prescaler** - balance resolution vs overflow risk
- **Consider hardware alternatives** - use OC_HW if CPU overhead is concern
## Device Support
| Device Family | Timer Resources | Notes |
|---|---|---|
| dsPIC30F/33F | Type A/B timers | Automatic allocation |
| dsPIC33E | Type A/B/C timers | Enhanced timer features |
| dsPIC33C/CH/CK | Type A/B timers | High-speed timer option |
| dsPIC33A | Type A/B timers | Modern timer architecture |
| PIC24 | Type A/B/C timers | Standard operation |
| PIC32 | 32-bit timers | Higher resolution available |
## Features
- **Interrupt-driven timing** - Software updates output pins via timer interrupts
- **Multiple operational modes** - Up/Down edges, Period control, Toggle
- **Dynamic timing changes** - Frequency and duty cycle adjustable at runtime
- **Automatic timer allocation** - Uses MCHP_Fun.TimerConfig() for resource management
- **Flexible pin mapping** - Works with any GPIO pin (not limited to OC pins)
- **Period input support** - Dynamic frequency control via Simulink signal
### Comparison: OC_HW vs OC_SW
| Feature | MCHP_OC_HW | MCHP_OC_SW |
|---|---|---|
| CPU Overhead | None (autonomous) | Interrupt per edge transition |
| Flexibility | Fixed modes (3, 5, 6, 7) | More modes (3, 5, 10, 32) |
| Pin Assignment | OC pins only (or PPS) | Any GPIO pin |
| Dynamic Changes | Glitch-free duty cycle | Full runtime reconfiguration |
| Best For | High-frequency PWM, motor control | Flexible timing, variable frequency |
## Examples
### Example 1: Variable Frequency Square Wave
**Application:** Generate square wave with dynamically adjustable frequency
```matlab
% Block parameters
Channel: 1
Mode: 32 % Toggle mode
InputPeriod: 'is a block input'
PIN_OC1: 'RA0'
% Simulink model
Frequency Command โ 1/f Calculator โ Gain: FCY/2
โ OC1_Toggle input
% Example: For 1 kHz output at 60 MHz FCY
% Toggle period = 60,000,000 / (2 ร 1000) = 30,000 counts
% This creates 1 kHz square wave (toggle every 500 ยตs)
Application: Servo motor control with microsecond precision
% Block parameters
Channel: 1
Mode: 5 % Up + Period
InputPeriod: 'is a parameter'
Period: 20000 % 20 ms for servo (50 Hz)
PIN_OC1: 'RB3'
% Simulink model
Servo Angle -90 to +90 โ Gain & Offset: 1000-2000 ยตs
โ OC1_Up input
% Creates 1-2 ms pulses at 50 Hz for standard servo control
% Pulse width determines servo angle
Application: Buck converter with independent rise/fall timing
% Block parameters
Channel: 1
Mode: 3 % Up & Down (independent control)
PIN_OC1: 'RC2'
% Simulink model
Voltage Controller โ Dead-time Compensator
โ OC1_Up: Rising edge timing
โ OC1_Down: Falling edge timing
% Allows precise control of both edges for:
% - Dead-time insertion
% - Resonant switching optimization
% - Frequency modulation
Application: Three-phase waveform generation
% Block parameters
Channel: [1 2 3]
Mode: [32 32 32] % Toggle mode for all
InputPeriod: 'is a parameter'
Period: 1000 % Base frequency
% Simulink configuration
% Three separate OC_SW blocks with phase-shifted initialization:
% Block 1: Initial state HIGH, starts at t=0
% Block 2: Initial state HIGH, starts at t=T/3
% Block 3: Initial state HIGH, starts at t=2T/3
% Creates 120ยฐ phase-shifted square waves
// Interrupt-driven output compare (Mode 3 example)
void __attribute__((__interrupt__, no_auto_psv)) _T2Interrupt(void)
TMR2 = 0; // Reset timer for next event
IFS0bits.T2IF = 0; // Clear interrupt flag
}
The block automatically allocates timers using MCHP_Fun.TimerConfig():
% Timer allocation example (from callback)
TimerNbr, TimerName = MCHP_Fun.TimerConfig(...
blk, ... % Block handle
'OC_SW', ... % Resource type
Channel, ... % Channel number
MCHP ... % MCHP structure
);
% Returns:
% TimerNbr: Timer number allocated (2, 3, 4, 5, etc.)
% TimerName: String identifier ('Timer2', 'Timer3', etc.)
// Timer setup (example for Timer2)
T2CONbits.TON = 0; // Stop timer during configuration
T2CONbits.TCS = 0; // Internal clock (FCY)
T2CONbits.TCKPS = prescaler; // Set prescaler
PR2 = period_value; // Set period
TMR2 = 0; // Clear timer count
IFS0bits.T2IF = 0; // Clear interrupt flag
IEC0bits.T2IE = 1; // Enable timer interrupt
T2CONbits.TON = 1; // Start timer
// GPIO configuration
TRISAbits.TRISA0 = 0; // Set as output
LATAbits.LATA0 = 0; // Initialize low