PWM on TCx module not working on a SAMD21 using ASFv4

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

Dear all,

 

I'm using a board with an SAMD21G18A, with some startup code from Atmel START (ASFv4), that configure three instances of the TC(3,4,5) to generate three different PWM signals. My clock comes from the internal osc32k, and is multiplied by the DPLL up to 48Mhz to the GEN0, which clocks the CPU and peripherals.

 

I've been trying for the last 2 days do something that is usually very simple: get 3 PWM signals working to drive a RGB led. I used Atmel Start to generate all the config and example code for an easy start. But here is the problem: I can set the frequency of the signal, which I can actually see on the scope, but can't set the DUTY cycle at all.

 

The issue is, I can write and read both duty and period from registers fine (either using the ASF4 functions, or straight down to the registers), but I only get a fixed signal with 99.9% duty, no matter what I try... Tried MANY configurations, registers, etc.. Cant figure out whats wrong. One thing is for sure, the code the Atmel START generates does not work out of the box for the PWM.

 

 

my hpl_tc_config.h (in short) and main file are as follows.

 

Thanks in advance!

#define CONF_TC4_ENABLE 1
#define CONF_TC4_PRESCALER TC_CTRLA_PRESCALER_DIV64_Val
#define CONF_TC4_PER 0x32
#define CONF_TC4_WAVE_PER_VAL 0x3e8
#define CONF_TC4_WAVE_DUTY_VAL 0x1f4

/* Caculate pwm ccx register value based on WAVE_PER_VAL and Waveform Duty Value */
#elif CONF_TC4_PRESCALER == TC_CTRLA_PRESCALER_DIV64_Val
#define CONF_TC4_CC0 ((uint32_t)(((double)CONF_TC4_WAVE_PER_VAL * CONF_GCLK_TC4_FREQUENCY) / 64000000 - 1))
#define CONF_TC4_CC1 ((CONF_TC4_CC0 * CONF_TC4_WAVE_DUTY_VAL) / 1000)

#define CONF_TC4_MODE TC_CTRLA_MODE_COUNT16_Val
#define CONF_TC4_RUNSTDBY 0
#define CONF_TC4_PRESCSYNC TC_CTRLA_PRESCSYNC_GCLK_Val

/* Commented intentionally. Timer uses fixed value. May be used by other abstractions based on TC. */
//#define CONF_TC4_DIR     0
//#define CONF_TC4_ONESHOT 0

/* Commented intentionally. Timer uses fixed value. May be used by other abstractions based on TC. */
//#define CONF_TC4_INVEN0 0
//#define CONF_TC4_INVEN1 0
//#define CONF_TC4_CPTEN0 0
//#define CONF_TC4_CPTEN1 0
#define CONF_TC4_DBGRUN 0
#define CONF_TC4_EVENT_CONTROL_ENABLE 0
#define CONF_TC4_OVFEO 0
#define CONF_TC4_TCEI 0
#define CONF_TC4_TCINV 0
#define CONF_TC4_EVACT TC_EVCTRL_EVACT_OFF_Val
#define CONF_TC4_MCEO0 0
#define CONF_TC4_MCEO1 0

The main file:

main(){
_pm_enable_bus_clock(PM_BUS_APBC, TC4);
_gclk_enable_channel(TC4_GCLK_ID, CONF_GCLK_TC4_SRC);
gpio_set_pin_function(P_LED_G, PINMUX_PB08E_TC4_WO0);

pwm_init(&PWM_1, TC4, _tc_get_pwm());

pwm_set_parameters(&PWM_1, 10000, 5000);
pwm_enable(&PWM_1);
}

while(1);

 

 

 

 

 

This topic has a solution.
Last Edited: Tue. Aug 1, 2017 - 09:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

CC0 is used to configure the period and CC1 the duty cycle so the PWM output is on WO1 not WO0 (which you have on PB08 now). On WO0 you get this:

On on every overflow/underflow, a one-TC-clock-cycle negative pulse is put out on WO[0]

/Lars 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Lars.

 

Ok, so by changing:

 

gpio_set_pin_function(P_LED_G, PINMUX_PB08E_TC4_WO0);

into

gpio_set_pin_function(P_LED_G, PINMUX_PB09E_TC4_WO1);

 and changing the definition of P_LED_G, it works. Great.

 

Thanks a lot, and congrats for the accurate eyes.

Last Edited: Tue. Aug 1, 2017 - 09:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi joaofl,

 

Can you share the code please ? i have the same issue, but it do not work.

 

Thank you in advance.