cancel
Showing results for 
Search instead for 
Did you mean: 

The values read by my ADC have not sense considering my RES setup (STM32H747).

HTess.1
Associate III

I am using the VREFBUF as a reference for my ADC reading and I set it up to the max (2.5 V) and used the capacitor circuit described in AN5690 p.2 Fig. 2. The code used for my ADC and VREFBUF are described here :

void VREFBUF_Init(void) {
  SET_BIT(RCC_C2->APB4ENR, RCC_APB4ENR_VREFEN_Msk);
  delay(1000);
  SET_BIT(VREFBUF->CSR, VREFBUF_CSR_ENVR_Msk);
  CLEAR_BIT(VREFBUF->CSR, VREFBUF_CSR_HIZ_Msk);
  while (VREFBUF_CSR_VRR & VREFBUF_CSR_VRR_Msk != 1) {}
}
void ADC_Init(void) {
  /*******************Horloges**************************/
  SET_BIT(RCC_C2->APB4ENR, RCC_APB4ENR_SYSCFGEN_Msk); //SYSCFG clock
  delay(1000);
  SET_BIT(RCC_C2->APB4ENR, RCC_APB4ENR_RTCAPBEN_Msk); //RTCAPB clock
  delay(1000);
  SET_BIT(RCC_C2->AHB1ENR, RCC_AHB1ENR_ADC12EN_Msk); //ADC12 clocks
  delay(1000);
  //SET_BIT(RCC_C2->AHB4ENR, RCC_AHB4ENR_GPIOAEN_Msk); //GPIOA clock
  //delay(1000);
  SET_BIT(RCC_C2->AHB4ENR, RCC_AHB4ENR_GPIOCEN_Msk); //GPIOA clock
  delay(1000);
  /********************Port config************************/
//  SET_BIT(GPIOA->MODER, GPIO_MODER_MODE1_0);
//  SET_BIT(GPIOA->MODER, GPIO_MODER_MODE1_1);
//  CLEAR_BIT(GPIOA->PUPDR, GPIO_PUPDR_PUPD1_0);
//  CLEAR_BIT(GPIOA->PUPDR, GPIO_PUPDR_PUPD1_1);
  
  SET_BIT(GPIOC->MODER, GPIO_MODER_MODE4_0);
  SET_BIT(GPIOC->MODER, GPIO_MODER_MODE4_1);
  CLEAR_BIT(GPIOC->PUPDR, GPIO_PUPDR_PUPD4_0);
  CLEAR_BIT(GPIOC->PUPDR, GPIO_PUPDR_PUPD4_1);
  
  //SET_BIT(SYSCFG->PMCR, SYSCFG_PMCR_PA0SO_Msk);
  delay(1000);//PA0_C in analog mode
  /********************ADC voltage regulator***************/
  CLEAR_BIT(ADC2->CR, ADC_CR_DEEPPWD_Msk); //END DEEPPWD
  SET_BIT(ADC2->CR, ADC_CR_ADVREGEN_Msk); //ENABLE ADC VOLTAGE REG
  delay(1000);//WAIT VOLTAGE REG
  /********************ADC calibration*********************/
  CLEAR_BIT(ADC2->CR, ADC_CR_ADCALDIF_Msk);
  SET_BIT(ADC2->CR, ADC_CR_ADCALLIN_Msk);
  SET_BIT(ADC2->CR, ADC_CR_ADCAL_Msk);
  while (ADC_CR_ADCAL & ADC_CR_ADCAL_Msk != 0) {}
  /******************ADC clock*****************************/
  SET_BIT(ADC12_COMMON->CCR, ADC_CCR_CKMODE_0 | ADC_CCR_CKMODE_1);
  /*******************ADC Prescaler************************/
  SET_BIT(ADC12_COMMON->CCR, ADC_CCR_PRESC_0 | ADC_CCR_PRESC_1 );
  /*******************Input Mode***************************/
  CLEAR_BIT(ADC2->DIFSEL, ADC_DIFSEL_DIFSEL_0); //Single Ended
  /*******************ADC Enable***************************/
  SET_BIT(ADC2->ISR, ADC_ISR_ADRDY_Msk);
  SET_BIT(ADC2->CR, ADC_CR_ADEN_Msk);
  while (ADC_ISR_ADRDY & ADC_ISR_ADRDY_Msk != 1) {}
  SET_BIT(ADC2->ISR, ADC_ISR_ADRDY_Msk);
  /********************ADC RES*****************************/
  SET_BIT(ADC2->CFGR, ADC_CFGR_RES_2 | ADC_CFGR_RES_1);
  CLEAR_BIT(ADC2->CFGR, ADC_CFGR_RES_0);
  /********************ADC Data Management*****************/
  SET_BIT(ADC2->CFGR, ADC_CFGR_DMNGT_0 | ADC_CFGR_DMNGT_1);//DMA Circular mode
  /********************OVRMODE*****************************/
  SET_BIT(ADC2->CFGR, ADC_CFGR_OVRMOD_Msk); //Erase old data
  /********************CONT/Single/Discont*****************/
  SET_BIT(ADC2->CFGR, ADC_CFGR_DISCEN_Msk); // discontinuous mode
  CLEAR_BIT(ADC2->CFGR, ADC_CFGR_CONT_Msk); // | ADC_CFGR_DISCEN_Msk
  /********************Trigger Detection*******************/
  SET_BIT(ADC2->CFGR, ADC_CFGR_EXTEN_0 | ADC_CFGR_EXTSEL_1 | ADC_CFGR_EXTSEL_3);//Trig rising edge TRGO2
  CLEAR_BIT(ADC2->CFGR, ADC_CFGR_EXTEN_1 | ADC_CFGR_EXTSEL_0 | ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_4);
  /********************INput Preselection******************/
  SET_BIT(ADC2->PCSEL, ADC_PCSEL_PCSEL_0);//Chan 0
  /********************Sample Time reg*********************/
  SET_BIT(ADC2->SMPR1, ADC_SMPR1_SMP0_0); //2.5 CLCK Cycles
  /********************ADC IT******************************/
  SET_BIT(ADC2->IER, ADC_IER_EOCIE_Msk | ADC_IER_EOSMPIE_Msk  );//| ADC_IER_EOSIE_Msk | ADC_IER_OVRIE_Msk
  NVIC_EnableIRQ(ADC_IRQn);
  NVIC_SetVector(ADC_IRQn, (uint32_t)&ADC_IRQHandler);
}

The ADC Data is managed by the DMA which is setup this way :

void DMA_Config(void) {
  /************DMA CLock Enable******************/
  SET_BIT(RCC_C2->AHB1ENR, RCC_AHB1ENR_DMA1EN_Msk);
  delay(1000);
  /***************P2M****************************/
  CLEAR_BIT(DMA1_Stream1->CR, DMA_SxCR_DIR_0 | DMA_SxCR_DIR_1);
  /******************Disable FIFO*************************/
  //LL_DMA_DisableFifoMode(DMA1, LL_DMA_STREAM_1);
  //LL_DMA_SetMemoryBurstxfer(DMA1, LL_DMA_STREAM_1, LL_DMA_MBURST_SINGLE);
  /******************Memory size**************************/
  SET_BIT(DMA1_Stream1->CR, DMA_SxCR_MSIZE_0);
  CLEAR_BIT(DMA1_Stream1->CR, DMA_SxCR_MSIZE_1);
  /******************MEM Increment**********************/
  SET_BIT(DMA1_Stream1->CR, DMA_SxCR_MINC_Msk);
  /******************MEM Address to buffer**************/
  DMA1_Stream1->M0AR = (uint32_t)&buff->M7toM4_1; //0x30000000;
  DMA1_Stream1->M1AR = (uint32_t)&buff->M7toM4_2; //0x30000000;
  /*******************Number of data transfer***********/
  SET_BIT(DMA1_Stream1->NDTR, DMA_SxNDT_3 | DMA_SxNDT_1);
  /***********************DMA Mode**********************/
  SET_BIT(DMA1_Stream1->CR, DMA_SxCR_CIRC_Msk);//circular
  SET_BIT(DMA1_Stream1->CR, DMA_SxCR_DBM_Msk);//Double Buffer Mode
  /*******************Flow controller*******************/
  //SET_BIT(DMA1_Stream1->CR, DMA_SxCR_PFCTRL_Msk);//ADC in control
  /******************Periph size************************/
  SET_BIT(DMA1_Stream1->CR, DMA_SxCR_PSIZE_0);
  CLEAR_BIT(DMA1_Stream1->CR, DMA_SxCR_PSIZE_1);
  /******************Peripheral no Increment*************/
  CLEAR_BIT(DMA1_Stream1->CR, DMA_SxCR_PINCOS_Msk);
  /******************Periph request**********************/
  SET_BIT(DMAMUX1_Channel1->CCR, DMAMUX_CxCR_DMAREQ_ID_1 | DMAMUX_CxCR_DMAREQ_ID_3);//adc2_dma
  //  SET_BIT(DMAMUX1_Channel1->CCR, DMAMUX_CxCR_SYNC_ID_0 | DMAMUX_CxCR_SYNC_ID_1 | DMAMUX_CxCR_SYNC_ID_2);//TIM12_TRGO
  //  SET_BIT(DMAMUX1_Channel1->CCR, DMAMUX_CxCR_SPOL_0);//rising edge
  //  DMAMUX1_Channel1->CCR = 0; //Number of requests after synchro (add 1 to the reg value)
  //  SET_BIT(DMAMUX1_Channel1->CCR, DMAMUX_CxCR_EGE_Msk);//Event Generation end of synchro req
  //  SET_BIT(DMAMUX1_Channel1->CCR, DMAMUX_CxCR_SE_Msk);//Synchro Enable
  /******************Periph address***********************/
  DMA1_Stream1->PAR = (uint32_t)&ADC2->DR;
  /******************TC IT********************************/
  SET_BIT(DMA1_Stream1->CR, DMA_SxCR_TCIE_Msk | DMA_SxCR_TEIE_Msk); //TC IT
  DMA1->LIFCR = DMA_LIFCR_CTCIF1;//Clear IT in LISR Register
  NVIC_SetVector(DMA1_Stream1_IRQn, (uint32_t)&DMA1_Stream1_IRQHandler);
  NVIC_EnableIRQ(DMA1_Stream1_IRQn);
  /*******************Enable DMA****************************/
  SET_BIT(DMA1_Stream1->CR, DMA_SxCR_EN_Msk);
}

Now when I read the value collected by my ADC under a 12bit res setup I do expect for a signal with a 1V offset and a 500mV amplitude to read values above 4095/2 yet I read values between 400 and 500, it seems like the signal is read correctly but not it s scale (I joined a picture of my GUI made with Labview illustrating my results, the signal is a bit deformed but it is linked to speed limitation for data exchange via serial, I can not represent every sample)?? I don't get the reason as to why it does not consider the scale properly ... even if I were to have the wrong voltage Ref value the ADC readings should still be much higher considering the fact that the max voltag ref should be around 3.3V (based on my component's inputs) .

3 REPLIES 3
Javier1
Principal

Check the resolution of the ADC you set.

if Vref=2,5v

if ADC- 12bit

1,5V=(4095*1,5/2,5)=2457

1V=(4095*1/2,5)=1638

0,5V=(4095*0,5/2,5)=819

(If i were you i would use a much slower square signal to test your ADC)

we dont need to firmware by ourselves, lets talk

I checked and I indeed did setup a 12 bit res for my ADC, the only point where I doubt is that I chose the 12 bit res but there is also a possibility to go with the 12 bit "legacy" mode, what is that?

Also I will try with a slower square signal as soon as I get my hands on an oscilloscope (but I doubt it will change anything to my readings in term of ADC values).

Could it be linked to data management I saw many exemples where they were right shifting data but I completely ignored that part since I did not see the point( I did not add an offset afterall).

HTess.1
Associate III

Hmm i tried going for a 16 bit res (RES=000) for my ADC but somehow while the values get within a 16 bit range the 0 V signal is referenced around 3000 also the maximum value of 2.5 v from the reference is referenced around 10000 what is leagues under what I should get for a 16 bit RES... maybe I should work on recalibrating the whole thing. Since I calibrated the ADC before initializing it maybe I should work on the VREFBUF trimming circuit (though the STM exemples don't imply such a big difference with theoretical values.