AnsweredAssumed Answered

ADC behavior abnormal after wake up from STOP mode

Question asked by dz huang on Apr 23, 2018
Latest reply on May 2, 2018 by Heath Raftery

Hello,

   I'm using STM32L071RBT6 MCU, encounter a strange issue. when MCU power on, using ADC channel 0 to monitor external battery voltage, the result is OK. but once system waked up from STOP mode, ADC converter behavior is abnormal, the sampling value random varied from 0 ~ 2000. following is my STOP method, can give me some hint?

 

/* ADC init function */
static void MX_ADC_Init(void)
{

ADC_ChannelConfTypeDef sConfig;

HAL_ADCEx_EnableVREFINT();

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc.Instance = ADC1;
hadc.Init.OversamplingMode = DISABLE;
hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV16;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.SamplingTime = ADC_SAMPLETIME_79CYCLES_5;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ContinuousConvMode = ENABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.DMAContinuousRequests = ENABLE;
hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerFrequencyMode = DISABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

/**Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

/**Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_1;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

}

 

/***********************************************************************
* trigger MCU enter stop mode
*/
void powerSaving(void){
        //config GPIO to analog mode (zero consumption for every analog GPIO)
        lightLed(LED_GREEN, false);
        
        
        //HAL_ADC_DeInit(&hadc);
        //clear wakeup flag
        __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
        //call power function to enter "STOP" mode
        HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
        //after stop, program continue run from here
        //config RCC
        SystemClock_Config();
        //sysclkConfig_after_stop();
        //adc init
        HAL_ADC_DeInit(&hadc);
        MX_ADC_Init();
        HAL_ADCEx_Calibration_Start(&hadc, ADC_SINGLE_ENDED);
        //config GPIO
}


// following is ADC sampling methods:

static volatile uint16_t adcValue[5][2];
/***************************************************************************************
* Get battery voltage
*/
static void handleBattVoltageFetch(void){
if (ADC_IS_CONVERSION_ONGOING_REGULAR(&hadc) == SET) return;
//enable MOSFET
HAL_GPIO_WritePin(BATT_ADC_EN_GPIO_Port, BATT_ADC_EN_Pin, GPIO_PIN_SET);
osDelay(100);
//start  timer
osTimerStart(myMotoTimerHandle, 500);
//set batt vol ADC enable flag
setAdcControlFlag(BATT_VOL_ADC_EN);
//start ADC
HAL_ADC_Start_DMA(&hadc, (uint32_t*)adcValue, sizeof(adcValue)/sizeof(uint16_t));
}

/***************************************************************************************
* ADC completed, calculate voltage value
*/
static void handleBattVolAdcAvail(void){
HAL_ADC_Stop_DMA(&hadc);
//disable MOSFET
HAL_GPIO_WritePin(BATT_ADC_EN_GPIO_Port, BATT_ADC_EN_Pin, GPIO_PIN_RESET);

if (xTimerIsTimerActive(myMotoTimerHandle)){
osTimerStop(myMotoTimerHandle);
}

uint32_t vol = 0;
for (int i=0;i<5;i++){
vol += adcValue[i][1] & 0xfff;
#ifdef DEBUG_LOG_LEVEL_1
printf("val[%d][0] = %d, val[%d][1] = %d\n", i, adcValue[i][0], i, adcValue[i][1]);
osDelay(10);
#endif
}
vol = (vol * 67 * VDDA_VOLTAGE) / (20 * 5 * 4096);
sensorData.voltageData.batteryVoltage = vol;
if (vol > BATTERY_VOLTAGE_WARNING)
sensorData.voltageData.flag = (uint8_t)BATT_INFO;
else if (vol >= BATTERY_VOLTAGE_LOW)
sensorData.voltageData.flag = (uint8_t)BATT_WARNING;
else
sensorData.voltageData.flag = (uint8_t)BATT_LOW;
sensorData.flag |= DATA_UPDATE_VOLTAGE;
//inform mainApp that vol data is ready
osSignalSet(mainAppTaskHandle, SIG_MAINAPP_VOL_DATA_OK);
}

/****************************************************************************************
* ADC DMA convert completed callback
*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle){
uint32_t val;

if (isVolAdcEn()){ //check Voltage
HAL_ADC_Stop_DMA(&hadc);
osSignalSet(sensorTaskHandle, SIG_SENSOR_VOL_AVAIL);
}
}

Outcomes