嵌入式学习——ADC

  • ADC: 就像一位"翻译官",把现实世界的模拟语言(连续变化的电压)翻译成单片机能懂的数字语言(离散的数值)。
  • DAC: 则反过来,把单片机的数字指令翻译成模拟世界的电压信号,用来控制模拟器件(比如驱动扬声器发出声音、控制电机速度等)。

模拟 vs. 数字

想象一下调节收音机的音量旋钮和按计算器的数字键:

  • 模拟 (Analog): 像音量旋钮,可以在一个范围内连续变化,有无限多个可能的音量值。现实世界的物理量大多是模拟的。
  • 数字 (Digital): 像计算器的按键,只有有限的、离散的状态(0, 1, 2...)。计算机和单片机处理的是数字信号。

ADC 的任务就是把模拟信号"采样"并"量化"成数字值。

分辨率 (精度)

分辨率决定了 ADC 能将模拟电压"切"成多少份,也就是它能区分多么细微的电压变化。通常用"位" (bits) 来表示。

例如,一个 12 位的 ADC,能表示 212=4096 个不同的数字级别。如果参考电压是 3.3V,那么它能分辨的最小电压变化大约是 3.3V/4096≈0.0008V 或 0.8mV。

分辨率越高,测量越精确,但转换速度可能越慢,成本也越高。

参考电压 (Reference Voltage, Vref)

参考电压是 ADC 进行测量的"标尺"。它定义了 ADC 能够转换的模拟电压的最大值。输入的模拟电压不能超过参考电压。

ADC 输出的数字值通常与输入电压的关系是:

Digital Value=Analog Input VoltageVref×(2Resolution−1)

在很多 STM32 单片机中,Vref 通常连接到 Vdda (模拟电源电压),比如 3.3V。精确的 Vref 对于准确的 ADC 转换至关重要。

采样率 (Sampling Rate)

采样率表示 ADC 每秒钟进行多少次模数转换。单位通常是 SPS (Samples Per Second) 或 Hz。

根据奈奎斯特采样定理,采样率必须至少是被测模拟信号最高频率的两倍,才能无失真地还原原始信号。采样率越高,越能捕捉到快速变化的模拟信号。

硬件连接:捕捉模拟信号

将模拟信号连接到 ADC 非常简单:

  1. 找到 ADC 输入引脚: 在你的 STM32 开发板上,通常会有标明如 `PA0`, `PC1` 等,并且这些引脚在 CubeMX 中可以配置为 ADC 的输入通道 (如 `ADC1_IN0`, `ADC1_IN11`)。查阅开发板原理图或引脚定义是最好的方法。
  2. 连接模拟信号源: 将你的模拟信号源(比如电位器、温度传感器、光敏电阻分压电路的输出端)连接到选定的 ADC 输入引脚。
  3. 连接地线 (GND): 确保模拟信号源的地线 (GND) 与 STM32 开发板的地线 (GND) 共地连接。这是保证测量准确的基础。
  4. (可选)连接 Vref: 确保 ADC 的参考电压引脚 (Vref+ 或 Vdda) 连接到稳定、精确的参考电压源(通常是开发板上的 3.3V)。

注意: 输入到 ADC 引脚的电压绝对不能超过其允许的最大范围(通常是 0V 到 Vdda/Vref+)。GND 必须连接!

点击编译


ADC 轮询法:最直接的读取方式

ADC 配置完成后(通常通过 STM32CubeMX 生成初始化代码),我们如何获取转换结果呢?最简单直接的方法就是轮询法 (Polling)

想象一下你要去楼下信箱取信:

  1. 走到信箱旁 (HAL_ADC_Start(&hadc1); - 启动一次转换)。
  2. 你站在那里一直等,直到邮递员把信投进去 (HAL_ADC_PollForConversion(&hadc1, timeout); - 循环检查转换完成标志位,直到超时)。
  3. 邮递员投完信后,你打开信箱,取出信件 (adc_val = HAL_ADC_GetValue(&hadc1); - 读取转换结果)。

这种方式简单粗暴,但在等待期间 CPU 基本被"卡住"了,不能干别的事。如果转换时间很长,或者需要频繁读取,效率会很低。但在某些简单场景下,不失为一种快速验证功能的方法。

守株待兔":代码实现

逻辑分解:

hadc1 是一个结构体句柄,用来标识并控制 ADC 外设。 

  1. HAL_ADC_Start(&hadc1);: "开始转换!" 通知 ADC 硬件启动一次模数转换过程。
  2. HAL_ADC_PollForConversion(&hadc1, 1000);: "等等看结果出来没?" 这个函数会不断检查 ADC 状态寄存器中的转换完成标志位 (EOC - End Of Conversion)。如果标志位被硬件置位,表示转换完成,函数返回 HAL_OK。如果超过了设定的超时时间 (1000ms) 标志位还没置位,就返回 HAL_TIMEOUT注意:这是一个阻塞函数,在等待期间,CPU 会卡在这里,执行一个循环检查。
  3. adc_val = HAL_ADC_GetValue(&hadc1);: "结果拿来!" 如果上一步返回 HAL_OK,就调用此函数从 ADC 数据寄存器中读取转换后的数字值。对于 12 位 ADC,这个值通常在 0 到 4095 之间。
  4. 电压计算: 将读取到的数字值根据参考电压和分辨率,按比例计算出对应的模拟电压值。这是可选步骤,取决于你的应用需求。
  5. HAL_ADC_Stop(&hadc1); (可能需要): 如果你在 CubeMX 中将 ADC 配置为连续转换模式 (Continuous Conversion Mode),调用 HAL_ADC_Start 后 ADC 会不停地转换。在这种情况下,读取完一次后如果想停止,就需要调用 HAL_ADC_Stop。如果是单次转换模式 (Single Conversion Mode),ADC 完成一次转换后会自动停止,通常不需要调用 Stop。请检查你的 CubeMX 配置。

ADC DMA + 定时处理:解放 CPU 的初步尝试 

为了让 CPU 能在 ADC 转换的同时处理其他任务,我们可以请出强大的帮手——DMA (Direct Memory Access)

这种方法的思路是:

  1. 配置 ADC 工作在连续转换模式
  2. 配置 DMA 通道,让它像一个勤劳的"搬运工",在 ADC 每完成一次转换后,自动将结果从 ADC 数据寄存器搬运到内存中的一个指定缓冲区(比如一个数组)。
  3. DMA
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值