cancel
Showing results for 
Search instead for 
Did you mean: 

I can only change the gain of the SDADC once, not twice or more

DMårt
Senior III

I want to change the SDADC gain while the MCU STM32F373VBTx is running.

That works, but only one time.

First, at the initialization of the SDADC, the STM32 CubeMX set the predefined gain.

Second, I set the gain by reading values from variables. That works.

But when I do that at the third time, nothing happens. Hmm...Why?

Is it something I need to wait for, until I can se the gain?

0693W00000DpsZ4QAJ.png 

One question more. Does the calibration function HAL_SDADC_CalibrationStart find the perfect offset, so I don't need to change it manually?

void STM32_PLC_Analog_Input_Set_Gain_Offset(uint8_t sdadc, uint8_t configuration_index, uint8_t gain, uint16_t SDADC_offset) {
	/* Initial selection */
	SDADC_HandleTypeDef *hsdadc;
	int16_t *DMA_address;
	uint8_t DMA_length;
	uint8_t SDADC_gain;
	switch(sdadc){
	case 1:
		hsdadc = handler_sdadc1;
		DMA_length = 9;
		DMA_address = SDADC1_Single;
		break;
	case 2:
		hsdadc = handler_sdadc2;
		DMA_length = 3;
		DMA_address = SDADC2_Single;
		break;
	case 3:
		hsdadc = handler_sdadc3;
		DMA_length = 5;
		DMA_address = SDADC3_Differential;
		break;
	default:
		hsdadc = handler_sdadc1;
		DMA_length = 9;
		DMA_address = SDADC1_Single;
		break;
	}
 
	/* Set gain and offset */
	switch(gain){
	case 0:
		SDADC_gain = 0b111;
		break;
	case 1:
		SDADC_gain = 0b0;
		break;
	case 2:
		SDADC_gain = 0b1;
		break;
	case 3:
		SDADC_gain = 0b10;
		break;
	case 4:
		SDADC_gain = 0b11;
		break;
	case 5:
		SDADC_gain = 0b100;
		break;
	case 6:
		SDADC_gain = 0b101;
		break;
	default:
		SDADC_gain = 0b0;
		break;
	}
 
	/* Stop SDADC with DMA */
	if(HAL_SDADC_InjectedStop_DMA(hsdadc) != HAL_OK)
		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]: */
			hsdadc->Instance->CONF0R |= SDADC_offset;     /* Bits 11:0 OFFSET0[11:0]: */
			break;
		case SDADC_CONF_INDEX_1:
			hsdadc->Instance->CONF1R |= SDADC_gain << 20;
		    hsdadc->Instance->CONF1R |= SDADC_offset;
			break;
		case SDADC_CONF_INDEX_2:
			hsdadc->Instance->CONF2R |= SDADC_gain << 20;
			hsdadc->Instance->CONF2R |= SDADC_offset;
			break;
		}
	}
 
	/* 3: Leave init-mode for the control register */
	hsdadc->Instance->CR1 &= ~(SDADC_CR1_INIT);
 
 
	/* Start ADC again */
	if (HAL_SDADC_CalibrationStart(hsdadc, SDADC_CALIBRATION_SEQ_3) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_PollForCalibEvent(hsdadc, HAL_MAX_DELAY) != HAL_OK)
		Error_Handler();
	if(HAL_SDADC_InjectedStart_DMA(hsdadc, (uint32_t*)DMA_address, DMA_length) != HAL_OK)
		Error_Handler();
}

1 ACCEPTED SOLUTION

Accepted Solutions

> hsdadc->Instance->CONF0R |= SDADC_gain << 20;

Where are the GAIN bits zeroed?

JW

View solution in original post

2 REPLIES 2

> hsdadc->Instance->CONF0R |= SDADC_gain << 20;

Where are the GAIN bits zeroed?

JW

No!

I will try that!

Thank you.

Edit:

Now it's working. I have ever worked with register programming for STM32 before. This is something new for me. Quite fun.

hsdadc->Instance->CONF0R &=  ~(0b111 << 20); /* Clear */
hsdadc->Instance->CONF0R |= SDADC_gain << 20; /* Bits 22:20 GAIN0[2:0]: */