Skip to main content
arnold_w
Senior II
June 21, 2016
Question

How do I read a voltage using the A/D converter in the most basic way?

  • June 21, 2016
  • 2 replies
  • 716 views
Posted on June 21, 2016 at 15:20

 

 

The original post was too long to process during our migration. Please click on the attachment to read the original post.
    This topic has been closed for replies.

    2 replies

    arnold_w
    arnold_wAuthor
    Senior II
    June 21, 2016
    Posted on June 21, 2016 at 15:35

    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?

    arnold_w
    arnold_wAuthor
    Senior II
    June 21, 2016
    Posted on June 21, 2016 at 16:41

    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;
    }