Go Down

Topic: Multiple PWM Outputs with Unique Frequencies (Read 9 times) previous topic - next topic

ralphnev

manual says:
      mclk/1024*1/255 is the slowest clock  ==   84000000/1024/255==321.69....HZ
theoreticaly the longest period should be 321.7/65535 =.00491.... hz or 203sec/ pulse...

i dislike the clock setting function / you may have better luck seting it explitistly from the associated values (Find your own dividers & send them to the function )

hook a led(& resistor) to pin 9 & try the code below
Code: [Select]

/*
  This example code is in the public domain.
*/

// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;
#define PWM_CHANNEL_0 0
#define PWM_CHANNEL_4 4
#define PWM_CHANNEL_5 5
#define PWM_CHANNEL_6 6
int period =2;


void
startTimer (Tc * tc, uint32_t channel, IRQn_Type irq, uint32_t frequency)
{
  pmc_set_writeprotect (false);
  pmc_enable_periph_clk ((uint32_t) irq);
  TC_Configure (tc, channel,
TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC |
TC_CMR_TCCLKS_TIMER_CLOCK4);
  uint32_t rc =
    (VARIANT_MCK / 128 / frequency) > 2 ? (VARIANT_MCK / 128 / frequency) : 2;
  //128 because we selected TIMER_CLOCK4 above
  TC_SetRA (tc, channel, rc / 2); //50% high, 50% low
  TC_SetRC (tc, channel, rc);
  TC_Start (tc, channel);
  tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPCS;
  tc->TC_CHANNEL[channel].TC_IDR = ~TC_IER_CPCS;
  NVIC_EnableIRQ (irq);
}
//--------------------------------------------------------------------------
// the setup routine runs once when you press reset:
void setup() {               
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT); 
   Serial.begin(9600);
  startTimer(TC1, 0, TC3_IRQn, 1);
  //PWM config
  pmc_enable_periph_clk(ID_PWM); 
 
  PWMC_DisableChannel(PWM, PWM_CHANNEL_4); 
 
  PWMC_ConfigureClocks(VARIANT_MCK/1024 /255, 0, VARIANT_MCK);

int ulPin = 9;
              // Setup PWM for this pin
              PIO_Configure(g_APinDescription[ulPin].pPort,
              g_APinDescription[ulPin].ulPinType,
              g_APinDescription[ulPin].ulPin,
              g_APinDescription[ulPin].ulPinConfiguration);
   //***************Channel 4           
   PWMC_ConfigureChannel(
     (Pwm*)     PWM,    // pPwm,
     (uint32_t)    PWM_CHANNEL_4  ,  // ul_channel,
     (uint32_t)    PWM_CMR_CPRE_CLKA  ,  // prescaler,
     (uint32_t)    0  ,  // alignment, 0=left alighned
     (uint32_t)    0  ); // polarity )
    PWMC_SetPeriod(
      (Pwm*) PWM,  //pPwm,
      (uint32_t) PWM_CHANNEL_4,//ul_channel,   
      (uint16_t) period
    );
    PWMC_SetDutyCycle(
      (Pwm*) PWM ,//pPwm,
      (uint32_t) PWM_CHANNEL_4,// ul_channel,
      (uint16_t) period/2 //duty
      );
  PWMC_EnableChannel(
        (Pwm*) PWM,  //pPwm,
        (uint32_t)  PWM_CHANNEL_4// ul_channel
      ) ;
}


//*******************************************************8
volatile boolean l;

// This function is called every 1 sec.
void TC3_Handler()
{
  // You must do TC_GetStatus to "accept" interrupt
  // As parameters use the first two parameters used in startTimer (TC1, 0 in this case)
  TC_GetStatus(TC1, 0);

  digitalWrite(led, l = !l);
  period < 4 ?  period = 4:period =period  << 1;
  period >65536 ? period = 4 :period;
      PWMC_SetPeriod(
      (Pwm*) PWM,  //pPwm,
      (uint32_t) PWM_CHANNEL_4,//ul_channel,
      (uint16_t) period-1
    );
      PWMC_SetDutyCycle(
      (Pwm*) PWM ,//pPwm,
      (uint32_t) PWM_CHANNEL_4,// ul_channel,
      (uint16_t) PWM->PWM_CH_NUM[4].PWM_CPRD/2 //duty
      );
}

// the loop routine runs over and over again forever:
void loop() {
Serial.println( PWM->PWM_CH_NUM[4].PWM_CPRD);
 
}

randomvibe

#6
Feb 12, 2013, 09:55 am Last Edit: Feb 12, 2013, 10:02 am by randomvibe Reason: 1
Okay, I finally came up with a clean alternate approach for setting up PWM frequencies from within a sketch, for up to two unique frequencies.  The trick is to utilize the two PWM clocks (CLKA & CLKB) provided by the SAM3X8E chip.

I wrote and enclosed a library (pwm01.h).  It includes 4 user functions to:  1) setup PWM resolution, 2) setup PWM pin, frequency & pick clock, 3) write duty cycle, and 4) stop PWM.  See example code for usage:

Code: [Select]
#include "C:\Programs\arduino-1.5.1r2\hardware\arduino\sam\libraries\Pwm01\pwm01.h"

void setup()
{
   uint32_t  pwm_duty = 32767;
   uint32_t  pwm_freq1 = 2;  
   uint32_t  pwm_freq2 = 5000;

   // Set PWM Resolution
   pwm_set_resolution(16);  

   // Setup PWM Once (Up to two unique frequencies allowed
   //-----------------------------------------------------    
   pwm_setup( 6, pwm_freq1, 1);  // Pin 6 freq set to "pwm_freq1" on clock A
   pwm_setup( 7, pwm_freq2, 2);  // Pin 7 freq set to "pwm_freq2" on clock B
   pwm_setup( 8, pwm_freq2, 2);  // Pin 8 freq set to "pwm_freq2" on clock B
   pwm_setup( 9, pwm_freq2, 2);  // Pin 9 freq set to "pwm_freq2" on clock B
     
   // Write PWM Duty Cycle Anytime After PWM Setup
   //-----------------------------------------------------    
   pwm_write_duty( 6, pwm_duty );  // 50% duty cycle on Pin 6
   pwm_write_duty( 7, pwm_duty );  // 50% duty cycle on Pin 7
   pwm_write_duty( 8, pwm_duty );  // 50% duty cycle on Pin 8
   pwm_write_duty( 9, pwm_duty );  // 50% duty cycle on Pin 9

   delay(30000);  // 30sec Delay; PWM signal will still stream
       
   // Force PWM Stop On All Pins
   //-----------------------------    
   pwm_stop( 6 );
   pwm_stop( 7 );
   pwm_stop( 8 );
   pwm_stop( 9 );
}

void loop()
{  
}



The pwm01.h library and example code were tested in IDE 1.5.1r2.  Additional notes on this library:
- Applies to Arduino-Due board, PWM pins 6, 7, 8 & 9.
- Libary Does not operate on the TIO pins.
- Unique frequencies set via PWM Clock-A ("CLKA") and Clock-B ("CLKB")
 Therefore, up to two unique frequencies allowed.
- Set max duty cycle counts (pwm_max_duty_Ncount) equal to 255 per Arduino approach.  
 This value is best SUITED for low frequency applications (2hz to 40,000hz) such as
 PWM motor drivers, 38khz infrared transmitters, etc.
- Future library versions will address high frequency applications.
- Arduino's "wiring_analog.c" function was very helpful in this effort.

dishimwe


Okay, I finally came up with a clean alternate approach for setting up PWM frequencies from within a sketch, for up to two unique frequencies.  The trick is to utilize the two PWM clocks (CLKA & CLKB) provided by the SAM3X8E chip.

I wrote and enclosed a library (pwm01.h).  It includes 4 user functions to:  1) setup PWM resolution, 2) setup PWM pin, frequency & pick clock, 3) write duty cycle, and 4) stop PWM.  See example code for usage:

The pwm01.h library and example code were tested in IDE 1.5.1r2.  Additional notes on this library:
- Applies to Arduino-Due board, PWM pins 6, 7, 8 & 9.


Do you know how use that to get higher frequencies like 25MHz?

ralphnev


Do you know how use that to get higher frequencies like 25MHz?

not possible
must beable to divide 84MHz by an integer so the limits are
42MHz , 28, 21, 16.8, 14, 12, 10.5 , ....

dishimwe

I have been using the pmc but i cannot get a clean square wave on higher frequencies, how can i use the PMW to generate 21MHz?

Go Up