|
使用的是ADC DMA循环模式,我的代码框架是,进入中断置标志位 -> while查询到标志位 -> 关闭三个ADC DMA -> 进行信号运算处理 -> 最后再打开ADC DMA,假如是这样一直运行的话,ADC一段时间后就会卡住,进入不了中断回调函数,而ADC2和ADC3是正常的,求大佬解答!
这是我的代码:
#include "main.h"
#include "adc.h"
#include "dac.h"
#include "dma.h"
#include "memorymap.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "fmc.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
//----------- ADC -----------//
__attribute__((section (".RAM_SDRAM"))) ADC_DMA_typedef ADC_Channels[3];
uint8_t keep_flag = 0;
//----------- FFT -----------//
__attribute__((section (".RAM_SDRAM"))) unlimitedfft_typedef infinite_fft_s[3];
fftPeak_typedef fft_Peak_Data[3];
//----------- Window -----------//
__attribute__((section (".RAM_SDRAM"))) float32_t ADC1_DMA_Windowed_Data[ADC_DMA_SAMPLE_LENGTH];
__attribute__((section (".RAM_SDRAM"))) float32_t ADC2_DMA_Windowed_Data[ADC_DMA_SAMPLE_LENGTH];
__attribute__((section (".RAM_SDRAM"))) float32_t ADC3_DMA_Windowed_Data[ADC_DMA_SAMPLE_LENGTH];
//----------- IIR -----------//
__attribute__((section (".RAM_SDRAM"))) float32_t ADC1_fliter_InputBufer[IIR_LENGTH]; // 滤波器输入数据数组
__attribute__((section (".RAM_SDRAM"))) float32_t ADC1_fliter_OutputBufer[IIR_LENGTH]; // 滤波器输出数据数组
__attribute__((section (".RAM_SDRAM"))) float32_t ADC2_fliter_InputBufer[IIR_LENGTH]; // 滤波器输入数据数组
__attribute__((section (".RAM_SDRAM"))) float32_t ADC2_fliter_OutputBufer[IIR_LENGTH]; // 滤波器输出数据数组
//----------- PID -----------//
// PID参数
#define Kp 3.5
#define Ki 2.0
#define Kd 0.01
// 积分限幅
#define INTEGRAL_LIMIT 100.0
float32_t err;
float32_t last_err;
float32_t proportion;
float32_t integral;
float32_t integration;
float32_t derivative;
float32_t adjust;
float32_t last_adjust;
float32_t filtered_adjust = 0; // 滤波后的调整值
#define FILTER_ALPHA 0.1f // 滤波系数(0.1~0.5,值越小越平滑)
/* 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 */
/* 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 */
/**
* @brief ADC转换完成回调函数
*
* 当ADC转换完成且DMA搬运结束时,此回调函数会被调用。
* 根据不同的ADC实例(ADC1或ADC2或ADC3),设置对应的ADC通道转换结束标志位。
*
* @param hadc 指向ADC句柄结构体的指针,包含了ADC的相关信息
*
* @return 无
*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC1){
ADC_Channels[0].ConvEnd_Flag = 1; /* ADC采集DMA搬运结束标志位置一 */
// printf("adc1触发\r\n");
}
if(hadc->Instance == ADC2){
ADC_Channels[1].ConvEnd_Flag = 1; /* ADC采集DMA搬运结束标志位置一 */
// printf("adc2触发\r\n");
}
if(hadc->Instance == ADC3){
ADC_Channels[2].ConvEnd_Flag = 1; /* ADC采集DMA搬运结束标志位置一 */
// printf("adc3触发\r\n");
}
}
/* 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();
/* Enable the CPU Cache */
/* Enable I-Cache---------------------------------------------------------*/
SCB_EnableICache();
/* Enable D-Cache---------------------------------------------------------*/
SCB_EnableDCache();
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
delay_init(400); /* 延时函数初始化 主频:400MHz */
/* 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_USART1_UART_Init();
MX_TIM6_Init();
MX_USART2_UART_Init();
MX_DAC1_Init();
MX_ADC1_Init();
MX_TIM7_Init();
MX_SPI4_Init();
MX_ADC3_Init();
MX_FMC_Init();
MX_ADC2_Init();
/* USER CODE BEGIN 2 */
//------------
// LED
//------------
LED1_TOGGLE();
//------------
// Key
//------------
button_init();
//------------------------------------------------------
// TFTLCD
//------------------------------------------------------
lcd_init();
lcd_show_string(10, 40, 240, 32, 32, "STM32", RED);
lcd_show_string(10, 80, 240, 24, 24, "TFTLCD", RED);
lcd_show_string(10, 110, 240, 16, 16, "ATOM@ALIENTEK", RED);
#if PICTURE_USE_FLAG
lcd_show_pieture(0,160,480,480,(uint16_t *)gImage_Test);
lcd_show_pieture(45,64,64,64,(uint16_t *)gImage_tong);
lcd_show_pieture(154,64,64,64,(uint16_t *)gImage_xin);
lcd_show_pieture(263,64,64,64,(uint16_t *)gImage_dian);
lcd_show_pieture(372,64,64,64,(uint16_t *)gImage_zi);
#endif
//---------------------------------------------------------------------------------------------
// 设置采样率 —— EXTI11 外部方波频率设置采样率
//---------------------------------------------------------------------------------------------
ADC_Channels[0].SamplingRate = 640000.0f;
ADC_Channels[1].SamplingRate = ADC_Channels[0].SamplingRate;
ADC_Channels[2].SamplingRate = ADC_Channels[1].SamplingRate;
//---------------------------------------------------------------------------------------------
// ADC-DMA 启动
//---------------------------------------------------------------------------------------------
HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); /* ADC1 校准 */
HAL_ADCEx_Calibration_Start(&hadc2, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); /* ADC1 校准 */
HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); /* ADC3 校准 */
delay_ms(100); /* 给ADC时间校准 */
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&ADC_Channels[0].DMA_Buffer, ADC_DMA_SAMPLE_LENGTH); /* 启动ADC1_DMA */
HAL_ADC_Start_DMA(&hadc2,(uint32_t*)&ADC_Channels[1].DMA_Buffer, ADC_DMA_SAMPLE_LENGTH); /* 启动ADC1_DMA */
HAL_ADC_Start_DMA(&hadc3,(uint32_t*)&ADC_Channels[2].DMA_Buffer, ADC_DMA_SAMPLE_LENGTH); /* 启动ADC3_DMA */
//---------------------------------------------------------------------------------------------
// 打印初始化信息
//---------------------------------------------------------------------------------------------
Set_Current_USART(USART1_IDX);
printf("\r\n\r\n");
printf("STM32H743ADC最高采样频率:5MHz\r\n");
printf("使用EXTI外部触发ADC采样,比定时器触发ADC采样更加精确\r\n");
printf("修改 adc.h 中 ADC_DMA_SAMPLE_LENGTH 宏定义参数,以此修改*采样*点数\r\n");
printf("修改 FFTInc.h 中 MAX_FFT_N 宏定义参数,以此修改*fft运算*点数\r\n");
printf("修改 WindowingFunction.h 中 WINDOW_LENGTH 宏定义参数,以此修改加*窗函数*点数\r\n");
printf("修改 Digital_Filter.h 中 FIR_LENGTH 和 IIR_LENGTH 宏定义参数,以此修改*FIR*与*IIR*滤波点数\r\n");
printf("修改 Digital_Filter.h 中 Mid_LENGTH 和 LMS_BLOCK_SIZE 宏定义参数,以此修改*中值滤波*和*LMS自适应滤波*点数\r\n");
printf("修改 SplineInterpFunction.h 中 SPLINE_INPUT_SAMPLES_LENGTH 和 SPLINE_OUTPUT_SAMPLES_LENGTH 宏定义参数,以此修改*输入数据*和*输出数据*点数\r\n");
//------------------------------------------------------------------
// DAC
//------------------------------------------------------------------
float32_t DAC_Freq = 100000; /* DAC 输出信号频率 */
float32_t DAC_Amp = 0; /* DAC 输出信号幅值 */
DAC_Init(CHANNEL_1); /* DAC ch1 初始化 */
DAC_Init(CHANNEL_2); /* DAC ch2 初始化 */
DAC_GenerateWave(DC, DAC_CHANNEL_1, DAC_Freq, DAC_Amp, DAC_WAVE_LENGTH); /* DAC 输出信号:波形 通道 频率 幅值 点数*/
DAC_GenerateWave(DC, DAC_CHANNEL_2, DAC_Freq, DAC_Amp, DAC_WAVE_LENGTH); /* DAC 输出信号:波形 通道 频率 幅值 点数 */
Set_Current_USART(USART1_IDX);
//------------------------------------------------
// AD9833
//------------------------------------------------
float32_t AD9833_Freq = 100000.0; /* AD9833 输出信号频率 */
delay_ms(50); /* 使 AD9833 先上电 */
AD9833_A_Init(); /* AD9833_A 初始化 */
AD9833_B_Init(); /* AD9833_B 初始化 */
AD9833_A_SetFrequencyQuick(AD9833_Freq, AD9833_A_SQUARER); /* AD9833_A 输出信号:频率 波形 */
AD9833_B_SetFrequencyQuick(AD9833_Freq, AD9833_B_SQUARER); /* AD9833_B 输出信号:频率 波形 */
//------------------------------------------------
// AD9959
//------------------------------------------------
delay_ms(50); /* 使 AD9959 先上电 */
AD9959_Init(); /* AD9959 初始化 */
AD9959_enablechannel0(); /* 使能通道0 */
AD9959_Setwavefrequency(6400000.0f); /* AD9959 输出信号:频率 */
AD9959_enablechannel1(); /* 使能通道1 */
AD9959_Setwavefrequency(6400000.0f); /* AD9959 输出信号:频率 */
AD9959_enablechannel2(); /* 使能通道2 */
AD9959_Setwavefrequency(6400000.0f); /* AD9959 输出信号:频率 */
AD9959_enablechannel3(); /* 使能通道3 */
AD9959_Setwavefrequency(6400000.0f); /* AD9959 输出信号:频率 */
//------------------------------------------------
// AD7606(目前采样率只有4ksps)
//------------------------------------------------
AD7606_Init();
uint16_t AD7606_Count = 0;
int16_t DB_data[8] = {0};
int16_t DB_intdata[1024] = {0};
//--------------------------------//
// 放while中
// AD7606_StartConvst();
// AD7606_Delay(1);
// while((BUSY == GPIO_PIN_SET)) // 读取BUSY的状态,为低电平表示电平转换结束,可以读取数据
// {
// AD7606_Delay(10);
// }
// AD7606_ReadData(DB_data); //读取数据放至数组DB_data[]
// DB_intdata[AD7606_Count] = (float)DB_data[0];
// AD7606_Count++;
// printf("%f,%f\r\n",(float)(DB_data[0]*10000.0/32768.0),(float)(DB_intdata[AD7606_Count]*10000.0/32768.0));
// if(AD7606_Count == 1023)AD7606_Count=0;
//--------------------------------//
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while(1)
{
//------------
// 按键操作
//------------
if(keep_flag == 0){
get_btn();
}else{
lwbtn_keys = 4;
}
//------------------------------------------------------------------------------------
// 开始按键按下操作
//------------------------------------------------------------------------------------
if(ADC_Channels[0].ConvEnd_Flag == 1 && ADC_Channels[1].ConvEnd_Flag == 1 && ADC_Channels[2].ConvEnd_Flag == 1 && lwbtn_keys == 4){
/** LED表示开始运行 **/
LED1_TOGGLE();
/** 停止采样-转运 **/
HAL_ADC_Stop_DMA(&hadc1);
HAL_ADC_Stop_DMA(&hadc2);
HAL_ADC_Stop_DMA(&hadc3);
/** 标志位置零 **/
ADC_Channels[0].ConvEnd_Flag = 0;
ADC_Channels[1].ConvEnd_Flag = 0;
ADC_Channels[2].ConvEnd_Flag = 0;
keep_flag += 1;if(keep_flag == 10)keep_flag = 1;
/* 将 ADC 采集到的整形数据提前转换为浮点数据存储 */
for(uint32_t i = 0; i < ADC_DMA_SAMPLE_LENGTH; i ++){
ADC_Channels[0].DMA_floatData[i] = (float32_t)ADC_Channels[0].DMA_Buffer[i];
ADC_Channels[1].DMA_floatData[i] = (float32_t)ADC_Channels[1].DMA_Buffer[i];
// ADC_Channels[2].DMA_floatData[i] = (float32_t)ADC_Channels[2].DMA_Buffer[i];
}
/* 去除直流分量 */
RemoveDCOffset(ADC_Channels[0].DMA_floatData, &ADC_Channels[0].DCpart, ADC_DMA_SAMPLE_LENGTH);
RemoveDCOffset(ADC_Channels[1].DMA_floatData, &ADC_Channels[1].DCpart, ADC_DMA_SAMPLE_LENGTH);
// RemoveDCOffset(ADC_Channels[2].DMA_floatData, &ADC_Channels[2].DCpart, ADC_DMA_SAMPLE_LENGTH);
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
// 主程序区:
/* IIR */
FIR_IIR_FliterRT(ADC_Channels[0].DMA_floatData, IIR_FILTER, ADC1_fliter_InputBufer, ADC1_fliter_OutputBufer);
FIR_IIR_FliterRT(ADC_Channels[1].DMA_floatData, IIR_FILTER, ADC2_fliter_InputBufer, ADC2_fliter_OutputBufer);
/* WINDOW */
PerformWindowing_f32(HAMMING_f32, ADC1_fliter_OutputBufer, ADC1_DMA_Windowed_Data, ADC_DMA_SAMPLE_LENGTH);
PerformWindowing_f32(HAMMING_f32, ADC2_fliter_OutputBufer, ADC2_DMA_Windowed_Data, ADC_DMA_SAMPLE_LENGTH);
// PerformWindowing_f32(HAMMING_f32, ADC_Channels[2].DMA_floatData, ADC3_DMA_Windowed_Data, ADC_DMA_SAMPLE_LENGTH);
/* FFT */
Infinite_FFT(ADC1_DMA_Windowed_Data, infinite_fft_s[0].fft_Input, infinite_fft_s[0].fft_Output, MAX_FFT_N);
Infinite_FFT(ADC2_DMA_Windowed_Data, infinite_fft_s[1].fft_Input, infinite_fft_s[1].fft_Output, MAX_FFT_N);
// Infinite_FFT(ADC3_DMA_Windowed_Data, infinite_fft_s[2].fft_Input, infinite_fft_s[2].fft_Output, MAX_FFT_N);
/* 计算 ADC1 采样信号的频率、幅值、相位 */
fft_Peak_Data[0].Freq = FindfftPeak_f32(infinite_fft_s[0].fft_Output, &fft_Peak_Data[0].MaxAmp, &fft_Peak_Data[0].MaxAmp_Index, ADC_Channels[0].SamplingRate, MAX_FFT_N);
infinite_fft_s[0].Phase = Find_PhaseAngle(infinite_fft_s[0].fft_Input, infinite_fft_s[0].fft_Output,MAX_FFT_N);
/* 计算 ADC2 采样信号的频率、幅值、相位 */
fft_Peak_Data[1].Freq = FindfftPeak_f32(infinite_fft_s[1].fft_Output, &fft_Peak_Data[1].MaxAmp, &fft_Peak_Data[1].MaxAmp_Index, ADC_Channels[1].SamplingRate, MAX_FFT_N);
infinite_fft_s[1].Phase = Find_PhaseAngle(infinite_fft_s[1].fft_Input, infinite_fft_s[1].fft_Output,MAX_FFT_N);
// /* 计算 ADC3 采样信号的频率、幅值、相位 */
// fft_Peak_Data[2].Freq = FindfftPeak_f32(infinite_fft_s[2].fft_Output, &fft_Peak_Data[2].MaxAmp, &fft_Peak_Data[2].MaxAmp_Index, ADC_Channels[2].SamplingRate, MAX_FFT_N);
// infinite_fft_s[2].Phase = Find_PhaseAngle(infinite_fft_s[2].fft_Input, infinite_fft_s[2].fft_Output,MAX_FFT_N);
// /* 串口打印时域波形 */
// for(uint32_t i = 0; i < ADC_DMA_SAMPLE_LENGTH; i++){
// printf("%f,%f,%f,%f,%f,%f\r\n", ADC1_fliter_OutputBufer[i]*ZOOM, ADC2_fliter_OutputBufer[i]*ZOOM, ADC_Channels[2].DMA_floatData[i]*ZOOM, infinite_fft_s[0].fft_Output[i], infinite_fft_s[1].fft_Output[i], infinite_fft_s[2].fft_Output[i]);
// }
// printf("信号1 ——> 基波频率:%f 基波幅值:%f 基波索引:%d 基波相位:%f\r\n", fft_Peak_Data[0].Freq, fft_Peak_Data[0].MaxAmp, fft_Peak_Data[0].MaxAmp_Index, infinite_fft_s[0].Phase);
// printf("信号2 ——> 基波频率:%f 基波幅值:%f 基波索引:%d 基波相位:%f\r\n", fft_Peak_Data[1].Freq, fft_Peak_Data[1].MaxAmp, fft_Peak_Data[1].MaxAmp_Index, infinite_fft_s[1].Phase);
// printf("信号3 ——> 基波频率:%f 基波幅值:%f 基波索引:%d 基波相位:%f\r\n", fft_Peak_Data[2].Freq, fft_Peak_Data[2].MaxAmp, fft_Peak_Data[2].MaxAmp_Index, infinite_fft_s[2].Phase);
// printf("信号1 与 信号2 相位差:%f\r\n",infinite_fft_s[0].Phase - infinite_fft_s[1].Phase);
// printf("信号2 与 信号3 相位差:%f\r\n",infinite_fft_s[1].Phase - infinite_fft_s[2].Phase);
// printf("信号1 与 信号3 相位差:%f\r\n",infinite_fft_s[0].Phase - infinite_fft_s[2].Phase);
/* PI */
last_adjust = adjust;
adjust = ((uint32_t)(adjust + 2.0 * (float32_t)(infinite_fft_s[0].Phase - infinite_fft_s[1].Phase) + 4095.0 * 2.0) % 4095);
if(fabs(adjust - last_adjust) > 3500 && fabs(adjust - last_adjust) < 4000) adjust = last_adjust;
if(fabs(adjust - last_adjust) > 540) adjust = last_adjust;
filtered_adjust = FILTER_ALPHA * adjust + (1 - FILTER_ALPHA) * filtered_adjust;
// printf("%f,%f\r\n",adjust,last_adjust);
AD9833_A_SetFrequencyQuick(fft_Peak_Data[0].Freq, AD9833_A_SINE);
AD9833_A_SetPhase(AD9833_A_REG_PHASE0, adjust);
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC_Channels[0].DMA_Buffer, ADC_DMA_SAMPLE_LENGTH); /* 启动ADC1_DMA */
HAL_ADC_Start_DMA(&hadc2, (uint32_t*)ADC_Channels[1].DMA_Buffer, ADC_DMA_SAMPLE_LENGTH); /* 启动ADC2_DMA */
HAL_ADC_Start_DMA(&hadc3, (uint32_t*)ADC_Channels[2].DMA_Buffer, ADC_DMA_SAMPLE_LENGTH); /* 启动ADC3_DMA */
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
|
|