Skip to main content
NNada.1
Associate II
April 7, 2024
Question

Bare Metal implementation for Continuous Conversion Mode

  • April 7, 2024
  • 7 replies
  • 2042 views

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;
}
}
}
This topic has been closed for replies.

7 replies

Uwe Bonnes
Chief
April 8, 2024

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 II
April 8, 2024

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
NNada.1Author
Associate II
April 8, 2024

@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

######
Senior II
April 8, 2024

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."

NNada.1
NNada.1Author
Associate II
April 8, 2024

@###### @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

######
Senior II
April 9, 2024

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.