Using TIMER1 to wash and TIMER0 to spin
#include <xc.h>
#define _XTAL_FREQ 4000000 // Define system clock frequency (4MHz)
#pragma config FOSC = HS // High-Speed Oscillator
#pragma config WDTE = OFF // Watchdog Timer Disable
#pragma config PWRTE = OFF // Power-up Timer Disable
#pragma config BOREN = ON // Brown-out Reset Enable
#pragma config LVP = OFF // Low Voltage Programming Disable
#pragma config CPD = OFF // Data EEPROM Protection
#pragma config WRT = OFF // Flash Program Memory Write Protection
#pragma config CP = OFF // Flash Program Memory Protection
volatile unsigned long spin_overflow_count = 0;
unsigned long spin_timer_limit = 0;
volatile unsigned long wash_overflow_count = 0;
unsigned long wash_timer_limit = 0;
void init_timers() {
T1CON = 0b00110001; // Enable Timer1, 1:8 prescaler, Internal clock
OPTION_REG = 0b00000100; // Use 1:8 prescaler for Timer0
TMR1 = 0; // Reset Timer1 counter
TMR0 = 0; // Reset Timer0 counter
TMR0IE = 1; // Enable Timer0 interrupt
TMR1IE = 1; // Enable Timer1 interrupt
PEIE = 1; // Enable peripheral interrupts
GIE = 1; // Enable global interrupts
}
void start_wash_timer(unsigned int duration_ms) {
TMR1 = 0; // Reset Timer1 register
wash_overflow_count = 0;
// Calculate number of overflows required
//Formula (duration * (Fosc / 4) / (Prescaler * TIMERSIZE (2^16)))
wash_timer_limit = (duration_ms * (_XTAL_FREQ / 4)) / (8 * 65536);
TMR1ON = 1; // Start Timer1
}
void start_spin_timer(unsigned int duration_ms) {
TMR0 = 0; // Reset Timer0 register
spin_overflow_count = 0;
// Calculate number of overflows required
spin_timer_limit = (duration_ms * (_XTAL_FREQ / 4)) / (8 * 256);
TMR0ON = 1; // Start Timer0
}
void stop_spin_timer() {
TMR0 = 0;
TMR0ON = 0;
spin_overflow_count = 0;
}
void stop_wash_timer() {
TMR1 = 0;
TMR1ON = 0;
wash_overflow_count = 0;
}
// Interrupt Service Routine
void __interrupt() ISR(void) {
if (TMR0IF) { // Timer0 Overflow Interrupt
TMR0IF = 0; // Clear Timer0 flag
if (spin_overflow_count < spin_timer_limit) {
spin_overflow_count++;
} else {
stop_spin_timer();
}
}
if (TMR1IF) {
// Timer1 Overflow Interrupt
TMR1IF = 0; // Clear Timer1 flag
if (wash_overflow_count < wash_timer_limit) {
wash_overflow_count++;
} else {
stop_wash_timer();
}
}
}
void main() {
init_timers();
start_wash_timer(300000); //wash for 5 minutes
start_spin_timer(300000); //spin for 5 minutes
while (1) {
}
}
Using TIMER2 for PWM
#include <xc.h>
// Configuration Bits
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = OFF
#define _XTAL_FREQ 4000000 // 4MHz Clock
const unsigned int PWM_freq = 1000; //1KHz pwm frequency
void PWM_Init(unsigned int duty_cycle) {
// Step 1: Set CCP1 to PWM Mode
CCP1CON = 0b00001100; // PWM Mode
// Step 2: Configure Timer2
T2CON = 0b00000100; // Timer2 ON, Prescaler 1:1
// Step 3: Set PWM Period (PR2)
// Formula: PR2 = (Fosc / (PWM_freq * 4 * TMR2_prescaler)) - 1
PR2 = (_XTAL_FREQ / (PWM_freq * 4 * 1)) - 1
// Step 4: Set Duty Cycle
CCPR1L = duty_cycle >> 2; // 8 MSBs
CCP1CONbits.DC1B = duty_cycle & 0x03; // 2 LSBs
}
void main() {
TRISC2 = 0; // Set RC2 as Output (PWM Pin)
PWM_Init(250); // Set Initial PWM Duty Cycle
while(1) {
}
}