|
#include "arm_math.h"
#include "stm32h7xx_hal.h"
#define FFT_SIZE 1024 // FFT 输入数组的大小
float32_t input[FFT_SIZE];
float32_t output[FFT_SIZE];
arm_cfft_instance_f32 fft_instance;
TIM_HandleTypeDef htim2;
ADC_HandleTypeDef hadc1;
void ADC_Init(void) {
ADC_ChannelConfTypeDef sConfig = {0};
__HAL_RCC_ADC12_CLK_ENABLE(); // 使能 ADC 时钟
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
HAL_ADC_Init(&hadc1);
sConfig.Channel = ADC_CHANNEL_10; // 选择通道 10
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; // 设置采样时间
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}
uint32_t Read_ADC_Value(void) {
uint32_t adc_value = 0;
HAL_ADC_Start(&hadc1); // 启动 ADC
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); // 等待转换完成
adc_value = HAL_ADC_GetValue(&hadc1); // 获取 ADC 值
HAL_ADC_Stop(&hadc1); // 停止 ADC
return adc_value;
}
void TIM_Init(void) {
__HAL_RCC_TIM2_CLK_ENABLE(); // 使能 TIM2 时钟
htim2.Instance = TIM2;
htim2.Init.Prescaler = 7999; // 对应 1kHz
htim2.Init.Period = 999; // 对应 1ms
htim2.Init.CounterMode = TIM_COUNTERMODE_UP; // 向上计数
HAL_TIM_Base_Init(&htim2); // 初始化定时器
HAL_TIM_Base_Start_IT(&htim2); // 启动定时器中断
}
void FFT_Init(void) {
arm_cfft_init_f32(&fft_instance, FFT_SIZE); // 初始化 FFT 实例
}
void Perform_FFT(void) {
arm_cfft_f32(&fft_instance, input, 0, 1); // 执行 FFT
arm_cmplx_mag_f32(input, output, FFT_SIZE); // 计算幅度
}
void Display_Frequency(void) {
float max_value = output[0];
uint32_t max_index = 0;
for (uint32_t i = 1; i < FFT_SIZE / 2; i++) {
if (output[i] > max_value) {
max_value = output[i];
max_index = i;
}
}
if (max_index > 10) {
HAL_GPIO_WritePin(GPIOO, GPIO_PIN_5, GPIO_PIN_SET); // 点亮 LED
} else {
HAL_GPIO_WritePin(GPIOO, GPIO_PIN_5, GPIO_PIN_RESET); // 熄灭 LED
}
}
int main(void) {
HAL_Init();
SystemClock_Config();
ADC_Init();
TIM_Init();
FFT_Init();
while (1) {
UART_Send_Data(corrected_value);
}
}
// 定时器溢出回调
void HAL_TIM_PERIOD_ELAPSED_CALLBACK(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM2) {
// 每次定时器溢出时读取 ADC 值
uint32_t adc_value = Read_ADC_Value(); // 获取 ADC 值
static uint32_t sample_index = 0;
input[sample_index] = (float32_t)adc_value; // 存储到 FFT 输入数组
sample_index++;
// 如果达到 FFT_SIZE 大小,则进行 FFT 计算
if (sample_index >= FFT_SIZE) {
sample_index = 0; // 重置索引
Perform_FFT();
Display_Frequency();
}
}
}