0
\$\begingroup\$

I am using a NUCLEO-L432KC board DATASHEET I am trying to configure the ADC conversion with a 10k potentiometer However the ADC seems to give a wrong results

I set the pot to output 5v (asserted with a multimeter) and used the result to control PWM duty cylcle on an LED However the glowing of the led seemed constant (no changes in the duty cycle by varying the pot)

The gdb output of the ADC_DR register shows the result of the ADC conversion changes to a wrong value immediately after reading it and stays that way

(gdb) x/d &ADC_DR 
0x50040040:     4095
(gdb) x/d &ADC_DR 
0x50040040:     1703
(gdb) 

The 4095 is the intended result for me as the multimeter shows 5v however the result goes back to arbitarly value under 2k without no instructions executed in between tried to raise the Sampling time to 24.5 clock cycles with no luck

The ADC_init function is as shown:

main:
    bl      clockInit80
    bl      TIM2_PWM_Init
    bl      ADC_Init
1:
    ldr     r1, =ADC_CR
    ldr     r0, [r1]
    orr     r0, #(1 << 2)       @ADCSTART = 1
    str     r0, [r1]
    @wait for the conversion to complete
    mov     r0, #30
    delay:
        subs    r0, #1
        bne     delay
    
    @read ADC_DR
    ldr     r1, =ADC_DR
    ldr     r0, [r1]
    ldr     r2, =5000
    mul     r0, r2
    ldr     r2, =4096
    sdiv    r0, r2

    @store the result in TIM2_CCR1
    ldr     r1, =TIM2_CCR1
    str     r0, [r1]

    ldr     r1, =TIM2_EGR
    ldr     r0, [r1]
    orr     r0, #(1 << 0)
    str     r0, [r1]
    


    b       1b


ADC_Init:
    @Select clock source for the ADC (Mandatory) else no clock 
    ldr     r1, =RCC_CCIPR
    ldr     r0, [r1]
    orr     r0, #(3 << 28)  @ADCSEL Bits [29:28]
    str     r0, [r1]

    @Enable clock for ADC
    ldr     r1, =RCC_AHB2ENR
    ldr     r0, [r1]
    orr     r0, #(1 << 13)  @ADCEN Bit 13
    str     r0, [r1]

    @Disable deep down power mode Bit 29
    ldr     r1, =ADC_CR
    ldr     r0, [r1]
    mvn     r2, #(1 << 29)
    and     r0, r2
    str     r0, [r1]

    @Enable the ADC voltage regulator ADVREGEN
    ldr     r1, =ADC_CR
    ldr     r0, [r1]
    orr     r0, #(1 << 28)
    str     r0, [r1]
    @ADC voltage regulator average wake up time is 20us wait for 50us
    @waitStart
    ldr     r0, =4000
    1:
        subs    r0, #1
        bne     1b
    @waitEnd
    
    @set the number of ADC conversion to be single conversion
    ldr     r1, =ADC_SQR1
    ldr     r0, [r1]
    orr     r0, #(1 << 0)   @L (sequence legnth) Bits [3:0]
    str     r0, [r1]

    @set the first (and only channel to be channel 5 (ADC_IN5 = PA0)
    ldr     r1, =ADC_SQR1
    ldr     r0, [r1]
    orr     r0, #(5 << 6)   @SQ1[10:6]
    str     r0, [r1]

    @set channel 5 adc sampling time to be 24.5 clock cycles
    ldr     r1, =ADC_SMPR1
    ldr     r0, [r1]
    orr     r0, #(3 << 15)      
    str     r0, [r1]

    @Enable ADC first clear the ADRDY bit 
    ldr     r1, =ADC_ISR
    ldr     r0, [r1]
    orr     r0, #(1 << 0)
    str     r0, [r1]

    @Set the ADEN bit in ADC_CR
    ldr     r1, =ADC_CR
    ldr     r0, [r1]
    orr     r0, #(1 << 0)
    str     r0, [r1]
    
    @wait for ADRDY bit to be set
    1:
        ldr     r1, =ADC_ISR
        ldr     r0, [r1]
        tst     r0, #(1 << 0)
        beq     1b

    @return
    bx      lr
        

EDIT1: The PA0 is connected directly to the 5v output from the 10k pot (PA0 is 5v tolerant as indicated in the datasheet)

AGAIN it actually shows the correct value for the conversion for a sec but it changes immediately to a wrong one so I don't think the problem has anything to do with the connection and it's varying by hunderds of digits as shown above

EDIT2: The 5V is changed to 3.3V as suggested and the ADC is asserted to be working fine using cubeMX and HAL code (No damage from the 5V the ADC_DR in the HAL code is constant with the correct value) The clock is configured to be the system clock at 80Mhz I suspect the problem is in my initialization code but I am already following the reference manual init sequence maybe there's some detail I am missing

Connection Schematic

enter image description here

\$\endgroup\$
7
  • \$\begingroup\$ what is your specific question? \$\endgroup\$
    – jsotola
    Mar 5, 2022 at 3:02
  • \$\begingroup\$ @jsotola The ADC gives the wrong output which is the second one in the gdb it immediately changes to a wrong value and stays that way the question is why and how to fix that \$\endgroup\$ Mar 5, 2022 at 3:44
  • 1
    \$\begingroup\$ @MahmoudSalah - Hi, Please add a schematic of your design (and, to add further clarity, a photo of your hardware would help too). You twice mention 5 V and a pot producing that voltage, but AFAIK that Nucleo-L432KC board does not have a pot onboard, so you seem to be adding some external components - is that correct? Are you connecting the 5 V from the pot directly to the STM32 ADC input? If so, why do you believe that is a valid configuration? If you are not connecting 5 V directly to the ADC, then the question is unclear. Either way, please edit & elaborate with more details. Thanks. \$\endgroup\$
    – SamGibson
    Mar 5, 2022 at 5:33
  • \$\begingroup\$ @SamGibson Yes it's connected directly PA0 is 5v tolerant and the gdb shows the correct output of "4095" for a sec but by the time it's read it's changed to a wrong value and the problem is I don't know what caused the change the OVR flag isn't set no other conversion is going in between even tried to use interrupt and disable any exception till the value is read still no luck \$\endgroup\$ Mar 5, 2022 at 6:38
  • 1
    \$\begingroup\$ @MahmoudSalah - Thanks for the reply. While I have been offline, Justme has written an answer quite similar to what I would have written. Read that answer and I recommend you to repeat your tests with the voltage on PA0 not exceeding \$V_{REF+} = V_{DDA} = V_{DD}\$ i.e. 3.3 V. See what the behaviour is for that test, and update the question with the results. \$\endgroup\$
    – SamGibson
    Mar 5, 2022 at 18:49

3 Answers 3

3
\$\begingroup\$

Don't feed the ADC pin with 5V, it is wrong.

The ADC cannot read voltages beyond the Vref, which is most likely same as Vdd, which is most likely 3.3V.

The GPIO pin as digital input can tolerate 5V, but as and ADC input it is not 5V tolerant, and even if it were, it will still read 4095 when voltage is above 3.3V because that is what the analog circuitry can handle.

Please note that setting the pot to the 5V extreme end migh have already damaged the MCU.

\$\endgroup\$
6
  • \$\begingroup\$ But The correct conversion value is placed in the ADC_DR register for some time it means the conversion channel is working just fine \$\endgroup\$ Mar 5, 2022 at 18:52
  • \$\begingroup\$ tried to use different pin with 3.3V same problem \$\endgroup\$ Mar 5, 2022 at 18:52
  • 1
    \$\begingroup\$ Justme - Hi, All agreed. In case it helps to give a reference, I think this is the datasheet for the OP's MCU and page 114 specifies exactly what you said that \$V_{AIN}\$ should not exceed \$V_{REF+}\$ for the ADC. \$\endgroup\$
    – SamGibson
    Mar 5, 2022 at 18:54
  • 2
    \$\begingroup\$ @MahmoudSalah - I'm not replying on behalf of Justme, but I respectfully disagree with your comment that: "The correct conversion value is placed in the ADC_DR register for some time it means the conversion channel is working just fine". Applying 5 V to the ADC input exceeds the specification (see my link in the comment above). Therefore after that, anything is possible. I deliberately didn't try this on my STM32-based designs exactly because of that reason. If you still get strange results with your own code, I suggest trying with known-good code sample & update the question with results. \$\endgroup\$
    – SamGibson
    Mar 5, 2022 at 19:03
  • 2
    \$\begingroup\$ @MahmoudSalah - Unfortunately I don't have time to get deeply involved here, which is why I said before, please edit the question to add new results / updates. Leaving new (important!) updates in a comment, which most people will not see, does not help you much. Please read the first paragraph here. Thanks. \$\endgroup\$
    – SamGibson
    Mar 5, 2022 at 21:02
1
\$\begingroup\$

After you've fed 5V to that ADC input pin, consider the MCU chip junk and replace it. It seems that the chip "works fine": you don't know that. After exceeding the absolute maximum ratings, the chip may misbehave in interesting ways, and you'll never be able to fully trust it. Just replace it.

Don't feed more than the ADC reference voltage, e.g. 3.3V. It should work fine then, assuming you've made no other mistakes. In many cases some initialization code, such as clock selection for the ADC, may have "interesting" side effects.

The ADC needs a clock signal, since it's a SAR, and that clock cannot be too fast or you'll be getting funky results. You also need to check in the datasheet whether the ADC data register allows multiple reads without starting another conversion, and make sure that you've set it for continuous conversion.

And most importantly: read the errata sheet for your chip. Datasheets document the wishes of the designers in ideal circumstances. Due to human mistakes, the actual chip you're using may not behave exactly as the datasheet would imply. On most complex MCUs I've seen, the A/D converter always has some errata.

\$\endgroup\$
0
\$\begingroup\$

I don't know what to say the problem was that the SQR1 register uses the Sequence 0000 for 1 conversion and I somehow saw and used it as 0001 after modification the Code works fine now and luckily the MCU isn't damaged from the earlier 5V mistake anyway thanks for your help..!! enter image description here

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.