在这个程序里,利用PWM点亮两个LED。
而这两个LED的PWM定义及GPIO的第几功能在
以下宏中定义:
/** PWM LED1 pin definitions. */
#define PIN_PWM_LED1_GPIO PIO_PC20_IDX
#define PIN_PWM_LED1_FLAGS (IOPORT_MODE_MUX_B)
#define PIN_PWM_LED1_CHANNEL PWM_CHANNEL_2
/** PWM LED0 pin definitions. */
#define PIN_PWM_LED0_GPIO PIO_PA0_IDX
#define PIN_PWM_LED0_FLAGS (IOPORT_MODE_MUX_A)
#define PIN_PWM_LED0_CHANNEL PWM_CHANNEL_0
以LED1为例,其数据手册,通道B正好是PWM通道2
这样PWM就同LED连接上了。
以下是程序:
- #include "asf.h"
- #include "stdio_serial.h"
- #include "conf_board.h"
- #include "conf_clock.h"
- /** PWM frequency in Hz */
- #define PWM_FREQUENCY 1000
- /** Period value of PWM output waveform */
- #define PERIOD_VALUE 100
- /** Initial duty cycle value */
- #define INIT_DUTY_VALUE 0
- #define STRING_EOL "\r"
- #define STRING_HEADER "-- PWM LED Example --\r\n" \
- "-- "BOARD_NAME" --\r\n" \
- "-- Compiled: "__DATE__" "__TIME__" --"STRING_EOL
- /** PWM channel instance for LEDs */
- pwm_channel_t g_pwm_channel_led;
- /**
- * \brief Interrupt handler for the PWM controller.
- */
- void PWM_Handler(void)
- {
- static uint32_t ul_count = 0; /* PWM counter value */
- static uint32_t ul_duty = INIT_DUTY_VALUE; /* PWM duty cycle rate */
- static uint8_t fade_in = 1; /* LED fade in flag */
- uint32_t events = pwm_channel_get_interrupt_status(PWM);
- /* Interrupt on PIN_PWM_LED0_CHANNEL */
- if ((events & (1 << PIN_PWM_LED0_CHANNEL)) ==
- (1 << PIN_PWM_LED0_CHANNEL)) {
- ul_count++;
- /* Fade in/out */
- if (ul_count == (PWM_FREQUENCY / (PERIOD_VALUE - INIT_DUTY_VALUE))) {
- /* Fade in */
- if (fade_in) {
- ul_duty++;
- if (ul_duty == PERIOD_VALUE) {
- fade_in = 0;
- }
- } else {
- /* Fade out */
- ul_duty--;
- if (ul_duty == INIT_DUTY_VALUE) {
- fade_in = 1;
- }
- }
- /* Set new duty cycle */
- ul_count = 0;
- 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);
- }
- }
- }
- /**
- * \brief Configure the Console UART.
- */
- static void configure_console(void)
- {
- const usart_serial_options_t uart_serial_options = {
- .baudrate = CONF_UART_BAUDRATE,
- .paritytype = CONF_UART_PARITY
- };
- /* Configure console UART. */
- sysclk_enable_peripheral_clock(CONSOLE_UART_ID);
- stdio_serial_init(CONF_UART, &uart_serial_options);
- }
- /**
- * \brief Application entry point for PWM with LED example.
- * Output PWM waves on LEDs to make them fade in and out.
- *
- * \return Unused (ANSI-C compatibility).
- */
- int main(void)
- {
- /* Initialize the SAM system */
- sysclk_init();
- board_init();
- /* Configure the console uart for debug information */
- configure_console();
- /* Output example information */
- puts(STRING_HEADER);
- /* Enable PWM peripheral clock */
- pmc_enable_periph_clk(ID_PWM);
- /* Disable PWM channels for LEDs */
- pwm_channel_disable(PWM, PIN_PWM_LED0_CHANNEL);
- pwm_channel_disable(PWM, PIN_PWM_LED1_CHANNEL);
- /* Set PWM clock A as PWM_FREQUENCY*PERIOD_VALUE (clock B is not used) */
- 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);
- /* Initialize PWM channel for LED0 */
- /* Period is left-aligned */
- g_pwm_channel_led.alignment = PWM_ALIGN_LEFT;
- /* Output waveform starts at a low level */
- g_pwm_channel_led.polarity = PWM_LOW;
- /* Use PWM clock A as source clock */
- g_pwm_channel_led.ul_prescaler = PWM_CMR_CPRE_CLKA;
- /* Period value of output waveform */
- g_pwm_channel_led.ul_period = PERIOD_VALUE;
- /* Duty cycle value of output waveform */
- 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);
- /* Enable channel counter event interrupt */
- pwm_channel_enable_interrupt(PWM, PIN_PWM_LED0_CHANNEL, 0);
- /* Initialize PWM channel for LED1 */
- /* Period is center-aligned */
- g_pwm_channel_led.alignment = PWM_ALIGN_CENTER;
- /* Output waveform starts at a high level */
- g_pwm_channel_led.polarity = PWM_HIGH;
- /* Period is left-aligned */
- g_pwm_channel_led.ul_prescaler = PWM_CMR_CPRE_CLKA;
- /* Period value of output waveform */
- g_pwm_channel_led.ul_period = PERIOD_VALUE;
- /* Duty cycle value of output waveform */
- 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);
- /* Disable channel counter event interrupt */
- pwm_channel_disable_interrupt(PWM, PIN_PWM_LED1_CHANNEL, 0);
-
-
- /* Configure interrupt and enable PWM interrupt */
- NVIC_DisableIRQ(PWM_IRQn);
- NVIC_ClearPendingIRQ(PWM_IRQn);
- NVIC_SetPriority(PWM_IRQn, 0);
- NVIC_EnableIRQ(PWM_IRQn);
- /* Enable PWM channels for LEDs */
- pwm_channel_enable(PWM, PIN_PWM_LED0_CHANNEL);
- pwm_channel_enable(PWM, PIN_PWM_LED1_CHANNEL);
-
- ioport_set_pin_level(LED2_GPIO, IOPORT_PIN_LEVEL_LOW);
- ioport_set_pin_level(LED3_GPIO, IOPORT_PIN_LEVEL_LOW);
- /* Infinite loop */
- while (1) {
-
-
-
-
-
- }
- }
经测试,两个LED,渐明渐暗。
|