單片機入門---ADC採樣

ADC:analogy-digital converter 模擬-數字轉換器。
首先可以參考這篇文章,對ADC採樣有個正確的認識。https://blog.csdn.net/euxnijuoh/article/details/81066739

在ADC的初始化過程中,有兩個很有意思的參數:

  hadc.Init.ContinuousConvMode = DISABLE;
  hadc.Init.DiscontinuousConvMode = ENABLE;

按照字面意思,我們會認爲如果選擇相反的設定的話,這兩個功能不就是完全相同的嗎?然鵝,實際上並不是這樣的。下面我們從代碼入手,結合寄存器描述來看一下:

  /* Configuration of ADC:                                                    */
  /*  - Resolution                                                            */
  /*  - Data alignment                                                        */
  /*  - Scan direction                                                        */
  /*  - External trigger to start conversion                                  */
  /*  - External trigger polarity                                             */
  /*  - Continuous conversion mode                                            */
  /*  - DMA continuous request                                                */
  /*  - Overrun                                                               */
  /*  - AutoDelay feature                                                     */
  /*  - Discontinuous mode                                                    */
  hadc->Instance->CFGR1 &= ~(ADC_CFGR1_ALIGN   |
                             ADC_CFGR1_SCANDIR |
                             ADC_CFGR1_EXTSEL  |
                             ADC_CFGR1_EXTEN   |
                             ADC_CFGR1_CONT    |
                             ADC_CFGR1_DMACFG  |
                             ADC_CFGR1_OVRMOD  |
                             ADC_CFGR1_AUTDLY  |
                             ADC_CFGR1_AUTOFF  |
                             ADC_CFGR1_DISCEN   );
  
  hadc->Instance->CFGR1 |= (hadc->Init.DataAlign                             |
                            ADC_SCANDIR(hadc->Init.ScanConvMode)             |
                            ADC_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode)    |
                            ADC_DMACONTREQ((uint32_t)hadc->Init.DMAContinuousRequests) |
                            hadc->Init.Overrun                               |
                            __HAL_ADC_CFGR1_AutoDelay(hadc->Init.LowPowerAutoWait) |
                            __HAL_ADC_CFGR1_AUTOFF(hadc->Init.LowPowerAutoPowerOff));
  
  /* Enable external trigger if trigger selection is different of software  */
  /* start.                                                                 */
  /* Note: This configuration keeps the hardware feature of parameter       */
  /*       ExternalTrigConvEdge "trigger edge none" equivalent to           */
  /*       software start.                                                  */
  if (hadc->Init.ExternalTrigConv != ADC_SOFTWARE_START)
  {
    hadc->Instance->CFGR1 |= hadc->Init.ExternalTrigConv |
                             hadc->Init.ExternalTrigConvEdge;
  }
  
  /* Enable discontinuous mode only if continuous mode is disabled */
  if (hadc->Init.DiscontinuousConvMode == ENABLE)
  {
    if (hadc->Init.ContinuousConvMode == DISABLE)
    {
      /* Enable the selected ADC group regular discontinuous mode */
      hadc->Instance->CFGR1 |= (ADC_CFGR1_DISCEN);
    }
    else
    {
      /* ADC regular group discontinuous was intended to be enabled,        */
      /* but ADC regular group modes continuous and sequencer discontinuous */
      /* cannot be enabled simultaneously.                                  */
      
      /* Update ADC state machine to error */
      SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
      
      /* Set ADC error code to ADC peripheral internal error */
      SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
    }
  }

上 面 是 stm32l0xx_hal_adc.c 文 件 中 HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef* hadc);函數的定義,這個函數中對配置寄存器ADC configuration register 1 (ADC_CFGR1)進行了設置。從上面的代碼中可以看到:

hadc->Instance->CFGR1 &= ~(ADC_CFGR1_ALIGN |
ADC_CFGR1_SCANDIR | ADC_CFGR1_EXTSEL | ADC_CFGR1_EXTEN | ADC_CFGR1_CONT | ADC_CFGR1_DMACFG | ADC_CFGR1_OVRMOD | ADC_CFGR1_AUTDLY | ADC_CFGR1_AUTOFF | ADC_CFGR1_DISCEN );

首先清除了bit16,即ADC_CFGR1_DISCEN 。
從spec上看,此處的定義在CFGR1寄存器中表述如下:
在這裏插入圖片描述
可以看到如果設定爲0的情況下是關閉了非連續模式。但是並沒有打開連續採樣模 式。接着往下看代碼

hadc->Instance->CFGR1 |= (hadc->Init.DataAlign		| ADC_SCANDIR(hadc->Init.ScanConvMode)	| ADC_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode) | ADC_DMACONTREQ((uint32_t)hadc->Init.DMAContinuousRequests) | hadc->Init.Overrun	|
    HAL_ADC_CFGR1_AutoDelay(hadc->Init.LowPowerAutoWait) |
    HAL_ADC_CFGR1_AUTOFF(hadc->Init.LowPowerAutoPowerOff));

此處對ContinuousConvMode這個參數進行了解讀和設置,設置部分的代碼如下:

/**
*@brief Enable ADC continuous conversion mode.
*@param _CONTINUOUS_MODE_ Continuous mode.
*@retval None
*/
#define ADC_CONTINUOUS(_CONTINUOUS_MODE_) ((_CONTINUOUS_MODE_) << 13U)

可以看出是對bit13進行了設置,而對這個寄存器的描述在spec中表述如下:
在這裏插入圖片描述

從以上描述中可以看出,這個位是單次轉換還是連續直到被清除。也就是這樣的設置 跟是否連續設置是沒有關係的。是兩個完全不同的寄存器的設置。但是兩處的描述中 都明確提示不能同時設置兩個寄存器爲1。
接着往下看,

/* Enable discontinuous mode only if continuous mode is disabled */ if (hadc->Init.DiscontinuousConvMode == ENABLE)
{
if (hadc->Init.ContinuousConvMode == DISABLE)
{
/* Enable the selected ADC group regular discontinuous mode */ hadc->Instance->CFGR1 |= (ADC_CFGR1_DISCEN);
}
else
{
/* ADC regular group discontinuous was intended to be enabled,	*/
/* but ADC regular group modes continuous and sequencer discontinuous */
/* cannot be enabled simultaneously.	*/

/* Update ADC state machine to error */
SET_BIT(hadc->State,   HAL_ADC_STATE_ERROR_CONFIG);

/* Set ADC error code to ADC peripheral internal error */ SET_BIT(hadc->ErrorCode,   HAL_ADC_ERROR_INTERNAL);
}
}

上面的代碼有意思的是,你不能夠在cubeMX同時設置如下兩個參數,但是如果你採 用人工手寫代碼的方式可以同時enable這兩個參數,這時候就走到上面代碼的else 分支中,會設定錯誤狀態。
在這裏插入圖片描述

如何使用ADC獲取正確的值呢?
首先在使用前,對ADC進行一下校準:

HAL_ADCEx_Calibration_Start(&hadc, ADC_SINGLE_ENDED);
for (i = 0; i < 10; i++) {
		  HAL_ADC_Start(&hadc);
		  HAL_ADC_PollForConversion(&hadc, 10);

		  if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc), HAL_ADC_STATE_REG_EOC)) {
			  ADC_Buf[i] = HAL_ADC_GetValue(&hadc);
		  }
	  }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章