AT32UC3C2512C PWM duty cycle

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi!
I have copy an PWM example and I'm trying to change the duty cycle on pwm1 but I don't know how to do that. pwm0 is generating 10KHz and pwm1 is generating 1KHz puls train and it works fine. Can someone help me with code exampe on how to change the duty cycle?

Regards!

[/code]
// =================================================================================
// For PWM
// =================================================================================
pwm_opt_t pwm0_opt; // PWM1 option config.
pwm_opt_t pwm1_opt; // PWM2 option config.

avr32_pwm_channel_t pwm0_channel = {{0}, // cmr
{0}, // cdty
{0}, // cdtyupd
{0}, // cprd
{0}, // cprdupd
{0}, // ccnt
{0}, // dt
{0}};// dtupd ; One channel config.
unsigned int channel0_id;

avr32_pwm_channel_t pwm1_channel = {{0}, // cmr
{0}, // cdty
{0}, // cdtyupd
{0}, // cprd
{0}, // cprdupd
{0}, // ccnt
{0}, // dt
{0}};// dtupd ; One channel config.
unsigned int channel1_id;

channel0_id = PWM0_CHANNEL_ID;
channel1_id = PWM1_CHANNEL_ID;
//gpio_enable_module_pin(PWM0_L_PIN, PWM0_L_FUNCTION);
gpio_enable_module_pin(PWM0_H_PIN, PWM0_H_FUNCTION);
gpio_enable_module_pin(PWM1_H_PIN, PWM1_H_FUNCTION);

// PWM0 controller configuration.
pwm0_opt.diva = AVR32_PWM_DIVA_CLK_OFF;
pwm0_opt.divb = AVR32_PWM_DIVB_CLK_OFF;
pwm0_opt.prea = AVR32_PWM_PREA_CCK;
pwm0_opt.preb = AVR32_PWM_PREB_CCK;

pwm0_opt.fault_detection_activated = false;
pwm0_opt.sync_channel_activated = false;
pwm0_opt.sync_update_channel_mode = PWM_SYNC_UPDATE_MANUAL_WRITE_MANUAL_UPDATE;
pwm0_opt.sync_channel_select[0] = false;
pwm0_opt.sync_channel_select[1] = false;
pwm0_opt.sync_channel_select[2] = false;
pwm0_opt.sync_channel_select[3] = false;
pwm0_opt.cksel = PWM_CKSEL_MCK; //PWM_CKSEL_MCK master clock. PWM_CKSEL_GCLK generic high speed clock
pwm_init(&pwm0_opt);

// PWM1 controller configuration.
pwm1_opt.diva = AVR32_PWM_DIVA_CLK_OFF;
pwm1_opt.divb = AVR32_PWM_DIVB_CLK_OFF;
pwm1_opt.prea = AVR32_PWM_PREA_CCK;
pwm1_opt.preb = AVR32_PWM_PREB_CCK;

pwm1_opt.fault_detection_activated = false;
pwm1_opt.sync_channel_activated = false;
pwm1_opt.sync_update_channel_mode = PWM_SYNC_UPDATE_MANUAL_WRITE_MANUAL_UPDATE;
pwm1_opt.sync_channel_select[0] = false;
pwm1_opt.sync_channel_select[1] = false;
pwm1_opt.sync_channel_select[2] = false;
pwm1_opt.sync_channel_select[3] = false;
pwm1_opt.cksel = PWM_CKSEL_MCK; //PWM_CKSEL_MCK master clock. PWM_CKSEL_GCLK generic high speed clock
pwm_init(&pwm1_opt);

// PWM0 channel configuration
pwm0_channel.CMR.dte = 1; // Enable Deadtime for complementary Mode
pwm0_channel.CMR.dthi = 1; // Deadtime Inverted on PWMH
pwm0_channel.CMR.dtli = 0; // Deadtime Not Inverted on PWML
pwm0_channel.CMR.ces = 0; // 0/1 Channel Event at the End of PWM Period
pwm0_channel.CMR.calg = PWM_MODE_LEFT_ALIGNED; // Channel mode.
pwm0_channel.CMR.cpol = PWM_POLARITY_LOW; // Channel polarity.
pwm0_channel.CMR.cpre = AVR32_PWM_CPRE_CCK; // Channel prescaler.
pwm0_channel.cdty = 200; // Channel duty cycle, should be < CPRD.
pwm0_channel.cprd = 797; // Channel period.
// With these settings, the output waveform period will be :
// (8MHz)/800 == 10KHz == (MCK/prescaler)/period, with MCK == 8MHz,
// prescaler == 1, period == 800.

// PWM1 channel configuration
pwm1_channel.CMR.dte = 1; // Enable Deadtime for complementary Mode
pwm1_channel.CMR.dthi = 1; // Deadtime Inverted on PWMH
pwm1_channel.CMR.dtli = 0; // Deadtime Not Inverted on PWML
pwm1_channel.CMR.ces = 0; // 0/1 Channel Event at the End of PWM Period
pwm1_channel.CMR.calg = PWM_MODE_LEFT_ALIGNED; // Channel mode.
pwm1_channel.CMR.cpol = PWM_POLARITY_LOW; // Channel polarity.
pwm1_channel.CMR.cpre = AVR32_PWM_CPRE_CCK; // Channel prescaler.
pwm1_channel.cdty = 4000; // Channel duty cycle, should be < CPRD.
pwm1_channel.cprd = 8000; // Channel period.
// With these settings, the output waveform period will be :
// (8MHz)/8000 == 1KHz == (MCK/prescaler)/period, with MCK == 8MHz,
// prescaler == 1, period == 8000.

pwm_channel_init(channel0_id, &pwm0_channel); // Set channel configuration to channel 0
pwm_start_channels((1 << channel0_id)); // Start channel 0.

pwm_channel_init(channel1_id, &pwm1_channel); // Set channel configuration to channel 0
pwm_start_channels((1 << channel1_id)); // Start channel 1.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dretlanning wrote:

pwm0_channel.CMR.calg = PWM_MODE_LEFT_ALIGNED; // Channel mode.

Both channels are left aligned, so have a look at Figure 33-5 Waveform Properties in the datasheet. Basically the PWM module starts counting, toggles once when it reaches CDTY and toggles a second time when it reaches CPRD.
Dretlanning wrote:

// PWM0 channel configuration
pwm0_channel.cdty = 200;  // Channel duty cycle, should be < CPRD.
pwm0_channel.cprd = 797;  // Channel period.

// PWM1 channel configuration
pwm1_channel.cdty = 4000; // Channel duty cycle, should be < CPRD.
pwm1_channel.cprd = 8000; // Channel period.

=====================================DearForumDontBreakMyLongLines

With CDTY = 200 and CPRD = 797 you have almost a 25/75 duty cycle. With CDTY = 4000 and CPRD = 8000 you have a 50/50 duty cycle. Use that to configure your desired duty cycle.

Well, I think that’s what the datasheet tried to tell me. Actually haven’t used PWM yet.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks!
But I want to change the duty cycle in my main program with the "Channel Cuty Cycle Update Register" to prevent unexpected output waveform. If some one have an simpel code example.
Regards!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I will answer my own question!
This seems to work for me.

pwm1_channel.cdtyupd = pwm_duty; // New duty cycle value
pwm1_channel.cprdupd = 8000; // New period value
pwm1_channel.dtupd = 0; // New dead-time value

pwm_update_channel(channel1_id,&pwm1_channel);
pwm_update_manual_write_manual_update();