簡體   English   中英

stm32多個ADC變紅錯誤

[英]stm32 multiple ADC redings error

我正在使用cubemx來啟動項目,我正在使用的mcu是stm32L053C6。 為此,我有2個傳感器和2個晶體管連接到ADC輸入。 下面的代碼顯示了如何從第一個溫度傳感器獲取輸入值,電壓。 然后,我對要讀取的每個值使用相同的代碼。 這里的問題是我讀取的第一個值始終是錯誤的,它給我2048,並且它是12位分辨率,所以...

我不知道該如何解決?

//Start ADC reading
if(HAL_ADC_Start(&hadc) != HAL_OK){
  while(1) {}
}

//Wait for EOC (end of conversion)
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
//Read ADC value

//Repeat for all channels.  
while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
experiments[0+index].temperature += hadc.Instance->DR;
printf("\n ex0 i rolling %d\n", experiments[0+index].temperature);  

讀取2個溫度傳感器和晶體管的電壓值的代碼如下。 我讀取了16次值並計算出平均值。 但是正如我所說的,我讀取的第一個值是2048。

void readRollingADC(int index){
  HAL_Delay(1);

  //Start ADC reading
  if(HAL_ADC_Start(&hadc) != HAL_OK){
    while(1) {}
  }

  //Wait for EOC (end of conversion)
  while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
  //Read ADC value

  *

> ****//Repeat for all channels.       while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}   experiments[0+index].temperature +=
> hadc.Instance->DR; printf("\n ex0 i rolling %d\n",
> experiments[0+index].temperature);****

* 

  while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
  experiments[0+index].ube += hadc.Instance->DR;

  while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
  experiments[0+index].vrb += hadc.Instance->DR;

  while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
  experiments[0+index].vrc += hadc.Instance->DR;

  while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
  experiments[1+index].temperature += hadc.Instance->DR;
printf("\n ex1 i rolling %d\n", experiments[1+index].temperature); 
  while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
  experiments[1+index].ube += hadc.Instance->DR;

  while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
  experiments[1+index].vrb += hadc.Instance->DR;

  while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
  experiments[1+index].vrc += hadc.Instance->DR;

}

我該如何解決? 它與代碼或ADC的啟動有關嗎? 我可以做的是讀取第一個值,而不是保存它,但是我認為這不是正確的方法:)

void MX_ADC_Init(void)
    {


        /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
        */
      hadc.Instance = ADC1;
      hadc.Init.OversamplingMode = DISABLE;
      hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
      hadc.Init.Resolution = ADC_RESOLUTION_12B;
      hadc.Init.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
      hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
      hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
      hadc.Init.ContinuousConvMode = DISABLE;
      hadc.Init.DiscontinuousConvMode = DISABLE;
      hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
      hadc.Init.DMAContinuousRequests = DISABLE;
      hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
      hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
      hadc.Init.LowPowerAutoWait = ENABLE;
      hadc.Init.LowPowerFrequencyMode = ENABLE;
      hadc.Init.LowPowerAutoPowerOff = ENABLE;
      HAL_ADC_Init(&hadc);

        sConfigAdc.Channel = ADC_CHANNEL_0;
        if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
            while(1){}
        }
            sConfigAdc.Channel = ADC_CHANNEL_1;
        if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
            while(1){}
        }

            sConfigAdc.Channel = ADC_CHANNEL_2;
        if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
            while(1){}
        }

            sConfigAdc.Channel = ADC_CHANNEL_3;
        if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
            while(1){}
        }

            sConfigAdc.Channel = ADC_CHANNEL_5;
        if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
            while(1){}
        }
            sConfigAdc.Channel = ADC_CHANNEL_6;
        if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
            while(1){}
        }
            sConfigAdc.Channel = ADC_CHANNEL_7;
        if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
            while(1){}
        }

            sConfigAdc.Channel = ADC_CHANNEL_8;
        if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
            while(1){}
        }
             /*
        sConfigAdc.Channel = ADC_CHANNEL_9;
        if(HAL_ADC_ConfigChannel(&hadc, &sConfigAdc) != HAL_OK){
            while(1){}
        }  */


    }

    void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
    {

      GPIO_InitTypeDef GPIO_InitStruct;
      if(hadc->Instance==ADC1)
      {
      /* USER CODE BEGIN ADC1_MspInit 0 */

      /* USER CODE END ADC1_MspInit 0 */
        /* Peripheral clock enable */
        __HAL_RCC_ADC1_CLK_ENABLE();

        /**ADC GPIO Configuration    
        PA0     ------> ADC_IN0
        PA1     ------> ADC_IN1
        PA2     ------> ADC_IN2
        PA3     ------> ADC_IN3
        PA5     ------> ADC_IN5
        PA6     ------> ADC_IN6
        PA7     ------> ADC_IN7
        PB0     ------> ADC_IN8
        PB1     ------> ADC_IN9 
        */
        GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 
                              |GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

      /* USER CODE BEGIN ADC1_MspInit 1 */

      /* USER CODE END ADC1_MspInit 1 */
      }
    }

    void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
    {

      if(hadc->Instance==ADC1)
      {
      /* USER CODE BEGIN ADC1_MspDeInit 0 */

      /* USER CODE END ADC1_MspDeInit 0 */
        /* Peripheral clock disable */
        __HAL_RCC_ADC1_CLK_DISABLE();

        /**ADC GPIO Configuration    
        PA0     ------> ADC_IN0
        PA1     ------> ADC_IN1
        PA2     ------> ADC_IN2
        PA3     ------> ADC_IN3
        PA5     ------> ADC_IN5
        PA6     ------> ADC_IN6
        PA7     ------> ADC_IN7
        PB0     ------> ADC_IN8
        PB1     ------> ADC_IN9 
        */
        HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 
                              |GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);

        HAL_GPIO_DeInit(GPIOB, GPIO_PIN_0|GPIO_PIN_1);

      }
      /* USER CODE BEGIN ADC1_MspDeInit 1 */

      /* USER CODE END ADC1_MspDeInit 1 */
    } 

    /* USER CODE BEGIN 1 */

    /* USER CODE END 1 */

問題是,我想讀取以下值:temp1,晶體管_1電壓(ube1,vrb1,vrc1),temp2晶體管_2電壓(ube2,vrb2,vrc2)

平均獲得16次代碼:

HAL_Delay(2);

  /* Set DAC at voltage level 1 (3.1v 0xF07)*/
  setDAC(0xF07);   // 
   printf("\n***************************\n");
  HAL_Delay(2);
  for(int i = 0; i < 16; i++){ 

    readRollingADC(0); // read All inputs 16 times. 

void shiftAverages(){
  for(int i = 0; i < 8; i++){
    experiments[i].temperature = (experiments[i].temperature >> 4);
    experiments[i].ube = (experiments[i].ube >> 4);
    experiments[i].vrb = (experiments[i].vrb >> 4);
    experiments[i].vrc = (experiments[i].vrc >> 4);
  }
}

我針對不同的setDAC值執行這些操作,每次我輸入函數readRollingADC()ut時,函數第一次讀取的值始終為2048,因此可以正常工作。

當我讀取第一個值時,似乎以某種方式給了我很高的東西,這些東西會自動存儲在ADC寄存器中嗎?

//Start ADC reading
  if(HAL_ADC_Start(&hadc) != HAL_OK){
    while(1) {}
  }

  //Wait for EOC (end of conversion)    
  while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
  experiments[0+index].temperature += hadc.Instance->DR;
printf("\n ex0 i rolling %d\n", experiments[0+index].temperature); 
 HAL_ADC_Stop(&hadc);
   HAL_Delay(20);
  HAL_ADC_Start(&hadc);
  HAL_Delay(20);

  while(!(hadc.Instance->ISR & ADC_ISR_EOC)){}
  experiments[0+index].ube += hadc.Instance->DR;
   printf("\n ube si %d\n", experiments[0+index].ube); 
  HAL_ADC_Stop(&hadc);
   HAL_Delay(20);
  HAL_ADC_Start(&hadc);
  HAL_Delay(20);

我確實喜歡這個,但是這給了我所有頻道相同的價值,這是您所要提及的還是我應該寫別的東西?

您具有hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONVhadc.Init.ContinuousConvMode = DISABLE 我想您需要在轉換每個通道后重新啟動ADC。 因此,在每次轉換之間,您需要先調用HAL_ADC_Stop然后再調用HAL_ADC_Start 您甚至不必在轉換之間清除ISR_EOC標志,而必須手動進行,因此最好調用HAL_ADC_PollForConversions來清除它。 並且您需要調用HAL_ADC_Start其計數與配置的通道完全相同,即。 9在您的設置中,否則ADC通道選擇將丟失您希望讀取的通道。
如果通道數量超過5個,我建議您使用DMA,並且將具有恰好字數的緩沖區作為通道來配置並設置hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV 這樣,通過單個HAL_ADC_Start_DMA您可以獲得所有通道字節。 在少於5個通道的情況下,一個常規通道+其余的具有自動注入功能的注入通道就可以完成工作。
切記將__LL_ADC_CALC_TEMPERATURE讀取ADC值從stm32l0_ll_adc.h轉換為溫度,並將__LL_ADC_CALC_DATA_TO_VOLTAGE為電壓。
您可以在此處閱讀有關stm32l0 hal驅動程序的信息

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM