Have you considered using the PWM module? Many people don't realize you can run the PWM module at very low frequencies by using a software "helper" ISR (interrupt service routine) to link together several much smaller/faster PWM period "frames" to form a much longer/slower overall period.
This method provides many of the advantages of the PWM module (zero jitter, interrupt tolerant, very high resolution pulse width, etc.) at the cost of using a small low overhead ISR software "helper". You can also use the 1-msec interrupt interval as a basis for timer operations.
Perhaps one of the PBP gurus can convert, test, and qualify this code for you?
Happy Holidays!
Mike, K8LH
Code:
// setup a 1000 usec PWM period with PR2 = 249 and prescaler
// 16:1 (16 MHz clock) or 4:1 (4 MHz clock) and then link 20
// of these 1000 usec PWM "frames" together to form the much
// longer 20-ms servo period (1-usec pulse width resolution)
int servo = 1500; // 0..20000 in 1 usec steps
int frame = 1; // frame number 1..20
void interrupt() //
{ int width; // work variable
pir1.TMR2IF = 0; // clear Timer 2 interrupt flag
frame--; //
if (frame == 0) // if end of the 20 msec period
{ frame = 20; // reset for new 20 msec period
width = servo; // reset 'width' work variable
}
if ((width > 1000) // if width > 1000 usecs
{ ccpr1l = 250; // do a 100% duty cycle frame
ccp1con.CCP1Y = 0; //
ccp1con.CCP1X = 0; //
width -= 1000; // subtract 1000 usecs
}
else // else do a 0..1000 usec frame
{ ccpr1l = (width >> 2); // 0..250 (0..1000 usecs)
ccp1con.CCP1Y = (width & 1);
ccp1con.CCP1X = (width & 2);
width = 0; // force remaining frames to 0%
}
}
Bookmarks