#include "stm32l031xx.h"
int main(void) {
// 1. Habilitar o Clock dos Portos GPIO (A e B) e do ADC1
RCC->IOPENR |= RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOBEN;
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
// --- CONFIGURAÇÃO DA ENTRADA ANALÓGICA (POTENCIÔMETRO) ---
// Pino físico: A0 (PA0)
// Forçar bits para 11 (Modo Analógico) no registrador MODER
GPIOA->MODER |= (3U << (0 * 2));
// --- CONFIGURAÇÃO DAS SAÍDAS DA BARRA DE LEDS ---
// Pinos físicos do Porto A: A1(PA1), A7(PA2), A2(PA3), A3(PA4), A4(PA5), A5(PA6), A6(PA7)
// Limpar os bits (00) e Setar (01) para Modo de Saída (Output)
GPIOA->MODER &= ~((3U << 2) | (3U << 4) | (3U << 6) | (3U << 8) | (3U << 10) | (3U << 12) | (3U << 14));
GPIOA->MODER |= ((1U << 2) | (1U << 4) | (1U << 6) | (1U << 8) | (1U << 10) | (1U << 12) | (1U << 14));
// Pino físico do Porto B: D3(PB0)
GPIOB->MODER &= ~(3U << 0);
GPIOB->MODER |= (1U << 0);
// --- INICIALIZAÇÃO DO CONVERSOR AD (ADC1) ---
// Habilitar o ADC e esperar a flag de pronto (ADRDY)
ADC1->CR |= ADC_CR_ADEN;
while ((ADC1->ISR & ADC_ISR_ADRDY) == 0);
// Selecionar o Canal 0 (que corresponde ao pino PA0)
ADC1->CHSELR = ADC_CHSELR_CHSEL0;
// --- VARIÁVEIS DO FILTRO DE MÉDIA MÓVEL (TAMANHO 8) ---
uint32_t leituras[8] = {0}; // Vetor para guardar as últimas 8 amostras
uint8_t indice = 0;
uint32_t soma = 0;
uint32_t media = 0;
while (1) {
// 1. Disparar uma nova conversão analógica
ADC1->CR |= ADC_CR_ADSTART;
// 2. Aguardar o fim da conversão (End Of Conversion - EOC)
while ((ADC1->ISR & ADC_ISR_EOC) == 0);
// 3. Ler o valor bruto convertido pelo ADC (faixa de 0 a 4095)
uint32_t valor_bruto = ADC1->DR;
// --- APLICAÇÃO DO FILTRO DE ESTABILIZAÇÃO ---
soma -= leituras[indice]; // Subtrai o valor mais antigo da soma
leituras[indice] = valor_bruto; // Armazena a nova leitura no vetor
soma += leituras[indice]; // Adiciona a nova leitura à soma
indice = (indice + 1) % 8; // Avança a posição circularmente
media = soma / 8; // Tira a média suavizada
// --- MAPEAR O VALOR (0-4095) PARA 8 NÍVEIS DE LEDS ---
uint8_t leds = 0;
if (media > 450) leds = 1;
if (media > 900) leds = 2;
if (media > 1400) leds = 3;
if (media > 1900) leds = 4;
if (media > 2400) leds = 5;
if (media > 2900) leds = 6;
if (media > 3400) leds = 7;
if (media > 3900) leds = 8;
// --- ACENDIMENTO DOS LEDS VIA REGISTRADOR ATÔMICO (BSRR) ---
// Se a quantidade de LEDs exigida for maior ou igual à posição do LED, acende. Senão, apaga.
// LED 1 (A1 -> PA1)
if (leds >= 1) GPIOA->BSRR = (1U << 1); else GPIOA->BSRR = (1U << (1 + 16));
// LED 2 (A2 -> PA3)
if (leds >= 2) GPIOA->BSRR = (1U << 3); else GPIOA->BSRR = (1U << (3 + 16));
// LED 3 (A3 -> PA4)
if (leds >= 3) GPIOA->BSRR = (1U << 4); else GPIOA->BSRR = (1U << (4 + 16));
// LED 4 (A4 -> PA5)
if (leds >= 4) GPIOA->BSRR = (1U << 5); else GPIOA->BSRR = (1U << (5 + 16));
// LED 5 (A5 -> PA6)
if (leds >= 5) GPIOA->BSRR = (1U << 6); else GPIOA->BSRR = (1U << (6 + 16));
// LED 6 (A6 -> PA7)
if (leds >= 6) GPIOA->BSRR = (1U << 7); else GPIOA->BSRR = (1U << (7 + 16));
// LED 7 (A7 -> PA2)
if (leds >= 7) GPIOA->BSRR = (1U << 2); else GPIOA->BSRR = (1U << (2 + 16));
// LED 8 (D3 -> PB0)
if (leds >= 8) GPIOB->BSRR = (1U << 0); else GPIOB->BSRR = (1U << (0 + 16));
}
}