// STM32 Nucleo-L031K6 HAL Blink + printf() example
// Simulation: https://wokwi.com/projects/367244067477216257
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stm32l0xx_hal.h>
#include <stm32l0xx.h>
void SystemClock_Config(void);
uint16_t adc_init_and_read_PA0(void);
int main(void)
{
RCC->IOPENR |= (1<<1);
GPIOB->MODER &= ~(0x3 << (3 * 2));
GPIOB->MODER |= (0x1 << (3 * 2)); // MODER0 = 11b
GPIOB->ODR |= (0 << 3);
HAL_Init();
SystemClock_Config();
uint16_t valor_adc = adc_init_and_read_PA0();
while(1){
valor_adc = adc_init_and_read_PA0();
if (valor_adc > 4000) GPIOB->ODR |= (1 << 3);
//else GPIOB-> &= ~(1 << 3);
}
}
#include <stdint.h>
uint16_t adc_init_and_read_PA0(void) {
// 1. Habilita clocks: GPIOA e ADC
RCC->IOPENR |= (1 << 0); // GPIOAEN
RCC->APB2ENR |= (1 << 9); // ADCEN
// 2. Configura PA0 como analógico
GPIOA->MODER &= ~(0x3 << (0 * 2));
GPIOA->MODER |= (0x3 << (0 * 2)); // MODER0 = 11b
// 3. Ativa regulador interno do ADC
ADC1->CR &= ~(0b11 << 28);
ADC1->CR |= (0b01 << 28); // ADVREGEN = 01 (intermediate)
for (volatile int i = 0; i < 1000; ++i); // Delay simples
ADC1->CR &= ~(0b11 << 28);
ADC1->CR |= (0b10 << 28); // ADVREGEN = 10 (enabled)
for (volatile int i = 0; i < 1000; ++i); // Delay simples
// 4. Calibração
ADC1->CR |= (1 << 31); // ADCAL = 1
while (ADC1->CR & (1 << 31)); // Espera calibrar
// 5. Habilita o ADC
ADC1->CR |= (1 << 0); // ADEN
while (!(ADC1->ISR & (1 << 0))); // Espera ADRDY = 1
// 6. Seleciona canal 0 (PA0 = ADC_IN0)
ADC1->CHSELR = (1 << 0); // Seleciona canal 0
// 7. Inicia conversão
ADC1->CR |= (1 << 2); // ADSTART
// 8. Espera fim da conversão
while (!(ADC1->ISR & (1 << 2))); // EOC = 1
// 9. Lê resultado
return (uint16_t)(ADC1->DR & 0xFFFF);
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_4;
RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
void Error_Handler(void)
{
/* User can add his own implementation to report the HAL error return state */
}