STM32
直播中

低调de炫耀爱

12年用户 762经验值
私信 关注
[问答]

如何使用ADC去采集电压呢

如何使用ADC去采集电压呢?有哪些操作流程?

回帖(1)

黄淳

2021-9-24 15:10:47
  学习目标:使用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。
  // CoreIncmain.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(“ADCn”);
  /* 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自动自校准这句话。
  以上。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分