stm32f4hal库adc
时间: 2025-05-11 20:25:49 浏览: 22
### STM32F4 HAL库 ADC 使用教程与示例代码
#### 1. 中断方式下的ADC使用
在STM32F4系列微控制器中,当使用HAL库配置ADC时,可以通过中断方式进行数据采集。以下是基于中断模式的ADC初始化和处理逻辑。
```c
#include "stm32f4xx_hal.h"
void MX_ADC_Init(void) {
ADC_HandleTypeDef hadc;
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */
hadc.Instance = ADC1;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; // 设置时钟分频
hadc.Init.Resolution = ADC_RESOLUTION_12B; // 设置分辨率为12位
hadc.Init.ScanConvMode = DISABLE; // 单次转换模式
hadc.Init.ContinuousConvMode = ENABLE; // 连续转换模式
hadc.Init.DiscontinuousConvMode = DISABLE; // 不启用不连续模式
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; // 外部触发禁用
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 数据右对齐
hadc.Init.NbrOfConversion = 1; // 转换次数为1
hadc.Init.DMAContinuousRequests = DISABLE; // 禁用DMA请求
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; // 结束标志选择单次转换结束
if (HAL_ADC_Init(&hadc) != HAL_OK) { // 初始化ADC
Error_Handler();
}
// 配置通道
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_0; // 选择通道0
sConfig.Rank = 1; // 排序等级为1
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; // 采样时间为3个周期
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) {
Error_Handler(); // 错误处理函数
}
}
// 中断服务程序
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {
static uint16_t adc_value;
adc_value = HAL_ADC_GetValue(hadc); // 获取ADC值
}
```
上述代码展示了如何通过HAL库初始化ADC模块,并设置其工作于中断模式下[^1]。`HAL_ADC_ConvCpltCallback()` 函数会在每次转换完成后调用,从而获取最新的ADC数值。
---
#### 2. DMA方式下的ADC使用
对于高精度或高频应用场合,推荐采用DMA传输机制来提高效率。以下是一个完整的DMA配合ADC使用的例子:
```c
#include "stm32f4xx_hal.h"
#define BUFFER_SIZE 2048
static uint16_t aADCxConvertedData[BUFFER_SIZE]; // 定义存储ADC采样的缓冲区
void MX_DMA_Init(void) {
__HAL_RCC_DMA2_CLK_ENABLE();
HDMA_ADC1.Instance = DMA2_Stream0; // 配置DMA流
HDMA_ADC1.Init.Channel = DMA_CHANNEL_0; // 配置DMA通道
HDMA_ADC1.Init.Direction = DMA_PERIPH_TO_MEMORY;// 方向:外设到内存
HDMA_ADC1.Init.PeriphInc = DMA_PINC_DISABLE; // 禁用外设地址自增
HDMA_ADC1.Init.MemInc = DMA_MINC_ENABLE; // 启用内存地址自增
HDMA_ADC1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; // 对齐半字节
HDMA_ADC1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; // 对齐半字节
HDMA_ADC1.Init.Mode = DMA_CIRCULAR; // 循环模式
HDMA_ADC1.Init.Priority = DMA_PRIORITY_HIGH; // 高优先级
if (HAL_DMA_Init(&HDMA_ADC1) != HAL_OK) {
Error_Handler();
}
__HAL_LINKDMA(&hadc, DMA_Handle, HDMA_ADC1);
}
void MX_ADC_Init(void) {
ADC_HandleTypeDef hadc;
hadc.Instance = ADC1;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.ScanConvMode = ENABLE; // 开启扫描模式
hadc.Init.ContinuousConvMode = ENABLE; // 开启连续转换模式
hadc.Init.DMAContinuousRequests = ENABLE; // 开启DMA持续请求
hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV; // 序列转换结束后产生EOC信号
if (HAL_ADC_Init(&hadc) != HAL_OK) {
Error_Handler();
}
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) {
Error_Handler();
}
}
int main(void) {
HAL_Init();
SystemClock_Config();
MX_DMA_Init();
MX_ADC_Init();
HAL_ADC_Start_DMA(&hadc, (uint32_t*)aADCxConvertedData, BUFFER_SIZE);
while (1) {}
}
```
此部分代码实现了利用DMA技术高效地将ADC采样数据写入指定缓冲区内存的操作[^3]。这种方式特别适合需要大量快速采集的应用场景。
---
#### 3. FFT分析中的ADC使用案例
如果目标是对输入信号执行傅里叶变换(FFT),则可以结合ADC、DMA以及DSP功能实现复杂的数据处理流程。下面给出一个简单的框架说明:
```c
#include "arm_math.h"
#include "arm_const_structs.h"
float32_t inputSignal[FFT_SIZE];
float32_t fftOutput[FFT_SIZE / 2];
void Process_FFT(uint16_t *buffer) {
arm_rfft_fast_instance_f32 S;
arm_rfft_init_fast_f32(&S, FFT_SIZE, 0); // 初始化RFFT实例
arm_float_to_q15((q7_t *)inputSignal, buffer, FFT_SIZE); // 将原始数据转化为浮点数形式
arm_cfft_radix4_f32(&S, inputSignal, IFftFlag, BitReverseFlag); // 执行离散傅立叶变换
arm_cmplx_mag_f32(inputSignal, fftOutput, FFT_SIZE / 2); // 计算幅值谱
}
```
以上片段演示了如何借助CMSIS-DSP库完成从ADC采样至最终频率域表示的过程[^2]。
---
阅读全文
相关推荐


















