一.ADC概述

  ADC芯片将模拟信号(光强、温度、湿度)转化为数字信号,是联系模拟现实世界和数字世界的中介。

  ADC数模转换一般包含三个关键步骤:采样(在间隔为T的T,2T,3T...时刻抽取被测模拟信号的幅值。T:采样周期。)、量化(把采样后的每个脉冲的幅度进行离散化处理,得到能被CPU处理的离散数值。)、编码(把量化的结果二进制表示出来。)。

1.1计算采样时间、频率

ADC转换时间 = 采样时间 + 12.5个周期

二.ADC的性能参数

2.1量程

ADC所能转化的模拟输入电压的范围,分为单极性(0~+3.3v)和双极性(-5~+5v)两种类型。

2.2分辨率

ADC所能分辨的最小模拟输入量,反应ADC对输入信号微小变化的响应能力。若小于最小变化量的输入模拟电压的任何变化,将不会引起ADC输出数字值的变化。

一个n(ADC的量化位数n)位ADC的分辨率等于ADC的满量程与2的n次方的比值(eg:12位AD值满量程0~+10v———10v/(2的12次方))。

2.3精度

对于ADC的数字输出(二进制码),实际需要的模拟输入值与理论上要求的模拟输入值之差。

2.4转换时间

ADC完成一次A/D转换需要的时间,从启动ADC开始到获得响应数据需要的总时间。

转换时间=采样时间+量化和编码时间。

三.ADC主要类型

3.1逐次逼近型

普遍,不需要通过中间变量即可直接把输入的模拟电压转换为输出的数字量。D/A转换器从高位到低位依次逐位增加转换位数,产生不同的输出电压,把输出电压与输入电压通过比较器比较,二分法查找数字值。特点:电路规模中等,转换速度较快,转换精度较高,功耗低。

3.2电压时间转换型

通过间接转换方式实现A/D转化器。

3.3电压频率转换型

四.定时器

TIM6/TIM7(基本定时器):只具备最基本的定时功能,累计时钟脉冲超过预定值时产生定时器溢出事件。如果使能了中断/DMA操作,将产生中断/DMA操作

TIM2~TIM5(通用定时器),除了具备基本的定时外,主要用于测量输入脉冲的频率和脉冲宽度以及输出PWM脉冲等场合,还具有编码器接口。

TIM1和TIM8(高级控制定时器)。

五.M32CubeMX

1.设置SYS

2.Analog--ADC1

触发源:TIM3的TRGO 

3.TIM

目标周期:1ms=0.001s

公式:周期=[(PSC+1)*(ARR+1)]/定时器时钟频率

所以,1000HZ=[(PSC+1)*(ARR+1)]/72HZ

-----PSC:71------[PSC+1=72]

-----ARR:999----[ARR+1=1000]

 4.USART1(串口1)

5.配置系统时钟

六.代码

(1)TIM+ADC

TIM3启动—每1ms产生TRGO信号—触发ADC转换—转换完成—进入中断回调函数处理数据

 1.开启ADC&TIM

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

2. 头文件

/* USER CODE BEGIN Includes */
#include<stdio.h>
#include<string.h>
/* USER CODE END Includes */

3.设置全局变量

/* USER CODE BEGIN PV */
uint32_t adc_value=0;
float voltage=0.0f;
/* USER CODE END PV */

4.中断函数

/* USER CODE BEGIN 4 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
  if (hadc->Instance == ADC1)  
  {

    adc_value = HAL_ADC_GetValue(&hadc1);
    voltage = adc_value * 3.3f / 4095.0f;
    
    char buffer[50];
    sprintf(buffer, "%.3f V\r\n", voltage);
    HAL_UART_Transmit_IT(&huart1, (uint8_t*)buffer, strlen(buffer));
  }
}


/* USER CODE END 4 */


5.实验结果

验证时间间隔的准确性:

验证接收转换电压的准确性:

将ADC1引脚与3.3v相连,打开串口调试助手

(2) DMA+TIM+ADC

1.增加Cubemx设置

2.重写代码

/* USER CODE BEGIN PV */
uint16_t adc_dma_buf[10] = {0};
uint8_t dma_transfer_complete = 0; 
float avg_voltage = 0.0f;
/* USER CODE END PV */
  /* USER CODE BEGIN 2 */
HAL_ADCEx_Calibration_Start(&hadc1);  // 启动ADC校准
HAL_TIM_Base_Start(&htim3);           // 启动定时器3(作为ADC的触发源)
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_dma_buf, 1);  // 启动ADC的DMA传输模式
  /* USER CODE END 2 */

 注:HAL_ADC_Start_DMA() 函数的第三个参数(uint32_t Length)决定了DMA 传输的数据项数量。传输一次后触发DAM中断,为 ADC 采样频率的 1/1。若改成10,为 ADC 采样频率的 1/10。储存多个样本可对样本求平均值。

/* USER CODE BEGIN 4 */


void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
  if (hadc->Instance == ADC1)
  {
  float voltage = adc_dma_buf[0] * 3.3f / 4095.0f;
    
    char buf[50];
    sprintf(buf, "%.3f \r\n", voltage);
    HAL_UART_Transmit_IT(&huart1, (uint8_t*)buf, strlen(buf));
  }
}

/* USER CODE END 4 */

结果

DMA 通过 “硬件直接传输、无 CPU 干预、时间确定性高” 的特性,消除了传统中断模式中 CPU 处理带来的延迟和不确定性,确保 ADC 采样数据按 TIM3 设定的 1ms 周期稳定传输,实现更精准的数据采集与传输。 

准确性的提升主要是ADC校准语句: HAL_ADCEx_Calibration_Start(&hadc1);的功劳。

七.示波器 

示波器探头:(探头钩)连接USART1_TX引脚处。(接地夹)接GND引脚,或者如图

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐