【动手学STM32G4】(1)STM32G431之创建项目
【动手学STM32G4】(2)STM32G431之外部中断
【动手学STM32G4】(3)STM32G431之定时器
【动手学STM32G4】(4)STM32G431之PWM输出
【动手学STM32G4】(5)STM32G431之ADC采样
【动手学STM32G4】(6)STM32G431之DAC输出
【动手学STM32G4】(7)STM32G431之UART 串口通信
【动手学STM32G4】(8)STM32G431之USB虚拟串口
【动手学STM32G4】(9)STM32G431之上位机波形显示
【动手学STM32G4】(5)STM32G431之ADC采样
-
- [1. 项目简介](#1. 项目简介)
-
- [1.1 实验目标](#1.1 实验目标)
- [1.2 ADC 的原理和架构](#1.2 ADC 的原理和架构)
- [1.3 软硬件准备](#1.3 软硬件准备)
- [2. CubeMX 工程创建与配置](#2. CubeMX 工程创建与配置)
-
- [2.1 新建工程](#2.1 新建工程)
- [2.2 基础配置](#2.2 基础配置)
- [2.3 ADC 配置](#2.3 ADC 配置)
- [2.4 时钟与项目配置](#2.4 时钟与项目配置)
- [3. STM32CubeIDE 编程和调试](#3. STM32CubeIDE 编程和调试)
-
- [3.1 编程和调试](#3.1 编程和调试)
- [3.2 上位机显示波形](#3.2 上位机显示波形)
- [4. 小结](#4. 小结)
1. 项目简介
在嵌入式系统中,模拟信号的采集与输出是连接物理世界与数字处理系统的关键环节。ADC(模数转换器) 是连接物理世界与数字系统的入口。无论是电压、电流、温度,还是电位器、传感器信号,最终都需要通过 ADC 转换为可处理的数字量。
ADC 的核心作用是把外部模拟电压转换为 MCU 能处理的数字量,并保证采样精度与时间一致性。掌握 ADC 的采样时间、分辨率、触发模式和读取方式,是实现采集链路的基础。
1.1 实验目标
本次实验旨在掌握STM32G4系列微控制器的ADC(模数转换器)模块的实际应用。我们将以NUCLEO-STM32G431RB开发板为硬件平台,实现模拟电压信号的采集、转换与显示功能。
本文将介绍如何在 CubeMX 中配置 ADC 参数,如何正确进行数值映射与转换,并最终通过上位机观察输入电压的变化。具体目标包括:
- 硬件配置:正确配置STM32G431的ADC模块,特别是连接至PC2引脚的ADC1_IN3通道,用于采集板载蓝色电位器的电压信号。
- 软件实现:编写ADC初始化、采样控制、数据转换等核心代码,将ADC原始数字值转换为实际的电压值(0-3.3V范围)。
- 数据可视化:通过两种方式展示采集结果:一是使用示波器直接观察ADC输出波形,二是通过USART串口通信将电压数据发送到上位机软件进行实时显示。
- 性能评估:测试ADC的采样速率、分辨率和精度等关键性能指标,为后续的传感器数据采集、信号监测等应用奠定基础。
通过这个完整的ADC数据采集系统,我们将理解 STM32G431 中模拟信号处理的全过程。
1.2 ADC 的原理和架构
ADC(Analog-to-Digital Converter,模数转换器)用于将连续的模拟电压转换为离散的数字量,是 MCU 采集外部信号的核心外设。
STM32 ADC 基于逐次逼近寄存器(SAR) 架构,基本原理是通过内部数模转换器(DAC) 与比较器的逐次比较,逐步逼近输入模拟电压的数值,最终输出对应的数字编码。
STM32G431 集成多路 12 位高速 ADC模块,支持12位、10位、8位和6位可选分辨率,最高可达4Msps的采样率(在160MHz系统时钟下),最多支持19个外部通道和3个内部通道(温度传感器、内部参考电压等)。
工作原理:
- 采样保持
ADC 通过采样开关对输入的模拟电压进行采样,采样完成后,采样开关断开,采样电容会保持该电压一段时间,供后续比较使用。采样时间可通过寄存器配置,以适配不同输入阻抗的信号源。 - 逐次比较
(1)SAR 寄存器从最高位(MSB)开始,依次设置每一位的数值,并将其送入内部 DAC,DAC 输出对应的参考电压 VDAC。
(2)比较器将采样保持的模拟电压 VIN 与 VDAC 进行比较:若 VIN≥VDAC,则保留当前位的 "1";若 VIN<VDAC,则将当前位清零。
(3)从最高位到最低位(LSB)依次完成上述比较,最终 SAR 寄存器中的数值就是模拟电压对应的数字量。 - 结果输出
比较完成后,数字结果会被存入 ADC 的数据寄存器(ADC_DR),同时触发相应的中断或 DMA 请求(若开启),供 MCU 读取。
工作模式:
- 单次转换模式(Single Conversion Mode)
每次触发完成一次转换。ADC在收到触发信号后,仅执行一次完整的转换过程,完成后自动停止,等待下一次触发。工作流程如下。
bash
触发信号 → 启动转换 → 完成一次转换 → 产生EOC中断 → 进入停止状态
- 连续转换模式(Continuous Conversion Mode)
自动连续进行转换。ADC启动后连续不断地进行转换,前一次转换完成后立即开始下一次转换,形成连续的数据流。工作流程如下。
bash
首次触发 → 转换1 → 转换2 → 转换3 → ... → 持续转换
↑ ↑ ↑
EOC中断 EOC中断 EOC中断
- 扫描模式(Scan Mode)
自动按顺序转换多个通道。ADC按照预设的顺序自动转换多个通道,每个通道可独立配置采样时间。工作流程如下。
bash
触发 → 转换通道1 → 转换通道2 → ... → 转换通道N → 完成所有通道 → EOC中断
- 不连续转换模式(Discontinuous Conversion Mode)
在扫描模式下,每次触发只转换指定数量的通道,而不是全部通道。工作流程如下。
bash
触发1 → 转换通道1-3 → EOC中断
触发2 → 转换通道4-6 → EOC中断
...
- 注入转换模式(Injected Conversion Mode)
可以打断规则通道转换的紧急通道。注入通道具有比规则通道更高的优先级,可以在规则序列转换过程中打断并执行注入转换,完成后恢复规则序列。
1.3 软硬件准备
硬件资源:
NUCLEO-G431RB 开发板:内置 STM32G431 具有高速 12 位 ADC、12 位 DAC 以及丰富的模拟外设资源,是本实验的核心平台。
Nucleo-G431RB 开发板通过其USB端口(Micro-USB)连接到PC。
Nucleo-G431RB 开发板上没有板载旋钮,堆叠插接 X-NUCLEO-IHM16M1 电机驱动扩展板 后,PC2 引脚连接到 NUCLEO-IHM16M1 驱动板上的板载旋钮电位器。
软件资源:
STM32CubeMX, STM32CubeIDE,VOFA+ 串口调试工具
2. CubeMX 工程创建与配置
2.1 新建工程
- 启动 STM 32CubeMX并选择芯片
(1)打开 STM32CubeMX。
(2)选择 New Project(或Ctrl-N快捷键)新建工程,进入 New Project 界面。
(3)选择 MCU 为 STM32G431RBT6(参考开发板的 MCU 型号选择)。
(4)双击芯片图标或点击"Start Project",创建新工程。

2.2 基础配置
工程创建后,进入主配置界面。
- 系统配置:在引脚配置(Pinout & Configuration)中,选择 "System Core -- SYS" 。
(1)设置调试器类型,将 Debug 模式设为 "Serial Wire"。
(2)设置基础时钟源(Timebase Source),可以选择默认设置 "SysTick"。

-
时钟配置:在引脚配置(Pinout & Configuration)中,选择 "System Core -- RCC" 配置时钟模式。
设置高速时钟为外部晶振,将 High Speed Clock (HSE) 设为 "Crystal/Ceramic Resonator"。
Low Speed Clock (LSE) 设为 "Disable"(本实验不需要)。
-
GPIO 配置。
(1)将 LD2(PA5)配置为输出模式 "GPIO_Output"。
(2)将用户按键(PC13)配置为外部中断 "GPIO_EXTI13"。
-
配置设置虚拟串口(LPUART)
如需要使用串口发送 ADC/DAC 数据到 PC 来显示波形:启用 LPUART1,模式设为 Asynchronous;波特率设置为 115200;引脚使用默认的 PA2(TX)/PA3(RX),连接到 Nucleo 板上的 ST-LINK 虚拟串口。
用于高频率发送数据到上位机或更新波形时,可以考虑为 LPUART1_TX 分配 DMA 通道。
2.3 ADC 配置
- 启用并配置 ADC 通道
(1)选择 "引脚配置(Pinout & Configuration)",从左侧下拉列表中选择 "Analog -- ADC1" ,使用 IN8(PC2) 作为模拟输入通道,将 IN8 设置为 "IN8 Singel-ended"。
(2)开启独立通道 IN8,设置为 "IN1 Single-ended"。
(3)在 Pinout view 视图中,将 PC2 引脚配置为 "ADC1_IN8"。PC2 引脚颜色变为绿色,表示已配置为模拟输入模式。

- 配置 ADC 工作模式和参数。
bash
ADCs_Common_Settings
Mode: Independent mode
ADC_Settings
Clock Prescaler: Asynchronous clock mode divided by 4
Resolution: ADC 12-bit resolution
Data Alignment: Right alignment(右对齐)
Gain Compensation: 0
Scan Conversion Mode:Disable
End of Conversion Selection:End of single of conversion
Continuous Conversion Mode: Disable
DMA Continuous Requests: Disabled
ADC_Regular_ConversionMode:
Number of Conversion: 1
External Trigger Conversion Source: Regular Conversion launched by software
Rank 1:
Channel: Channel 8
Smapling Time: 24.5 Cycles
Offset Number: No offset
youcans@qq.com
添加 DMA 通道:
- 在 ADC1 的 DMA Settings 中添加一个 DMA 通道。
bash
Add DMA Request:ADC1
Mode:Circular
Data Width:Half Word(16-bit)
2.4 时钟与项目配置
- 配置系统时钟树。
(1)点击顶部 "Clock Configuration" 选项卡,进入时钟树配置。
(2)设置输入频率 Input frequency=24 MHz,SysCLK frequency=160 MHz。
配置完成后,System Clock 显示为160MHz,HCLK、PCLK1、PCLK2 均为160MHz。
bash
Input frequency: 24 MHz (HSE)
SysCLK frequency: 160 MHz (HSE)
System Clock Mux: PLLCLK
AHB Prescaler: 1 (不分频)
APB1 Prescaler: 1
APB2 Prescaler: 1
- 工程管理配置。
(1)点击 "Project Manager"→ "Project",输入项目名称 "STM32G431_ADC01"。。
(2)点击 "Project Manager"→ "Code Generator",设置如下。
bash
Project:
- Project Name: STM32G431_ADC01
- Toolchain/IDE: STM32CubeIDE
Code Generator:
√ Generate peripheral initialization as a pair of '.c/.h'
√ Keep User Code when re-generating
√ Backup previously generated files
youcans@qq.com
- 生成代码。
(1)点击右上角"GENERATE CODE"按钮,将自动由工程文件 "STM32G431_ADC01.ioc" 生成初始代码。
(2)生成初始代码完成后,弹出代码生成提示窗口,点击 "Open Project" 直接进入 STM32CubeIDE 并打开代码。

3. STM32CubeIDE 编程和调试
3.1 编程和调试
-
在 STM32CubeIDE 打开 "STM32G431_ADC01" 项目。
代码生成后,打开STM32G431_ADC01 项目。在 "Core\Src" 目录中,已经生成了 adc.c, main.c 等基础程序。
-
从 "Core\Src" 目录打开程序文件 adc.c,检查 CubeMX 生成的 ADC 配置。
c
/* ADC1 init function */
void MX_ADC1_Init(void)
{
ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/* Common config */
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.GainCompensation = 0;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/* Configure the ADC multi-mode */
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
Error_Handler();
}
/* Configure Regular Channel */
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_24CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
- 修改 main.c 代码。
(1)从 "Core\Src" 目录打开程序文件 main.c,如下图所示。
(2)在 main.c 程序开头的用户代码引用区包含需要的头文件。
c
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
(3)变量定义。为兼容与上位机进行多通道数据传输,按 3 通道定义串口发送的数据结构。
c
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
// 用户变量 youcans@qq.com
uint16_t adc_raw = 0; // ADC原始值
//float Vknob = 0.0f; // ADC测量电压
// 串口发送缓冲区
// DMA Transmission Buffer: 3 Channels of float = 12 Bytes
typedef union {
float f;
uint8_t b[4];
} FloatBytes;
// One frame of data: 3 channels of float + 4-byte frame tail = 4*4 = 16 bytes
FloatBytes frame[4]; // frame[0]~[2] = 3 waveform channels; frame[3] = frame tail
volatile uint8_t txReady = 1; // 1 = New DMA transmission can be initiated; 0 = Transmission in progress
/* USER CODE END PV */
(4)轮询程序 while(1) 代码如下。
c
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// ADC 采样
HAL_ADC_Start(&hadc1); // 启动ADC单次转换
HAL_ADC_PollForConversion(&hadc1, 10); // 轮询等待ADC转换完成
adc_raw = HAL_ADC_GetValue(&hadc1); // 读取ADC转换结果
// Vknob = adc_raw * 3.3f / 4095.0f; // 计算ADC测量电压(0-3.3V)
// Update the transmission
float Vch1 = adc_raw * 3.3f / 4095.0f;
float Vch2 = 0.0f;
float Vch3 = 3.3f;
// New DMA transmission can only be initiated after the previous one is completed
if (txReady)
{
txReady = 0;
frame[0].f = Vch1; // VOFA+CH1
frame[1].f = Vch2; // VOFA+CH2
frame[2].f = Vch3; // VOFA+CH3
// The frame tail at frame[3] is a fixed value
// A total of 4 floats (3 channels of data + 1 frame tail), 16 bytes in total.
HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)frame, 4 * sizeof(float));
}
HAL_Delay(10); // 1ms
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); // LD2_Pin
}

- 程序编辑、编译与调试
(1)硬件连接
用 USB连接线,连接 PC 与 NUCLEO-G431RB 开发板。
(2)软件调试- 点击工具栏中 "Build Debug" 按键对程序代码进行编译。
- 点击工具栏中 "Debug" 按键,将程序下载烧录到目标板 NUCLEO-G431RB 。
- 点击工具栏中 "Resume" 按键 或 F8 快捷键,运行程序。
bash
09:41:52 **** Incremental Build of configuration Debug for project STM32G431_ADC01 ****
make -j20 all
arm-none-eabi-size STM32G431_ADC01.elf
text data bss dec hex filename
37004 472 2472 39948 9c0c STM32G431_ADC01.elf
youcans Finished building: default.size.stdout
09:41:52 Build Finished. 0 errors, 0 warnings. (took 188ms)
- 打开 VOFA+ 软件:
(1)点击 "数据引擎" 下拉菜单,选择 "JustFloat" 协议。
(2)点击 "数据接口" 下拉菜单,选择 "串口"。
(3)点击 "端口号" 下拉菜单,选中 STM STLink Virtual COM Port。
(4)将配置参数设为与 STM32CubeMX 中 "Connectivity -- LPUART1" 的配置一致:
bash
波特率:115200
数据位:8 Bits
校验位:None
数据流控:None
停止位:1
3.2 上位机显示波形
- 点击 VOFA+ 左上角的 "连接" 按钮,在数据显示区就将显示 HEX 格式的数据,并在上方图形区域显示 ADC 采样的波形。
调节 IHM16M1 驱动板上的板载旋钮电位器,采样波形跟随变化如下图所示。

4. 小结
通过本章实验,我们成功完成了STM32G4的ADC采样系统构建。掌握了从CubeMX工程配置到代码实现的完整流程,实现了电位器电压的精确采集与串口数据传输。
版权声明:
【动手学电机驱动】是 youcans@qq 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/157101980)
Copyright@youcans 2026
Crated:2026-1