cancel
Showing results for 
Search instead for 
Did you mean: 

Bare Metal implementation for Continuous Conversion Mode

NNada.1
Associate II

Hello All,

  I am trying to implement baremetal implementation for Continous Conversion Mode. I have wrote the below code. I am expecting that the ADC will read A0-B0-A1-B0 in this sequence. However the code is only reading A0 and not any other pins.

I am using STM32F401RE nucleo Board.

I am not able to clear EOC as well!!

typedef struct{
float AN[4];
}ADC_Vals_t;

int main(void)
{
uint16_t data;
float  ADC_volt;
ADC_Vals_t ADCVal;
int i=0;
/*Enable clock to GPIO peripheral*/

RCC->AHB1ENR|= (0x1<<RCC_AHB1ENR_GPIOAEN_Pos);  //Enable GPIOA
RCC->AHB1ENR |= (0x1<<RCC_AHB1ENR_GPIOBEN_Pos);  //Enable GPIOB
/*Set GPIO to Analog Mode*/
GPIOA->MODER |= (0x3<<GPIO_MODER_MODER0_Pos); // GPIO A0
GPIOA->MODER |= (0x3<<GPIO_MODER_MODER1_Pos); //GPIO A1
GPIOA->MODER |= (0x3<<GPIO_MODER_MODER4_Pos); //GPIO A4
GPIOB->MODER |= (0x3<<GPIO_MODER_MODER0_Pos); //GPIO B0

/*Enable clock to ADC peripheral*/
RCC->APB2ENR |=(0x1<<RCC_APB2ENR_ADC1EN_Pos);

/*Configure ADC trigerring and resolution*/
ADC1->CR2=0;

//Enable COntinous Mode
ADC1->CR2 |= (0x1<<ADC_CR2_CONT_Pos);


/*Set conversion sequence and length*/
ADC1->SQR1 |= (0x3<<ADC_SQR1_L_Pos); //Set length of sequence

ADC1->SQR3 |= (0x0 <<  ADC_SQR3_SQ1_Pos);     //Set Sequence number ADC1_IN0
ADC1->SQR3 |= (0x8<<ADC_SQR3_SQ2_Pos);  //ADC1_IN8
ADC1->SQR3 |= (0x1<<ADC_SQR3_SQ3_Pos);    //ADC1_IN1
ADC1->SQR3 |= (0x4<<ADC_SQR3_SQ4_Pos);   //ADC1_IN4


/*SCAN mode*/
ADC1->CR1 |= (1<<ADC_CR1_SCAN_Pos);
/*Enable ADC*/
ADC1->CR2 |=(0x1<<ADC_CR2_ADON_Pos);


for(;;){

/*Start conversion*/
ADC1->CR2 |= (1<<ADC_CR2_SWSTART_Pos);

/*Wait for conversion to end*/
while(!(ADC1->SR & 0x2));
/*REad Data*/
data = ADC1->DR;
/*Multiply with prescaler
* data is 12Bit resolution
*
* */
ADC_volt = ((3.3/4095)*data);
ADCVal.AN[i++] =ADC_volt;
if(i==4){
i=0;
}
}
}
7 REPLIES 7
Uwe Bonnes
Principal III

Read again the ADC chapter of the reference manual. At least, I miss Calibration and ADC_CR_ADVREGEN_0 in your code. Using numbers and not the proprt defines obscures readlitity and enables more typos.

######
Senior

Things to research:

  • Clock prescaler in ADC->CCR register.
  • Sampling cycles in ADC->SMPRx registers.
  • Scan Mode in ADC->CR1 register.

I also agree with comments of the previous post regarding readability. Best to be consistent with hex for most of the register data manipulations in my opinion. i.e. 0x01 << 3U rather than 1 << 3.

NNada.1
Associate II

@Uwe Bonnes @######  Thanks for the feedback. I have udpated the code. In scan mode I am getting values that are not in expected sequence. Any suggestion for that?

Thank you

Are you now correctly reading sequenced vales? What sequence do you want?

Your comment and code don't seem to match in my opinion.

PA0 = ADC_IN0

PA1 = ADC1_IN1

PA4 = ADC1_IN4

PB0 = ADC1_IN8

ADC1->SQR3 |= (0x0 <<  ADC_SQR3_SQ1_Pos);     //Set Sequence number ADC1_IN0
ADC1->SQR3 |= (0x8<<ADC_SQR3_SQ2_Pos);  //ADC1_IN8
ADC1->SQR3 |= (0x1<<ADC_SQR3_SQ3_Pos);    //ADC1_IN1
ADC1->SQR3 |= (0x4<<ADC_SQR3_SQ4_Pos);   //ADC1_IN4

If your configuration of ADCs is correct the sequence should be A0, B0, A1, A4

Your question above requests the following:

"I am expecting that the ADC will read A0-B0-A1-B0 in this sequence."

Decipher the resulting sequence and re-check your actual register settings  and compare to the reference manual.

NNada.1
Associate II

@###### @Uwe Bonnes Thank you for the insights.

 

Screenshot 2024-04-08 225203.png

As you can see the code.

1.I switched to single sample mode.

2.I have enable the SCAN mode bit in the ADC1.

I expect that on each Start of conversion I read the ADC in the set sequence, however it is just sampling the samething. I am not clear,where am I getting it wrong.

Please guide me what can I check?

Thank you

I would check using a debugger that the ADC Peripheral registers are being written to as you expect. Sometimes peripherals need to be enabled before the register contents will accept changes.

Also I would ensure your sampling cycles are correct. This is the period to wait in clock cycles before a valid reading can be taken and is in the Sampling cycles in ADC->SMPRx registers.

Also, try reading AN3116 if you haven't already.

https://www.st.com/resource/en/application_note/an3116-stm32s-adc-modes-and-their-applications-stmicroelectronics.pdf

This gives a good description of the ADC modes and may help your understanding better.