但是这里有一个很严重的问题,想让DAC完整的输出这个信号并不容易,因为DAC只能输出整周期的信号。在这里博主也是卡了比较,最后才想到用FFT将这个学习后输出的信号分解为幅频和相频后,再使用傅里叶级数将这个信号重新合成为一个周期的信号,再用DAC输出出来。
//--------------------------------------------------------- 进阶部分2 ---------------------------------------------------------//
// ADC1 用来接收外部信号,获得频率等信息后,进行DAC输出
__attribute__((section (".RAM_SDRAM"))) float32_t up2_adc1_float_data[ADC_SAMPLE_LENGTH]; // 浮点数据
__attribute__((section (".RAM_SDRAM"))) float32_t up2_adc1_fft_input[MAX_FFT_N * 2]; // fft 输入数组(原始输出)
__attribute__((section (".RAM_SDRAM"))) float32_t up2_adc1_fft_output[MAX_FFT_N]; // fft输出数组
float32_t up2_adc1_DC_part;
float32_t up2_adc1_base_freq;
float32_t up2_adc1_base_amp;
float32_t up2_adc1_base_phase;
// ADC2 用来接收DAC反馈信号,进行锁相
__attribute__((section (".RAM_SDRAM"))) float32_t up2_adc2_float_data[ADC_SAMPLE_LENGTH]; // 浮点数据
__attribute__((section (".RAM_SDRAM"))) float32_t up2_adc2_fft_input[MAX_FFT_N * 2]; // fft 输入数组(原始输出)
__attribute__((section (".RAM_SDRAM"))) float32_t up2_adc2_fft_output[MAX_FFT_N]; // fft输出数组
float32_t up2_adc2_DC_part;
float32_t up2_adc2_base_freq;
float32_t up2_adc2_base_phase;
// fir
uint32_t up2_adc1_fir_index;
float32_t up2_fir_output[ADC_SAMPLE_LENGTH];
float32_t up2_fit_dc_part;
float32_t up2_fir_window[ADC_SAMPLE_LENGTH];
__attribute__((section (".RAM_SDRAM"))) float32_t up2_fir_fft_intput[MAX_FFT_N * 2];
__attribute__((section (".RAM_SDRAM"))) float32_t up2_fir_fft_output[MAX_FFT_N];
float32_t up2_fir_output_base_amp;
float32_t up2_fir_output_base_freq;
float32_t up2_fir_output_last_base_freq;
//波形标志
volatile uint8_t wave_falg;
volatile uint8_t lase_wave_falg;
uint16_t up2_dac_wave[DAC_WAVE_LENGTH];
// 三角波
uint32_t sanjiaobo_index;
float32_t sanjiaobo_amp[10];
float32_t sanjiaobo_phase[10];
// 方波
uint32_t fangbo_index;
float32_t fangbo_amp[10];
float32_t fangbo_phase[10];
// 占空比波
uint32_t zhankong_index;
float32_t zhankong_amp[20];
float32_t zhankong_phase[20];
// DAC信号频率 = 触发时钟频率 / DAC周期点数
static uint16_t dac_buffer_output[DAC_WAVE_LENGTH];
void up2_adc12_opration(void)
{
if (adc_ch[0].conv_end_flag == 1 && adc_ch[1].conv_end_flag == 1) {
adc_ch[0].conv_end_flag = 0;
adc_ch[1].conv_end_flag = 0;
// 浮点数据转换
for (uint32_t i = 0; i < ADC_SAMPLE_LENGTH; i++) {
up2_adc1_float_data[i] = (float32_t)adc_ch[0].adc_buf[i];
up2_adc2_float_data[i] = (float32_t)adc_ch[1].adc_buf[i];
}
// 去直流
remove_dc_part(up2_adc1_float_data, &up2_adc1_DC_part, ADC_SAMPLE_LENGTH);
remove_dc_part(up2_adc2_float_data, &up2_adc2_DC_part, ADC_SAMPLE_LENGTH);
// FFT处理
inf_fft_with_mag_norm_f32(up2_adc1_float_data, up2_adc1_fft_input, up2_adc1_fft_output, MAX_FFT_N);
inf_fft_with_mag_norm_f32(up2_adc2_float_data, up2_adc2_fft_input, up2_adc2_fft_output, MAX_FFT_N);
// 频率测量
up2_adc1_base_freq = find_fft_freq_amp(up2_adc1_fft_output, FREQ, ADC_SAMPLE_RATE, MAX_FFT_N);
up2_adc2_base_freq = find_fft_freq_amp(up2_adc2_fft_output, FREQ, ADC_SAMPLE_RATE, MAX_FFT_N);
// 幅值测量
up2_adc1_base_amp = find_fft_freq_amp(up2_adc1_fft_output, AMP, ADC_SAMPLE_RATE, MAX_FFT_N);
// 相位测量
up2_adc1_base_phase = find_phase_f32(up2_adc1_fft_input, up2_adc1_fft_output, MAX_FFT_N);
up2_adc2_base_phase = find_phase_f32(up2_adc2_fft_input, up2_adc2_fft_output, MAX_FFT_N);
printf ("up2_adc1_base_amp = %f V\r\n", up2_adc1_base_amp);
// 正弦波
if (up2_adc1_base_amp > 0.99f && up2_adc1_base_amp < 1.013f) {
wave_falg = 1;
up2_adc1_fir_index = (uint32_t)((up2_adc1_base_freq - 1000.0f) / 200.0f);
fir_fliter_function(up2_adc1_float_data, up2_fir_output, ADC_SAMPLE_LENGTH, LMS_NUM_TAPS, &up1_save_fir_Coeffs32[up2_adc1_fir_index][LMS_NUM_TAPS]);
flat_top_window(up2_fir_output, up2_fir_window, ADC_SAMPLE_LENGTH);
// fir fft运算
inf_fft_with_mag_norm_f32(up2_fir_output, up2_fir_fft_intput, up2_fir_fft_output, MAX_FFT_N);
up2_fir_output_base_amp = find_fft_freq_amp(up2_fir_fft_output, AMP, ADC_SAMPLE_RATE, MAX_FFT_N);
up2_fir_output_base_freq = find_fft_freq_amp(up2_fir_fft_output, FREQ, ADC_SAMPLE_RATE, MAX_FFT_N);
if (up2_fir_output_last_base_freq != up2_fir_output_base_freq || lase_wave_falg != wave_falg) {
memset(up2_dac_wave,0,sizeof(up2_dac_wave));
for (int i = 0; i < MAX_FFT_N / 2;i++) {
printf ("%f, %f\r\n", up2_fir_output[i] * ZOOM, up2_fir_fft_output[i]);
}
Set_Current_USART(USART1_IDX);
printf ("正弦波基波幅值 = %f V\r\n", up2_fir_output_base_amp);
printf ("正弦波基波频率 = %f Hz\r\n", up2_fir_output_base_freq);
printf ("\r\n");
set_dac_freq(up2_adc1_base_freq);
for (uint16_t i = 0; i < DAC_WAVE_LENGTH; i++) {
up2_dac_wave[i] = (uint32_t)(0.961538f * (up2_fir_output_base_amp * 2.0f) * 2047.0f / 3.246f * (sin(2.0f * PI * i / DAC_WAVE_LENGTH) + 1.5f));
}
// dac输出
HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, (uint32_t*)up2_dac_wave, DAC_WAVE_LENGTH, DAC_ALIGN_12B_R);
}
up2_fir_output_last_base_freq = up2_fir_output_base_freq;
}
// 三角波
else if (up2_adc1_base_amp < 0.85f && up2_adc1_base_amp > 0.800f) {
wave_falg = 2;
up2_adc1_fir_index = (uint32_t)((up2_adc1_base_freq - 1000.0f) / 200.0f);
fir_fliter_function(up2_adc1_float_data, up2_fir_output, ADC_SAMPLE_LENGTH, LMS_NUM_TAPS, &up1_save_fir_Coeffs32[up2_adc1_fir_index][LMS_NUM_TAPS]);
flat_top_window(up2_fir_output, up2_fir_window, ADC_SAMPLE_LENGTH);
// fft
inf_fft_with_mag_norm_f32(up2_fir_output, up2_fir_fft_intput, up2_fir_fft_output, MAX_FFT_N);
up2_fir_output_base_amp = find_fft_freq_amp(up2_fir_fft_output, AMP, ADC_SAMPLE_RATE, MAX_FFT_N);
sanjiaobo_index = find_fft_freq_amp(up2_fir_fft_output, INDEX, ADC_SAMPLE_RATE, MAX_FFT_N);
up2_fir_output_base_freq = find_fft_freq_amp(up2_fir_fft_output, FREQ, ADC_SAMPLE_RATE, MAX_FFT_N);
if (up2_fir_output_last_base_freq != up2_fir_output_base_freq || lase_wave_falg != wave_falg) {
memset(up2_dac_wave, 0, sizeof(up2_dac_wave));
Set_Current_USART(USART1_IDX);
for (int i = 0; i < MAX_FFT_N / 2;i++) {
printf ("%f, %f\r\n", up2_fir_output[i] * ZOOM, up2_fir_fft_output[i]);
}
printf ("三角波基波幅值 = %f V\r\n", up2_fir_output_base_amp);
printf ("三角波基波频率 = %f Hz\r\n", up2_fir_output_base_freq);
printf ("\r\n");
// 谐波幅值
sanjiaobo_amp[0] = up2_fir_output_base_amp;
for (int i = 1; i < 10; i ++) {
// 幅值、相位
sanjiaobo_phase[i] = atan2f(up2_fir_fft_intput[2 * sanjiaobo_index * (i * 2 + 1)+1], up2_fir_fft_intput[2 * sanjiaobo_index * (i * 2 + 1)]);
sanjiaobo_amp[i] = up2_fir_fft_output[sanjiaobo_index * (i * 2 + 1)];
Set_Current_USART(USART1_IDX);
printf("三角波%d次谐波 = %f mV\r\n", (i * 2 + 1),sanjiaobo_amp[i]);
}
for (int i = 0; i < DAC_WAVE_LENGTH; i ++) {
float32_t theta = 2.0f * PI * i / DAC_WAVE_LENGTH; //相位角度
float32_t fixed_coeff = 1.33f * (4150.0f / 3.246f) * (8.0f / (PI * PI));
float32_t signal = 1.5f // 直流
+ sanjiaobo_amp[0] * arm_sin_f32(theta * 1.0f + sanjiaobo_amp[0] )
- sanjiaobo_amp[1] * arm_sin_f32(theta * 3.0f + sanjiaobo_amp[1] )
+ sanjiaobo_amp[2] * arm_sin_f32(theta * 5.0f + sanjiaobo_amp[2] )
- sanjiaobo_amp[3] * arm_sin_f32(theta * 7.0f + sanjiaobo_amp[3] )
+ sanjiaobo_amp[4] * arm_sin_f32(theta * 9.0f + sanjiaobo_amp[4] )
- sanjiaobo_amp[5] * arm_sin_f32(theta * 11.0f + sanjiaobo_amp[5] )
+ sanjiaobo_amp[6] * arm_sin_f32(theta * 13.0f + sanjiaobo_amp[6] )
- sanjiaobo_amp[7] * arm_sin_f32(theta * 15.0f + sanjiaobo_amp[7] )
+ sanjiaobo_amp[8] * arm_sin_f32(theta * 17.0f + sanjiaobo_amp[8] )
- sanjiaobo_amp[9] * arm_sin_f32(theta * 19.0f + sanjiaobo_amp[9] );
up2_dac_wave[i] = (uint16_t)(fixed_coeff * signal);
}
set_dac_freq(up2_adc1_base_freq);
// dac输出
HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, (uint32_t*)up2_dac_wave, DAC_WAVE_LENGTH, DAC_ALIGN_12B_R);
}
up2_fir_output_last_base_freq = up2_fir_output_base_freq;
}
// 方波
else if (up2_adc1_base_amp > 1.27f) {
wave_falg = 3;
up2_adc1_fir_index = (uint32_t)((up2_adc1_base_freq - 1000.0f) / 200.0f);
fir_fliter_function(up2_adc1_float_data, up2_fir_output, ADC_SAMPLE_LENGTH, LMS_NUM_TAPS, &up1_save_fir_Coeffs32[up2_adc1_fir_index][LMS_NUM_TAPS]);
flat_top_window(up2_fir_output, up2_fir_window, ADC_SAMPLE_LENGTH);
// fft
inf_fft_with_mag_norm_f32(up2_fir_output, up2_fir_fft_intput, up2_fir_fft_output, MAX_FFT_N);
// 求幅值
up2_fir_output_base_amp = find_fft_freq_amp(up2_fir_fft_output, AMP, ADC_SAMPLE_RATE, MAX_FFT_N);
// 求频率
up2_fir_output_base_freq = find_fft_freq_amp(up2_fir_fft_output, FREQ, ADC_SAMPLE_RATE, MAX_FFT_N);
// 求索引
fangbo_index = find_fft_freq_amp(up2_fir_fft_output, INDEX, ADC_SAMPLE_RATE, MAX_FFT_N);
if (up2_fir_output_last_base_freq != up2_fir_output_base_freq || lase_wave_falg != wave_falg) {
memset(up2_dac_wave,0,sizeof(up2_dac_wave));
Set_Current_USART(USART1_IDX);
for (int i = 0; i < MAX_FFT_N / 2;i++) {
printf ("%f, %f\r\n", up2_fir_output[i] * ZOOM, up2_fir_fft_output[i]);
}
printf ("方波基波幅值 = %f V\r\n", up2_fir_output_base_amp);
printf ("方波基波频率 = %f Hz\r\n", up2_fir_output_base_freq);
printf ("\r\n");
// 谐波幅值
fangbo_amp[0] = up2_fir_output_base_amp;
for (int i = 1; i < 10; i ++) {
// 幅值、相位
fangbo_phase[i] = atan2f(up2_fir_fft_intput[2 * fangbo_index * (i * 2 + 1)+1], up2_fir_fft_intput[2 * fangbo_index * (i * 2 + 1)]);
fangbo_amp[i] = up2_fir_fft_output[fangbo_index * (i * 2 + 1)];
Set_Current_USART(USART1_IDX);
printf("方波%d次谐波 = %f mV\r\n", (i * 2 + 1),fangbo_amp[i]);
}
// 滤波后方波合成 - 修正部分
for (int i = 0; i < DAC_WAVE_LENGTH; i++) {
float32_t theta = 2.0f * PI * i / DAC_WAVE_LENGTH;
float32_t signal = 1.5f; // DC偏移
signal += (4.0f / PI) * (
fangbo_amp[0] * arm_sin_f32(theta * 1 + fangbo_phase[0]) +
fangbo_amp[1] * arm_sin_f32(theta * 3 + fangbo_phase[1]) +
fangbo_amp[2] * arm_sin_f32(theta * 5 + fangbo_phase[2]) +
fangbo_amp[3] * arm_sin_f32(theta * 7 + fangbo_phase[3]) +
fangbo_amp[4] * arm_sin_f32(theta * 9 + fangbo_phase[4]) +
fangbo_amp[5] * arm_sin_f32(theta * 11 + fangbo_phase[5]) +
fangbo_amp[6] * arm_sin_f32(theta * 13 + fangbo_phase[6]) +
fangbo_amp[7] * arm_sin_f32(theta * 15 + fangbo_phase[7]) +
fangbo_amp[8] * arm_sin_f32(theta * 17 + fangbo_phase[8]) +
fangbo_amp[9] * arm_sin_f32(theta * 19 + fangbo_phase[9])
);
up2_dac_wave[i] = (uint16_t)((4095.0f / 3.246f) * signal);
}
set_dac_freq(up2_adc1_base_freq);
// dac输出
HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, (uint32_t*)up2_dac_wave, DAC_WAVE_LENGTH, DAC_ALIGN_12B_R);
}
up2_fir_output_last_base_freq = up2_fir_output_base_freq;
}
lase_wave_falg = wave_falg;
// 以下都是可以用的,现在测试保底注释而已
// G_Start = false;
// // ADC1频率 —— fir系数表索引换算
// up2_adc1_fir_index = (uint32_t)((up2_adc1_base_freq - 1000.0f) / 200.0f);
// fir_fliter_function(up2_adc1_float_data, up2_fir_output, ADC_SAMPLE_LENGTH, LMS_NUM_TAPS, &up1_save_fir_Coeffs32[up2_adc1_fir_index][LMS_NUM_TAPS]);
// uint32_t fir_start_index = LMS_NUM_TAPS / 2;
// for (uint32_t i = 0; i < DAC_WAVE_LENGTH; i ++) {
// dac_buffer_output[i] = (uint16_t)((up2_fir_output[fir_start_index + i] * ZOOM + up2_adc1_DC_part * ZOOM) * (4095 / 3.3));
// Set_Current_USART(USART1_IDX);
// printf("%f, %f\r\n", up2_fir_output[fir_start_index + i] * ZOOM, dac_buffer_output[i] * DAC_ZOOM);
// }
// Set_Current_USART(USART1_IDX);
// printf("up2_adc1_base_freq = %f Hz\r\n", up2_adc1_base_freq);
// set_dac_freq((uint32_t)up2_adc1_base_freq);
// HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, (uint32_t*)dac_buffer_output, DAC_WAVE_LENGTH, DAC_ALIGN_12B_R);
}
}它是怎么做到的请告诉我以下几点1.它用ADC+DMA的时候是要等DMA传输完成才进行下一次ADC采集还是什么2.它说用傅里叶级数是怎么做到的
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dac.h"
#include "dma.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "intruppt.h"
#include "LMS.h"
#include "simple_fft.h"
#include "stdio.h"
#include "string.h"
#include "lms_matcher.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
extern DMA_HandleTypeDef hdma_adc1;
extern DMA_HandleTypeDef hdma_adc2;
extern DMA_HandleTypeDef hdma_dac1_ch1;
volatile uint16_t adc_buffer_1[BUF_SIZE]; // ADC1 DMA缓冲区(通道1)
volatile uint16_t adc_buffer_2[BUF_SIZE]; // ADC2 DMA缓冲区(通道2)
volatile uint8_t flag_test = 0; // ADC1 DMA完成标志
volatile uint8_t flag_test2 = 0; // ADC2 DMA完成标志
volatile float adc_buf[2][BUF_SIZE]; //转换成真实电压
float lms_filter[LMS_BUF][FILTER_LEN];//存储lms滤波系数
volatile uint8_t flag_lms = 0; //lms把系数全部存储下来时
volatile uint8_t flag_fir = 0; //如果值1就执行DAC输出
volatile uint8_t flag_start =0; //当按下PE10的时候开始采集
// FFT相关变量
SimpleFFT simple_fft; // FFT实例
float32_t fft_data[FFT_SIZE]; // FFT输入数据缓冲区
volatile uint16_t fft_index = 0; // FFT数据填充索引
volatile uint8_t fft_ready = 0; // FFT数据准备标志
float32_t detected_frequency = 0.0f; // 检测到的频率值
volatile uint16_t flag_which = 0;
//DAC相关变量
float output_DAC = 0.0f;
uint16_t dac_output_data[BUF_SIZE]; // DAC输出数据缓冲区
uint8_t flag_dac = 0;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void PeriphCommonClock_Config(void);
static void MPU_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int fputc(int ch,FILE *f)
{
//采用轮询方式发送1字节数据,超时时间设置为无限等待
HAL_UART_Transmit(&huart2,(uint8_t *)&ch,1,100);
return ch;
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* Configure the peripherals common clocks */
PeriphCommonClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART2_UART_Init();
MX_ADC1_Init();
MX_TIM3_Init();
MX_ADC2_Init();
MX_USART3_UART_Init();
MX_DAC1_Init();
MX_TIM4_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Stop(&htim3); //停止ADC硬件触发
HAL_TIM_Base_Stop(&htim4); //停止DAC硬件触发
LMS_init(&lms,0.0001); // 初始化LMS
SimpleFFT_Init(&simple_fft); // 初始化FFT
LMS_matcher_Init(); // 初始化匹配算法
// 确保所有标志位都正确初始化
flag_start = 0;
flag_test = 0;
flag_test2 = 0;
flag_fir = 0;
flag_lms = 0;
flag_dac = 0;
flag_which=0;
//启动ADC DMA采集
HAL_Delay(2);
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer_1, BUF_SIZE);
__HAL_DMA_DISABLE_IT(&hdma_adc1, DMA_IT_HT);
HAL_ADC_Start_DMA(&hadc2, (uint32_t*)adc_buffer_2, BUF_SIZE);
__HAL_DMA_DISABLE_IT(&hdma_adc2, DMA_IT_HT);
HAL_TIM_Base_Start(&htim3);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// 检测PE10按键按下,开始LMS数据采集
if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_10)==0)
{
HAL_Delay(20);
if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_10)==0)
{
flag_start=1;
}
}
if(flag_start==1)//如果按键按下PE10开始采集,扫频LMS学习
{
HAL_Delay(10);
static uint8_t flag_printf = 1;
if(flag_printf){printf("好的\r\n");flag_printf=0;}
if(flag_lms<LMS_BUF)//学习完就退出
{
if(flag_test && flag_test2) //双通道ADC DMA采集完成
{
// 定时器和ADC已在中断中停止
flag_test = 0;
flag_test2 = 0;
// 复制数据到处理缓冲区
for(int i = 0; i < BUF_SIZE; i++)
{
adc_buf[0][i] = (float)(adc_buffer_1[i]*ADC_SCALE-ADC_Baic);//转换成真实电压
adc_buf[1][i] = (float)(adc_buffer_2[i]*ADC_SCALE-ADC_Baic);//-ADC_Baic;
}
// LMS单样本逐点处理
for(int i = 0; i < BUF_SIZE; i++)
{
float x_in = adc_buf[0][i];
float d_in = adc_buf[1][i];
// 单样本LMS处理
LMS_study_cul(&lms, x_in, d_in);
}
// 将LMS系数存储到数组中
for(int i = 0;i < FILTER_LEN; i++)
{
lms_filter[flag_lms][i] = lms.w[i];
}
flag_lms++;
printf("%d\r\n",flag_lms);
printf("error:%f\r\n",lms.error);
// 重新启动ADC DMA采集
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer_1, BUF_SIZE);
__HAL_DMA_DISABLE_IT(&hdma_adc1, DMA_IT_HT);
HAL_ADC_Start_DMA(&hadc2, (uint32_t*)adc_buffer_2, BUF_SIZE);
__HAL_DMA_DISABLE_IT(&hdma_adc2, DMA_IT_HT);
HAL_TIM_Base_Start(&htim3);
}
}
}
if(flag_lms>=246)//如果LMS学习完
{
//上一种情况已经开启了ADC采集
flag_lms=0; //后续一直是0不会再用
flag_start=2;
}
if(flag_start==2)// 执行FFT检测和频率匹配
{
if(flag_test && flag_test2)
{
flag_test=0;
flag_test2=0;
// 复制数据到处理缓冲区
for(int i = 0; i < BUF_SIZE; i++)
{
adc_buf[0][i] = (float)(adc_buffer_1[i]*ADC_SCALE-ADC_Baic);//转换成真实电压
}
// FFT数据收集
uint16_t copy_count = (BUF_SIZE < FFT_SIZE - fft_index) ? BUF_SIZE : (FFT_SIZE - fft_index);
for(uint16_t i = 0; i < copy_count; i++)
{
fft_data[fft_index + i] = adc_buf[0][i];
}
fft_index += copy_count;
if(fft_index >= FFT_SIZE)
{
fft_ready = 1;
fft_index = 0;
}
// 执行FFT检测和频率匹配
if(fft_ready)
{
fft_ready = 0;
detected_frequency = SimpleFFT_DetectFrequency(&simple_fft, fft_data);
flag_which=LMS_matcher(detected_frequency);
//printf("%.1f\r\n",detected_frequency);
//printf("%d\r\n",flag_which);
flag_start=3;
}
}
}
if(flag_start == 3) // 执行滤波器输出和DAC控制
{
for(int i = 0; i < BUF_SIZE; i++)
{
float y_in = adc_buf[0][i];
output_DAC = LMS_output_cul(&lms, y_in, lms_filter, flag_which);
dac_output_data[i] = (uint16_t)((output_DAC / 3.3f) * 4095.0f + 1/3.3f*4095);
}
static uint8_t dac_started = 0; // 标记DAC是否已启动
// 条件1:仅在第一次进入时启动DAC(之后不再启动/停止)
if(dac_started == 0)
{
dac_started = 1;
HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1,
(uint32_t*)dac_output_data,
BUF_SIZE,
DAC_ALIGN_12B_R);
__HAL_DMA_DISABLE_IT(&hdma_dac1_ch1, DMA_IT_HT);
HAL_TIM_Base_Start(&htim4);
}
// 回到flag_start==2,继续FFT频率检测
flag_start = 2;
// 继续采集ADC数据
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer_1, BUF_SIZE);
__HAL_DMA_DISABLE_IT(&hdma_adc1, DMA_IT_HT);
HAL_ADC_Start_DMA(&hadc2, (uint32_t*)adc_buffer_2, BUF_SIZE);
__HAL_DMA_DISABLE_IT(&hdma_adc2, DMA_IT_HT);
HAL_TIM_Base_Start(&htim3);
}
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Supply configuration update enable
*/
HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = 64;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 34;
RCC_OscInitStruct.PLL.PLLP = 1;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLFRACN = 3072;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief Peripherals Common Clock Configuration
* @retval None
*/
void PeriphCommonClock_Config(void)
{
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
PeriphClkInitStruct.PLL2.PLL2M = 4;
PeriphClkInitStruct.PLL2.PLL2N = 12;
PeriphClkInitStruct.PLL2.PLL2P = 2;
PeriphClkInitStruct.PLL2.PLL2Q = 2;
PeriphClkInitStruct.PLL2.PLL2R = 2;
PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
// 立即停止当前完成的ADC,防止循环模式覆盖数据
if(hadc->Instance == ADC1)
{
HAL_ADC_Stop_DMA(&hadc1); // 立即停止ADC1
flag_test = 1;
}
else if(hadc->Instance == ADC2)
{
HAL_ADC_Stop_DMA(&hadc2); // 立即停止ADC2
flag_test2 = 1;
}
// 两个ADC都完成后停止定时器
if(flag_test && flag_test2)
{
HAL_TIM_Base_Stop(&htim3);
}
}
// DAC DMA传输完成回调
//void HAL_DAC_ConvCpltCallbackCh1(DAC_HandleTypeDef* hdac)
//{
// if(hdac->Instance == DAC1)
// {
// // 重要改动:不再停止DMA和定时器
// // 让DMA继续循环运行,只标记一下
// flag_dac = 1; // 仅标记DAC完成,让主程序更新数据
// }
//}
/* USER CODE END 4 */
/* MPU Configuration */
void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};
/* Disables the MPU */
HAL_MPU_Disable();
/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0x0;
MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
MPU_InitStruct.SubRegionDisable = 0x87;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enables the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
这是我的代码那我跟它的差距又是什么