stm32的adc实验
stm32的adc实验
更多
好的,我们来详细讲解一下 STM32 的 ADC(模数转换器)基础实验。这个实验通常的目标是:使用 ADC 读取一个模拟输入信号(如电位器分压值),并通过某种方式(如串口或调试器)观察转换后的数字值。
这里我们假设:
- 使用 STM32CubeIDE 开发环境。
- 使用 STM32 HAL 库 进行开发。
- 目标是一个常见的开发板(如 STM32F1/F4 系列),并使用其板载电位器(如果可用)或自己连接一个电位器到 ADC 引脚。
- 使用 单通道、轮询模式 进行单次转换。这是最简单的方式。
实验步骤详解
1. 硬件准备
- STM32 开发板: 如 STM32F103C8T6 (Blue Pill), STM32F407 Discovery, NUCLEO 系列等。
- ADC 输入源:
- 板载电位器 (推荐): 很多开发板(如 STM32F407 Discovery)自带一个连接到 ADC 通道的电位器。查看你的板子的原理图,找到对应的引脚(如 PC0, PA0 等)。
- 外接电位器: 如果没有板载的,连接一个电位器(如 10KΩ):
- 电位器一端接
3.3V(开发板的3.3V输出)。 - 另一端接
GND(开发板的GND)。 - 中间抽头(滑动端)连接到你选择的 ADC 输入引脚(如 PA0)。
- 电位器一端接
- 调试/输出:
- ST-Link/V2 调试器: 用于下载程序和在线调试(查看变量值)。
- 串口转 USB 模块 (可选): 如果你想通过串口打印 ADC 值到电脑,需要连接开发板的 UART TX 引脚(如 PA9)到转接模块的 RX,并将转接模块连接到电脑。
2. STM32CubeIDE 工程配置 (以 STM32F103C8T6 PA0 为例)
- 创建工程: 启动 STM32CubeIDE,选择你的目标芯片型号(如 STM32F103C8)。
- 时钟配置 (Clock Configuration):
- 配置系统时钟(通常使用外部晶振 HSE,倍频到最高频率,如 72MHz)。
- 关键:配置 ADC 时钟。 ADC 时钟不能超过芯片规定的最大值(对于 F1 是 14MHz)。在时钟树中找到
APB2 Peripheral Clocks->ADC Prescaler。如果系统时钟是 72MHz,选择PCLK2 divided by 6(72MHz / 6 = 12MHz < 14MHz)。
- 引脚配置 (Pinout & Configuration):
- ADC 通道引脚: 找到你想使用的 ADC 输入引脚(例如 PA0)。将其功能设置为
ADC1_IN0(表示 ADC1 的通道 0)。 - 串口引脚 (可选): 如果使用串口输出,找到 USART1 (或其他 USART),将模式设置为
Asynchronous。配置对应的 TX (如 PA9) 和 RX (如 PA10) 引脚。
- ADC 通道引脚: 找到你想使用的 ADC 输入引脚(例如 PA0)。将其功能设置为
- ADC 配置 (Analog -> ADC1):
- Parameter Settings 标签页:
Clock Prescaler: 确保与时钟树中的配置匹配(如PCLK2 divided by 6)。Resolution: 选择转换精度(常用12-bit)。Data Alignment: 选择Right alignment(便于数据处理)。Scan Conversion Mode:Disabled(因为我们只用一个通道)。Continuous Conversion Mode:Disabled(我们希望按需启动单次转换)。Discontinuous Conversion Mode:Disabled。DMA Continuous Requests:Disabled(轮询模式不用 DMA)。End Of Conversion Selection:EOC flag at the end of single channel conversion。
- Rule Conversion 标签页:
- 点击
Add,选择Channel 0(对应 PA0)。 - 设置
Sampling Time:选择采样时间。采样时间越长,转换精度越高但速度越慢。对于信号源阻抗较小(如电位器直接连接),可以选择相对短的时间(如Cycles55.5或Cycles71.5)。对于高阻抗源需要更长时间(如Cycles239.5)。
- 点击
- Parameter Settings 标签页:
- 项目生成:
- 转到
Project Manager标签页,填写项目名、位置,选择MDK-ARM/STM32CubeIDE作为 Toolchain/IDE。 - 点击右上角
GENERATE CODE生成初始化代码。
- 转到
3. 编写用户代码 (main.c 示例)
在生成的代码中,我们需要在 main.c 文件中添加逻辑:
/* USER CODE BEGIN Includes */
#include <stdio.h> // 如果使用 printf 需要包含
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
// 定义全局变量存放 ADC 值和电压值
uint32_t adc_value = 0;
float voltage = 0.0f;
/* USER CODE END PV */
/* USER CODE BEGIN 0 */
// 如果需要使用 printf 重定向到串口 (可选)
#ifdef __GNUC__
int __io_putchar(int ch) {
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY); // 假设使用 huart1
return ch;
}
#endif
/* USER CODE END 0 */
int main(void) {
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_USART1_UART_Init(); // 如果使用了串口,确保初始化
/* USER CODE BEGIN 2 */
// 校准 ADC (推荐,提高精度)
HAL_ADCEx_Calibration_Start(&hadc1); // hadc1 是 CubeMX 生成的 ADC 句柄
/* USER CODE END 2 */
while (1) {
/* USER CODE BEGIN 3 */
// 启动 ADC 转换 (单次转换)
HAL_ADC_Start(&hadc1);
// 轮询等待转换完成
if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK) { // 超时 10ms
// 读取转换结果 (12位右对齐,范围 0-4095)
adc_value = HAL_ADC_GetValue(&hadc1);
// 计算实际电压值 (假设 Vref+ = 3.3V, Vref- = 0V)
voltage = (float)adc_value * 3.3f / 4095.0f; // 12位分辨率最大值 2^12 - 1 = 4095
// 方式1: 通过调试器查看变量 adc_value 和 voltage (在线调试时)
// 方式2: 通过串口打印 (需要重定向 printf)
printf("ADC Value: %lu, Voltage: %.2f V\r\n", adc_value, voltage);
// 方式3: 翻转一个LED灯表示ADC在运行 (可选)
// HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); // 需配置LED引脚
}
// 简单延时 (HAL_Delay 会阻塞,实际项目考虑用定时器)
HAL_Delay(500); // 每 500ms 采样一次
}
/* USER CODE END 3 */
}
4. 代码关键点解释
- 初始化:
MX_ADC1_Init()由 CubeMX 自动生成,配置了 ADC 的基本参数、通道和采样时间。 - 校准:
HAL_ADCEx_Calibration_Start()是推荐的步骤,用于补偿 ADC 模块内部的误差,提高转换精度。 - 启动转换:
HAL_ADC_Start(&hadc1)启动一次 ADC 转换。 - 等待转换完成:
HAL_ADC_PollForConversion(&hadc1, timeout)阻塞等待直到转换完成或超时。轮询模式简单但占用 CPU。 - 读取结果:
HAL_ADC_GetValue(&hadc1)读取转换后的数字值(12位模式下:0 - 4095)。 - 计算电压:
电压 = (ADC值 / 4095) * Vref。默认Vref通常等于芯片的VDDA引脚电压(大多数开发板是 3.3V)。重要: 确保VDDA电压稳定准确是获得精确电压值的关键。 - 输出结果:
- 调试器查看: 在 STM32CubeIDE 的 Debug 模式下,添加
adc_value和voltage到Expressions或Live Expressions窗口实时查看。 - 串口打印: 需要实现
printf重定向(示例中提供了__io_putchar的简单实现),并通过串口助手(如 PuTTY, Tera Term)查看打印信息。 - LED: 简单指示程序在运行。
- 调试器查看: 在 STM32CubeIDE 的 Debug 模式下,添加
5. 编译、下载与调试
- 编译: 点击 STM32CubeIDE 的锤子图标或
Project -> Build All。 - 下载: 确保 ST-Link 连接好,点击
Run -> Run或小虫子图标旁边的下拉箭头选择Debug As -> STM32 MCU C/C++ Application。 - 调试/运行:
- 进入 Debug 视图。
- 可以在
while(1)循环内设置断点观察变量。 - 或者直接在
Live Expressions窗口添加adc_value和voltage,全速运行 (Resume F8) 时也能实时刷新查看数值。 - 如果使用了串口,打开串口助手,设置正确的 COM 口、波特率(与
huart1初始化的波特率一致,如 115200)查看打印信息。
6. 观察结果与验证
- 旋转电位器(或改变输入电压)。
- 观察 ADC 值在 0 - 4095 之间变化(12位模式)。
- 观察计算出的电压值在 0V - ~3.3V 之间变化(对应 ADC 值 0 - 4095)。
- 当电位器旋到
3.3V端时,ADC 值应接近 4095,电压接近 3.3V。 - 当电位器旋到
GND端时,ADC 值应接近 0,电压接近 0V。
7. 常见问题及解决
- ADC 值一直是 0 或 4095/固定值:
- 检查 ADC 输入引脚配置是否正确(设为模拟输入
ADCx_INy)。 - 检查电位器连接是否正确(滑动端接 ADC 引脚,两端接 3.3V 和 GND)。
- 检查
HAL_ADC_Start和HAL_ADC_PollForConversion是否调用成功(检查返回值)。 - 检查采样时间是否太短(尝试增加采样时间)。
- 检查 ADC 输入引脚配置是否正确(设为模拟输入
- ADC 值波动大:
- 确保模拟电源
VDDA和VSSA稳定(通常需要连接去耦电容,0.1uF + 1uF 到地)。 - 检查模拟输入信号是否稳定(可以用示波器看)。
- 接地不良 是常见干扰源。确保开发板 GND 和电位器 GND 良好共地。
- 尝试增加采样时间。
- 软件上可以尝试简单的滤波(如多次采样取平均)。
- 确保模拟电源
- 计算出的电压不准:
- 最可能原因:
VDDA电压不是精确的 3.3V!很多 USB 供电的开发板,其 3.3V 是由稳压器从 5V USB 降压而来,可能有微小误差(如 3.28V 或 3.32V)。测量开发板VDDA或3.3V引脚的实际电压,并用这个实际电压值替换代码中的3.3f来计算。 - 检查 ADC 参考电压引脚 (
VREF+,VREF-) 的连接(大部分芯片VREF+内部连接到VDDA,VREF-连接到VSSA)。 - 尝试进行 ADC 校准。
- 最可能原因:
- 串口没输出:
- 检查串口线连接是否正确(开发板 TX --> 转接模块 RX)。
- 检查串口助手的波特率、数据位、停止位、校验位设置是否与代码初始化一致。
- 检查
printf重定向函数是否有效。
进阶方向
- 多通道扫描: 配置多个规则通道,使 ADC 自动按顺序扫描这些通道。
- 连续转换模式: 设置
Continuous Conversion Mode为Enabled,ADC 会自动连续转换。 - DMA 传输: 结合 DMA 将 ADC 转换结果自动搬运到内存数组,极大提高效率,几乎不占用 CPU。这是实际项目中最常用的方式。
- 注入通道: 用于需要打断规则转换的高优先级任务。
- 模拟看门狗: 设置阈值,当 ADC 值超出范围时触发中断。
- 定时器触发: 使用定时器精确控制 ADC 的采样时刻。
这个基础实验是理解 STM32 ADC 功能的起点。成功完成它后,你就可以根据具体应用需求探索更高级的功能了。祝你实验顺利!
STM32的ADC采样及各式滤波算法实现
本文为手把手教学ADC采样及各式滤波算法的教程,本教程的MCU采用STM32F103ZET6。以HAL库的ADC采样函数为基础进行教学,通过各式
2024-10-28 10:51:11
STM32 ADC 的使用说明
前言 最近是有一个产品用到了ADC,使用的是STM32L051 芯片,使用 STM32CubeMX 生成的代码,本来以为简简单单,但是在调用 H
2023-06-22 10:15:00
7天热门专题
换一换
换一换
- 如何分清usb-c和type-c的区别
- 中国芯片现状怎样?芯片发展分析
- vga接口接线图及vga接口定义
- 芯片的工作原理是什么?
- 华为harmonyos是什么意思,看懂鸿蒙OS系统!
- 什么是蓝牙?它的主要作用是什么?
- ssd是什么意思
- 汽车电子包含哪些领域?
- TWS蓝牙耳机是什么意思?你真的了解吗
- 什么是单片机?有什么用?
- 升压电路图汇总解析
- plc的工作原理是什么?
- 再次免费公开一肖一吗
- 充电桩一般是如何收费的?有哪些收费标准?
- ADC是什么?高精度ADC是什么意思?
- dtmb信号覆盖城市查询
- EDA是什么?有什么作用?
- 中科院研发成功2nm光刻机
- 苹果手机哪几个支持无线充电的?
- type-c四根线接法图解
- 华为芯片为什么受制于美国?
- 怎样挑选路由器?
- 元宇宙概念股龙头一览
- 锂电池和铅酸电池哪个好?
- 如何进行编码器的正确接线?接线方法介绍
- 什么是场效应管?它的作用是什么?
- 虚短与虚断的概念介绍及区别
- 晶振的作用是什么?
- 大疆无人机的价格贵吗?大约在什么价位?
- amoled屏幕和oled区别
- 苹果nfc功能怎么复制门禁卡
- 单片机和嵌入式的区别是什么
- 复位电路的原理及作用
- BLDC电机技术分析
- dsp是什么意思?有什么作用?
- 苹果无线充电器怎么使用?
- iphone13promax电池容量是多少毫安
- 芯片的组成材料有什么
- 特斯拉充电桩充电是如何收费的?收费标准是什么?
- 直流电机驱动电路及原理图
- 传感器常见类型有哪些?
- 自举电路图
- 苹果笔记本macbookpro18款与19款区别
- 通讯隔离作用
- 新斯的指纹芯片供哪些客户
- 伺服电机是如何进行工作的?它的原理是什么?
- 无人机价钱多少?为什么说无人机烧钱?
- 以太网VPN技术概述
- 手机nfc功能打开好还是关闭好
- 十大公认音质好的无线蓝牙耳机