单片机入门---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);
		  }
	  }
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值