Getting started with Atmel SAM4S-EK2

LED 4

Let's try to make the LED fade using PWM module.The addition module required for this project is Pulse Width Modulation.

First initialize the system clock and board.

We need an interrupt handler for the PWM controller. Define the PWM interrupt handler.

void PWM_Handler(void);

In PWM_Handler(), get PWM interrupt status

events = pwm_channel_get_interrupt_status(PWM);

Check whether the PWM channel 0 interrupt has occurred.

if ((events & (1 << PIN_PWM_LED0_CHANNEL)) ==
            (1 << PIN_PWM_LED0_CHANNEL))

If the PWM channel 0 interrupt has occurred, update the ul_duty value.

if (fade_in) {
    ul_duty++;
    if (ul_duty == PERIOD_VALUE) {
        fade_in = 0;
    }
} else {
    ul_duty--;
    if (ul_duty == INIT_DUTY_VALUE) {
        fade_in = 1;
    }
}

If the ul_duty value has been updated, change the wave duty.

g_pwm_channel_led.channel = PIN_PWM_LED0_CHANNEL;
pwm_channel_update_duty(PWM, &g_pwm_channel_led, ul_duty);
g_pwm_channel_led.channel = PIN_PWM_LED1_CHANNEL;
pwm_channel_update_duty(PWM, &g_pwm_channel_led, ul_duty);

Now in the main(), we need to enable the peripheral clock. It takes a Peripheral ID as its argument. The ID for PWM is given in sam4sd32c.h file which is found in Dependencies.

pmc_enable_periph_clk(ID_PWM);

Define the PWM channel instance for the LEDs.

pwm_channel_t g_pwm_channel_led;

Disable the PWM channels for LED's.

pwm_channel_disable(PWM, PIN_PWM_LED0_CHANNEL);
pwm_channel_disable(PWM, PIN_PWM_LED1_CHANNEL);

Now, we have to setup clock for PWM module.

pwm_clock_t clock_setting = {
    .ul_clka = PWM_FREQUENCY * PERIOD_VALUE,
    .ul_clkb = 0,
    .ul_mck = sysclk_get_cpu_hz()
};
pwm_init(PWM, &clock_setting);

Initailizing PWM channel for LED0 and LED1.

g_pwm_channel_led.alignment = PWM_ALIGN_LEFT;
g_pwm_channel_led.polarity = PWM_LOW;
g_pwm_channel_led.ul_prescaler = PWM_CMR_CPRE_CLKA;
g_pwm_channel_led.ul_period = PERIOD_VALUE;
g_pwm_channel_led.ul_duty = INIT_DUTY_VALUE;
g_pwm_channel_led.channel = PIN_PWM_LED0_CHANNEL;
pwm_channel_init(PWM, &g_pwm_channel_led);

g_pwm_channel_led.alignment = PWM_ALIGN_CENTER;
g_pwm_channel_led.polarity = PWM_HIGH;
g_pwm_channel_led.ul_prescaler = PWM_CMR_CPRE_CLKA;
g_pwm_channel_led.ul_period = PERIOD_VALUE;
g_pwm_channel_led.ul_duty = INIT_DUTY_VALUE;
g_pwm_channel_led.channel = PIN_PWM_LED1_CHANNEL;
pwm_channel_init(PWM, &g_pwm_channel_led);

Diabling channel counter event interrupt.

pwm_channel_disable_interrupt(PWM, PIN_PWM_LED0_CHANNEL, 0);
pwm_channel_disable_interrupt(PWM, PIN_PWM_LED1_CHANNEL, 0);

Now to configure interrupt and enable the PWM interrupt.

NVIC_DisableIRQ(PWM_IRQn);
NVIC_ClearPendingIRQ(PWM_IRQn);
NVIC_SetPriority(PWM_IRQn, 0);
NVIC_EnableIRQ(PWM_IRQn);

Now we can enable the PWM channels for the LEDs.

pwm_channel_enable(PWM, PIN_PWM_LED0_CHANNEL);
pwm_channel_enable(PWM, PIN_PWM_LED1_CHANNEL);

And an infinite loop in the end.

Click here for project code