2020-03-27 05:41 AM
Hi I am currently working on a project where I have to use single channel ADC with continuous conversion mode of STM32G431KB on NUCLEO board. However my code stucks at while loop where calibration needs to happen. Also I noticed that ADC12_Common register do not take value of 0b0001 which is divide clock by two. I am giving 42.5MHz ADC from PLLP divider and was planning to divide it by 2.
#include "main.h"
#include "SysClock_Config.h"
void DummyDelay(int x)
{
int temp = x;
while(temp)
{
temp--;
}
}
void Initialization(void)
{
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN | RCC_AHB2ENR_ADC12EN;
GPIOB->MODER |= GPIO_MODER_MODER0; //Set PB0 as Analog
ADC12_COMMON->CCR |= (0b0001 << ADC_CCR_PRESC_Pos); //ADC Clock divided by 2
ADC1->CR &= ~(ADC_CR_DEEPPWD); //Disable ADC Deep-Power-Down mode
ADC1->CR |= ADC_CR_ADVREGEN; //Enable ADC Voltage Regulator
DummyDelay(5000);
ADC1->CR &= ~(ADC_CR_ADEN); //Disable ADC
ADC1->CR &= ~(ADC_CR_ADCALDIF); //Single Ended Mode Calibration
ADC1->CR |= ADC_CR_ADCAL; //Start Calibration
while(ADC1->CR & ADC_CR_ADCAL); //Wait Until Calibration Complete
ADC1->CFGR |= ADC_CFGR_CONT; //ADC continuous mode
ADC1->CFGR &= ~(ADC_CFGR_RES); //12-bit ADC
ADC1->SQR1 |= (1 << ADC_SQR1_L_Pos) | (15 << ADC_SQR1_SQ1_Pos); // Only 1 conversion for ADC channel 15
ADC1->CR |= ADC_CR_ADEN; //Enable ADC
while(!(ADC1->ISR & ADC_ISR_ADRDY)); //Wait Until ADC Enables
}
int main(void)
{
HAL_Init();
SystemClock_Config();
Initialization();
ADC1->CR |= ADC_CR_ADSTART; //Start ADC Sampling/Conversion Sequence
while (1)
{
}
}
#include "main.h"
void Error_Handler(void)
{
}
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_BOOST);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV6;
RCC_OscInitStruct.PLL.PLLN = 85;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV8;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses 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_8) != HAL_OK)
{
Error_Handler();
}
SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk);
}
NOTE: I am using STM32CubeIDE.
2020-03-27 06:50 AM
Why not use the cubemx generated code to initialize the adc as well? Probably just missing something.
2020-03-28 08:26 AM
I don't like cubemx generating everything sometimes it gets buggy. Is there someone who programmed STM32G4 at register level?
2020-03-28 10:14 AM
> I don't like cubemx generating everything sometimes it gets buggy.
Who has the buggy code now?
Like it or not, pretty much all software has bugs. Even if you don't want to use CubeMX, the code it generates can be helpful for figuring out what you're doing wrong.
In this case, your clock initialization is different from what HAL does. Depending on your compiler settings, it may be a problem, or it may not.
This is from the H7, but I'm sure the G4 code is similar:
#define __HAL_RCC_ADC12_CLK_ENABLE() do { \
__IO uint32_t tmpreg; \
SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_ADC12EN);\
/* Delay after an RCC peripheral clock enabling */ \
tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_ADC12EN);\
UNUSED(tmpreg); \
} while(0)
2020-03-30 01:15 AM
I have sometimes had to give the ADCs more time to convert. Try adding longer pre-scale times