PIC18F2550 PWM Square wave generator

I am trying to generate a square wave on 50% Duty Cycle using my PIC18F2550. The signal is to be outputted through a loudspeaker. The frequency does not really matter, as long as it is in the hearing range (a few Khz should do).

This is my rather simplistic code;

#include "xc.h"

void PWM_init(void);
void Chip_init(void);

void main(void){

Chip_init();
PWM_init();
while(1);
}
void PWM_init(void) {

/****Set All PWM Registers*****/
PR2 = 0b11111111;
T2CON = 0b00000111;
CCPR2L = 0b01111111;
CCP2CON = 0b00111100;
}

void Chip_init(void){

/** Initialize all outputs ****/
LATCbits.LATC1 = 0;
TRISCbits.TRISC1 = 0;
LATBbits.LATB3 = 0;
TRISBbits.TRISB3 = 0;
}


This should give me a PWM signal of about 3Khz on either C1 or B3, atleast to my understanding. But i am getting nothing, unfortunately. Can anyone tell me where I went wrong?

• Did you try to measure the output without connecting the loudspeaker on the scope? I hope since some loudspeaker have as low impedance as 8 ohms, the microcontroller GPIO won't drive enough current and will brown out. – lucas92 May 4 '16 at 15:27
• I did try that, I would just get what seemed like a regular output on the CCP pin? it was a series of pulses on a frequency lower than 10 Hz. Though that only seemed to appear when the PIC was in bootloader mode. Anyway. It wasn't the output that this code should give and the output was there all the time. – TheAlPaca02 May 4 '16 at 15:30
• Might be a good idea that you make the uC sleeps in the while loop (sleeping in bursts of 1ms is ok). – lucas92 May 4 '16 at 15:34
• Yeah this code was just a test to see if it would work. – TheAlPaca02 May 4 '16 at 15:38
• I tested your code with MPLAB SIM and in an actual 18F2455 (same as 18F2550 except for less ROM) and got ~500Hz PWM on RB3 with CPU clock at 8MHz. What are your configuration bit settings? – Bruce Abbott May 4 '16 at 21:42

1 Answer

I ended up changing my code to this. Now I am getting a 3khz PWM signal of square pulses.

The prescaler was increased from 4 to 16 and I assigned most bits individually. Im not 100 % sure yet what the mistakes were in my earlier code.

#include <xc.h>

/*Function prototypes*/
void initChip(void);
void initPWM(void);

void main(void) {
initChip();
initPWM();
while(1);
}

void initChip(void)
{
PORTB = 0x00; //Initial PORTB
TRISB = 0x00; //Define PORTB as output
PORTC = 0x00; //Initial PORTC
TRISC = 0x00; //Define PORTC as output
INTCONbits.GIE = 0; // Turn Off global interrupt
}

void initPWM(void)
{
PR2 = 0xFF;
CCPR2L = 0x7F; //
CCP2CONbits.DC2B0 = 0;
CCP2CONbits.DC2B1 = 0;
TRISB = 0x00; // Clear Tris registers
TRISC = 0x00;
T2CONbits.T2CKPS1 = 1; // Timer 2 Prescaler = 16
T2CONbits.T2CKPS0 = 1;
T2CONbits.TMR2ON = 1; // Enable Timer 2
CCP2CONbits.CCP2M3 = 1; // Set CCP as PWM
CCP2CONbits.CCP2M2 = 1;
}

• In your original code you had T2CON = 0b00000111, which sets the prescaler to 16. Now you have ?????111, which should be the same if the other bits are still at their power-on default values. I got the same frequency using both old and new versions of your code. – Bruce Abbott May 9 '16 at 18:23
• Perhaps the difference is that your bootloader is changing some registers from their power-on defaults? (in which case your code might fail if a different bootloader is used). Try changing your code back to the original 1 line at a time, testing it each time to see which line (if any) is making the difference. Then you can figure out why it makes a difference. – Bruce Abbott May 9 '16 at 18:24
• Huh thats weird, i didn't notice that. At the moment it keeps working though. If I find the time I will investigate further. thanks – TheAlPaca02 May 10 '16 at 8:29