【STM32G4-FOC】(1)STM32G431 之创建项目
【STM32G4-FOC】(2)STM32G431 之 TIM+ADC
【STM32G4-FOC】(3)STM32G431之三相互补 PWM
【STM32G4-FOC】(4)PWM 硬件触发 ADC 同步采样
【STM32G4-FOC】(5)DAC 受控输出闭环链路
【STM32G4-FOC】(2)STM32G431之 TIM+ADC
- 1. 项目简介
- 1.1 定时触发采样的重要性
- 1.2 定时器触发ADC的原理
- 2. CubeMX工程配置
- 2.1 CubeMX 工程配置
- 2.2 ADC 配置
- 2.3 TIM 配置
- 2.4 工程配置
- 3. CubeIDE 编程与调试
- 2.1 CubeIDE编程
- 2.2 编译与调试
- 4. 小结
1. 项目简介
在【动手学STM32G4】(5)STM32G431之ADC采样 中,我们介绍了STM32G4的ADC采样系统构建,实现了电位器电压的采集。
本文介绍使用定时器触发 ADC 转换,并使用 DMA 进行数据传输。通过设置定时器的触发间隔,就能实现 ADC 定时采样转换功能。
1.1 定时触发采样的重要性
在嵌入式数据采集系统中,时序精度往往决定了整个系统的性能上限。软件触发 ADC 采样方式存在诸多局限:CPU需要频繁响应中断,采样间隔受限于中断延迟,多任务环境下难以保证时间一致性。
定时触发采样通过硬件机制确保了数据采集的时间精度,实现了纳秒级的时间一致性,这对于需要严格时序控制的电机控制、音频处理等应用至关重要;同时,它将CPU从频繁的中断处理中解放出来,配合DMA大幅提升了系统效率;更重要的是,定时器能够精确协调ADC、PWM、DAC等多个外设的协同工作,为复杂嵌入式系统提供了硬件级的同步保障;在抗干扰方面,硬件触发独立于CPU执行,有效避免了软件调度带来的时序抖动,增强了系统的稳定性。
1.2 定时器触发ADC的原理
STM32G431的TIM1作为高级定时器,具备独立的时钟源和可配置的触发输出功能,能够产生精确的时间基准。当TIM1配置为触发ADC时,其工作原理如下:
定时器在计数达到预设定值后产生更新事件(UEV),这个硬件事件通过TIM1的TRGO(Trigger Output)输出,直接连接到ADC的外部触发输入。ADC检测到这个触发信号后,立即启动转换过程,无需CPU干预。这种硬件级联动确保了采样时刻的精确性和可重复性,将时间抖动控制在纳秒级别。
关键时序关系可表示为:
定时器配置: 时钟源 → PSC分频 → 计数器 → ARR重载 → 更新事件 ↓ 触发中断&触发ADC检测 ↓ ADC启动转换 → 开始转换触发延迟主要包括ADC的采样时间和转换时间,这些参数在CubeMX中可配置,为系统设计提供了灵活性和可预测性。
2. CubeMX工程配置
2.1 CubeMX 工程配置
- 新建工程。
启动 STM32CubeMX,点击 “Start New Project” (或Ctrl-N快捷键)新建工程,进入 New Project 界面。
选择MCU为 STM32G431RBT6(参考开发板的 MCU 型号选择)。
选择开发板为 NUCLEO-G431RB 开发板。
点击右上角 “Start Project” 创建项目。
- 配置系统时钟树。
(1)点击顶部 “Clock Configuration” 选项卡,进入时钟树配置。
(2)设置输入频率 Input frequency=24 MHz,SysCLK frequency=160 MHz。
配置完成后,System Clock 显示为160MHz,HCLK、PCLK1、PCLK2 均为160MHz。
Input frequency:24MHz(HSE)SysCLK frequency:160MHz(HSE)System Clock Mux: PLLCLK AHB Prescaler:1(不分频)APB1 Prescaler:1APB2 Prescaler:1系统配置:在引脚配置(Pinout & Configuration)中,选择 “System Core – SYS” 。
(1)设置调试器类型,将 Debug 模式设为 “Serial Wire”。
(2)设置基础时钟源(Timebase Source),可以选择默认设置 “SysTick”。
(3)时钟配置:在引脚配置(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.2 ADC 配置
Nucleo-G431RB 开发板上没有板载旋钮,堆叠插接 X-NUCLEO-IHM16M1 电机驱动扩展板 后,PC2 引脚连接到 NUCLEO-IHM16M1 驱动板上的板载旋钮电位器。
- 启用并配置 ADC 通道
(1)选择 “引脚配置(Pinout & Configuration)”,从左侧下拉列表中选择 “Analog – ADC1” ,使用 IN8(PC2) 作为模拟输入通道,将 IN8 设置为 “IN8 Singel-ended”。
(2)开启独立通道 IN8,设置为 “IN1 Single-ended”。
(3)在 Pinout view 视图中,将 PC2 引脚配置为 “ADC1_IN8”。PC2 引脚颜色变为绿色,表示已配置为模拟输入模式。
(4)在 NVIC 设置中为 ADC1 启用中断,以便在回调函数中 ADC 转换结束时可以切换 GPIO。
(5)配置 ADC 工作模式和参数,注意触发源配置为 Timer 1 定时器触发。
ADCs_Common_Settings Mode: Independent mode ADC_Settings Clock Prescaler: Asynchronous clock mode divided by4Resolution: ADC12-bit resolution Data Alignment: Right alignment(右对齐) Gain Compensation:0Scan 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:1External Trigger Conversion Source: Timer1Trigger Out event External Trigger Conversion Edge: Trigger detection on the rising edge Rank1: Channel: Channel8Smapling Time:24.5Cycles Offset Number: No offset youcans@qq.com2.3 TIM 配置
配置定时器 TIM1 中断频率为 1kHz。
计算预分频器(PSC)
TIM1 挂载在APB1总线,时钟频率 = 160MHz。
所需中断频率 = 1kHz。考虑ARR通常设为较小值以获得高分辨率,选择 PSC = 159,分频后频率 = 160MHz / (159+1) = 160MHz / 160 = 1000kHz。
计算自动重载值(ARR):
中断频率 = 分频后频率 / (ARR+1)
ARR = (分频后频率 / 中断频率) - 1 = (1000kHz / 1kHz) - 1 = 1000 - 1 = 999
| 参数 | 设置值 | 说明 |
|---|---|---|
| Clock Source | Internal Clock | 使用内部时钟源 |
| Prescaler (PSC) | 159 | 预分频值 |
| Counter Mode | Up | 向上计数模式 |
| Counter Period (ARR) | 999 | 自动重载值 |
| auto-reload preload | Disabled | 禁用自动重载预装载 |
| Trigger Event Selection | Update Event | 选择更新事件作为触发输出 |
- 启用并配置TIM1 :
(1)选择 “引脚配置(Pinout & Configuration)”,从左侧下拉列表中选择 “Timers – TIM1 – TIM1 Mode and Configuration ” ,将通道1 配置为生成但不输出 PWM: “PWM Generation No Output”,用于定时器内部触发 ADC。
2.4 工程配置
- 工程管理配置。
(1)点击 "Project Manager"→ “Project”,输入项目名称 “STM32G431_ADC02”。。
(2)点击 "Project Manager"→ “Code Generator”,设置如下。
Project: - Project Name: STM32G431_ADC02 - 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_ADC02.ioc” 生成初始代码。
(2)生成初始代码完成后,弹出代码生成提示窗口,点击 “Open Project” 直接进入 STM32CubeIDE 并打开代码。
3. CubeIDE 编程与调试
2.1 CubeIDE编程
在 STM32CubeIDE 打开代码文件 main.c。
代码生成后,已经自动进入 STM32CubeIDE,并打开创建的 STM32G431_DAC01 项目。在 “Core\Src” 目录中,已经生成了 dac.c 和 main.c 等基础程序。程序 main.c 的架构如下:
main.c ├── 系统初始化 │ ├── 系统时钟配置(160MHz) │ ├── GPIO初始化 │ ├── TIM1初始化 │ └── ADC1初始化 ├── 主程序 │ ├── ADC校准 │ ├── 启动ADC中断模式 │ ├── 启动TIM1 PWM输出 │ ├── 配置TIM1 主从模式 │ └── 主循环 │ └── 串口输出 ADC 数据(可选) └── 中断服务 └──HAL_ADC_ConvCpltCallback()├── 读取ADC转换值 ├── 更新转换计数器 └── 每10次转换切换LED(可选) youcans@qq.com- 生成代码并添加变量:
/* USER CODE BEGIN PV */// 用户变量volatileuint16_tadc_raw=0;// ADC 转换原值volatileuint16_tadc_count=0;// ADC 转换计数/*USER CODE END PV*/- 主函数初始化后添加代码:
/* USER CODE BEGIN 2 */// 校准ADC(youcans@qq.com)if(HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED)!=HAL_OK)Error_Handler();// 使能 ADC 中断if(HAL_ADC_Start_IT(&hadc1)!=HAL_OK)Error_Handler();// 启动 TIM1 CH1 的 PWM 输出(用于触发ADC)if(HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1)!=HAL_OK)Error_Handler();- 添加ADC转换完成回调函数:
voidHAL_ADC_ConvCpltCallback(ADC_HandleTypeDef*hadc){if(hadc->Instance==ADC1){// 获取ADC转换值(youcans@qq.com)adc_raw=HAL_ADC_GetValue(&hadc1);adc_count++;// 每10次转换切换一次LED(便于观察)if(adc_count==10){HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);adc_count=0;}}}- 添加串口调试功能:
/* Infinite loop youcans@qq.com*//* USER CODE BEGIN WHILE */while(1){// Update the transmissionfloatVch1=adc_raw*3.3f/4095.0f;floatVch2=0;// low levelfloatVch3=3.3;// high level// New DMA transmission can only be initiated after the previous one is completedif(txReady){txReady=0;frame[0].f=Vch1;// VOFA+CH1frame[1].f=Vch2;// VOFA+CH2frame[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(1);// 1ms}2.2 编译与调试
程序编辑、编译与调试:
点击工具栏中 “Build Debug” 按键对程序代码进行编译。
点击工具栏中 “Debug” 按键,将程序下载烧录到目标板 NUCLEO-G431RB 。
点击工具栏中 “Resume” 按键 或 F8 快捷键,运行程序。频率验证:用示波器测量PA5(LD2)引脚,看到 50Hz方波,如下图所示。
TIM1 中断频率为 1kHz,LED 每10次转换(10ms)切换一次,因此 LED 的闪烁周期为 50Hz。这说明 采样频率精确控制为1kHz。
- 采样结果验证:
板载电位器连接到 PC2 (ADC1_IN8),提供0-3.3V模拟电压。旋转板载电位器,通过串口查看 ADC 值变化,如下图所示。
AD 转换的最小值为 0 ,最大值为 3.3,输出波形随电位器而变化,说明 AD 采样正常。
4. 小结
本实验成功实现了基于STM32G431的定时器触发ADC周期性采样系统。通过配置TIM2定时器产生精确的1kHz触发信号,驱动ADC1对板载电位器电压进行周期性采样,并在每次转换完成后通过中断回调函数处理数据,同时利用LED的50Hz方波输出直观验证系统运行状态。
本实验不仅实现了基本的ADC采样功能,更重要的是构建了一个可扩展、可验证、高可靠性的数据采集框架。通过严格的时序控制和中断管理,为后续更复杂的嵌入式应用开发奠定了坚实基础。
版权声明:
【动手学电机驱动】是 youcans@qq 原创作品,转载必须标注原文链接:【STM32G4-FOC】(2)STM32G431之 TIM+ADC(https://blog.csdn.net/youcans/article/details/157174163)
Copyright@youcans 2026
Crated:2026-1