// IFMA - Embarcatech - jan-fev/2025
// Atividade Capítulos 05 a 08 - Clock e Temporizador
// Nome: Alberto Carlos de Oliveira Andrade
// Tarefa 2:
// 05 - Modifique o exemplo de código apresentado na videoaula (reproduzido abaixo) para
// controlar os três LEDs RGB da placa BitDogLab usando o módulo PWM e interrupções, seguindo
// as orientações a seguir:
// A. O LED vermelho deve ser acionado com um PWM de 1kHz.
// B. O duty cycle deve ser iniciado em 5% e atualizado a cada 2 segundos em incrementos de 5%.
// Quando atingir o valor máximo, deve ‐retornar a 5%.
// - O LED azul deve ser acionado com um PWM de 10kHz.
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/pwm.h"
const uint LED_R = 13; // LED Vermelho
const uint LED_G = 11; // LED Verde
const uint LED_B = 12; // LED Azul
// Definição dos parâmetros de PWM para o LED vermelho
const uint16_t PERIOD_RED = 12500; // Período do PWM (aproximadamente 1 kHz)
const float DIVIDER_PWM_RED = 10.0; // Divisor de clock para o PWM (ajusta a frequência)
const uint16_t LED_STEP = 625; // Passo de ajuste do brilho do LED vermelho
const uint32_t PWM_REFRESH_LEVEL = 2000; // Número de ciclos de PWM para aguardar antes de atualizar o brilho
const uint32_t TRANSITION_TIME = 2000000; // Tempo de transição (em microssegundos) para o LED vermelho
uint16_t led_level = LED_STEP; // Nível inicial de brilho do LED vermelho
uint32_t last_transition_time = 0; // Tempo do último ajuste de transição
int8_t direction = 1; // Direção do ajuste de brilho: 1 para aumentar e -1 para diminuir
uint slice_red; // Número do slice PWM para o LED vermelho
// Definição dos parâmetros de PWM para o LED azul
const uint16_t PERIOD_BLUE = 12500; // Período do PWM do LED azul (aproximadamente 1 kHz)
const float DIVIDER_PWM_BLUE = 16.0; // Divisor de clock para o LED azul (ajusta a frequência)
const uint16_t DUTY_CYCLE_BLUE = 100; // Ciclo de trabalho do LED azul (em %)
// Função de interrupção do PWM que controla a transição de brilho do LED vermelho
void pwm_irq_handler() {
static uint32_t count = 0; // Contador para limitar a frequência da interrupção
uint32_t current_time = time_us_32();// Obtém o tempo atual em microssegundos
pwm_clear_irq(slice_red); // Limpa a flag de interrupção do PWM
// Se o contador for menor que o nível de atualização do PWM, não faz nada
if (count++ < PWM_REFRESH_LEVEL) return;
count = 0;
// Se o tempo desde a última transição for menor que o tempo de transição, não faz nada
if (current_time - last_transition_time < TRANSITION_TIME) return;
last_transition_time = current_time;
// Atualiza o nível de brilho do LED vermelho de acordo com a direção
led_level += (direction * LED_STEP);
// Se o nível de brilho ultrapassar os limites, inverte a direção e ajusta o nível
if (led_level >= PERIOD_RED || led_level <= LED_STEP) {
direction *= -1;
led_level = (led_level > PERIOD_RED) ? PERIOD_RED : LED_STEP;
}
// Aplica o novo nível de brilho no LED vermelho
pwm_set_gpio_level(LED_R, led_level);
// Exibe o ciclo de trabalho do LED vermelho no terminal
printf("Duty Cycle do LED Vermelho: %.f%%\n", (led_level * 100.0) / PERIOD_RED);
}
// Função de configuração do PWM para os LEDs
void setup_pwm() {
// Configura o LED vermelho para usar PWM
gpio_set_function(LED_R, GPIO_FUNC_PWM);
slice_red = pwm_gpio_to_slice_num(LED_R); // Obtém o slice de PWM do pino do LED vermelho
pwm_config config_red = pwm_get_default_config(); // Configuração padrão para PWM
pwm_config_set_clkdiv(&config_red, DIVIDER_PWM_RED); // Define o divisor de clock para o PWM do LED vermelho
pwm_config_set_wrap(&config_red, PERIOD_RED); // Define o período do PWM para o LED vermelho
pwm_init(slice_red, &config_red, true); // Inicializa o PWM com a configuração definida
pwm_set_gpio_level(LED_R, led_level); // Define o nível inicial de brilho para o LED vermelho
// Configura o LED azul para usar PWM
gpio_set_function(LED_B, GPIO_FUNC_PWM); // Configura o pino do LED azul como PWM
uint slice_blue = pwm_gpio_to_slice_num(LED_B); // Obtém o slice de PWM do pino do LED azul
pwm_config config_blue = pwm_get_default_config(); // Configuração padrão para PWM
pwm_config_set_clkdiv(&config_blue, DIVIDER_PWM_BLUE); // Define o divisor de clock para o PWM do LED azul
pwm_config_set_wrap(&config_blue, PERIOD_BLUE); // Define o período do PWM para o LED azul
pwm_init(slice_blue, &config_blue, true); // Inicializa o PWM com a configuração definida
pwm_set_gpio_level(LED_B, (DUTY_CYCLE_BLUE * PERIOD_BLUE) / 100); // Define o ciclo de trabalho para o LED azul
// Exibe uma mensagem informando que o LED azul foi configurado
printf("LED Azul configurado com PWM de 10 kHz (Duty Cycle: 100%).\n", PERIOD_BLUE);
// Configura o manipulador de interrupção para o PWM
irq_set_exclusive_handler(PWM_IRQ_WRAP, pwm_irq_handler); // Define a função de interrupção para o PWM
pwm_set_irq_enabled(slice_red, true); // Habilita a interrupção para o PWM do LED vermelho
irq_set_enabled(PWM_IRQ_WRAP, true); // Habilita as interrupções globais
}
int main() {
stdio_init_all(); // Inicializa a comunicação serial para impressão no terminal
setup_pwm(); // Chama a função de configuração do PWM para os LEDs
// Loop principal que mantém o código rodando indefinidamente
while (true) {
sleep_ms(10); // Aguarda 10 milissegundos antes de verificar novamente (pode ser ajustado conforme necessário)
}
}