//Aluno: ANTONIO JOSÉ PORTELA DE JESUS SANTOS
//UNIT04 - Cap. 05 a 08 - ATIVIDADE: TAREFA DE ENVIO - Clock e temporizador
/* Tarefa 2 - Questão 5 - 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.
*/
//Declaração das bibliotecas
#include "pico/stdlib.h"
#include "hardware/pwm.h"
#include "hardware/clocks.h"
#include <stdio.h>
//Definição das variáveis globais, GPIO e constantes
#define LED_R_PIN 12
#define LED_G_PIN 13
#define LED_B_PIN 11
const uint16_t FREQ_R = 1000;
const uint16_t FREQ_B = 10000;
const uint16_t PASSO = 500;
uint dutyc = 500; //Duty cicle 0 = 0% e 10000 = 100%. 500 equivale a um passo de 5%.
//Definição dos protótipos de funções
void set_rgb();
void set_pwm_pin(uint pin, uint freq);
void pwm_irq_handler();
//Função main
void main(){
set_rgb;
set_pwm_pin(LED_R_PIN,FREQ_R);
set_pwm_pin(LED_B_PIN,FREQ_B);
}
//Funções implementadas
void set_rgb(){
gpio_init(LED_R_PIN);
gpio_set_dir(LED_R_PIN, GPIO_OUT);
gpio_init(LED_G_PIN);
gpio_set_dir(LED_G_PIN, GPIO_OUT);
gpio_init(LED_B_PIN);
gpio_set_dir(LED_B_PIN, GPIO_OUT);
}
void set_pwm_pin(uint pin, uint freq) { // duty_c between 0..10000
gpio_set_function(pin, GPIO_FUNC_PWM);
uint slice_num = pwm_gpio_to_slice_num(pin);
pwm_config config = pwm_get_default_config();
float div = (float)clock_get_hz(clk_sys) / (freq * 10000);
pwm_config_set_clkdiv(&config, div);
pwm_config_set_wrap(&config, 10000);
pwm_init(slice_num, &config, true); // start the pwm running according to the config
irq_set_exclusive_handler(PWM_IRQ_WRAP, pwm_irq_handler); // Define o handler da interrupção do PWM
pwm_clear_irq(slice_num); // Limpa interrupções pendentes do slice
pwm_set_irq_enabled(slice_num, true); // Habilita interrupções para o slice do PWM
irq_set_enabled(PWM_IRQ_WRAP, true); // Habilita interrupções globais para o PWM
}
void pwm_irq_handler(){
const uint32_t PWM_REFRESH_LEVEL = 40000;
static uint up_down = 1; // Variável que controla se o LED está aumentando ou diminuindo o brilho
static uint32_t count = 0; // Contador para controlar a frequência de atualização do PWM
uint32_t slice = pwm_get_irq_status_mask(); // Obtém o status da interrupção do PWM
pwm_clear_irq(slice); // Limpa a interrupção do slice correspondente
if (count++ < PWM_REFRESH_LEVEL) return; // Verifica se o contador atingiu o nível de atualização do PWM
count = 0; // Reseta o contador para iniciar a próxima verificação
pwm_set_gpio_level(LED_R_PIN, dutyc); // Atualiza o duty cycle do PWM para o pino do LED
pwm_set_gpio_level(LED_B_PIN, dutyc);
sleep_ms(2000);
if (up_down){// Ajusta o duty cycle do LED, alternando entre aumentar e diminuir
dutyc = dutyc + PASSO; // Incrementa o nível do LED
if (dutyc >= 10000)
up_down = 0; // Muda a direção para diminuir o brilho quando atinge o valor máximo
}
else{
dutyc = dutyc - PASSO; // Decrementa o nível do LED
if (dutyc <= 500)
up_down = 1; // Muda a direção para aumentar o brilho quando atinge o valor mínimo
}
}