Skip to main content
Visitor II
April 7, 2024
Question

Bare Metal implementation for Continuous Conversion Mode

  • April 7, 2024
  • 4 replies
  • 1957 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.

    4 replies

    Graduate II
    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.

    Graduate 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.1Author
    Visitor 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

    Graduate 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.1Author
    Visitor 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

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