硬汉嵌入式论坛

 找回密码
 立即注册
查看: 559|回复: 6
收起左侧

[SDRAM] 有关H7使用SDRAM内存存储FFT点数

[复制链接]

6

主题

24

回帖

42

积分

新手上路

积分
42
发表于 2025-3-4 21:11:09 | 显示全部楼层 |阅读模式
之前的硬错误中断问题,已经解决了,就是自己写一个初始化函数,放到启动文件那里,配合上硬汉哥的内存使用方式就解决了(虽然也是用了三天)。
看起来是可以正常使用SDRAM了,但是ADC采样点数和FFT点数,测试最高只能到32768(这个点数下测试的是没有问题的),一给到65536,调试的时候就发现,连ADC的DMA的中断回调函数都没进入,所以不能进行那么多点数的采样或者FFT。
我在调试的时候看了分配到SDRAM的变量,是字节对齐的,是不是SDRAM的什么限制内存问题还是什么ADC采样还是DMA转运有这个限制呢?下面是我的代码,以及调试的窗口


#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"

//----------- ADC -----------//
__attribute__((section (".RAM_SDRAM"))) ADC_DMA ADC_Channels[2];        /* 定义包含 ADC1_CH3 和 ADC3_CH3 的数组 */

//----------- FFT -----------//
__attribute__((section (".RAM_SDRAM"))) struct compx        ADC1_CH3_infinite_fft_s[MAX_FFT_N];
__attribute__((section (".RAM_SDRAM"))) struct compx        ADC3_CH3_infinite_fft_s[MAX_FFT_N];

void SystemClock_Config(void);
void PeriphCommonClock_Config(void);
static void MPU_Config(void);

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
        if(hadc->Instance == ADC1){
//                HAL_ADC_Stop_DMA(&hadc1);                /* 循环模式则需开启:停止DMA以防止数据覆盖 */
                HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC_Channels[0].DMA_Buffer, ADC_DMA_SAMPLE_LENGTH);        /* 再次启动 ADC1_IN3 */       
                ADC_Channels[0].ConvEnd_Flag = 1;                                                                                                                                                                                                                                        /* ADC采集DMA搬运结束标志位置一 */
                for(uint32_t i = 0; i < ADC_DMA_SAMPLE_LENGTH; i++){                                                                                                                                                        /* 处理 ADC1_IN3 缓冲 */
                        ADC_Channels[0].DMA_intData = ADC_Channels[0].DMA_Buffer;                                                                                                        /* 将采集到的DMA数据转移到int待处理数组中 */
                        ADC_Channels[0].DMA_floatData = (float32_t)ADC_Channels[0].DMA_intData;                                                /* 将采集到的整形数据提前转换为浮点数据存储 */
                }
        }
        if(hadc->Instance == ADC3){
//                HAL_ADC_Stop_DMA(&hadc3);                /* 循环模式则需开启:停止DMA以防止数据覆盖 */
                HAL_ADC_Start_DMA(&hadc3, (uint32_t*)ADC_Channels[1].DMA_Buffer, ADC_DMA_SAMPLE_LENGTH);        /* 再次启动 ADC3_IN3 */       
                ADC_Channels[1].ConvEnd_Flag = 1;                                                                                                                                                                                                                                        /* ADC采集DMA搬运结束标志位置一 */
                for(uint32_t i = 0; i < ADC_DMA_SAMPLE_LENGTH; i++){                                                                                                                                                        /* 处理 ADC3_IN3 缓冲 */
                        ADC_Channels[1].DMA_intData = ADC_Channels[1].DMA_Buffer;                                                                                                        /* 将采集到的DMA数据转移到int待处理数组中 */
                        ADC_Channels[1].DMA_floatData = (float32_t)ADC_Channels[1].DMA_intData;                                                /* 将采集到的整形数据提前转换为浮点数据存储 */
                }
        }
}

//SDRAM内存测试            
void fsmc_sdram_test(void)
{  
        __IO uint32_t i=0;            
        __IO uint32_t temp=0;          
        __IO uint32_t sval=0;//在地址0读到的数据                                            
        //每隔16K字节,写入一个数据,总共写入2048个数据,刚好是32M字节
        for(i=0;i<32*1024*1024;i+=16*1024){
                *(__IO uint32_t *)(SDRAM_BANK_ADDR+i)=temp;
                temp++;
        }
        //依次读出之前写入的数据,进行校验                  
        for(i=0;i<32*1024*1024;i+=16*1024) {       
          temp=*(__IO uint32_t *)(SDRAM_BANK_ADDR+i);
                if(i==0)sval=temp;
                else if(temp<=sval)break;//后面读出的数据一定要比第一次读到的数据大.                             
                printf("SDRAM Capacity:%dKB\r\n",(uint16_t )(temp-sval+1)*16);//打印SDRAM容量
        }                                         
}
/* USER CODE END 0 */
int main(void)
{


  /* 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();

  /* 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_TIM3_Init();
  MX_TIM7_Init();
  MX_SPI4_Init();
  MX_ADC3_Init();
  MX_FMC_Init();
  /* USER CODE BEGIN 2 */
        /***** LED0 *****/
        LED0_TOGGLE();
       
        /***** LCD *****/
        lcd_init();
        #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

        /***** 采样率 *****/
        ADC_Channels[0].SamplingRate = Set_SamplingRate(&htim3,200000000,40960);                                                                                /* 必须要在定时器启动前进行设置!*/
        ADC_Channels[1].SamplingRate = ADC_Channels[0].SamplingRate;
        /***** ADC *****/
  delay_ms(10);                                                                                                                                                                                                                                                                                                /* 给ADC时间校准 */
  HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);                                                /* ADC 校准 */
        HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);                                                /* ADC 校准 */
  HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&ADC_Channels[0].DMA_Buffer, ADC_DMA_SAMPLE_LENGTH);        /* 启动DMA转换ADC_DMA_SAMPLE_LENGTH次,完成后回调callback */
        HAL_ADC_Start_DMA(&hadc3,(uint32_t*)&ADC_Channels[1].DMA_Buffer, ADC_DMA_SAMPLE_LENGTH);        /* 启动DMA转换ADC_DMA_SAMPLE_LENGTH次,完成后回调callback */
  HAL_TIM_Base_Start(&htim3);                                                                                                                                                                                                                                        /* 启动定时器3 */
       
  Set_Current_USART(USART1_IDX);

       
        /***** DAC *****/
        uint32_t DAC_Freq = 5000;        /* DAC 输出信号频率 */
        DAC_Init(CHANNEL_1);                        /* DAC ch1 初始化 */
        DAC_Init(CHANNEL_2);                        /* DAC ch2 初始化 */
        DAC_GenerateWave(SINE, DAC_CHANNEL_1, DAC_Freq, 2, DAC_WAVE_LENGTH);        /* DAC 输出信号:波形 通道 频率 幅值 点数*/
        DAC_GenerateWave(SINE, DAC_CHANNEL_2, DAC_Freq, 2, DAC_WAVE_LENGTH);        /* DAC 输出信号:波形 通道 频率 幅值 点数 */
        Set_Current_USART(USART1_IDX);

        /***** AD9833 *****/
        delay_ms(200);                                                                                                                                                                /* 使 AD9833 先上电 */
        AD9833_A_Init();                                                                                                                                                        /* AD9833_A 初始化 */
        AD9833_B_Init();                                                                                                                                                        /* AD9833_B 初始化 */
        AD9833_A_SetFrequencyQuick(1000.0, AD9833_A_SINE);                /* AD9833_A 输出信号:频率 波形 */
        AD9833_B_SetFrequencyQuick(1000.0, AD9833_B_SINE);                /* AD9833_B 输出信号:频率 波形 */
       
        /***** AD9959 *****/
        delay_ms(200);                                                                                        /* 使 AD9959 先上电 */
        AD9959_Init();                                                                                        /* AD9959 初始化 */
        AD9959_enablechannel0();                                                 /* 使能通道0 */
        AD9959_Setwavefrequency(1000000);                /* AD9959 输出信号:频率 */
        AD9959_enablechannel1();                                                 /* 使能通道1 */
        AD9959_Setwavefrequency(2000000);                /* AD9959 输出信号:频率 */
        AD9959_enablechannel2();                                                 /* 使能通道2 */
        AD9959_Setwavefrequency(3000000);                /* AD9959 输出信号:频率 */
        AD9959_enablechannel3();                                                 /* 使能通道3 */
        AD9959_Setwavefrequency(4000000);                /* AD9959 输出信号:频率 */
                                                                                                               
        /***** SDRAM *****/
        fsmc_sdram_test();


  while (1)
  {
               
                uint8_t Key = KEY_Scan(0);
               
                if(ADC_Channels[0].ConvEnd_Flag == 1 && ADC_Channels[1].ConvEnd_Flag == 1 && Key == 4){
                        ADC_Channels[0].ConvEnd_Flag = 0;
                        Key = 0;
                       
//                        HAL_ADC_Stop_DMA(&hadc1);                /* 停止 ADC1_IN3 */
//                        HAL_ADC_Stop_DMA(&hadc3);                /* 停止 ADC3_IN3 */
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
//主程序区:
                       
                        Infinite_FFT(ADC_Channels[0].DMA_floatData, ADC1_CH3_infinite_fft_s, MAX_FFT_N);
                        Infinite_FFT(ADC_Channels[1].DMA_floatData, ADC3_CH3_infinite_fft_s, MAX_FFT_N);
                        for(uint32_t i=0;i<ADC_DMA_SAMPLE_LENGTH;i++){
                                printf("%f,%f,%f,%f\r\n", ADC_Channels[0].DMA_floatData*ZOOM, ADC_Channels[1].DMA_floatData*ZOOM, ADC1_CH3_infinite_fft_s.real, ADC3_CH3_infinite_fft_s.real);
                        }
                       

                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
                       
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
                        HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC_Channels[0].DMA_Buffer, ADC_DMA_SAMPLE_LENGTH);        /* 再次启动 ADC1_IN3 */       
                        HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC_Channels[1].DMA_Buffer, ADC_DMA_SAMPLE_LENGTH);        /* 再次启动 ADC3_IN3 */       
                }
  }
}


ADC存储变量

ADC存储变量

FFT实部虚部

FFT实部虚部



回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2025-3-5 05:02:34 | 显示全部楼层
不使用ADC的数据,单纯的做个随机数据,测试下FFT 65536点
回复

使用道具 举报

6

主题

24

回帖

42

积分

新手上路

积分
42
 楼主| 发表于 2025-3-5 12:11:00 | 显示全部楼层
eric2013 发表于 2025-3-5 05:02
不使用ADC的数据,单纯的做个随机数据,测试下FFT 65536点

使用生成的65536个点数的5kHz的正弦波,是可以进行65536个点的FFT的。
所以ADC还是DMA有什么限制吗?
今天测试的时候又发现个问题,就是在定义全局变量,好像必须用你的方法来把变量内存放到SDRAM里,否则就会硬错误中断
回复

使用道具 举报

6

主题

24

回帖

42

积分

新手上路

积分
42
 楼主| 发表于 2025-3-5 12:23:02 | 显示全部楼层
eric2013 发表于 2025-3-5 05:02
不使用ADC的数据,单纯的做个随机数据,测试下FFT 65536点

噢抱歉,又测试了下,发现65535个元素的数组不能定义在AXISRAM里,换成32768定义在AXISRAM又正常了,感觉65536是个瓶颈啊
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2025-3-5 14:35:09 | 显示全部楼层
sssuuu 发表于 2025-3-5 12:23
噢抱歉,又测试了下,发现65535个元素的数组不能定义在AXISRAM里,换成32768定义在AXISRAM又正常了,感觉 ...

你是不是ADC DMA缓冲大小设置成65536次了,这个通用DMA,每轮最大65535次传输。
回复

使用道具 举报

6

主题

24

回帖

42

积分

新手上路

积分
42
 楼主| 发表于 2025-3-5 15:00:08 | 显示全部楼层
eric2013 发表于 2025-3-5 14:35
你是不是ADC DMA缓冲大小设置成65536次了,这个通用DMA,每轮最大65535次传输。

噢噢原来是这样!改成65535个元素又能正常运行了
顺便在CubeMX里看了看,好像没有别的DMA可用了,应该是补零再FFT了,谢谢硬汉哥
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2025-3-6 09:11:33 | 显示全部楼层
sssuuu 发表于 2025-3-5 15:00
噢噢原来是这样!改成65535个元素又能正常运行了
顺便在CubeMX里看了看,好像没有别的DMA可用了,应该是 ...

可以补0,也可以DMA双缓冲解决。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-13 02:21 , Processed in 0.046777 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表