1) Where to put the duty cycle value?
The name of the configuration register CCPR1L made me think this is the lower 8 bits of the duty cycle value. In fact, these are the upper 8 bits while the lower two bits (=least significant bits, LSB) are bits [5:4] at CCP1CON which also holds the PWM configuration values. This means we always have to split our desired duty cycle value (in my case, an integer counting from 0 to 1023) and write bits [0:1] to [4:5] of CCP1CON and bits [2:9] to [0:7] of CCPR1L. With my limited knowlege of C, this caused a bit of head-scratching here ;)
2) Output Current
When I had my code running, I connected one of my low-current LED to the PWM output with an 1k resistor to ground, which causes the LED to draw about 3.2mA. At this time, I had a small speaker connected to another pin on PORTC (for software PWM) with a small transistor-amplifier. Now each time I used the hardware PWM, this speaker would beep at about my PWM frequency, even though I didn't drive its port pin! Damn, I thought to myself, the PWM causes a lot of noise. Sadly, I don't own an oscilloscope to investigate such problems.
In the end, I set the duty cycle fix to 100% and measured the current drawn on the PWM pin, finding that it would only output 2.9mA max. This means, even my low-current LED overloads the PWM pin. Putting a small signal transistor in between solved things.
Here's my code:
#include <p18cxxx.h> #include <p18f2550.h> #include <delays.h> //Pin Reset Configurations #pragma config PBADEN = OFF //RB0 through RB4 pins are configured as digital I/O on Reset //#pragma config CCP2MX = ON //CCP2 multiplexed with RC1 //Oscillator Settings #pragma config PWRT = ON //Soft Power-Up #pragma config FOSC = HSPLL_HS //HS oscillator, PLL enabled, HS used by USB #pragma config PLLDIV = 5 //PLL prescaler divides by 5 (20 MHz oscillator input) #pragma config CPUDIV = OSC1_PLL2 //CPU @PLL/2=48MHz //Features #pragma config MCLRE = ON //MCLR pin enabled; RE3 digital input disabled #pragma config LVP = OFF //Single-Supply ICSP disabled, free RB5 #pragma config DEBUG = OFF //Background debugger disabled, RB6 and RB7 configured as I/O pins #pragma config WDT = OFF //HW Disabled - SW Controlled #pragma config BOR = OFF //Brown-out Reset disabled in hardware and software void main (void); void main (void) { TRISC &= ~0x04; //clear rc2 tris bit for output CCP1CON = 0x0C; //0b00XX1100 for single mode pwm //XX are bits [0:1] of the 10bit duty cycle value CCPR1L = 0x00; //reset pwm duty cycle bits [2:9] PR2 = 0xFF; //pwm period = 750kHz / 256 ~= 2930Hz T2CON = 0x07; //enable, prescale 1:16 => tmr0 counting at 750kHz while(1){ //fade from 0 to 5v for (i = 0; i < 1024; i++) { CCPR1L = i >> 2; //shifting bits [2:9] to [0:7] CCP1CON = 12 | ((i << 4) & ~12); //clearing bits [2:3] //shifting bits [0:3] to [4:7] //and setting bits [2:3] for pwm configuration Delay10KTCYx(5); } //fade back to 0v for (i = 1023; i >= 0; i--) { CCPR1L = i >> 2; CCP1CON = 12 | ((i << 4) & ~12); Delay10KTCYx(5); } } }Testing Circuit
The Transistor is a BC338 with a hfe of ~400, so when drawing 3.1mA for the LED, the pwm output pin only has to deliver 1/400th of this current.
Keine Kommentare:
Kommentar veröffentlichen