The supported board list:
- SAM D21/R21/L21/L22/DA1/C21/HA1G16A Xplained Pro
In this use case, the TCC will be used to generate a PWM signal, with a varying duty cycle. Here the pulse width is increased each time the timer count matches the set compare value. There is a recoverable fault input which controls PWM output. When this fault is active (low) the PWM output will be frozen (could be off or on, no light changing). When fault is released (input high) the PWM output will go on.
When the PWM signal connects to LED, LED will light. If fault input is from a button, the LED will be frozen and not changing it's light when the button is down and will go on when the button is up. To see the PWM waveform, you may need an oscilloscope. SAMHA1G16A Xpro LED is PA00 which isn't connected out, use PA04 instead, so we can't see LED blink but only see the waveform from oscilloscope.
The PWM output and fault input is set up as follows:
Board | Pin | Connect to |
SAM D21 Xpro | PB30 | LED0 |
SAM D21 Xpro | PA15 | SW0 |
SAM R21 Xpro | PA06 | EXT1 Pin 3 |
SAM R21 Xpro | PA28 | SW0 |
SAM L21 Xpro | PB10 | LED0 |
SAM L21 Xpro | PA16 | SW0 |
SAM L22 Xpro | PB18 | EXT3 Pin 9 |
SAM L22 Xpro | PC01 | SW0 |
SAM DA1 Xpro | PB30 | LED0 |
SAM DA1 Xpro | PA15 | SW0 |
SAM C21 Xpro | PA15 | LED0 |
SAM C21 Xpro | PA28 | SW0 |
SAM HA1G16A Xpro | PA04 | NULL |
SAM HA1G16A Xpro | PB03 | SW0 |
The TCC module will be set up as follows:
- GCLK generator 0 (GCLK main) clock source
- Use double buffering write when set top, compare, or pattern through API
- No dithering on the counter or compare
- No prescaler
- Single Slope PWM wave generation
- GCLK reload action
- Don't run in standby
- No waveform extentions
- No inversion of waveform output
- No capture enabled
- Count upward
- Don't perform one-shot operations
- No event input except channel 0 event enabled
- No event action
- No event generation enabled
- Counter starts on 0
- Recoverable Fault A is generated from channel 0 event input, fault halt acts as software halt, other actions or options are all disabled
Quick Start
Prerequisites
There are no prerequisites for this use case.
Code
Add to the main application source file, before any functions, according to the kit used:
- SAM D21 Xplained Pro
#define CONF_PWM_MODULE LED_0_PWM4CTRL_MODULE
#define CONF_PWM_CHANNEL LED_0_PWM4CTRL_CHANNEL
#define CONF_PWM_OUTPUT LED_0_PWM4CTRL_OUTPUT
#define CONF_PWM_OUT_PIN LED_0_PWM4CTRL_PIN
#define CONF_PWM_OUT_MUX LED_0_PWM4CTRL_MUX
#define CONF_FAULT_EIC_PIN SW0_EIC_PIN
#define CONF_FAULT_EIC_PIN_MUX SW0_EIC_PINMUX
#define CONF_FAULT_EIC_LINE SW0_EIC_LINE
#define CONF_FAULT_EVENT_GENERATOR EVSYS_ID_GEN_EIC_EXTINT_15
#define CONF_FAULT_EVENT_USER EVSYS_ID_USER_TCC0_MC_0
- SAM R21 Xplained Pro
#define CONF_PWM_MODULE TCC1
#define CONF_PWM_CHANNEL 0
#define CONF_PWM_OUTPUT 0
#define CONF_PWM_OUT_PIN PIN_PA06E_TCC1_WO0
#define CONF_PWM_OUT_MUX MUX_PA06E_TCC1_WO0
#define CONF_FAULT_EIC_PIN SW0_EIC_PIN
#define CONF_FAULT_EIC_PIN_MUX SW0_EIC_PINMUX
#define CONF_FAULT_EIC_LINE SW0_EIC_LINE
#define CONF_FAULT_EVENT_GENERATOR EVSYS_ID_GEN_EIC_EXTINT_8
#define CONF_FAULT_EVENT_USER EVSYS_ID_USER_TCC1_MC_0
- SAM L21 Xplained Pro
#define CONF_PWM_MODULE LED_0_PWM4CTRL_MODULE
#define CONF_PWM_CHANNEL LED_0_PWM4CTRL_CHANNEL
#define CONF_PWM_OUTPUT LED_0_PWM4CTRL_OUTPUT
#define CONF_PWM_OUT_PIN LED_0_PWM4CTRL_PIN
#define CONF_PWM_OUT_MUX LED_0_PWM4CTRL_MUX
#define CONF_FAULT_EIC_PIN SW0_EIC_PIN
#define CONF_FAULT_EIC_PIN_MUX SW0_EIC_PINMUX
#define CONF_FAULT_EIC_LINE SW0_EIC_LINE
#define CONF_FAULT_EVENT_GENERATOR EVSYS_ID_GEN_EIC_EXTINT_2
#define CONF_FAULT_EVENT_USER EVSYS_ID_USER_TCC0_MC_0
- SAM L22 Xplained Pro
#define CONF_PWM_MODULE TCC0
#define CONF_PWM_CHANNEL 0
#define CONF_PWM_OUTPUT 0
#define CONF_PWM_OUT_PIN PIN_PB18F_TCC0_WO0
#define CONF_PWM_OUT_MUX MUX_PB18F_TCC0_WO0
#define CONF_FAULT_EIC_PIN SW0_EIC_PIN
#define CONF_FAULT_EIC_PIN_MUX SW0_EIC_PINMUX
#define CONF_FAULT_EIC_LINE SW0_EIC_LINE
#define CONF_FAULT_EVENT_GENERATOR EVSYS_ID_GEN_EIC_EXTINT_9
#define CONF_FAULT_EVENT_USER EVSYS_ID_USER_TCC0_MC_0
- SAM DA1 Xplained Pro
#define CONF_PWM_MODULE LED_0_PWM4CTRL_MODULE
#define CONF_PWM_CHANNEL LED_0_PWM4CTRL_CHANNEL
#define CONF_PWM_OUTPUT LED_0_PWM4CTRL_OUTPUT
#define CONF_PWM_OUT_PIN LED_0_PWM4CTRL_PIN
#define CONF_PWM_OUT_MUX LED_0_PWM4CTRL_MUX
#define CONF_FAULT_EIC_PIN SW0_EIC_PIN
#define CONF_FAULT_EIC_PIN_MUX SW0_EIC_PINMUX
#define CONF_FAULT_EIC_LINE SW0_EIC_LINE
#define CONF_FAULT_EVENT_GENERATOR EVSYS_ID_GEN_EIC_EXTINT_15
#define CONF_FAULT_EVENT_USER EVSYS_ID_USER_TCC0_MC_0
- SAM C21 Xplained Pro
#define CONF_PWM_MODULE LED_0_PWM4CTRL_MODULE
#define CONF_PWM_CHANNEL LED_0_PWM4CTRL_CHANNEL
#define CONF_PWM_OUTPUT LED_0_PWM4CTRL_OUTPUT
#define CONF_PWM_OUT_PIN LED_0_PWM4CTRL_PIN
#define CONF_PWM_OUT_MUX LED_0_PWM4CTRL_MUX
#define CONF_FAULT_EIC_PIN SW0_EIC_PIN
#define CONF_FAULT_EIC_PIN_MUX SW0_EIC_PINMUX
#define CONF_FAULT_EIC_LINE SW0_EIC_LINE
#define CONF_FAULT_EVENT_GENERATOR EVSYS_ID_GEN_EIC_EXTINT_8
#define CONF_FAULT_EVENT_USER EVSYS_ID_USER_TCC0_EV_0
- SAM HA1G16A Xplained Pro:
#define CONF_PWM_MODULE LED_0_PWM4CTRL_MODULE
#define CONF_PWM_CHANNEL LED_0_PWM4CTRL_CHANNEL
#define CONF_PWM_OUTPUT LED_0_PWM4CTRL_OUTPUT
#define CONF_PWM_OUT_PIN LED_0_PWM4CTRL_PIN
#define CONF_PWM_OUT_MUX LED_0_PWM4CTRL_MUX
#define CONF_FAULT_EIC_PIN SW0_EIC_PIN
#define CONF_FAULT_EIC_PIN_MUX SW0_EIC_PINMUX
#define CONF_FAULT_EIC_LINE SW0_EIC_LINE
#define CONF_FAULT_EVENT_GENERATOR EVSYS_ID_GEN_EIC_EXTINT_3
#define CONF_FAULT_EVENT_USER EVSYS_ID_USER_TCC0_EV_0
Add to the main application source file, before any functions: Add to the main application source file, outside of any functions: struct events_resource event_resource;
Copy-paste the following callback function code to your user application: static void tcc_callback_to_change_duty_cycle(
{
static uint32_t delay = 10;
static uint32_t i = 0;
if (--delay) {
return;
}
delay = 10;
i = (i + 0x0800) & 0xFFFF;
(TCC_MATCH_CAPTURE_CHANNEL_0 + CONF_PWM_CHANNEL),
i + 1);
}
static void eic_callback_to_clear_halt(void)
{
}
}
Copy-paste the following setup code to your user application: static void configure_tcc(void)
{
config_tcc.counter.period = 0xFFFF;
config_tcc.compare.match[CONF_PWM_CHANNEL] = 0xFFFF;
config_tcc.wave_ext.recoverable_fault[CONF_PWM_CHANNEL].source =
config_tcc.wave_ext.recoverable_fault[CONF_PWM_CHANNEL].halt_action =
config_tcc.pins.enable_wave_out_pin[CONF_PWM_OUTPUT] = true;
config_tcc.pins.wave_out_pin[CONF_PWM_OUTPUT] = CONF_PWM_OUT_PIN;
config_tcc.pins.wave_out_pin_mux[CONF_PWM_OUTPUT] = CONF_PWM_OUT_MUX;
tcc_init(&tcc_instance, CONF_PWM_MODULE, &config_tcc);
events.on_event_perform_channel_action[CONF_PWM_CHANNEL] = true;
}
static void configure_tcc_callbacks(void)
{
&tcc_instance,
tcc_callback_to_change_duty_cycle,
(
enum tcc_callback)(TCC_CALLBACK_CHANNEL_0 + CONF_PWM_CHANNEL));
(
enum tcc_callback)(TCC_CALLBACK_CHANNEL_0 + CONF_PWM_CHANNEL));
}
static void configure_eic(void)
{
config.filter_input_signal = true;
config.gpio_pin = CONF_FAULT_EIC_PIN;
config.gpio_pin_mux = CONF_FAULT_EIC_PIN_MUX;
events.generate_event_on_detect[CONF_FAULT_EIC_LINE] = true;
}
static void configure_event(void)
{
struct events_config config;
events_get_config_defaults(&config);
config.generator = CONF_FAULT_EVENT_GENERATOR;
config.path = EVENTS_PATH_ASYNCHRONOUS;
events_allocate(&event_resource, &config);
events_attach_user(&event_resource, CONF_FAULT_EVENT_USER);
}
Add to user application initialization (typically the start of main()
): configure_tcc();
configure_tcc_callbacks();
configure_eic();
configure_event();
Workflow
Configure TCC
- Create a module software instance struct for the TCC module to store the TCC driver state while it is in use.
- Note
- This should never go out of scope as long as the module is in use. In most cases, this should be global.
- Create a TCC module configuration struct, which can be filled out to adjust the configuration of a physical TCC peripheral.
- Initialize the TCC configuration struct with the module's default values.
- Note
- This should always be performed before using the configuration struct to ensure that all values are initialized to known default settings.
- Alter the TCC settings to configure the counter width, wave generation mode, and the compare channel 0 value and fault options. Here the Recoverable Fault input is enabled and halt action is set to software mode (must use software to clear halt state).
config_tcc.counter.period = 0xFFFF;
config_tcc.compare.match[CONF_PWM_CHANNEL] = 0xFFFF;
config_tcc.wave_ext.recoverable_fault[CONF_PWM_CHANNEL].source =
config_tcc.wave_ext.recoverable_fault[CONF_PWM_CHANNEL].halt_action =
- Alter the TCC settings to configure the PWM output on a physical device pin.
config_tcc.pins.enable_wave_out_pin[CONF_PWM_OUTPUT] = true;
config_tcc.pins.wave_out_pin[CONF_PWM_OUTPUT] = CONF_PWM_OUT_PIN;
config_tcc.pins.wave_out_pin_mux[CONF_PWM_OUTPUT] = CONF_PWM_OUT_MUX;
- Configure the TCC module with the desired settings.
tcc_init(&tcc_instance, CONF_PWM_MODULE, &config_tcc);
- Create a TCC events configuration struct, which can be filled out to enable/disable events and configure event settings. Reset all fields to zero.
- Alter the TCC events settings to enable/disable desired events, to change event generating options and modify event actions. Here channel event 0 input is enabled as source of recoverable fault.
events.on_event_perform_channel_action[CONF_PWM_CHANNEL] = true;
- Enable and apply events settings.
- Enable the TCC module to start the timer and begin PWM signal generation.
- Register the Compare Channel 0 Match callback functions with the driver.
&tcc_instance,
tcc_callback_to_change_duty_cycle,
(
enum tcc_callback)(TCC_CALLBACK_CHANNEL_0 + CONF_PWM_CHANNEL));
- Enable the Compare Channel 0 Match callback so that it will be called by the driver when appropriate.
(
enum tcc_callback)(TCC_CALLBACK_CHANNEL_0 + CONF_PWM_CHANNEL));
Configure EXTINT for fault input
- Create an EXTINT module channel configuration struct, which can be filled out to adjust the configuration of a single external interrupt channel.
- Initialize the channel configuration struct with the module's default values.
- Note
- This should always be performed before using the configuration struct to ensure that all values are initialized to known default settings.
- Adjust the configuration struct to configure the pin MUX (to route the desired physical pin to the logical channel) to the board button, and to configure the channel to detect both rising and falling edges.
config.filter_input_signal = true;
config.gpio_pin = CONF_FAULT_EIC_PIN;
config.gpio_pin_mux = CONF_FAULT_EIC_PIN_MUX;
- Configure external interrupt channel with the desired channel settings.
- Create a TXTINT events configuration struct, which can be filled out to enable/disable events. Reset all fields to zero.
- Adjust the configuration struct, set the channels to be enabled to
true
. Here the channel to the board button is used. events.generate_event_on_detect[CONF_FAULT_EIC_LINE] = true;
- Enable the events.
- Define the EXTINT callback that will be fired when a detection event occurs. For this example, when fault line is released, the TCC fault state is cleared to go on PWM generating.
static void eic_callback_to_clear_halt(void)
{
}
}
- Register a callback function
eic_callback_to_clear_halt()
to handle detections from the External Interrupt Controller (EIC).
- Enable the registered callback function for the configured External Interrupt channel, so that it will be called by the module when the channel detects an edge.
Configure EVENTS for fault input
- Create an event resource instance struct for the EVENTS module to store.
struct events_resource event_resource;
- Note
- This should never go out of scope as long as the resource is in use. In most cases, this should be global.
- Create an event channel configuration struct, which can be filled out to adjust the configuration of a single event channel.
struct events_config config;
- Initialize the event channel configuration struct with the module's default values.
events_get_config_defaults(&config);
- Note
- This should always be performed before using the configuration struct to ensure that all values are initialized to known default settings.
- Adjust the configuration struct to request that the channel will be attached to the specified event generator, and that the asynchronous event path will be used. Here the EIC channel connected to board button is the event generator.
config.generator = CONF_FAULT_EVENT_GENERATOR;
config.path = EVENTS_PATH_ASYNCHRONOUS;
- Allocate and configure the channel using the configuration structure.
events_allocate(&event_resource, &config);
- Note
- The existing configuration struct may be re-used, as long as any values that have been altered from the default settings are taken into account by the user application.
- Attach a user to the channel. Here the user is TCC channel 0 event, which has been configured as input of Recoverable Fault.
events_attach_user(&event_resource, CONF_FAULT_EVENT_USER);
Use Case
Code
Copy-paste the following code to your user application:
Workflow
- Enter an infinite loop while the PWM wave is generated via the TCC module.