// STM32 Nucleo-L031K6 HAL Blink example
// Este comentário indica o propósito do código: um exemplo de piscar LED para a placa STM32 Nucleo-L031K6.
// Simulation: https://wokwi.com/projects/367244067477216257 (original)
// Este link aponta para uma simulação online do projeto original no Wokwi.
#include <stdint.h>
// Inclui a biblioteca de tipos inteiros padrão. Essencial para garantir tamanhos de variáveis precisos (ex: uint8_t, uint32_t),
// o que é crucial em programação de sistemas embarcados para compatibilidade com hardware e registradores.
#include <stm32l0xx_hal.h>
// Inclui a biblioteca HAL (Hardware Abstraction Layer) específica para a família de microcontroladores STM32L0.
// Esta biblioteca fornece funções e estruturas para interagir com o hardware do microcontrolador de forma padronizada.
// ST Nucleo Green user LED (PB3)
// Comentário explicando que o LED de usuário verde na placa Nucleo está conectado ao pino PB3.
#define LED_PORT GPIOB
// Define uma macro "LED_PORT" que representa o registrador do Grupo B de GPIOs (General Purpose Input/Output).
// Isso torna o código mais legível, referindo-se ao "porta do LED" em vez de GPIOB diretamente.
#define LED_PIN GPIO_PIN_3
// Define uma macro "LED_PIN" que representa o pino 3 do GPIO.
// Novamente, melhora a legibilidade, indicando que este é o "pino do LED".
#define LED_PORT_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE
// Define uma macro para habilitar o clock do Grupo B de GPIOs.
// Habilitar o clock é um passo fundamental para usar qualquer periférico no STM32,
// pois o clock fornece energia e sincronização para o hardware funcionar.
void SystemClock_Config(void);
// Declaração de uma função que irá configurar os clocks principais do sistema (CPU, periféricos).
void osSystickHandler(void)
// Declaração de uma função que é esperada ser chamada periodicamente pelo SysTick Timer (um timer do Cortex-M).
// Esta função atua como um "tick" de tempo para o sistema.
{
// 1 Hz blinking:
// Comentário indicando que o LED irá piscar a uma frequência de 1 Hertz (1 vez por segundo).
if ((HAL_GetTick() % 500) == 0)
// Verifica se o resto da divisão do tempo atual do sistema (em milissegundos, retornado por HAL_GetTick()) por 500 é zero.
// Isso significa que a cada 500ms, esta condição será verdadeira.
{
HAL_GPIO_TogglePin(LED_PORT, LED_PIN);
// Chama a função HAL para alternar o estado do pino do LED (se estiver ligado, desliga; se estiver desligado, liga).
// Combinado com a condição acima, isso fará o LED piscar a cada 500ms.
}
}
void initGPIO()
// Declaração de uma função para inicializar o pino do GPIO conectado ao LED.
{
GPIO_InitTypeDef GPIO_Config;
// Declara uma estrutura de configuração GPIO. Esta estrutura contém os parâmetros que definem como um pino GPIO deve se comportar.
GPIO_Config.Mode = GPIO_MODE_OUTPUT_PP;
// Configura o modo do pino como saída Push-Pull (PP). Isso permite que o pino forneça tanto alta quanto baixa corrente.
GPIO_Config.Pull = GPIO_NOPULL;
// Configura o resistor de pull-up/pull-down do pino como "nenhum". O pino não terá resistores internos de pull-up ou pull-down ativados.
GPIO_Config.Speed = GPIO_SPEED_FREQ_HIGH;
// Configura a velocidade de comutação do pino como alta. Relevante para sinais que mudam rapidamente.
GPIO_Config.Pin = LED_PIN;
// Atribui à estrutura o pino específico que será configurado, usando a macro LED_PIN (que é GPIO_PIN_3).
LED_PORT_CLK_ENABLE();
// Habilita o clock para a porta GPIO à qual o LED está conectado (Porta B, via a macro LED_PORT_CLK_ENABLE).
HAL_GPIO_Init(LED_PORT, &GPIO_Config);
// Inicializa o pino GPIO especificado (LED_PIN na LED_PORT) com as configurações definidas na estrutura GPIO_Config.
// Esta linha ja foi habilitada por LED_PORT_CLK_ENABLE(); poderia ser removida
// __HAL_RCC_GPIOB_CLK_ENABLE();
// Este é um comentário indicando que esta linha (que faz o mesmo que a macro LED_PORT_CLK_ENABLE)
// é redundante e pode ser removida.
}
int main(void)
// A função principal do programa, onde a execução começa.
{
HAL_Init();
// Inicializa a camada de abstração de hardware (HAL) do STM32.
// Isso configura o SysTick timer para gerar ticks de tempo (usado por HAL_GetTick() e osSystickHandler).
SystemClock_Config();
// Chama a função para configurar os clocks do sistema para as frequências desejadas.
initGPIO();
// Chama a função para inicializar o pino do LED.
HAL_GPIO_TogglePin(LED_PORT, LED_PIN);
// Alterna o estado do LED uma vez na inicialização.
// Se o LED começar desligado, esta linha o liga. Se já estiver ligado, o desliga.
while (1);
// Entra em um loop infinito. O programa permanece aqui para sempre,
// permitindo que o LED continue piscando devido à função osSystickHandler()
// que é chamada por interrupções do SysTick em segundo plano.
return 0;
// Esta linha nunca é alcançada devido ao loop while(1), mas é boa prática ter um retorno em main.
}
void SystemClock_Config(void)
// Implementação da função de configuração de clock do sistema.
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
// Declara e inicializa uma estrutura para configurar os osciladores do RCC (Reset and Clock Control).
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
// Declara e inicializa uma estrutura para configurar os clocks dos barramentos (CPU, AHB, APB).
// RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; // Removido, pois não há periféricos específicos de clock agora.
// Esta linha foi comentada/removida, pois não é mais necessário configurar clocks específicos para periféricos como a UART.
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
// Configura a escala de voltagem do regulador de energia interno do microcontrolador.
// Isso afeta o desempenho e o consumo de energia.
/** Initializes the RCC Oscillators according to the specified parameters
in the RCC_OscInitTypeDef structure.
*/
// Comentário explicando o propósito do próximo bloco de código: inicializar os osciladores.
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
// Define o tipo de oscilador a ser usado como HSI (High-speed internal), um oscilador interno de alta velocidade.
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
// Habilita o oscilador HSI.
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
// Define o valor de calibração para o HSI (geralmente o valor padrão de fábrica).
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
// Habilita o PLL (Phase-Locked Loop), que é um multiplicador de frequência para gerar clocks mais altos.
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
// Define a fonte do PLL como o HSI.
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_4;
// Define o fator de multiplicação do PLL como 4.
RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
// Define o fator de divisão do PLL como 2.
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
// Tenta configurar os osciladores com os parâmetros definidos.
{
Error_Handler();
// Se a configuração falhar (retornar algo diferente de HAL_OK), chama a função Error_Handler.
}
/** Initializes the CPU, AHB and APB buses clocks
*/
// Comentário explicando o propósito do próximo bloco de código: inicializar os clocks dos barramentos.
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
// Define quais clocks serão configurados: HCLK (clock do CPU/AHB), SYSCLK (clock do sistema),
// PCLK1 (clock do barramento APB1) e PCLK2 (clock do barramento APB2).
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
// Define a fonte do clock do sistema (SYSCLK) como o clock gerado pelo PLL.
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
// Define o divisor para o clock AHB (HCLK) como 1 (sem divisão).
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
// Define o divisor para o clock APB1 como 1 (sem divisão do HCLK).
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
// Define o divisor para o clock APB2 como 1 (sem divisão do HCLK).
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
// Tenta configurar os clocks dos barramentos e a latência da Flash.
{
Error_Handler();
// Se a configuração falhar, chama a função Error_Handler.
}
// PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2; // Removido
// PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1; // Removido
// if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) // Removido
// {
// Error_Handler();
// }
// Essas linhas, que configuravam o clock específico para a UART2, foram removidas.
}
void Error_Handler(void)
// Função chamada em caso de erro na inicialização HAL ou RCC.
{
/* User can add his own implementation to report the HAL error return state */
// Comentário indicando que o usuário pode adicionar seu próprio código para relatar o erro.
while(1);
// Entra em um loop infinito, travando o programa. Isso é útil em depuração para indicar que um erro ocorreu.
}
// Funções de UART e _write() foram removidas
// Comentário final indicando que as partes relacionadas à comunicação serial foram removidas.