2016-06-21 06:20 AM
2016-06-21 06:35 AM
I just found out that the ''working code'' is not working so great. I seem to always read channel 9 (pin PB1) properly, but channel 2 (pin PA2) sometimes return values around 26-28 and sometime it returns values around 2888-2890, but the correct value is around 550. Does anybody know what's wrong?
2016-06-21 07:41 AM
I have reduced the code a bit, but it still behaves the same.
static
Bool_t HAL_ADC_ConfigChannel_(uint32_t channel)
{
if
(ADC_CHANNEL_9 < channel)
{
DEBUG_CODE( UART2_SW_TransmitNullTerminatedString((uint8_t*)
''
Only channels 1-9 are implemented!''
); )
return
FALSE;
}
ADC1->SMPR2 &= ~ADC_SMPR2(ADC_SMPR2_SMP0, channel);
// Clear the old sample time
ADC1->SMPR2 |= ADC_SMPR2(ADC_SAMPLETIME_3CYCLES, channel);
// Set the new sample time
// Rank 1 to 6
ADC1->SQR3 &= ~ADC_SQR3_RK(ADC_SQR3_SQ1, 1);
// Clear the old SQx bits for the selected rank
ADC1->SQR3 |= ADC_SQR3_RK(channel, 1);
// Set the SQx bits for the selected rank
return
TRUE;
}
static
void
HAL_ADC_Start_(
void
)
{
// Enable the ADC peripheral
// Check if ADC peripheral is disabled in order to enable it and wait during
// Tstab time the ADC's stabilization
if
((ADC1->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON)
{
ADC1->CR2 |= ADC_CR2_ADON;
// Enable the Peripheral
delayMicroseconds(ADC_STAB_DELAY_US);
}
if
(HAL_IS_BIT_SET(ADC1->CR2, ADC_CR2_ADON))
{
// Start conversion if ADC is effectively enabled
// Clear regular group conversion flag and overrun flag
ADC1->SR = ~ADC_FLAG_EOC;
// Clear end of conversion flag
// If instance of handle correspond to ADC1 and no external
// trigger present enable software conversion of regular channels
if
(((ADC1->CR2 & ADC_CR2_EXTEN) == RESET))
{
// Enable the selected ADC software conversion for regular group
ADC1->CR2 |= (uint32_t)ADC_CR2_SWSTART;
}
}
}
static
Bool_t HAL_ADC_PollForConversion_(uint32_t Timeout)
{
uint32_t numOneMillisecondIterations = Timeout;
while
((0 < numOneMillisecondIterations--) && ((ADC1->SR & ADC_FLAG_EOC) == 0))
{
delayMicroseconds(1000);
}
if
(numOneMillisecondIterations == 0)
{
DEBUG_CODE( UART2_SW_TransmitNullTerminatedString((uint8_t*)
''
Timeout when waiting for conversion completion!''
); )
return
FALSE;
}
ADC1->SR = ~(ADC_FLAG_STRT | ADC_FLAG_EOC);
// Clear end of conversion flag and channel start flag
return
TRUE;
}
uint16_t readADC(uint32_t channel)
{
__HAL_RCC_ADC1_CLK_ENABLE();
ADC->CCR &= ~(ADC_CCR_ADCPRE);
// Set ADC parameters
ADC->CCR |= ADC_CLOCKPRESCALER_PCLK_DIV2;
// Set the ADC clock prescaler
ADC1->CR1 &= ~(ADC_CR1_SCAN);
// Set ADC scan mode
ADC1->CR1 |= ADC_CR1_SCANCONV(DISABLE);
// Set ADC scan mode
ADC1->CR1 &= ~(ADC_CR1_RES);
// Set ADC resolution
ADC1->CR1 |= ADC_RESOLUTION_12B;
// Set ADC resolution
ADC1->CR2 &= ~(ADC_CR2_ALIGN);
// Set ADC data alignment
ADC1->CR2 |= ADC_DATAALIGN_RIGHT;
// Set ADC data alignment
ADC1->CR2 &= ~(ADC_CR2_EXTSEL);
// Reset the external trigger
ADC1->CR2 &= ~(ADC_CR2_EXTEN);
// Reset the external trigger
ADC1->CR2 &= ~(ADC_CR2_CONT);
// Disable ADC continuous conversion mode
ADC1->CR2 |= ADC_CR2_CONTINUOUS(DISABLE);
// Disable ADC continuous conversion mode
ADC1->CR1 &= ~(ADC_CR1_DISCEN);
// Disable the selected ADC regular discontinuous mode
ADC1->SQR1 &= ~(ADC_SQR1_L);
// Set ADC number of conversion
ADC1->SQR1 |= ADC_SQR1(1);
// Set ADC number of conversion
ADC1->CR2 &= ~(ADC_CR2_DDS);
// Disable ADC DMA continuous request
ADC1->CR2 |= ADC_CR2_DMAContReq(DISABLE);
// Disable ADC DMA continuous request
ADC1->CR2 &= ~(ADC_CR2_EOCS);
// Disable ADC end of conversion selection
ADC1->CR2 |= ADC_CR2_EOCSelection(DISABLE);
// Disable ADC end of conversion selection
if
(!HAL_ADC_ConfigChannel_(channel))
{
return
0xFFFF;
}
HAL_ADC_Start_();
if
(!HAL_ADC_PollForConversion_(10))
{
return
0xFFFF;
}
return
ADC1->DR;
}