// Experimento 1 - GPIO
// Leitor de DIP switch com espelhamento em LEDs e verificação de paridade
// Placa: STM32 Nucleo-32 L031K6
// Configuração de periféricos feita inteiramente via registradores (CMSIS),
// sem pinMode/digitalWrite/digitalRead/delay.
// Pinos de entrada (chaves 1-4), na ordem dos bits 0..3
const uint8_t pinos_entrada[4] = {0, 1, 3, 4}; // PA0, PA1, PA3, PA4 (serigrafia A0, A1, A2, A3)
// Pinos de saída (LEDs espelho), na ordem dos bits 0..3
const uint8_t pinos_saida[4] = {2, 5, 6, 7}; // PA2, PA5, PA6, PA7 (serigrafia A7, A4, A5, A6)
const uint8_t pino_paridade = 8; // PA8 (serigrafia D9)
const uint8_t pino_extensao = 9; // PA9 (serigrafia D1)
void setup() {
// 1) Habilita o clock do periférico GPIOA
RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
// 2) Configura as entradas com pull-up interno
for (uint8_t i = 0; i < 4; i++) {
uint8_t pin = pinos_entrada[i];
GPIOA->MODER &= ~(0x3UL << (pin * 2)); // 00 = entrada
GPIOA->PUPDR &= ~(0x3UL << (pin * 2));
GPIOA->PUPDR |= (0x1UL << (pin * 2)); // 01 = pull-up
}
// 3) Configura as saídas (LEDs espelho + paridade + extensão) push-pull
uint8_t saidas_todas[6] = {
pinos_saida[0], pinos_saida[1], pinos_saida[2], pinos_saida[3],
pino_paridade, pino_extensao
};
for (uint8_t i = 0; i < 6; i++) {
uint8_t pin = saidas_todas[i];
GPIOA->MODER &= ~(0x3UL << (pin * 2));
GPIOA->MODER |= (0x1UL << (pin * 2)); // 01 = saída
GPIOA->OTYPER &= ~(1UL << pin); // push-pull
GPIOA->PUPDR &= ~(0x3UL << (pin * 2)); // sem pull
}
}
void loop() {
uint32_t idr = GPIOA->IDR;
// 4) Lê cada chave e monta o valor de 4 bits
// Convenção: pull-up + chave fechada = nível baixo = bit 1 (ativo em nível baixo)
uint8_t valor = 0;
for (uint8_t i = 0; i < 4; i++) {
bool nivel_alto = (idr >> pinos_entrada[i]) & 0x1;
if (!nivel_alto) valor |= (1 << i);
}
// 5) Paridade: conta quantos bits estão em 1
uint8_t uns = 0;
for (uint8_t i = 0; i < 4; i++) if (valor & (1 << i)) uns++;
bool paridade_par = (uns % 2) == 0;
// 6) Atualiza os LEDs espelho
uint32_t odr = GPIOA->ODR;
for (uint8_t i = 0; i < 4; i++) {
if (valor & (1 << i)) odr |= (1UL << pinos_saida[i]);
else odr &= ~(1UL << pinos_saida[i]);
}
// LED de paridade: aceso quando a quantidade de bits em 1 é PAR
if (paridade_par) odr |= (1UL << pino_paridade);
else odr &= ~(1UL << pino_paridade);
// LED extra: aceso quando o valor lido é >= 8
if (valor >= 8) odr |= (1UL << pino_extensao);
else odr &= ~(1UL << pino_extensao);
GPIOA->ODR = odr;
}