cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F373 SDADC - wrong values

Evan Slatyer
Associate
Posted on October 19, 2017 at 04:22

Hello everyone,

Could I please get a little bit of help with getting the STM32F373 SDADCs working?

The chip is an STM32F373CBT6, with VREFSD+ and VDDSD both connected to VCC (3.3V). I've followed the ST guidelines on decoupling capacitors, all the caps are on the opposite side of the board (it's only 0.8mm thick) just about as close as I can possibly get them to the pins. Schematic of that section of the board:

0690X0000060418QAA.jpg

Current code:

void setupTemperatureCurrentInput() {

    // Turn on the clock to ports B & E

    RCC->AHBENR |= RCC_AHBENR_GPIOEEN;

    RCC->APB2ENR |= RCC_APB2ENR_SDADC2EN;

    RCC->APB1ENR |= RCC_APB1ENR_PWREN;

    PWR->CR |= PWR_CR_ENSD2;

    GPIOE->MODER &= ~GPIO_MODER_MODER9;

    GPIOE->MODER |= (3 << GPIO_MODER_MODER9_Pos); // Analogue mode

    SDADC2->CR2 = SDADC_CR2_ADON;

    // Wait for the ADC to stabilize.

    while (SDADC2->ISR & SDADC_ISR_STABIP);

    // Enable initialization mode

    SDADC2->CR1 |= SDADC_CR1_INIT;

    while ((SDADC2->ISR & SDADC_ISR_INITRDY) == 0);

    SDADC2->CR1 |= SDADC_CR1_REOCIE;

    SDADC2->CR2 |= (7 << SDADC_CR2_RCH_Pos); // Only convert channel 7

    SDADC2->CONF0R = (1 << SDADC_CONF0R_COMMON0_Pos) | (3 << SDADC_CONF0R_SE0_Pos) | (0 << SDADC_CONF0R_GAIN0_Pos);

    SDADC2->CONFCHR1 = (0 << SDADC_CONFCHR1_CONFCH7_Pos);

    // Drop out of initialization mode

    SDADC2->CR1 &= ~SDADC_CR1_INIT;

    // Calibrate

    SDADC2->CR2 |= SDADC_CR2_STARTCALIB;

    while (SDADC2->ISR & SDADC_ISR_CALIBIP);

    NVIC_EnableIRQ(SDADC2_IRQn);

    NVIC_SetPriority(SDADC2_IRQn,15); // Lowest priority

}

void startReadTemperatureCurrent() {

    SDADC2->CR2 |= SDADC_CR2_RSWSTART;

}

void SDADC2_IRQHandler() {

    uint32_t rdata = SDADC2->RDATAR;

    int16_t data = rdata & 0x0000FFFF;

    currentOutput = data;

    currentUpdated = true;

}

I'm not using HAL because I'd prefer to have low-level access to the hardware; this way I know that all the registers are set up properly. Clock in this case is 72MHz CPU, divided by 6 to get 12MHz, and then the SDADCs have (according to Figure 12 on page 102 of RM0313) a further division by 2 to drop it down to the SDADC preferred 6MHz operating clock.

At the moment I'm trying to get SDADC2, Input 7 (port E9, ''CURRENT'') to work. This is connected to an Allegro ACS711

current monitor, which should output about 1.65V + 110mV/A (since the only things using power are four SMD LEDs and the STM32, total power draw is next to nothing). The ADC is set up for single-ended zero-referenced mode, gain bits 000 (ie gain 1X), so I'd be expecting a value somewhere around 32800 - 32900. What I actually get (both output on the UART and seen in the debugger) is 0x4FA (1274 decimal, about 64mV).

What I've tried:

- Put a multimeter on the microcontroller pin, which reads 1.655V.

- Put an oscilloscope on the microcontroller pin, which reads 1.655V and does not show either noise or deviation during ADC samples.

- Putting the ADC into single-ended offset mode. I would have expected this to give a value around 0 (since the reference voltage is meant to be 1.65V for a 3.3V supply, and the actual voltage I'm putting in is almost 1.65V). The actual result is a value of 0x7FFF (32767), the maximum positive value.

- Changing the gain to 0.5X (gain bits 111). This gives a conversion result of 49762, indicating a voltage of (49762/65536*3.3/0.5) = 5.0V. Since the ACS711 driving this only has a 3.3V supply, this seems particularly unlikely.

- Running in injected conversion mode instead. Same result.

- Using SDADC1 (which can use the same pin) instead. Same result.

- Using the other input (TEMP_OUT). This gives a reading indicating 2.8V when in fact the voltage on the pin is 1.3V, rising to 1.5V during a sample (checked with the oscilloscope). However, since I can easily change the temperature, I can at least verify that the ADC reading changes (it does).

- Skipping calibration. This doesn't seem to have a significant effect.

- Halving the clock down to 3MHz. No effect.

At this point I suspect that either I've made some silly mistake in the code, or I've damaged the chip. Obviously the former is very much preferable - but I've been over the datasheet and reference manual a few times and I can't find any issues. Is anyone else here (a) seeing a mistake in my code, or (b) aware of a problem with the SDADC that might cause this?

Thanks,

Evan

#stm32f373 #sdadc
1 REPLY 1
Evan Slatyer
Associate
Posted on October 19, 2017 at 08:03

Good news! Just as the moderators approved this post I figured out what was going on.

The problem was a misunderstanding of ST's 'zero-volt reference' and 'offset' modes (the 'zero-volt reference' mode applies a Vcc/2 offset, and the 'offset' mode applies no offset). I'm now getting 1.345V (temperature) and 1.712V (current) - which is about as close as I can reasonably expect to get.

So, the chip is fine, the SDADCs are working correctly, it was just a failure to read the datasheet properly.