To increase the resolution of a PWM, the counter overflow increments a a few bits of a concatenated secondary counter to increase the 8-bit's counter overflow period to something like.
So why does the specsheet offer this silly(difficult to understand) formula to calculate resolution?
Resolution in bits = ( LOG(4 * (PRX+1) )/2
It shows the output of the 8-bit concatenated counter toggling the RS flipflop, but RS flipflops don't toggle, they do set/reset.
if they concatenate at the lsb or msb it still creates the same bit-length counter that feeds into a comparator.
I wish Microchip would have included a waveform diagram that showed the simultaneous behavior of clocks and counters and comparators and logic in PWM operation, or even better, a C-code example on how to setup at least one of the many PWM possible pin outputs.
I get ziltch at the output.
So why does the specsheet offer this silly(difficult to understand) formula to calculate resolution?
Resolution in bits = ( LOG(4 * (PRX+1) )/2
It would seem to me that to get 10-bit resolution of duty cycle using an 8-bit PWM freq, the comparison would require using a clock running 4x as fast, synchronizing the start of the 8-bit PWM counter to the 10-bit comparsion 4x as fast counter.
I also don't understand why two bits of the system clock are used for comparison.
So why does the specsheet offer this silly(difficult to understand) formula to calculate resolution?
Resolution in bits = ( LOG(4 * (PRX+1) )/2
For instance, suppose I have battery-operated device and I want to know what is the lowest system clock freq. usable and still have 10-bit resolution.
CONFIG3H CCP2MX = PORTC1
pwm_setup ; sequence from datasheet
movlw b'11111001' ; period = 2000 hz at 4mhz with tm2 prescaler 4
movwf PR2
clrf CCPR1L ; set pwm1 duty to zero
clrf CCPR2L ; set pwm2 duty to zero
bcf TRISC,2 ; ensure /set ccp1/2 ports to output
bcf TRISC,1
movlw b'01111100' ; tmr2=ON,pre=1:4
movwf T2CON
bsf T2CON,TMR2ON
movlw b'00111100' ; set ccp1 to pwm mode
movwf CCP1CON
movlw B'00111100' ; set ccp2to pwm mode
movwf CCP2CON
pwm_run
movlw 0x4F ; raise LED1 PWM to start value of 0xnn
movwf CCPR1L
movlw 0xAF ; raise LED2 PWM to start value of 0xnn
movwf CCPR2L
Thanks picandmix, but I am totally lost in assembly, it is hard enough to troubleshoot complex operations in C, I would imagine going to even a lower level would be an horror.
Update: I put a test bit in main() to blink a LED if the TMR4>0 (LED on), if TMR0>250 (LED on RC3 off)
Test LED turns on and briefly off, Means TMR4 is resetting on 256.. PR4, but no CCP1 pin output
//outputs
sbit MOT at LATD5_bit; //PWM output for motor
sbit MOT_TRIS at TRISD5_bit; //TRIS bit for PWM output
#define MOT_PWM 0b0010
//sets PWM duty cycle. Takes unsigned int as duty value, splits off LSBs to DC1B bits, the rest goes into CCPR1L
void pwm_set_duty(unsigned int duty) {
if(duty >= 1023) duty = 1023; //ensure duty cycle does not go too far
CCP1CON.B4 = lo(duty).B0; //set lsbs in ccp1con register
CCP1CON.B5 = lo(duty).B1;
CCPR1L = (unsigned char)(duty>>2); //lop off LSBs, MSBs to register.
}
//initialise pwm. requires comparator to have been configured previously
//comparator config not shown in code below
void pwm_init() {
pwm_set_duty(0); //default zero duty cycle
MOT = 0; //drive output latches low
MOT_TRIS = 1; //set outputs as inputs to prevent spurious signals, we have an external pulldown
T2CON = 0; //turn off timer
PR2 = PR2_CONFIG; //set period register
TMR2 = 0; //reset TMR2
PSTR1CON = 0b00010000 | MOT_PWM; //steer on next pwm period, set correct output to drive
CCPTMRS0 = 0; //all pwm uses tmr2
CCPTMRS1 = 0; // " " " "
ECCP1AS = 0b10110000; //auto shutdown enabled, comparator 1 source, drive all pins low on fault
PWM1CON = 0; //auto restart disbaled for now, 0Tosc delay after fault.
CCP1CON = 0b00001100; //Enhanced PWM, single output, P1A (steerable) active high
CCPR1L = 0; //definitely zero duty cycle
MOT = 0; //ensure output latches are low ready for TRIS
MOT_TRIS = 0; //set outputs
T2CON = T2CON_CONFIG; //start the timer
PWM1CON.P1RSEN = 1; //start the PWM - enable auto-restart after shutdown (hardware clears CCP1ASE [bit 7] of ECCP1AS register)
}
void main() {
OSCCON = 0b01110010; //16MHz Primary oscillator (PLL disabled in CONFIG word); /*go fast*/
OSCCON2 = 0;
OSCTUNE = 0;
LATA = 0; //all outputs default to low
LATB = 0;
LATC = 0;
LATD = 0;
LATE = 0;
TRISA = TRISA_CONFIG;
ANSELA = ANSELA_CONFIG;
TRISB = TRISB_CONFIG;
ANSELB = ANSELB_CONFIG;
WPUB = WPUB_CONFIG;
TRISC = TRISC_CONFIG;
ANSELC = ANSELC_CONFIG;
TRISD = TRISD_CONFIG;
ANSELD = ANSELD_CONFIG;
TRISE = TRISE_CONFIG;
ANSELE = ANSELE_CONFIG;
INTCON = 0; //ensure no interrupts are enabled
WDTCON = 0;
delay_us(10); //wait for oscillator to stabilise. VERY IMPORTANT FOR ECCP MODULE for some reason
PMD0 = PMD0_CONFIG;
PMD1 = PMD1_CONFIG;
PMD2 = PMD2_CONFIG;
RCON = RCON_CONFIG;
//peripheral initialisations
pwm_init(); //initialise PWM after delay
// MAIN LOOP
while(1) {
//stuff
}
}
//CCP1CON holds duty cycle LSb in bits<5:4>LSbs, but CCPR1L=MSbits
CCP1CON=00000000; //DCyc=0 off PWM1 channel
CCPR1L=(CCPR1L & 0xC0); //Mask P1M bits, MSbits of DCyc=0, CPR1H not used
I downloaded the .odb file and it loads successfully into Excel 2007 and yet yields a blank spreadsheet.
Thanks Bruce Abbot, but according to the 25K22 specsheet bits 6 and 7 of CCP1CON are used for P1M advanced output configuration bits