【stm32】hal库学习笔记-ADC模数转换(超详细!)

【stm32】hal库学习笔记-ADC模数转换(超详细!)

本篇章介绍了ADC实现电压检测的三种方式

ADC原理及选型

ADC将连续的模拟电压信号转换为二进制的数字信号

选型参数

速度(采样频率)
功耗
精度【stm32】hal库学习笔记-ADC模数转换(超详细!)_第1张图片

转换原理

【stm32】hal库学习笔记-ADC模数转换(超详细!)_第2张图片

ADC hal库驱动函数

【stm32】hal库学习笔记-ADC模数转换(超详细!)_第3张图片

普通通道检测电压

CubeMX图形化配置

导入TFT_LCD配置(配置方法见上一篇博客)

时钟树配置
【stm32】hal库学习笔记-ADC模数转换(超详细!)_第4张图片
打开外部时钟
【stm32】hal库学习笔记-ADC模数转换(超详细!)_第5张图片
FSMC配置
【stm32】hal库学习笔记-ADC模数转换(超详细!)_第6张图片
ADC配置
【stm32】hal库学习笔记-ADC模数转换(超详细!)_第7张图片

将Time base的优先级调为0 打开中断

【stm32】hal库学习笔记-ADC模数转换(超详细!)_第8张图片

代码实现

  /* USER CODE BEGIN 2 */
  lcd_init();
//  lcd_show_str(10, 40, 24, "ADC1-IN5 channel", RED);
//  lcd_show_str(10, 70, 24, "Please set jumper at first", RED);
//  lcd_show_str(10,100, 24, "Tune potentiometer for input", RED);
  lcd_show_str(10,130, 24, "ADC 12-bits Value = ", RED);
  lcd_show_str(10,190, 24, "Voltage(mV) = ", RED);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  HAL_ADC_Start(&hadc1);
	  if (HAL_ADC_PollForConversion(&hadc1, 200) == HAL_OK) {
		  uint32_t val = HAL_ADC_GetValue(&hadc1);
		  lcd_show_num(50, 160, val, 4, 24, RED);

		  uint32_t Volt = 3300 * val >> 12;
		  lcd_show_num(50, 220, Volt, 4, 24, RED);
	  }
	  //HAL_ADC_Stop(&hadc1);
	  HAL_Delay(500);
    /* USER CODE END WHILE */

实现效果

【stm32】hal库学习笔记-ADC模数转换(超详细!)_第9张图片
每0.5秒采样一次(不精确)

外部中断触发检测电压

CubeMX图形化配置

打开外部中断触发
【stm32】hal库学习笔记-ADC模数转换(超详细!)_第10张图片
【stm32】hal库学习笔记-ADC模数转换(超详细!)_第11张图片
修改时钟树
【stm32】hal库学习笔记-ADC模数转换(超详细!)_第12张图片
设置TIM3
【stm32】hal库学习笔记-ADC模数转换(超详细!)_第13张图片
参数设置原理见博客定时器篇章
更改中断优先级
【stm32】hal库学习笔记-ADC模数转换(超详细!)_第14张图片

代码实现

  /* USER CODE BEGIN 2 */
  lcd_init();
  lcd_show_str(10,160, 24, "ADC 12-bits Value = ", RED);
  lcd_show_str(10,220, 24, "Voltage(mV) = ", RED);

  HAL_ADC_Start_IT(&hadc1);
  HAL_TIM_Base_Start(&htim3);
  /* USER CODE END 2 */

重写回调函数

/* USER CODE BEGIN 4 */
__weak void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
	if (hadc->Instance == ADC1) {
		uint32_t val = HAL_ADC_GetValue(&hadc1);
		lcd_show_num(50, 190, val, 4, 24, RED);

		uint32_t Volt = 3300 * val >> 12;
		lcd_show_num(50, 250, Volt, 4, 24, RED);
	}
}
/* USER CODE END 4 */

实现效果

每0.5秒采样一次(较精确)

DMA和多通道传输

设置三个输入通道
使用扫描转换模式
利用DMA方式传输数据

CubeMX图形化配置

DMA设置
【stm32】hal库学习笔记-ADC模数转换(超详细!)_第15张图片
ADC设置
【stm32】hal库学习笔记-ADC模数转换(超详细!)_第16张图片
【stm32】hal库学习笔记-ADC模数转换(超详细!)_第17张图片

代码实现

#define		BATCH_DATA_LEN	3
uint32_t	dmaDataBuffer[BATCH_DATA_LEN];
/* USER CODE END PV */
  /* USER CODE BEGIN 2 */
  lcd_init();
//  lcd_show_str(10, 40, 24, "Conversion triggered by", RED);
//  lcd_show_str(10, 70, 24, "TIM3 with interval of 500ms", RED);
  lcd_show_str(10,100, 24, "Channel 5 Voltage(mV) = ", RED);
  lcd_show_str(10,160, 24, "Reference Voltage(mV) = ", RED);
  lcd_show_str(10,220, 24, "Battery   Voltage(mV) = ", RED);

  HAL_ADC_Start_DMA(&hadc1, dmaDataBuffer, BATCH_DATA_LEN);
  HAL_TIM_Base_Start(&htim3);
  /* USER CODE END 2 */

重写回调函数

/* USER CODE BEGIN 4 */
__weak void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
	uint32_t adcValue = 0, Volt;
	for (uint8_t i = 0; i < BATCH_DATA_LEN; ++i) {
		adcValue = dmaDataBuffer[i];
		Volt = 3300 * adcValue >> 12;
		if (i % 3 == 0) {
			lcd_show_num(50, 130, Volt, 4, 24, RED);
		} else if (i % 3 == 1) {
			lcd_show_num(50, 190, Volt, 4, 24, RED);
		} else if (i % 3 == 2) {
			lcd_show_num(50, 250, Volt, 4, 24, RED);
		}
	}
}
/* USER CODE END 4 */

实现效果

【stm32】hal库学习笔记-ADC模数转换(超详细!)_第18张图片

你可能感兴趣的:(stm32,学习,笔记,嵌入式硬件)