2
\$\begingroup\$

I want to change the SDADC register while the STM32F373VBTx is running.

  • First time, the MX_SDADC_init() set the SDADC gain.
  • Second time, my software set the SDADC gain by reading some variables.
  • Third time, I set the gain manually. That works.

But the fourth time, the gain does not change. Why? The SDADC_gain is a 7-bit parameter.

To change the gain, I'm setting the register like this

/* 0: Check if SDADC is ready */
if(hsdadc->State != HAL_SDADC_STATE_READY)
    Error_Handler();

/* 1: Enter init-mode for the control register */
hsdadc->Instance->CR1 |= SDADC_CR1_INIT;
uint32_t tickstart = HAL_GetTick();
bool isAtInitMode = true;
/* Wait for INITRDY bit on SDADC_ISR */
while ((hsdadc->Instance->ISR & SDADC_ISR_INITRDY) == (uint32_t) RESET) {
    if ((HAL_GetTick() - tickstart) > 200) {
        isAtInitMode = false;
    }
}

/* 2: If init mode, then set gain and offset registers */
if(isAtInitMode){
    switch(configuration_index){
    case SDADC_CONF_INDEX_0:
        hsdadc->Instance->CONF0R |= SDADC_gain << 20; /* Bits 22:20 GAIN0[2:0]: */
        break;
    case SDADC_CONF_INDEX_1:
        hsdadc->Instance->CONF1R |= SDADC_gain << 20;
        break;
    case SDADC_CONF_INDEX_2:
        hsdadc->Instance->CONF2R |= SDADC_gain << 20;
        break;
    }
}

/* 3: Leave init-mode for the control register */
hsdadc->Instance->CR1 &= ~(SDADC_CR1_INIT);

So why does e.g hsdadc->Instance->CONF0R not change? It remains constant.

enter image description here

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Is it this: You only OR the bits, so you never clear the bits, e.g. going from gain 3 to 2,1, or 0 won't work? \$\endgroup\$
    – Justme
    Aug 20, 2021 at 12:13
  • \$\begingroup\$ @Justme You solved the issue! Thank you. Write an answer please. \$\endgroup\$
    – DanM
    Aug 20, 2021 at 13:02

2 Answers 2

3
\$\begingroup\$

The code only uses the OR operator to set bits high.

If the mode change needs to set any of the bits low, the code does not do that, it needs to be done separately.

\$\endgroup\$
1
  • \$\begingroup\$ That's what Lundin below did not say - separately? \$\endgroup\$
    – DanM
    Aug 20, 2021 at 14:26
3
\$\begingroup\$

The correct way to initialize any hardware register is to write to it once, setting all required fields. Example:

CONF0R = SOMETHING | SOMETHING_ELSE | (SDADC_gain << 20);

In case either of the items you use for initialization contains arithmetic or similar complex expressions, then build everything up in a temporary RAM variable:

uint32_t conf0r = get_something() | (SDADC_gain << 20);
CONF0R = conf0r;

Don't do this:

// BAD
CONF0R |= SOMETHING;
CONF0R |= SOMETHING_ELSE;
CONF0R |= SDADC_gain << 20;
\$\endgroup\$
1
  • \$\begingroup\$ Yes, but now I need to clear the bits. \$\endgroup\$
    – DanM
    Aug 20, 2021 at 14:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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