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.
| 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 |
| 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 |
| 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 |
// 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
Application: Generate square wave with dynamically adjustable frequency
% 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
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
## Related Blocks
- [**MCHP_OC_HW**](output_compare_hw) - Hardware output compare (lower CPU overhead)
- [**MCHP_TIMER_Config**](../timers/timer_config) - Timer resource management
- [**MCHP_IC**](input_capture) - Measure external pulse timing
- [**MCHP_PWM**](../pwm_io/pwm) - Dedicated PWM peripheral
- [**MCHP_Digital_Output**](../digital_io/digital_output) - Basic GPIO output control
## See Also
### Application Notes
- [AN1156](https://www.microchip.com/AN1156)
- [AN580](https://www.microchip.com/AN580)