I'm currently trying to change the baudrate at runtime for my STM32 based on whatever input my ESP32 sends it over UART. I'm. not really sure how to go about it or if its even possible to do so.
Basically I'm sending a uint32 over UART to the STM32 and hoping it is receiving it as the number I'm sending then aborting and deinitializing the UART, reinitializing it with the new baud rate and then initializing the UART again.
However, this does not seem to be having any effect. I can't tell if what I'm sending it just not making it to the STM32 as the value I intended or if it's receiving the value and just not doing anything. Any help or advice would be greatly appreciated.
uint8_t Rx_data[100] = "<Hello World\n>";
int baud = 115200;
uint8_t Tx_data[100];
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration-------------------------------------------
-------------*/
/* Reset of all peripherals, Initializes the Flash interface
and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
// Transmit data via UART
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // Blink
// HAL_Delay(1000); // Delay blink for 1 second
HAL_UART_Receive(&huart1, (uint8_t*)Tx_data, 100, 100); //
Receive comms from ESP32
uint8_t Tx_value = Tx_data;
if(baud != Tx_value) {
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // Blink
HAL_Delay(1000); // Delay blink for 1 second
baud = Tx_value;
Change_baud(baud);
}
HAL_UART_Transmit(&huart2,(uint8_t*) Tx_data, 100, 100); // Transmit comms from ESP32 to terminal
HAL_UART_Transmit(&huart1, Rx_data, sizeof(Rx_data), 100);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//HAL_UART_Receive(&huart2, Rx_data, 4, 1000);
}
/* USER CODE END 3 */
}
void Change_baud(int baud) {
HAL_UART_DeInit(&huart2);
MX_USART2_UART_Init_baud(baud);
HAL_UART_Receive_IT(&huart2, (uint8_t*)Rx_data, 100);
}
static void MX_USART2_UART_Init_baud(int baud)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = baud;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE END USART2_Init 2 */
}
I realize this is not the best written code, I'm VERY new to STM32 and how to program it.
I'm using an STM32H755 (on NUCLEO-Board) with CubeIDE and trying to set up an ADC with HAL.
Without any changes to the default ADC and clock setup, the ADC goes into "error internal" state when trying to read values. Any Ideas why?
I didn't touch any ADC or clock settings, just set the runtime context in the .ioc file.
When initialized, the ADC state goes to "Ready" (after calling MX_ADC1_Init()) but after starting it with HAL_ADC_Start(&hadc1), HAL_ADC_GetError(&hadc1) and HAL_ADC_GetState(&hadc1) read the error message "error internal" and no values can be read.
Side note: with the same setup, DAC and DMA are working fine.
Here is my code (irrelevant code cut out) :
/* Private variables ---------------------------------------------------------*/
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma location=0x30000000
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
#pragma location=0x30000200
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
#pragma location=0x30000260
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE]; /* Ethernet Receive Buffers */
#elif defined ( __CC_ARM ) /* MDK ARM Compiler */
__attribute__((at(0x30000000))) ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
__attribute__((at(0x30000200))) ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
__attribute__((at(0x30000260))) uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE]; /* Ethernet Receive Buffer */
#elif defined ( __GNUC__ ) /* GNU Compiler */
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE] __attribute__((section(".RxArraySection"))); /* Ethernet Receive Buffers */
#endif
ETH_TxPacketConfig TxConfig;
ADC_HandleTypeDef hadc1;
ETH_HandleTypeDef heth;
UART_HandleTypeDef huart3;
PCD_HandleTypeDef hpcd_USB_OTG_FS;
/* USER CODE BEGIN PV */
uint64_t state = 0;
uint64_t error = 0;
uint16_t value = 0;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ETH_Init(void);
static void MX_USART3_UART_Init(void);
static void MX_USB_OTG_FS_PCD_Init(void);
static void MX_ADC1_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* USER CODE BEGIN Boot_Mode_Sequence_0 */
int32_t timeout;
/* USER CODE END Boot_Mode_Sequence_0 */
/* USER CODE BEGIN Boot_Mode_Sequence_1 */
/* Wait until CPU2 boots and enters in stop mode or timeout*/
timeout = 0xFFFF;
while((__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) != RESET) && (timeout-- > 0));
if ( timeout < 0 )
{
Error_Handler();
}
/* USER CODE END Boot_Mode_Sequence_1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN Boot_Mode_Sequence_2 */
/* When system initialization is finished, Cortex-M7 will release Cortex-M4 by means of
HSEM notification */
/*HW semaphore Clock enable*/
__HAL_RCC_HSEM_CLK_ENABLE();
/*Take HSEM */
HAL_HSEM_FastTake(HSEM_ID_0);
/*Release HSEM in order to notify the CPU2(CM4)*/
HAL_HSEM_Release(HSEM_ID_0,0);
/* wait until CPU2 wakes up from stop mode */
timeout = 0xFFFF;
while((__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) == RESET) && (timeout-- > 0));
if ( timeout < 0 )
{
Error_Handler();
}
/* USER CODE END Boot_Mode_Sequence_2 */
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ETH_Init();
MX_USART3_UART_Init();
MX_USB_OTG_FS_PCD_Init();
MX_ADC1_Init();
/* USER CODE BEGIN 2 */
HAL_Delay(1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
error = HAL_ADC_GetError(&hadc1);
state = HAL_ADC_GetState(&hadc1);
HAL_ADC_Start(&hadc1);
error = HAL_ADC_GetError(&hadc1);
state = HAL_ADC_GetState(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 1000);
error = HAL_ADC_GetError(&hadc1);
state = HAL_ADC_GetState(&hadc1);
value = HAL_ADC_GetValue(&hadc1);
}
/* USER CODE END 3 */
}
/**
* #brief System Clock Configuration
* #retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Supply configuration update enable
*/
HAL_PWREx_ConfigSupply(PWR_DIRECT_SMPS_SUPPLY);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 1;
RCC_OscInitStruct.PLL.PLLN = 24;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 4;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
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_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV1;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}
/**
* #brief ADC1 Initialization Function
* #param None
* #retval None
*/
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.Resolution = ADC_RESOLUTION_16B;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_3;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
sConfig.OffsetSignedSaturation = DISABLE;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}
Found the error by myself...
In the MX_ADC1_Init() function, there was the line hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1 missing to set the adc clock. There was no option to select this setting in the .ioc file ;-/
Turns out that with the default value for hadc1.Init.ClockPrescaler in the HAL, the adc won't work
The goal is to read multiple ADC channels by polling. It does not need to be fast - the idea is to read the voltages from different batteries that are attached. I have a STM32L071 microcontroller. The programming is a bit different compared to the STM32F0 model. I am using platformio.
I found already very helpful information here:
Individually read distinct inputs with STM32F0 ADC
https://controllerstech.com/stm32-adc-multiple-channels/
https://deepbluembedded.com/stm32-adc-tutorial-complete-guide-with-examples/
However, unfortunately I cannot read out multiple channels. The problems are probably related to HAL_ADC_Init and HAL_ADC_ConfigChannel.
Here is a minimal code example:
#include <Arduino.h>
#include <STM32IntRef.h>
uint32_t a1=0, a2=0;
#define HAL_ADC_MODULE_ENABLED
ADC_HandleTypeDef hadc1;
void displaying(){
Serial.println("values:");
Serial.println("-------");
Serial.print("ch1 - ");
Serial.println(a1);
Serial.print("ch2 - ");
Serial.println(a2);
Serial.println("");
}
void config_ext_channel_ADC(uint32_t channel, bool val) {
hadc1.Instance = ADC1;
hadc1.Init.SamplingTime = ADC_SAMPLETIME_79CYCLES_5;
HAL_ADC_Init(&hadc1);
ADC_ChannelConfTypeDef sConfig;
sConfig.Channel = channel;
if (val == true) {
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
} else {
sConfig.Rank = ADC_RANK_NONE;
}
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
Serial.println("Error ADC Config Channel");
//Error_Handler();
}
}
uint32_t r_single_ext_channel_ADC(uint32_t channel) {
/* read the ADC and output result */
uint32_t digital_result;
config_ext_channel_ADC(channel, true);
HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 1000);
digital_result = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
config_ext_channel_ADC(channel, false);
return digital_result;
}
void readBat() {
/* read voltages */
a1 = r_single_ext_channel_ADC(1);
a2 = r_single_ext_channel_ADC(PA2);
}
void setup() {
// put your setup code here, to run once:
// Serial monitor
Serial.begin(9600);
Serial.println(F("Starting now"));
// initialize pins for ADC
analogReadResolution(ADC_RESOLUTION);
pinMode(PA1, INPUT);
//pinMode(BATTERY_SENSE_PIN2, INPUT);
pinMode(PA2, INPUT_ANALOG);
}
void loop() {
// put your main code here, to run repeatedly:
readBat();
displaying();
delay(2000);
}
The output is:
values:
-------
ch1 - 0
ch2 - 140
Sounds reasonable, but applying some voltages at the pins does not change the values.
Could somebody please provide me some advice, ideas?
Okay, in the meantime I found the problem. The software is fine; I took the Arduino framework and used analogRead().
I needed to clean all the solder flux from the PCB which caused some contacts between the pins.
Moreover, if one wants to use address the HAL directly, one should set the ClockDivider such that the ADC samples below 1 MHz.
Code to read different ADC channels (here ADC2 with 2 channels) separetly (Generated By CubeMX):
Note: We have to use ScanConvMode plus DiscontinuousConvMode and NO ContinuousConvMode.
/* ADC2 init function */
void MX_ADC2_Init(void)
{
/* USER CODE BEGIN ADC2_Init 0 */
/* USER CODE END ADC2_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC2_Init 1 */
/* USER CODE END ADC2_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc2.Instance = ADC2;
hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc2.Init.Resolution = ADC_RESOLUTION_12B;
hadc2.Init.ScanConvMode = ENABLE;
hadc2.Init.ContinuousConvMode = DISABLE;
hadc2.Init.DiscontinuousConvMode = ENABLE;
hadc2.Init.NbrOfDiscConversion = 1;
hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc2.Init.NbrOfConversion = 2;
hadc2.Init.DMAContinuousRequests = DISABLE;
hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc2) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_9;
sConfig.Rank = 2;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC2_Init 2 */
/* USER CODE END ADC2_Init 2 */
}
Now, to read:
void readChannel(){
//read the next channel
HAL_ADC_Start(&hadc2);
uint8_t ret = HAL_ADC_PollForConversion(&hadc2, 1000 /*timeout*/);
uint16_t value = HAL_ADC_GetValue(hadc);
printf("HAL_ADC_PollForConversion status: %d, VALLLL: %d\n", ret, value);
}
int main(){
while(1){
//Automatically read the first channel (channel 8):
readChannel();
HAL_Delay(100);
//Automatically read the second channel (channel 9):
readChannel();
HAL_Delay(100);
}
}
Did you miss to set the io to analog in mode? It should be something like this somewhere (usually in your hal msp file, adc_init func).
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
edit => you missed it for ch1
analogReadResolution(ADC_RESOLUTION);
pinMode(PA1, INPUT);
//pinMode(BATTERY_SENSE_PIN2, INPUT);
pinMode(PA2, INPUT_ANALOG);
It should be the same as PA2, input is "digital mode".
I am using an STM32G431CB (and the HAL) to record ADC data data using DMA, control/read GPIOs, communicate via I2C and USB CDC (virtual comm port), and use timers. I have verified that each of these peripherals work correctly individually both on a dev board (NUCLEO-G431KB) and on my custom board with the 48 pin version of the same chip (STM32G431CB).
However, the problem that I am running into is that the program will occasionally jump to an instruction at address 0x1fff4be0. This is in system memory. After inspecting disassembly, I don't see any instruction that would cause it to branch here. In different versions of this program with one or few of the peripherals running, this jump has happened when calling different HAL functions including:
HAL_GPIO_ReadPin
HAL_GPIO_WritePin
HAL_I2C_Master_Transmit
HAL_ADC_Start_DMA
I don't think that there is any correlation between the function called and the jump to system memory.
What can cause the STM32 to do this? I am trying to use PB8-BOOT0 as a GPIO output. When I leave PB8-BOOT0 unconfigured (reset state), I do not run into this issue.
main.c:
#include "main.h"
#include "usb_device.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdint.h>
#include "mymain.h"
#include "usbd_cdc_if.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
I2C_HandleTypeDef hi2c3;
TIM_HandleTypeDef htim6;
TIM_HandleTypeDef htim7;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_DMA_Init(void);
static void MX_I2C3_Init(void);
static void MX_TIM7_Init(void);
static void MX_TIM6_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint16_t ADC_result[4]; // ADC results: {TEMP_SENSOR, AC_CHG, R_SLIDER, L_SLIDER}
uint8_t I2Cdata;
uint8_t USB_tx_buffer[24];
struct SB_data SB1;
struct SB_data SB2;
uint16_t GPIO_data = 0x00c0;
/* USER CODE END 0 */
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_DMA_Init();
MX_I2C3_Init();
MX_USB_Device_Init();
MX_TIM7_Init();
MX_TIM6_Init();
/* USER CODE BEGIN 2 */
HAL_DMA_Init(&hdma_adc1);
TPS55288Q1_Init();
// GPIO initial states
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // Initialize USB 3 hub in reset until tablet supplies power on TAB_DCOUT->VBUS_DET3V3 (PA2)
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET); // Initialize 5V, 3.3V, 2.5V, 1.2V supplies off (net Enable_Power)
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET); // Initialize L mouse off
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET); // Enable EN_EXT_USB_PWR by default
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET); // DISABLE_CHG1
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET); // DISABLE_CHG2
// BEGIN TESTING ONLY //
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET);
// END TESTING ONLY //
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// ADC DMA Start
//HAL_ADC_Start_DMA(&hadc1, (uint32_t*) ADC_result, 4);
// Log GPIO data
log_GPIO_data();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* #brief System Clock Configuration
* #retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(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.PLLM = RCC_PLLM_DIV1;
RCC_OscInitStruct.PLL.PLLN = 12;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV4;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
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_HSI;
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_0) != HAL_OK)
{
Error_Handler();
}
}
/**
* #brief ADC1 Initialization Function
* #param None
* #retval None
*/
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.GainCompensation = 0;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 4;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_2;
sConfig.Rank = ADC_REGULAR_RANK_2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_4;
sConfig.Rank = ADC_REGULAR_RANK_3;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR_ADC1;
sConfig.Rank = ADC_REGULAR_RANK_4;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}
/**
* #brief I2C3 Initialization Function
* #param None
* #retval None
*/
static void MX_I2C3_Init(void)
{
/* USER CODE BEGIN I2C3_Init 0 */
/* USER CODE END I2C3_Init 0 */
/* USER CODE BEGIN I2C3_Init 1 */
/* USER CODE END I2C3_Init 1 */
hi2c3.Instance = I2C3;
hi2c3.Init.Timing = 0x00303D5B;
hi2c3.Init.OwnAddress1 = 0;
hi2c3.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c3.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c3.Init.OwnAddress2 = 0;
hi2c3.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c3.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c3.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c3) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c3, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter
*/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c3, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C3_Init 2 */
/* USER CODE END I2C3_Init 2 */
}
/**
* #brief TIM6 Initialization Function
* #param None
* #retval None
*/
static void MX_TIM6_Init(void)
{
/* USER CODE BEGIN TIM6_Init 0 */
/* USER CODE END TIM6_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM6_Init 1 */
/* USER CODE END TIM6_Init 1 */
htim6.Instance = TIM6;
htim6.Init.Prescaler = 1600-1;
htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
htim6.Init.Period = 19999;
htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM6_Init 2 */
/* USER CODE END TIM6_Init 2 */
}
/**
* #brief TIM7 Initialization Function
* #param None
* #retval None
*/
static void MX_TIM7_Init(void)
{
/* USER CODE BEGIN TIM7_Init 0 */
/* USER CODE END TIM7_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM7_Init 1 */
/* USER CODE END TIM7_Init 1 */
htim7.Instance = TIM7;
htim7.Init.Prescaler = 1600-1;
htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
htim7.Init.Period = 121;
htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim7) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim7, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM7_Init 2 */
/* USER CODE END TIM7_Init 2 */
}
/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMAMUX1_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
/**
* #brief GPIO Initialization Function
* #param None
* #retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4|GPIO_PIN_10, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_8, GPIO_PIN_RESET);
/*Configure GPIO pins : PA4 PA10 */
GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PB2 PB11 PB12 PB8 */
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
// Initializes TPS55288Q1 buck-boost converters by configuring external voltage divider, resetting error flags, and disabling output
void TPS55288Q1_Init() {
I2Cdata = 0b10000011;
HAL_I2C_Mem_Write(&hi2c3, TPS55288Q1_TAB_DCIN_DEV_ADDR<<1, TPS55288Q1_VOUT_FS_ADDR, 1, &I2Cdata, 1, 2); // Use external voltage divider
HAL_I2C_Mem_Write(&hi2c3, TPS55288Q1_12V_DEV_ADDR<<1, TPS55288Q1_VOUT_FS_ADDR, 1, &I2Cdata, 1, 2);
HAL_I2C_Mem_Read(&hi2c3, TPS55288Q1_TAB_DCIN_DEV_ADDR<<1, TPS55288Q1_STATUS_R, 1, &I2Cdata, 1, 2); // Read and reset error flags
HAL_I2C_Mem_Read(&hi2c3, TPS55288Q1_12V_DEV_ADDR<<1, TPS55288Q1_STATUS_R, 1, &I2Cdata, 1, 2);
I2Cdata = 0b00100000; // ~OE, all else default
HAL_I2C_Mem_Write(&hi2c3, TPS55288Q1_TAB_DCIN_DEV_ADDR<<1, TPS55288Q1_MODE_R_ADDR, 1, &I2Cdata, 1, 2);
HAL_I2C_Mem_Write(&hi2c3, TPS55288Q1_12V_DEV_ADDR<<1, TPS55288Q1_MODE_R_ADDR, 1, &I2Cdata, 1, 2);
}
// switches the channel being read on ADC1
void ADC1_Select_Channel(uint32_t channel) {
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = channel;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
Error_Handler();
}
}
// reads GPIO inputs that will be transmitted to the tablet
// {DISABLE_CHG2, DISABLE_CHG1, ~BATID2, ~BATID1, RB2, RB1, LB2, LB1}
void log_GPIO_data() {
GPIO_data &= 0xffc0; // clear bottom 6 bits
GPIO_data |= HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6) | (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7) << 1) |
(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) << 2) | (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) << 3) |
(!HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_13) << 4) | (!HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_1) << 5);
}
void set_bit(uint16_t* data, uint8_t bit_pos, uint8_t value) {
if (value) {
*data |= 1<<bit_pos;
} else {
*data &= ~(1<<bit_pos);
}
}
// Returns 1 if either battery is inserted and not fully discharged or if AC_CHG_Det is 1. Indicates active power source
uint8_t PWRsource_det() {
return (bat1_inserted() && (SB1.status[0] & 0x10)) || (bat2_inserted() && (SB2.status[0] & 0x10)) || (GPIO_data & 0x0100);
}
// Returns 1 if Smart Battery 1 is inserted, 0 otherwise
uint8_t bat1_inserted() { // internal pull down resistor on smart battery when detected. Pin is low when battery is inserted
return GPIO_data & (1<<4);
}
// Returns 1 if Smart Battery 2 is inserted, 0 otherwise
uint8_t bat2_inserted() { // internal pull down resistor on smart battery when detected. Pin is low when battery is inserted
return GPIO_data & (1<<5);
}
// loads the USB CDC transmission buffer. Multi-byte data fields are Little Endian. Ends in \n\r.
void load_USB_TX_buffer(uint8_t* TX_buffer, struct SB_data* bat1, struct SB_data* bat2, uint16_t* ADC_readings, uint16_t GPIO_inputs, uint16_t temperature) {
TX_buffer[0] = bat1->status[0];
TX_buffer[1] = bat1->status[1];
TX_buffer[2] = bat1->timetoempty[0];
TX_buffer[3] = bat1->timetoempty[1];
TX_buffer[4] = bat1->voltage[0];
TX_buffer[5] = bat1->voltage[1];
TX_buffer[6] = bat1->chgpercent;
TX_buffer[7] = bat2->status[0];
TX_buffer[8] = bat2->status[1];
TX_buffer[9] = bat2->timetoempty[0];
TX_buffer[10] = bat2->timetoempty[1];
TX_buffer[11] = bat2->voltage[0];
TX_buffer[12] = bat2->voltage[1];
TX_buffer[13] = bat2->chgpercent;
TX_buffer[14] = (uint8_t) (ADC_readings[1] >> 8); // Right slider
TX_buffer[15] = (uint8_t) ADC_readings[1];
TX_buffer[16] = (uint8_t) (ADC_readings[0] >> 8); // Left Slider
TX_buffer[17] = (uint8_t) ADC_readings[0];
TX_buffer[18] = (uint8_t) (temperature >> 8); // Temperature sensor
TX_buffer[19] = (uint8_t) temperature;
TX_buffer[20] = (uint8_t) (GPIO_inputs & 0xff);
TX_buffer[21] = (uint8_t) ((GPIO_inputs >> 8) & 0xff);
TX_buffer[22] = (uint8_t) '\n';
TX_buffer[23] = (uint8_t) '\r';
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) {
if (htim == &htim6) { // USB RX Comms 2s timeout
HAL_TIM_Base_Stop_IT(&htim7); // Stop USB TX
HAL_TIM_Base_Stop_IT(&htim6);
// disable 12V and TAB_DCIN
uint8_t data = 0b00100000; // ~OE, all else default
HAL_I2C_Mem_Write(&hi2c3, TPS55288Q1_TAB_DCIN_DEV_ADDR<<1, TPS55288Q1_MODE_R_ADDR, 1, &data, 1, 10);
data = 0b00100100; // ~OE, address=0x75, all else default
HAL_I2C_Mem_Write(&hi2c3, TPS55288Q1_12V_DEV_ADDR<<1, TPS55288Q1_MODE_R_ADDR, 1, &data, 1, 10);
// disable 5V, 3.3V, 2.5V, 1.2V supplies (net Enable_Power)
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET);
} else if (htim == &htim7) { // USB TX call (82Hz)
uint16_t temperature = __HAL_ADC_CALC_TEMPERATURE(3300, ADC_result[3], ADC_RESOLUTION_12B);
load_USB_TX_buffer(USB_tx_buffer, (struct SB_data*) &SB1, (struct SB_data*) &SB2, (uint16_t*) ADC_result, GPIO_data, temperature);
CDC_Transmit_FS(USB_tx_buffer, sizeof(USB_tx_buffer));
/* ** UART DEBUG **
uint8_t usart_d[] = "SRS\n\r";
HAL_UART_Transmit(&huart2, usart_d, sizeof(usart_d), 2);
*/
}
}
/* USER CODE END 4 */
/**
* #brief This function is executed in case of error occurrence.
* #retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* #brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* #param file: pointer to the source file name
* #param line: assert_param error line source number
* #retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
Your microcontroller is executing the embedded bootloader.
Depending on the micro that can be caused by one or more of the following:
Obtion byte settings
BOOT0 pin
Content of the first word of flash during BOR.
Option byte are loaded only on BOR if an update is not explicited called through OBL_LAUNCH. Flash empty flag (the last point) is also only evaluated during BOR. No update is possible without BOR. You can exit bootloader with an approriate command via bootloader interfaces.
Probably due to the fact you are using BOOT0 as a GPIO (unless it is a specific feature of the STM32G4, I know only H7 and L4).
I think if a reset occurs for whatever reason , and the signal is at the wrong state, you will end up booting on System Flash.
I have to measure adc value using internal reference voltage in STM32L422. According to datasheet STM32L422 internal reference voltage is 1.2 V. I enabled internal Vref from CubeMX.
Analog input is 1V but I get 0.58 V. what is the problem here anyone ?
STM32L422 datasheet says that internal Vref = 1.2 V. When I measured Vref pin, it was 0.53 V.
What is wrong over here ?
For 1 V input which is obtained using 20K, 10K voltage divider, for 3V, digital and analog values obtained are are follows:
Digital: 1983, Analog value: 0.581099
#define VREFINT_ADDR 0x1FFF75AA // VREF voltage
#define VREFINT (*((uint16_t *) VREFINT_ADDR))
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_SPI1_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
MX_TIM6_Init();
MX_RTC_Init();
/* USER CODE BEGIN 2 */
printf("System Booting On! \n");
printf("VREFINT: %ud\n", VREFINT);
printf("ADC Calibration! \n");
while(HAL_ADCEx_Calibration_Start(&hadc1,0) != HAL_OK);
printf("Battery Voltage Check ...\n");
HAL_Delay(100); // 1000ms OK => 100ms OK
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1,100);
ADC_Val=HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
float Result = (float)((1.200 * ADC_Val) / 4095);
printf("****************************************************************\n");
printf("Digital: %d, Analog value : %f\r\n", ADC_Val, Result);
printf("****************************************************************\n");
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
;
}
/* USER CODE END 3 */
}
void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV8;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_12;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_92CYCLES_5;
// sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}
STM32 ADC works a bit different way than you think and the Vrefint name is a bit confusing. Always read the Reference Manual.
Vrefint is not the reference voltage for ADC. It is simply connected one of the channels. When you measure this voltage you can know your Vref for ADC (in your case it is Vdda) So the formula you use is wrong.
STM32L422 datasheet says that internal Vref = 1.2 V
Do not read the datasheet only Reference Manual
Then you need to measure your Vref (Vdda) and rthen you can measure your voltage on the pin.