variable PWM setting in PIC24FJ64GA002 - c

I am working on project in which I need to display different colors on RGB led. I am using pwm to drive different colors on LED. My Pic is PIC24FJ64GA004 with which I am working on now. Basic concept of this project is to use switch to controls colors.
Colors on RGB led will be according to days and month in year. For that I am using 7-segment led with switch to count days and month.
Problem at the moment is following code. I am trying to change PWM values by following settings. But instead of changing it it is giving me some thing weird.
I need your help guys. Could you please help me with this thing.
for( counter=0x0000;counter<=0x4571;counter++){
//*****Timer2 starting from here*****//
PR2 = 0x4571; // Initialize PR2 with 0x4571 = 17777 as PWM cycle
IFS0bits.T2IF = 0; // Clear Output Compare interrupt flag
IEC0bits.T2IE = 1; // Enable Output Compare interrupts
T2CONbits.TON = 1; // Start Timer2 with assumed settings
//**********************************//
//*****For RED LED OC1 choosed with timer 2*****//
OC1CONbits.OCM = 0; // Output compare channel is disabled
OC1R = 0x0000 ; // Initialize Compare Register1 with 50% duty cycle
OC1RS = counter; // Initialize Secondary Compare Register1 with 50% duty cycle
OC1CONbits.OCSIDL = 0; // Output capture will continue to operate in CPU Idle mode
OC1CONbits.OCFLT = 0; // No PWM Fault condition has occurred (this bit is only used when OCM<2:0> = 111)
OC1CONbits.OCTSEL = 0; // Timer2 is the clock source for output Compare
OC1CONbits.OCM = 0x6; // PWM mode on OC, Fault pin disabled
//*****For Green Led OC2 and OC3 Choosed with timer2 as well*****//
OC2CONbits.OCM = 0; // Output compare channel is disabled
OC2R =0x0000; // Initialize Compare Register1 with 50% duty cycle
OC2RS =counter; // Initialize Secondary Compare Register1 with 50% duty cycle
OC2CONbits.OCSIDL = 0; // Output capture will continue to operate in CPU Idle mode
OC2CONbits.OCFLT = 0; // No PWM Fault condition has occurred (this bit is only used when OCM<2:0> = 111)
OC2CONbits.OCTSEL = 0; // Timer2 is the clock source for output Compare
OC2CONbits.OCM = 0x6; // PWM mode on OC, Fault pin disabled
//*****For Blue Led OC2 and OC3 Choosed with timer2 as well*****//
OC3CONbits.OCM = 0; // Output compare channel is disabled
OC3R = 0x0000; // Initialize Compare Register1 with 50% duty cycle
OC3RS = counter; // Initialize Secondary Compare Register1 with 50% duty cycle
OC3CONbits.OCSIDL = 0; // Output capture will continue to operate in CPU Idle mode
OC3CONbits.OCFLT = 0; // No PWM Fault condition has occurred (this bit is only used when OCM<2:0> = 111)
OC3CONbits.OCTSEL = 0; // Timer2 is the clock source for output Compare
OC3CONbits.OCM = 0x6; // PWM mode on OC, Fault pin disabled
}
But this code is working alright. I put different values as well. It works fine.
//*****For RED LED OC1 choosed with timer 2*****//
OC1CONbits.OCM = 0; // Output compare channel is disabled
OC1R = 0x22B8; // Initialize Compare Register1 with 50% duty cycle
OC1RS = 0x22B8; // Initialize Secondary Compare Register1 with 50% duty cycle
OC1CONbits.OCSIDL = 0; // Output capture will continue to operate in CPU Idle mode
OC1CONbits.OCFLT = 0; // No PWM Fault condition has occurred (this bit is only used when OCM<2:0> = 111)
OC1CONbits.OCTSEL = 0; // Timer2 is the clock source for output Compare
OC1CONbits.OCM = 0x6; // PWM mode on OC, Fault pin disabled
//*****For Green Led OC2 and OC3 Choosed with timer2 as well*****//
OC2CONbits.OCM = 0; // Output compare channel is disabled
OC2R =0x22B8; // Initialize Compare Register1 with 50% duty cycle
OC2RS =0x22B8;//0x22B8; // Initialize Secondary Compare Register1 with 50% duty cycle
OC2CONbits.OCSIDL = 0; // Output capture will continue to operate in CPU Idle mode
OC2CONbits.OCFLT = 0; // No PWM Fault condition has occurred (this bit is only used when OCM<2:0> = 111)
OC2CONbits.OCTSEL = 0; // Timer2 is the clock source for output Compare
OC2CONbits.OCM = 0x6; // PWM mode on OC, Fault pin disabled
//*****For Blue Led OC2 and OC3 Choosed with timer2 as well*****//
OC3CONbits.OCM = 0; // Output compare channel is disabled
OC3R = 0x22B8; // Initialize Compare Register1 with 50% duty cycle
OC3RS = 0x22B8; // Initialize Secondary Compare Register1 with 50% duty cycle
OC3CONbits.OCSIDL = 0; // Output capture will continue to operate in CPU Idle mode
OC3CONbits.OCFLT = 0; // No PWM Fault condition has occurred (this bit is only used when OCM<2:0> = 111)
OC3CONbits.OCTSEL = 0; // Timer2 is the clock source for output Compare
OC3CONbits.OCM = 0x6; // PWM mode on OC, Fault pin disabled
//*****Timer1 starting from here*****//
PR1 = 65535; // Initialize PR2 cycle
T1CONbits.TCKPS = 2; // Setting pre-scaler to 1/64
IFS0bits.T1IF = 0; // Clear Output Compare interrupt flag
IEC0bits.T1IE = 1; // Enable Output Compare interrupts
T1CONbits.TON = 1; // Start Timer1 with assumed settings
//*****Timer2 starting from here*****//
PR2 = 0x4571; // Initialize PR2 with 0x4571 = 17777 as PWM cycle
IFS0bits.T2IF = 0; // Clear Output Compare interrupt flag
IEC0bits.T2IE = 1; // Enable Output Compare interrupts
T2CONbits.TON = 1; // Start Timer2 with assumed settings
//**********************************//

You are updating your PWMs each time around the loop.
It's very unlikely that the counter has had time to expire, therefore you keep resetting it before it has chance to "do" a PWM cycle.
At the end of the loop, you need to wait for (at least one of) your PWMs to have expired.
An alternative way might be to set up the next value you want in the loop and have an interrupt service routine copy that to the PWM register when the timer expires. And once that has happened, you can set up the next next value :) You need to take care about how you transfer values between the main loop and the ISR as they are effectively different "thread" contexts.

Related

Arduino CTC timer interrupt ~2x fast

Afternoon all
I'm looking for some assistance please with something that has been confusing me whilst trying to learn timer interrupts
You'd be best treating me as a novice. I have no specific goal here other than learning something that I think would be useful feather to add to my cap!
I have written the below sketch as a stab at a rigid framework for executing different fcns at different rates. I've done something similar using millis() and whilst that worked I found it inelegant that a) there was no obvious way to check for task overruns and backing-up the execution rate and b) the processor is bunged up by checking millis() every program cycle.*
Essentially what I think should be a 1ms timer interrupt on Timer2 (16MHz/64 prescaler /250 compare register =1000hz) is coming out around 0.5ms. I've been confused for hours on this but I'm prepared to accept it could be something fundamental/basic!
What's also throwing a spanner in the works is that using serial comms to try and debug the faster task rates seems to slow things down considerably, so I'm inferring the problem by counting up 1ms tasks to call 10,100 and 1000ms tasks and debugging at the slower level. I suppose chewing through a few characters at 9600baud probably is quite slow.**
I've pasted the code below. Any pointers highly appreciated. Be as harsh as you like :)
cheers
Al
*Whilst not what I'm confused about - any comments on my logic here also welcome
** Although I don't get how Serial.println manages to slow the program down. It's driven from interrupts so it should surely just drop the comms and perform the next ISR - effectively a task overrun. Any comments here also welcome
//NOTES
//https://www.robotshop.com/letsmakerobots/arduino-101-timers-and-interrupts
//https://sites.google.com/site/qeewiki/books/avr-guide/timers-on-the-atmega328
//http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf
//
//INITIALISE EVERYTHING
const int ledPin = 13;
volatile int nStepTask1ms = 0; // init 0 - to be used for counting number of 1ms tasks run and hence calling 10ms task
volatile int nStepTask10ms = 0;
volatile int nStepTask100ms = 0;
volatile int nStepTask1000ms = 0;
volatile int LEDFlashState = 0; // init 0 - variable to flip when LED on
volatile int millisNew = 0; // to store up to date time
volatile int millisOld = 0; // to store prev time
volatile int millisDelta = 0; // to store deltas
//
void setup()
{
Serial.begin(9600); //set up serial comms back to PC
pinMode(ledPin,OUTPUT); //to flash the embedded LED
noInterrupts(); //turn off interrupts while we set the registers
//set up TIMER first
TCCR2A = 0; //sets TCCR1A byte to zero, bits to be later individually mod'd
TCCR2B = 0; //sets TCCR1B byte to zero, bits to be later individually mod'd
TCNT2 = 0; //ensures counter value starting from zero
Serial.println("Timer1 vars reset");
TCCR2B |= (1<<WGM12); // bitwise or between itself and WGM12. TCCR2B = TCCR2B | 00001000. Sets WGM12 high. (CTC mode so WGM12=1, WGM 13,11,10 all 0) https://stackoverflow.com/questions/141525/what-are-bitwise-shift-bit-shift-operators-and-how-do-they-work
Serial.println("Mode 4 CTC set");
Serial.println("TCCR2B=");
Serial.println(TCCR2B,BIN);
TCCR2B |= (1<<CS11); // sets CS11 high
TCCR2B |= (1<<CS10); // sets CS10 high (i.e. this and above give /64 prescaler)
Serial.println("Prescaler set to 64");
OCR2A = 250; //compare match register for timer2
Serial.println("Compare Register set");
Serial.println("OCR2A=");
Serial.println(OCR2A);
TIMSK2 |= (1 << OCIE2A); //enables interrupts - https://playground2014.wordpress.com/arduino/basics-timer-interrupts/
Serial.println("Interrupt Mask Register Set");
Serial.println("TIMSK2=");
Serial.println(TIMSK2);
interrupts(); //enable interrupts again - not sure if this is required given OCIE1A being set above?
}
//set up ISR for Timer2 - timer structure called every interrump (1ms) that subsequently calls 1,10,100 and 1000msec task fcns
ISR(TIMER2_COMPA_vect)
{
TASK_1ms();
if (nStepTask1ms>9)
{
TASK_10ms();
if (nStepTask10ms>9)
{
TASK_100ms();
if (nStepTask100ms>9)
{
TASK_1000ms();
}
}
}
}
void TASK_1ms()
{
// 1ms tasks here
nStepTask1ms++;
}
void TASK_10ms()
{
//10ms tasks here
nStepTask1ms=0;
nStepTask10ms++;
}
void TASK_100ms()
{
//100ms tasks here
nStepTask10ms=0;
nStepTask100ms++;
//Serial.println(nStepTask100ms);
}
void TASK_1000ms()
{
//1000ms tasks here
nStepTask100ms=0;
//do something
changeLEDFlashState();
//check timing tick of this task
millisNew=millis();
millisDelta=millisNew-millisOld;
Serial.println(millisDelta);
millisOld=millisNew;
nStepTask1000ms++;
}
void changeLEDFlashState()
{
if(LEDFlashState==0)
{
digitalWrite(ledPin,HIGH);
LEDFlashState=1;
//Serial.println("LED Turned On");
}
else
{
digitalWrite(ledPin,LOW);
LEDFlashState=0;
//Serial.println("LED Turned Off");
}
}
void loop()
{
// empty
}
You have two lines here:
TCCR2B |= (1<<CS11); // sets CS11 high
TCCR2B |= (1<<CS10); // sets CS10 high (i.e. this and above give /64 prescaler)
These two lines set the lower three bits of TCCR2B to 011, which is a /32 prescaler.
Note that for Timer1 and Timer2, the prescaler settings are different than Timer0.
For Timer0, the settings above would give you a /64 prescaler.

how can I make multiple ultrasonic sensors work at the same time using atmega32

I am working on an auto-parking car robot and I am using 8 (hc-sr04) ultrasonic sensors (2 at each side) but the problem is that I am using atmega32 which has limited resources only 3 external interrupts and 3 timers (and even if using interrupts somehow works I might run into risk to have two interrupts triggered at the same time).
I am using this sensor : http://ram-e-shop.com/oscmax/catalog/product_info.php?products_id=907
I've tried using digital I/O pins with polling procedure but it didn't work.
here is the code for polling procedure:
unsigned int read_sonar(){
int dist_in_cm = 0;
init_sonar(); // Setup pins and ports
trigger_sonar(); // send a 10us high pulse
while(!(ECHO_PIN & (1<<ECHO_BIT))){ // while echo pin is still low
USART_Message("echo pin low\r\n");
trig_counter++;
uint32_t max_response_time = SONAR_TIMEOUT;
if (trig_counter > max_response_time){ // SONAR_TIMEOUT
return TRIG_ERROR;
}
}
TCNT1=0; // reset timer
TCCR1B |= (1<<CS10); // start 16 bit timer with no prescaler
TIMSK |= (1<<TOIE1); // enable overflow interrupt on timer1
overFlowCounter=0; // reset overflow counter
sei(); // enable global interrupts
while((ECHO_PIN & (1<<ECHO_BIT))){ // while echo pin is still high
USART_Message("echo pin high\r\n");
if (((overFlowCounter*TIMER_MAX)+TCNT1) > SONAR_TIMEOUT){
USART_Message("timeout");
return ECHO_ERROR; // No echo within sonar range
}
};
TCCR1B = 0x00; // stop 16 bit timer with no prescaler
cli(); // disable global interrupts
no_of_ticks = ((overFlowCounter*TIMER_MAX)+TCNT1); // counter count
dist_in_cm = (no_of_ticks/(CONVERT_TO_CM*CYCLES_PER_US)); // distance in cm
return (dist_in_cm );}
This method doesn't work if I want to read all sensors at the same time, because it gets stuck in the loop for a while.
I also tried using freeRTOS to build a task that checks the state of pins like every 1msec but this won't be a time accurate.
any help?
Assuming that You use internal clock which is 8MHz I would try to handle this inside timer overflow interrupt and would use whole port to connect the sensors.
Use Timer in normal mode or CTC mode (which I find quite intuitive) to ensure periodical interrupts. Set the appropriate period. Remember that the clock has pretty low frequency so don't exaggerate (I think that 0,25 ms will fit).
Connect the sensors to one port, e.g. PORTB. This is a nice situation because ATmega32 has 4 ports with pins numbered from 0-7 and you use 8 sensors so the register for the specific port can cover all of the pins and You can use one read to get states of all of the pins.
Implement the logic:
volatile uint8_t sensors_states;
volatile uint8_t read_flag = 0;
ISR(TIMER0_OVF_vect)
{
sensors_states = PORTB;
read_flag = 1;
}
int main()
{
// Initialize peripherals ...
// You must assume on your own how much time could the pin be held
// in the same state. This is important because the number must not
// be bigger than max value for the type of the array
uint8_t states_time[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t prev_sensors_states = PORTB;
while(1)
{
// Wait until the flag will be set in the ISR
if(read_flag)
{
for(uint8_t i = 0, mask = 0x80 ; i < 8 ; i ++, mask >>= 1)
{
states_time[i]++;
// Compare the previous state and present state on each pin
uint8_t state = mask & sensors_states;
if((mask & prev_sensors_states) != state)
{
// Here you can use the state of the pin and the duration of that state.
// Remember that when 'state' is > 0 it means that previous state of the
// pin was '0' and if if 'state' is == 0 then the previous pin state
// was '1' (negation).
do_something_with_pin_change(states_time[i], state);
states_time[i] = 0;
}
}
// Save the previous states of the pins
prev_sensors_states = sensors_states;
// Clear the flag to await next data update
read_flag = 0;
}
}
}
If You will try to use FreeRTOS You could use ulTaskNotifyTake and vTaskNotifyGiveFromISR, instead of using read_flag, to implement a simple mechanism which will notify a task from the interrupt that the port has been read. The processor will go into idle state for a while and you could then invoke a sleep function to minimize power consumption.
I don't know what You want to do with this data so I've invoked do_something_with_pin_change function to indicate the point where You can use the data.
To sum up for this solution You would only use one interrupt and of course 8 pins.

Embedded C code to control a DC motor with a PIC microcontroller

Im trying to create an embedded c code to control a dc motor with the PIC32MX460F512L microcontroller. Ive Configured the system clock at 80MHz, and the peripheral clock at 10MHz, Am using Timer 1 for pulsing the PWM with a given duty cycle, and Timer 2 for measuring the motor run time. I have a header file(includes.h) that contains system configuration information eg clock. Ive created most of the functions but some are a bit challenging. For example, initializing the LEDS and the functions for forward, backward movements and stop, I wanted the dc motor to run in forward direction for 4 sec at 70% duty cycle, then stop for 1 sec then reverse for 3 sec at 50% duty cycle and then stop for 1 sec and then forward again for 3 sec at 40% duty cycle, stop for 1 sec and finally forward for 5 sec at 20% duty cycle. Any suggestions for the forward, stop, and reverse functions
#include <stdio.h>
#include <stdlib.h>
#include <includes.h>
void main()
{
// Setting up PIC modules such as Timers, IOs OCs,Interrupts, ...
InitializeIO();
InitializeLEDs();
InitializeTimers();
while(1) {
WaitOnBtn1();
Forward(4.0,70);
Stop(1.0);
Backward(3.0,50);
Stop(2);
Forward(3.0,40);
Stop(1.0);
Backward(2.0,20);
LEDsOFF();
}
return;
}
void InitializeIO(){
TRISAbits.TRISA6 = 1;
TRISAbits.TRISA7 = 1;
TRISGbits.TRISG12 = 0;
TRISGbits.TRISB13 = 0;
LATGbits.LATB12 = 0;
LATGbits.LATB13 = 0;
return;
}
void InitializeLEDs(){
//code to initialize LEDS
}
void InitializeTimers(){
// Initialize Timer1
T1CON = 0x0000; // Set Timer1 Control to zeros
T1CONbits.TCKPS=3; // prescale by 256
T1CONbits.ON = 1; // Turn on Timer
PR1= 0xFFFF; // Period of Timer1 to be full
TMR1 = 0; // Initialize Timer1 to zero
// Initialize Timer2
T2CON = 0;
T2CONbits.TCKPS = 7; // prescale by 256
T2CONbits.T32 = 1; // use 32 bits timer
T2CONbits.ON = 1;
PR2 = 0xFFFFFFFF; // Period is set for 32 bits
TMR2 = 0;
}
void WaitOnBtn1(){
// wait on Btn1 indefinitely
while(PORTAbits.RA6 == 0);
// Turn On LED1 indicating it is Btn1 is Pushed
LATBbits.LATB10 = 1;
return;
}
void Forward(float Sec, int D){
int RunTime = (int)(Sec*39000); // convert the total
time to number of Tics
TMR2 = 0;
//LEDs
LATGbits.LATG12 = 1; // forward Direction
LATBbits.LATB12 = 0;
LATBbits.LATB13 = 0;
LATBbits.LATB11 = 1;
// Keep on firing the PWM as long as Run time is not
elapsed
while (TMR2 < RunTime){
PWM(D);
}
return;
}
void PWM(int D){
TMR1 = 0;
int Period = 400;
while (TMR1< Period) {
if (TMR1 < Period*D/100){
LATGbits.LATG13 = 1;
}
else{
LATGbits.LATG13 = 0;
}
}
Functions, not methods, to be precise.
So what is exactly the question?
What I can say from a quick look on a source code:
LEDs initialisation should be done as you did in InitializeIO() function. Simply set proper TRISx bits to 0 to configure LED pins as output.
For the PWM and motor control functions you should take some time and try to understand how builtin PWM peripheral works. It is a part of OC (Output Compare) and it is very easy to use. Please, take look on following link http://ww1.microchip.com/downloads/en/DeviceDoc/61111E.pdf
and this one for the minimal implementation using builtin peripheral libraries https://electronics.stackexchange.com/questions/69232/pic32-pwm-minimal-example
Basically you need to set up OC registers to "make" OC module acts like PWM. You need to allocate one of the timers to work with OC module (it will be used for base PWM frequency) and that's it.
All you need after that is to set PWM duty cycle value by setting timer PRx register, you don't need to swap bits like in your PWM routine.
To stop it simple stop it simply disable the timer.
To run it again run the timer.
To change direction (it depends of your driver for the motor) I guess you need just to toggle direction pin.
I hope it helps...

CCP module - PWM mode

I'm trying to make a PWM output with this code, but apparently something is missing. Because when I check the Logic Analyzer in MPLab, nothing happens on CCP2 output. I'm working with the pic18f25k80.
void main() {
// Set up PWM
CCP2CON = 0b00001100; // Enable PWM on CCP2, bits 5:4 are LSB part of duty cycle
CCPTMRS = 0b00000000; // Use timer2 for all CCP modules
CCPR2L = 31; // MSB part of duty cycle
TRISC = 0b00000000; // Set port C as output
PORTC = 0; // Clear port C
// Set Up timer2
PR2 = 249; // PWM period = (PR+1)*4*Tcy = 1ms
T2CON = 0b00000100; // Enable TMR2 with prescaler = 1
while(1)
{
}
}
I expect when
TMR2 = PR2, CCP2 output toggles and timer is reset
further, TMR2 = CCPR2L (duty cycle), CCP2 output toggles
TMR2 keeps counting until step 1 is reached.
I suppose this is what should happen automatically. I mean I don't have to write the code for that, because that's THE function of the PWM module, right?
What am I missing?
Additional info:
TMR 2 is counting.
When I add PORTC = 0xFF; in the while loop and debug the code again. All signals on Port C are set, except RC2 (RC2 = corresponding output of CCP2).
When I try the same code for CCP3, all signals on port C are set, except RC2 and RC6 (RC6 = corresponding output of CCP3).
When I replace PORTC = 0xFF; with PORTCbits.CCP2 = 1;, only RC1 is set high.
Does this last bullet mean that the CCP2 is muxed with RC1 instead of RC2?

Can't initialize PWM on dsPIC33F

I'm probably just having a can't-see-the-forest-for-the-trees moment with one of these registers, but I can't get the PWM working on the dsPIC33FJ32MC102 microcontroller (warning: big PDF) I'm playing around with. I've followed both the datasheet and further application note (warning: another PDF) and even code samples and I can't see what I'm doing wrong, though on my testbench I'm getting Vcc on the high output and Ground on the low output. I've tied the fault pins both to Vcc and disabled the register keycode so my changes should see some effect. What am I doing wrong?
#define FOSC (3686400ULL)
#define FCY (FOSC/2)
#include <xc.h>
#include <libpic30.h>
...
#pragma config PWMPIN = ON // Motor Control PWM Module Pin Mode bit (PWM module pins controlled by PORT register at device Reset)
#pragma config PWMLOCK = OFF
...
void main(void){
...
//setup PWM
//Clear faults
IFS3bits.PWM1IF = 0;
IFS3bits.FLTA1IF = 0;
IFS4bits.FLTB1IF = 0;
//Setup dead times
P1DTCON1bits.DTAPS = 0b00; //Dead time tick is 1 TCY
P1DTCON1bits.DTBPS = 0b00;
P1DTCON1bits.DTA = 10; //Dead time is 10TCY ~= 3uS
P1DTCON1bits.DTB = 10;
P1DTCON2bits.DTS1A = 0; //Active and Inactive transition dead times
P1DTCON2bits.DTS2A = 0; //0 takes A dead time
P1DTCON2bits.DTS3A = 0; //1 takes B dead time
P1DTCON2bits.DTS1I = 1;
P1DTCON2bits.DTS2I = 1;
P1DTCON2bits.DTS3I = 1;
P1TCONbits.PTOPS = 0b0000; //1 CPU tick = 1 PWM tick
P1TCONbits.PTCKPS = 0b00;
P1TCONbits.PTMOD = 0b00;
P1TCONbits.PTSIDL = 0; //Run when CPU idles
// no longer necessary since I disabled register write lock:
// __builtin_write_PWMSFR(&P1FLTACON,0x0000,&PWM1KEY);
// __builtin_write_PWMSFR(&P1FLTBCON,0x0000,&PWM1KEY);
// __builtin_write_PWMSFR(&PWM1CON1 ,0x0077,&PWM1KEY);
PWM1CON1 = 0x0077; //Enable all 3 channels
P1FLTACON = 0x0000; //Disable faults
P1FLTBCON = 0x0000;
//Setup Wave freq/duty
//Fosc = 7.3728 MHz -> Fcy = 3.6864MHz
//Desire a PWM of 20250Hz (smaller scalar error than 20kHz)
//P1TPER = [Fcy/(Fpwm*Scalar)] - 1
//Therefore P1TPER = [3.6864M/(20250*1)] - 1 = 181;
P1TPER = 181;
P1DC1 = 0x7FFF; // 0x7FFF for 50%
P1DC2 = 0x7FFF;
P1DC3 = 0x7FFF;
P1OVDCON = 0x3F00; //Disable override; override disables PWM
PWM1CON2 = 0x0000;
P1TCONbits.PTEN = 1; //Turn on
...
while(1);
}
I believe you have set up the timer to count from 0 to 181 (P1TPER) and then reset and repeat. But you have set the duty cycle registers to 0x7FFF, which is greater than 181. So I believe the duty cycle value will never be less than the timer value and therefore the output will never change. Try setting the duty cycle registers to 181/2 = 90 to get a duty cycle of 50%.

Resources