06 ADC实验
up的视频讲解把传感器电压转换成数字,再沿电路关系还原光照、温度与声音的变化。
up视频里的实验代码: 👣ADC实验代码
1 🌡️ 光/热传感器-光照/温度采集实验
1.1 实验连接
传感器 AO 接 PA1,串口 PA9 接 CH340 的 RXD,用于观察采样结果。

1.2 实验原理
NTC 热敏电阻和光敏电阻先把物理量变化转换为阻值变化。分压电路再把阻值变化转换为 AO 电压,ADC 对这个电压采样。

读取结果后,先换算电压,再根据分压关系得到电阻,最后根据传感器模型计算温度或光照。每一步都有自己的参数,不能只看最终输出数字。
1.3 CubeMX配置
选择 ADC1 的通道 1,对应 PA1。本实验只采集一个通道,关闭扫描和连续转换,规则组选择软件触发。

温度和光照变化较慢,选用较长的采样时间,让输入采样电容有充分的充电时间。打开 ADC 中断,使程序能在转换完成后读取结果。


再开启 USART1 异步发送,与串口助手保持相同的波特率和帧格式。程序启动一次转换,回调保存结果,主循环发送并重新启动下一次转换。
1.4 实验代码
全局
#include <stdio.h>
uint16_t adc_val = 0;
uint8_t flag = 0;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC1)
{
adc_val = HAL_ADC_GetValue(&hadc1);
flag = 1;
}
}
main()
HAL_ADC_Start_IT(&hadc1);
while(1)
if(flag == 1)
{
char buf[64] = {0};
sprintf(buf,"adc_val=%d V_AO=%f\r\n",adc_val,adc_val/4096.0f*3.3f);
HAL_UART_Transmit(&huart1,buf,strlen(buf),1000);
flag = 0;
HAL_ADC_Start_IT(&hadc1);
}
1.5 温度/光照 计算

下面分别给出温度和光照的计算代码。阅读时先核对固定电阻、标称电阻和模型参数,再看计算公式。光照代码中的经验关系适合观察变化,并不等同于经过标定的照度计。
1.6 温度计算代码
//==================== NTC热敏电阻参数(B3950‑10K) ====================
#include "math.h"
#define NTC_R_FIX 10000.0f //电路上拉固定电阻R1=10k
#define R25 10000.0f //25℃标称NTC电阻
#define T25 298.15f //25℃开尔文
#define B 3950.0f //B值
#define ADC_MAX 4095.0f
/**
* @brief NTC热敏电阻B值模型计算温度
* @param adc_val: ADC原始采样值,范围0~4095
* @retval 温度值,单位℃
* @note 硬件电路:VCC →10k固定电阻 →AO采样点 →NTC →GND
*/
float NTC_GetTemperature(uint16_t adc_val)
{
// 根据ADC分压换算NTC当前实时电阻
float R_ntc = NTC_R_FIX * adc_val / (ADC_MAX - adc_val);
// NTC B值公式,计算开尔文温度
float invT = 1.0f / T25 + (1.0f / B) * logf(R_ntc / R25);
float T_K = 1.0f / invT;
// 开尔文温度转换为摄氏温度
float T_C = T_K - 273.15f;
return T_C;
}
1.7 光照计算代码
//==================== GL5528光敏电阻参数 ====================
#include "math.h"
#define LDR_R_FIX 10000.0f //电路上拉固定电阻R1=10k
#define LDR_R10 10000.0f //10Lux时光敏电阻阻值10kΩ
#define LDR_GAMMA 0.7f //GL5528伽马值γ
#define ADC_MAX 4095.0f
/**
* @brief GL5528光敏电阻计算光照度
* @param adc_val: ADC原始采样值,范围0~4095
* @retval 光照度,单位Lux(勒克斯),仅相对值,非计量级精度
* @note 硬件电路:VCC →10k固定电阻 →AO采样点 →LDR →GND
* 公式: Lux = 10 * pow(R10 / Rldr, 1/gamma)
*/
float LDR_GetLux(uint16_t adc_val)
{
// 根据ADC分压换算光敏电阻当前实时电阻
float R_ldr = LDR_R_FIX * adc_val / (ADC_MAX - adc_val);
// 光敏电阻照度‑电阻经验公式,计算环境光照度Lux
float lux = 10.0f * powf( LDR_R10 / R_ldr, 1.0f / LDR_GAMMA );
return lux;
}
2 🎙️ 麦克风- 音频采集实验
2.1 实验连接
麦克风输出连接 PA1,串口继续把采样数据送到电脑。

2.2 实验原理
麦克风把声音变化转成电压变化,ADC 把不同时刻的电压记录成一串数字。串口助手按顺序绘制这些数字,就得到时域波形。
本实验用定时器安排采样节奏,用 ADC 完成转换,再由主循环输出结果。先观察声音变化与波形的对应关系,后面的 DMA 课程再讨论连续数据的批量搬运。
2.3 CubeMX配置
使用 TIM3 的更新事件触发 ADC:选择内部时钟,预分频设置为 72 - 1,自动重装载设置为 200 - 1。当定时器时钟为 72 MHz 时,更新频率为 5 kHz。
在 TIM3 的触发输出中选择更新事件,在 ADC 规则组中选择 TIM3 触发。将采样时间设为 7.5 个 ADC 时钟周期,随后重新生成工程。
主程序启动 ADC 等待触发,再启动 TIM3。此时下一次转换由定时器触发,不再由主循环反复软件启动。
串口输出只保留采样数字与换行,串口助手才能按数值绘制波形。这里的 5 kHz 是硬件触发频率;逐点文本发送能保留多少数据,还受到串口速度与程序处理时间影响。
2.4 实验代码
全局
#include <stdio.h>
uint16_t adc_val = 0;
uint8_t flag = 0;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC1)
{
adc_val = HAL_ADC_GetValue(&hadc1);
flag = 1;
}
}
main()
HAL_ADC_Start_IT(&hadc1);
HAL_TIM_Base_Start(&htim3);
while(1)
if(flag == 1)
{
char buf[64] = {0};
sprintf(buf,"%d\r\n",adc_val);
HAL_UART_Transmit(&huart1,buf,strlen(buf),1000);
flag = 0;
}