2019-05-22 02:27 PM
I have an old project already using PA 0,1,2,3,5,7 and PC 1,2,3 as analogue inputs, all on ADC 1 and 2. Due the nature of the project I read some of them in a interrupt timer, and some on demand,when a UART command kicks in.
I had to add 3 more ADC's on PB0 PB1 PB2 on ADC3. My code follows same initialization for ADC3 as ADC1/2, which is standard CUBEMX code.
Upon reading, the ADC3 times out waiting for ISR bit.
static HAL_StatusTypeDef ADC_Enable(ADC_HandleTypeDef* hadc)
{
uint32_t tickstart = 0U;
/* ADC enable and wait for ADC ready (in case of ADC is disabled or */
/* enabling phase not yet completed: flag ADC ready not yet set). */
/* Timeout implemented to not be stuck if ADC cannot be enabled (possible */
/* causes: ADC clock not running, ...). */
if (ADC_IS_ENABLE(hadc) == RESET)
{
/* Check if conditions to enable the ADC are fulfilled */
if (ADC_ENABLING_CONDITIONS(hadc) == RESET)
{
/* Update ADC state machine to error */
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
/* Set ADC error code to ADC IP internal error */
SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
return HAL_ERROR;
}
/* Enable the ADC peripheral */
__HAL_ADC_ENABLE(hadc);
/* Wait for ADC effectively enabled */
tickstart = HAL_GetTick();
while(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_RDY) == RESET)
{
if((HAL_GetTick() - tickstart) > ADC_ENABLE_TIMEOUT)
{
/* Update ADC state machine to error */
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
/* Set ADC error code to ADC IP internal error */
SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
return HAL_ERROR; <<<<==== TIMEOUTS
}
}
}
/* Return HAL status */
return HAL_OK;
}
I disabled all the code around leaving only the ADC3. The flags and timer for ADC3 is started. I am struggling with this issue for a 2 days now. Here is my code for reference. Anyone can spot something wrong would be appreciated.
My Init code (never failed on ADC1 and 2 for few months)
///////////////////////////////////////////
// MAIN
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART3_UART_Init();
INIT_PWM_TIMERS() // TIM2(10Khz) TIM3-ch1,ch2 (100Khz) TIM4-ch1,2,3,4 (100Khz) & __HAL_RCC_TIM 2,3,4_CLK_ENABLE
// MX_ADC1_Init();
// MX_ADC2_Init();
MX_ADC3_Init();
// readPinValue(PA7); //<- this works on ADC2
readPinValue(PB0); //<- this fails
return 0;
}
/////////////////////////////////////////////////////////////
MX_ADC[1..3]_Init()
{
ADC_ChannelConfTypeDef sConfig;
hadc3.Instance = ADC[1..3];
myInit_Adc(&hadc[1..3]);
if (HAL_ADC_Init(&hadc[1..3]) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
myInitChannels(&hadc[1..3], &sConfig);
}
/////////////////////////////////////////////////////////////
static void myInit_Adc(ADC_HandleTypeDef* hadc)
{
hadc->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc->Init.Resolution = ADC_RESOLUTION_12B;
hadc->Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc->Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc->Init.EOCSelection = DISABLE; // to turn on once. ADC_EOC_SINGLE_CONV; //ADC_EOC_SEQ_CONV
hadc->Init.LowPowerAutoWait = DISABLE;
//hadc->Init.LowPowerAutoPowerOff = DISABLE;
hadc->Init.ContinuousConvMode = DISABLE;
hadc->Init.DiscontinuousConvMode = DISABLE;
hadc->Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc->Init.DMAContinuousRequests = DISABLE;
hadc->Init.Overrun = ADC_OVR_DATA_PRESERVED;
}
/////////////////////////////////////////////////////////////
static void myInitChannels(ADC_HandleTypeDef* hadc,
ADC_ChannelConfTypeDef* sConfig)
{
struct AnalogPin* pp = &Anals[0];
for(; pp->typ!=PNA; pp++)
{
if(pp->adc == hadc)
{
sConfig->Channel = pp->channel; // from PIN right channel
sConfig->Rank = pp->rank; // allways ADC_RANK_CHANNEL_NUMBER
sConfig->SingleDiff = ADC_SINGLE_ENDED;
sConfig->SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
sConfig->OffsetNumber = ADC_OFFSET_NONE;
sConfig->Offset = 0;
if (HAL_ADC_ConfigChannel(hadc, sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
}
}
///
/// MSP INIT
///
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(adcHandle->Instance==ADC1)
{
HAL_RCC_ADC12_CLK_ENABLED++;
if(HAL_RCC_ADC12_CLK_ENABLED==1){
__HAL_RCC_ADC12_CLK_ENABLE();
}
/**ADC1 GPIO Configuration
PC0 ------> ADC1_IN6
PC1 ------> ADC1_IN7
PC2 ------> ADC1_IN8
PC3 ------> ADC1_IN9
PA0 ------> ADC1_IN1
PA1 ------> ADC1_IN2
PA2 ------> ADC1_IN3
PA3 ------> ADC1_IN4
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
else if(adcHandle->Instance==ADC2)
{
HAL_RCC_ADC12_CLK_ENABLED++;
if(HAL_RCC_ADC12_CLK_ENABLED==1){
__HAL_RCC_ADC12_CLK_ENABLE();
}
/**ADC2 GPIO Configuration
PA5 ------> ADC2_IN2
PA6 ------> ADC2_IN3
PA7 ------> ADC2_IN4
PB2 ------> ADC2_IN12
*/
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
else if(adcHandle->Instance==ADC3)
{
/* USER CODE BEGIN ADC3_MspInit 0 */
HAL_RCC_ADC34_CLK_ENABLED++;
if(HAL_RCC_ADC34_CLK_ENABLED==1){
__HAL_RCC_ADC34_CLK_ENABLE();
}
/**ADC3 GPIO Configuration
PB0 ------> ADC3_IN12
PB1 ------> ADC3_IN1
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
}
My read code:
//
// SELECT ADC
//
ADC_ChannelConfTypeDef sConfig;
sConfig.Channel = ADC_CHANNEL_[FOR PIN]; (11 for ADC3 PB0)
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
HAL_ADC_ConfigChannel(HADC, &sConfig);
//
// START
//
HAL_ADC_Start(HADC); /// <<<< fails for ADC3 as described above
//
// rewad
//
HAL_ADC_PollForConversion(...)
HAL_ADC_GetValue(...)
HAL_ADC_Stop(HADC);