cancel
Showing results for 
Search instead for 
Did you mean: 

ADC SampleRate

smile
Associate II

I wonder why I have data in the buffer when my sample rate is 30KHz and 0 when the sample rate is 50KHz.

f99145d781a5fcb8359072aa8206816.png
f1be29b49f1cb0445c3628c3ac7be42.png

 

b165ac61fbe58954536a4774397358b.png

cee005af684f9800dd5c4568c02061d.png

44ade4a41c9f3f4e07ea463d79104d2.png

8ab135ed9500848d02bf1e3b02945af.png

  


My code:

/* 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 "spi.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
//#include "AD9833.h"
// #include "Key.h"  
// #include "LCD.h"
// #include "LowPowerCtrl.h"
// // #include "stm32f4xx_hal_rcc.h"
// #include "SignalGenerator.h"
// #include "SignalSampling.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 */
#define ADC1_TRIGGER htim3

uint8_t ADC1_CompleteFlag = 0; // ADC1转换完成标志位
uint8_t ADC2_CompleteFlag = 0; // ADC2转换完成标志位

#define ADC_TIM_Clock 84e6 // 定时器时钟频率

#define ADC_BUFFER_SIZE 1024  // 假设采2048组数据(FFT一般要2的幂次)

#define ADC_SampleRate 30e3

uint32_t adc_buffer[ADC_BUFFER_SIZE]; // 注意是uint32_t,因为双ADC打包成32位

uint16_t adc_buffer1[ADC_BUFFER_SIZE]; 
uint16_t adc_buffer2[ADC_BUFFER_SIZE]; 


void ADC_SetSampleRate(TIM_HandleTypeDef *htim, float sample_rate)
{
    uint32_t Timer_Clock = ADC_TIM_Clock / (htim->Instance->PSC + 1);
    uint32_t timer_reload_value = (uint32_t)(Timer_Clock / sample_rate) - 1;
    if (timer_reload_value < 1) timer_reload_value = 1;

    HAL_TIM_Base_Stop(htim);                   // 安全:暂停 TIM
    __HAL_TIM_SET_AUTORELOAD(htim, timer_reload_value);
    __HAL_TIM_SET_COUNTER(htim, 0);            // 重置计数器
    HAL_TIM_Base_Start(htim);                  // 重新启动 TIM

    USART_Printf(&huart1, "ADC TimerClock=%lu, ARR=%lu, SampleRate=%.1f Hz\r\n",
                 Timer_Clock, timer_reload_value, sample_rate);
}


/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

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

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SPI1_Init();
  MX_USART1_UART_Init();
  MX_TIM2_Init();
  MX_TIM1_Init();
  MX_ADC1_Init();
  MX_ADC2_Init();
  MX_DAC_Init();
  MX_TIM3_Init();
  MX_TIM4_Init();
  MX_TIM5_Init();
  MX_TIM6_Init();
  /* USER CODE BEGIN 2 */





  ADC_SetSampleRate(&ADC1_TRIGGER,ADC_SampleRate);
  HAL_ADC_Start(&hadc2);
  HAL_ADCEx_MultiModeStart_DMA(&hadc1,adc_buffer,ADC_BUFFER_SIZE);
  HAL_TIM_Base_Start(&ADC1_TRIGGER);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {


    if(ADC1_CompleteFlag == 1)
    {
      

      for(uint16_t i = 0 ; i< ADC_BUFFER_SIZE ; i++)
      {
        adc_buffer1[i] = (adc_buffer[i] & 0x0000FFFF);
        adc_buffer2[i] = (adc_buffer[i] & 0xFFFF0000) >> 16;

        // USART_Printf(&huart1,"%d,%d,%d\n",adc_buffer[i],adc_buffer1[i],adc_buffer2[i]);
        // USART_Printf(&huart1,"%d,%d\n",adc_buffer1[i],adc_buffer2[i]);
        //USART_Printf(&huart1,"%d\n",adc_buffer2[i]);
      }
      
      ADC1_CompleteFlag =  0;
    }
      



    
      // Key_Process();  

      // HAL_Delay(10); 




    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }

  /** Enables the Clock Security System
  */
  HAL_RCC_EnableCSS();
}

/* USER CODE BEGIN 4 */


void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
  if(hadc == &hadc1)
  {
    HAL_TIM_Base_Stop(&ADC1_TRIGGER);
    // USART_Printf(&huart1,"ADC Complete!\n");
    ADC1_CompleteFlag = 1; // 

  }

}


// void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
// {
//   if(htim == &ADC1_TRIGGER)
//   {
//     // USART_Printf(&huart1, "ADC_Timer Interrupt\n");
//   }

//   if(htim == &htim5)
//   {


//   }

//   if(htim == &htim6)
//   {
    
//   }
// }

  // while(HAL_GPIO_ReadPin(WKUP_GPIO_Port,WKUP_Pin) == GPIO_PIN_SET);  

  // if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB)) 
  // { 
  //      USART_Printf(&huart1,"IF:SB:%d  WU:%d\n",__HAL_PWR_GET_FLAG(PWR_FLAG_SB),__HAL_PWR_GET_FLAG(PWR_FLAG_WU));
  //     __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);  // 
  //     __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);  // 
      
  // }

  // HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
  // USART_Printf(&huart1,"SB:%d  WU:%d\n",__HAL_PWR_GET_FLAG(PWR_FLAG_SB),__HAL_PWR_GET_FLAG(PWR_FLAG_WU));


// define:
//   #define ADC_BUFFER_SIZE 1024  // 假设采2048组数据(FFT一般要2的幂次)
//   uint32_t adc_buffer[ADC_BUFFER_SIZE]; // 注意是uint32_t,因为双ADC打包成32位
//   uint16_t adc_buffer1[ADC_BUFFER_SIZE]; 
//   uint16_t adc_buffer2[ADC_BUFFER_SIZE]; 
//   #define ADC1_TRIGGER htim3
//   #define ADC_TIM_Clock 84e6
//   #define ADC_SampleRate 10e3
//   void ADC_SetSampleRate(TIM_HandleTypeDef *htim, float sample_rate)
//   {
//       uint32_t Timer_Clock = ADC_TIM_Clock / (htim->Instance->PSC + 1);
//       uint32_t timer_reload_value = (uint32_t)(Timer_Clock / sample_rate) - 1;
//       if (timer_reload_value < 1) timer_reload_value = 1;

//       HAL_TIM_Base_Stop(htim);                   // 安全:暂停 TIM
//       __HAL_TIM_SET_AUTORELOAD(htim, timer_reload_value);
//       __HAL_TIM_SET_COUNTER(htim, 0);            // 重置计数器
//       HAL_TIM_Base_Start(htim);                  // 重新启动 TIM

//       USART_Printf(&huart1, "ADC TimerClock=%lu, ARR=%lu, SampleRate=%.1f Hz\r\n",
//                   Timer_Clock, timer_reload_value, sample_rate);
//   }

// // int main()
//   ADC_SetSampleRate(&ADC1_TRIGGER,ADC_SampleRate);
//   HAL_ADC_Start(&hadc2);
//   HAL_ADCEx_MultiModeStart_DMA(&hadc1,adc_buffer,ADC_BUFFER_SIZE);
//   HAL_TIM_Base_Start(&ADC1_TRIGGER);
//   while (1)
//   {


//     if(ADC1_CompleteFlag == 1)
//     {
//       for(uint16_t i = 0 ; i< ADC_BUFFER_SIZE ; i++)
//       {
//         adc_buffer1[i] = (adc_buffer[i] & 0x0000FFFF);
//         adc_buffer2[i] = (adc_buffer[i] & 0xFFFF0000) >> 16;

//         //USART_Printf(&huart1,"%d,%d,%d\n",adc_buffer[i],adc_buffer1[i],adc_buffer2[i]);
//         //USART_Printf(&huart1,"%d,%d\n",adc_buffer1[i],adc_buffer2[i]);
//         USART_Printf(&huart1,"%d\n",adc_buffer2[i]);
//       }
//       ADC1_CompleteFlag =  0;
//     }
//   }

  
//   void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
// {
//   if(hadc == &hadc1)
//   {
//     ADC1_CompleteFlag = 1; // 设置ADC1转换完成标志位

//   }

// }
//   ADC TimerClock=84000000, ARR=8399, SampleRate=10000.0 Hz
// ADC TimerClock=84000000, ARR=2099, SampleRate=40000.0 Hz
// ADC TimerClock=84000000, ARR=1679, SampleRate=50000.0 Hz

// 为什么采样率设置为50K时,主循环没有打印串口数据,DMA是normal模式,排除串口速度跟不上
/* USER CODE END 4 */

/**
  * @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 */



ADC:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    adc.c
  * @brief   This file provides code for the configuration
  *          of the ADC instances.
  ******************************************************************************
  * @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 "adc.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

ADC_HandleTypeDef hadc1;
ADC_HandleTypeDef hadc2;
DMA_HandleTypeDef hdma_adc1;

/* ADC1 init function */
void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_MultiModeTypeDef multimode = {0};
  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */

  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure the ADC multi-mode
  */
  multimode.Mode = ADC_DUALMODE_REGSIMULT;
  multimode.DMAAccessMode = ADC_DMAACCESSMODE_2;
  multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_8;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}
/* ADC2 init function */
void MX_ADC2_Init(void)
{

  /* USER CODE BEGIN ADC2_Init 0 */

  /* USER CODE END ADC2_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC2_Init 1 */

  /* USER CODE END ADC2_Init 1 */

  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  */
  hadc2.Instance = ADC2;
  hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc2.Init.Resolution = ADC_RESOLUTION_12B;
  hadc2.Init.ScanConvMode = DISABLE;
  hadc2.Init.ContinuousConvMode = DISABLE;
  hadc2.Init.DiscontinuousConvMode = DISABLE;
  hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc2.Init.NbrOfConversion = 1;
  hadc2.Init.DMAContinuousRequests = DISABLE;
  hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc2) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_9;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC2_Init 2 */

  /* USER CODE END ADC2_Init 2 */

}

void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(adcHandle->Instance==ADC1)
  {
  /* USER CODE BEGIN ADC1_MspInit 0 */

  /* USER CODE END ADC1_MspInit 0 */
    /* ADC1 clock enable */
    __HAL_RCC_ADC1_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**ADC1 GPIO Configuration
    PB0     ------> ADC1_IN8
    */
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* ADC1 DMA Init */
    /* ADC1 Init */
    hdma_adc1.Instance = DMA2_Stream0;
    hdma_adc1.Init.Channel = DMA_CHANNEL_0;
    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_WORD;
    hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_adc1.Init.Mode = DMA_NORMAL;
    hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
    hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1);

  /* USER CODE BEGIN ADC1_MspInit 1 */

  /* USER CODE END ADC1_MspInit 1 */
  }
  else if(adcHandle->Instance==ADC2)
  {
  /* USER CODE BEGIN ADC2_MspInit 0 */

  /* USER CODE END ADC2_MspInit 0 */
    /* ADC2 clock enable */
    __HAL_RCC_ADC2_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**ADC2 GPIO Configuration
    PB1     ------> ADC2_IN9
    */
    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN ADC2_MspInit 1 */

  /* USER CODE END ADC2_MspInit 1 */
  }
}

void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{

  if(adcHandle->Instance==ADC1)
  {
  /* USER CODE BEGIN ADC1_MspDeInit 0 */

  /* USER CODE END ADC1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_ADC1_CLK_DISABLE();

    /**ADC1 GPIO Configuration
    PB0     ------> ADC1_IN8
    */
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_0);

    /* ADC1 DMA DeInit */
    HAL_DMA_DeInit(adcHandle->DMA_Handle);
  /* USER CODE BEGIN ADC1_MspDeInit 1 */

  /* USER CODE END ADC1_MspDeInit 1 */
  }
  else if(adcHandle->Instance==ADC2)
  {
  /* USER CODE BEGIN ADC2_MspDeInit 0 */

  /* USER CODE END ADC2_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_ADC2_CLK_DISABLE();

    /**ADC2 GPIO Configuration
    PB1     ------> ADC2_IN9
    */
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_1);

  /* USER CODE BEGIN ADC2_MspDeInit 1 */

  /* USER CODE END ADC2_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

 

1 REPLY 1
KnarfB
Super User

For small Timer_Clock  and high sample_rate, (uint32_t)(Timer_Clock / sample_rate) will be zero. Subtracting 1 yields an overflow because of unsigned, which results in a huge number. This may effectively stop your ADC capture.

hth

KnarfB