Configuração Avançada de GPIO para Entrada em Microcontroladores STM32

Este artigo aborda a configuração e uso de pinos GPIO no modo de entrada pura — sem funções alternativas — com foco em detecção de teclas em placas STM32 típicas usadas em competições como a Blue Bridge Cup. O conteúdo é compatível com o pacote de recursos oficial de 2023 e utiliza HAL Library.

Estrutura Interna do Pino GPIO (Modo Entrada)

O bloco funcional de entrada inclui dois elementos principais:

  • Driver de entrada digital: composto por um buffer Schmitt-trigger (exceto no modo analógico) e controles de resistência de pull-up/pull-down configuráveis via registradores.
  • Proteção física do pino: duas diodos de clamp (entre VDDIO e GND) e resistores internos (~40 kΩ) que limitam corrente e evitam danos por sobretensão ou ESD.

Quatro modos de entrada são suportados:

  • Floating input: sem resistência de pull, sensível a ruído;
  • Pull-up input: nível lógico alto quando desligado;
  • Pull-down input: nível lógico baixo quando desligado;
  • Analog input: bypass do estágio digital (Schmitt trigger desativado), usado apenas com ADC.

Análise do Módulo de Tecla Física

Nas placas de referência, as teclas geralmente conectam o pino diretamente ao GND quando pressionadas, enquanto uma resistência de pull-up externa (ou interna) mantém o nível alto na condição normal. Assim:

Estado da Tecla Nível Lógico no Pino
Soltar Alto (1)
Pressionar Baixo (0)

Devido à natureza mecânica dos interruptorse, ocorrrem oscilações transitórias (bounce) durante a comutação — tipicamente com duração de 5–20 ms. Esses transientes devem ser filtrados para evitar múltiplas leituras errôneas.

Implementação em Software

1. Configuração no STM32CubeMX

Defina os pinos correspondentes às teclas como GPIO_Input. Ative opcionalmente as resistências de pull-up internas se não houver componentes externos.

2. Varredura com debounce por tempo fixo

A seguir, uma implementação robusta de varredura com fitlragem temporal baseada em contador de ticks:

// Estado interno das teclas
static uint8_t last_key_state = 0;
static uint8_t current_key_state = 0;
static uint32_t last_scan_time = 0;

uint8_t scan_keys(void) {
  uint8_t result = 0;

  if (HAL_GetTick() - last_scan_time < 30U) return 0; // Janela de debounce: 30 ms
  last_scan_time = HAL_GetTick();

  // Leitura sequencial (exemplo para 4 teclas)
  if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET) result |= (1U << 0);
  if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET) result |= (1U << 1);
  if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET) result |= (1U << 2);
  if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) result |= (1U << 3);

  return result;
}

void process_key_events(void) {
  uint8_t new_state = scan_keys();
  uint8_t pressed = new_state & ~last_key_state;
  uint8_t released = ~new_state & last_key_state;

  if (pressed & (1U << 0)) handle_key_press(KEY_1);
  if (pressed & (1U << 1)) handle_key_press(KEY_2);
  if (pressed & (1U << 2)) handle_key_press(KEY_3);
  if (pressed & (1U << 3)) handle_key_press(KEY_4);

  last_key_state = new_state;
}

3. Alternativa com Interrupção Externa

Para maior eficiência energética e resposta imediata, pode-se usar interrupções externas (EXTI). Cada linha EXTI corresponde a um único pino por porta (ex.: PA0 → EXTI0, PB0 → EXTI0 — conflito!). Configure o modo de detecção como Falling edge para detectar apertos simples ou Rising/Falling edge para suporte a pressionamento longo.

Exemplo de callback para PA0:

void HAL_GPIO_EXTI_Callback(uint16_t pin) {
  if (pin == GPIO_PIN_0) {
    // Tratamento específico para tecla B4
    trigger_key_action(KEY_B4);
  }
}

Importante: ao usar EXTI, desative a varredura periódica e garanta que o pino esteja configurado como EXTI Line no CubeMX, com External Interrupt habilitado e detecção de borda definida.

Tags: STM32 GPIO HAL debounce EXTI

Publicado em 8-9 21:56