STM32之CubeL4 ( ADC )

学习目标:使用ADC采集电压

通过配置ADC1_IN1通道,结合ADC模数转换函数,将电压模拟量转换为数字量,并将数据通过串口打印输出。

CubeMX配置

参数配置

Analog 中选择 ADC1 设置,并选择 IN1 通道1,选择 IN1 Single-ended单通道。
在这里插入图片描述
ADC具体配置参数下图所示
在这里插入图片描述

需要配置的参数已在图中框出,其他只需要保持默认就可以。

  • ADC_Settings:

    • Clock Prescaler:
      Asynchronous clock mode divided by 1 1分频
    • Resolution
      ADC 12-bit resolution 12位分辨率
    • Data Alignment
      Right alignment 转换结果数据右对齐,一般选择右对齐模式。
    • Scan Conversion Mode
      Disabled 禁止扫描模式。单通道使用 DISABLE。
      Enabled 自动连续转换。
    • Continuous Conversion Mode:
      Disabled 单次转换。只转换一次。
      Enabled 自动连续转换。
    • DiscontinuousConvMode:
      Disabled 禁止间断模式。在某个事件触发下,开启转换。
      Enabled 开启间断模式。
    • DMA Continuous Requests
      Disabled DMA请求是以单次模式执行,达到转换次数时,DMA传输停止。
      Enabled 连续模式执行,无论转换次数多少,DMA传输无限制。
  • ADC_Regular_ConversionMode:

    • Enable Regular Conversions 是否使能规则转换。
    • Number Of Conversion ADC 转换通道数目,有几个写几个就行 。
    • External Trigger Conversion Source 外部触发选择。一般采用软件触发方式。
  • Rank:

    • Channel ADC 转换通道
    • Sampling Time 采样周期选择,采样周期越短,ADC数据输出周期短 精度低,采样周期越长,ADC数据输出周期长 精度高。
  • ADC_Injected_ConversionMode:

    • Enable Injected Conversions 是否使能注入转换。注入通道只有在规则通道存在时才会出现。
  • WatchDog:

    • Enable Analog WatchDog Mode 是否使能模拟看门狗中断。当被 ADC 转换的模拟电压低于低阈值或者高于高阈值时,就会产生中断。

这里有些参数我也没使用过所以参数并不全。

配置ADC时钟,这里时钟不要超过14M,否则ADC采集电压有偏差。
ADC 的转换时间跟 ADC 的输入时钟和采样时间有关。
公式为:Tconv = 采样时间 + 12.5 个周期。当 ADCLK = 14MHZ (最高),采样时间设置为 1.5 周期(最快),那么总的转换时间(最短)Tconv = 1.5 周期 + 12.5 周期 = 14 周期 = 1us。

在这里插入图片描述
接下来配置USART1。
这里就列出来了,串口配置以及程序可以参考直接写过的 STM32L4 CubeMAX之USART
接下来生成代码后到KEIL MDK V5工程中继续新增用户控制逻辑。

完成用户控制逻辑

添加电压值转换
模拟电压经过 ADC 转换后,是一个 12 位的数字值,如果通过串口以 16 进制打印出来的话,可读性比较差,那么有时候我们就需要把数字电压转换成模拟电压,也可以跟实际的模拟电压(用万用表测)对比,看看转换是否准确。
我们一般在设计原理图的时候会把 ADC 的输入电压范围设定在:0~3.3v,因为 ADC 是 12 位的,那么 12 位满量程对应的就是 3.3V,12 位满量程对应的数字值是:2^12。数值 0 对应的就是 0V。如果转换后的数值为 X ,X 对应的模拟电压为 Y,那么会有这么一个等式成立: 2^12 / 3.3 = X / Y,=> Y = (3.3 * X ) / 2^12。

// Core\Inc\main.c
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

	int adc_value=0;
	float vol=0,num=0;
	char buf[20];
	
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

	if(HAL_UART_Receive_IT(&huart1, &usart1_buf.aRxBuff, 1) != HAL_OK)
	{
		Error_Handler();
	}
	
		printf("ADC\n");
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		
		HAL_ADC_MspInit(&hadc1);
		HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);//ADC自动自校准
		HAL_ADC_Start(&hadc1);	                //启动ADC单次转换
		HAL_ADC_PollForConversion(&hadc1, 50);	//等待ADC转换完成
		adc_value = HAL_ADC_GetValue(&hadc1); 	//读取ADC转换数据
		
		vol =((double)adc_value/4096)*3.3;
		printf("adc_value = %d, vol = %.2fV.\n", adc_value, vol);
		
		HAL_Delay(500);
		

  }
  /* USER CODE END 3 */
}

下载编译程序观察串口调试助手,ADC采集电压

在这里插入图片描述

使用万用表实际电压,还是精度还可以。

在这里插入图片描述

总结

一开始发现AD读出来的电压值总是会有0.1V的偏差,最后找到原因是ADC采样数据与实际数据相差比较大,小了很多。

解决办法
配置adc的时候,采样周期设置大一些。

采样周期太小,会导致采样不准确,采样周期越大越准确。
采样周期太大会影响采样时间,因为我实验中采集的VBAT电池分压之后的电压,所以我设置的采样周期最大。采样时间大家可以自己去试。
计算公式:
采样时间(us) = (12.5+SamplingTime ) / ADC时钟(MHZ)

还有一点就是最好在写程序的加上HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);//ADC自动自校准这句话。

以上。

  • 3
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值