PWM on TCx module not working on a SAMD21 using ASFv4

Go To Last Post
4 posts / 0 new
  • 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_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 */
#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)


/* 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_OVFEO 0
#define CONF_TC4_TCEI 0
#define CONF_TC4_TCINV 0
#define CONF_TC4_MCEO0 0
#define CONF_TC4_MCEO1 0

The main file:

_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);







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]


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);


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.