chipKIT® Development Platform

Inspired by Arduino™

High frequency (> 1 MHz) PWM

Created Tue, 28 Jul 2015 08:06:18 +0000 by Suwandy


Suwandy

Tue, 28 Jul 2015 08:06:18 +0000

Hi guys, I'm using ChipKit Uno32 (PIC32MX320F) with system clock 80MHz. I would like to produce PWM with frequency around 10MHz to 30MHz. Is this possible?

The datasheet show calculation of PWM by this equation:

PWM Period = [ (PR + 1) * TPB * (TMR Prescaller Value) ] PWM Frequency = 1 / PWM Period

I tried using Output Compare Module with PWM mode without fault pin (OCM<2:0> 110) I used Timer3 as clock source, 1:1 prescaller, and set the PR3 = 152. I should get

F = 1 / [ (152 + 1) * (1 / 80MHz) * (1) ] F = 522,875.816 Hz or 522KHz

So far this is true. i used oscilloscope to look the frequency and it's true.

But when i go above 800 KHz, the oscilloscope showed nothing. if i feed PR3 = 100, i still got PWM with 792KHz on oscilloscope. But when i go **lower than 100,**the oscilloscope showed nothing?

how can i produce PWM beyond 1 MHz ? Are there better way to approach this than using OCxR module?


EmbeddedMan

Tue, 28 Jul 2015 14:21:28 +0000

Yes, it should work. I'm not sure why it's not working for you. I think you can technically have a PR value down to 1.

Are you sure your oscilloscope can measure frequencies higher than what you're seeing?

*Brian


Suwandy

Wed, 29 Jul 2015 04:25:52 +0000

After re-check i found the culprit. Register that control Duty Cycleis OCxR and OCxRs. To control Duty Cycle, i have to keep ratio of OCxR / PRx below 1. Apparently i left OCxR static and when i tried with lower PRx value for higher frequency, the OCxR value greather than PRx, making the PWM cannot be executed.

int DutyCycle[9];

void setup() {
  pinMode(3,OUTPUT);
  
  T3CON &amp;= ~(1&lt;&lt;15);  //turn OFF timer3
  T3CON &amp;= ~(1&lt;&lt;4);
  T3CON &amp;= ~(1&lt;&lt;5);   // 00, 1:1 prescaler
  TMR3 = 0;           //clear timer3 counter
  PR3 = 2;          //timer3 Period, PR = (FPB / (PWM Freq * PreScal)) - 1
  T3CON |= (1&lt;&lt;15);   //turn ON timer3
  
  DutyCycle[0] = 0.1f * PR3;  //10%
  DutyCycle[1] = 0.2f * PR3;  //20%
  DutyCycle[2] = 0.3f * PR3;  //30%
  DutyCycle[3] = 0.4f * PR3;  //40%
  DutyCycle[4] = 0.5f * PR3;  //50%    DutyCycle
  DutyCycle[5] = 0.6f * PR3;  //60%
  DutyCycle[6] = 0.7f * PR3;  //70%
  DutyCycle[7] = 0.8f * PR3;  //80%
  DutyCycle[8] = 0.9f * PR3;  //90%
  
  OC1CON &amp;= ~(1&lt;&lt;15);   //turn OFF OutputCompare module
  OC1CON &amp;= ~(1&lt;&lt;0);
  OC1CON |= (1&lt;&lt;1);     // 110, PWM mode, faultPin disabled
  OC1CON |= (1&lt;&lt;2);
  OC1CON |= (1&lt;&lt;3);     //timer3 as clock source
  OC1R = DutyCycle[4];  //using 50% DutyCycle
  OC1RS = DutyCycle[4]; //using 50% DutyCycle
  OC1CON |= (1&lt;&lt;15);    //turn ON OutputCompare module
  
}

void loop() {
  
}

After setting it dynamic for 50% Duty Cycle, everything running okay down to PRx=2 (around 26.66 MHz).

Questions: