can't print ADC data at high Sample Rate
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
ā2025-06-10 7:36 AM - last edited on ā2025-06-10 8:06 AM by Andrew Neil
I configured dual DAC synchronous samplingļ¼DMA is in normal mode for data transfer.
When the timer frequency of the ADC is 10KHz, the main cycle can print serial port information, but when the timer frequency is 50KHz, the main cycle does not print ADC data information. What is the reason for this? Below is my cubemx software configuration and related code.
int main()
CallBack:
ADC
DMA
NVIC
Solved! Go to Solution.
- Labels:
-
ADC
-
UART-USART
-
VSCode for STM32
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
ā2025-06-10 8:02 AM
Printing out samples over UART at 50 kHz is a non-starter. The bandwidth is insufficient.
In general, don't put long blocking calls like UART transmissions in your interrupt handlers.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
ā2025-06-10 8:02 AM
Please see How to insert source code - not as images.
A complex system designed from scratch never works and cannot be patched up to make it work.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
ā2025-06-10 8:02 AM
Printing out samples over UART at 50 kHz is a non-starter. The bandwidth is insufficient.
In general, don't put long blocking calls like UART transmissions in your interrupt handlers.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
ā2025-06-10 8:15 AM
/* 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 */
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 ADC_TIM_Clock 84e6 // å®ę¶åØę¶éé¢ē
#define ADC1_TRIGGER htim3
#define ADC_BUFFER_SIZE 128 // å设é2048ē»ę°ę®ļ¼FFTäøč¬č¦2ēå¹ę¬”ļ¼
#define ADC_SampleRate 50e3
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);
}
// RTC_AlarmTypeDef RTCB_sTime;
//ęé®åŗęµčÆ
/* 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 */
// 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));
// DAC_Init();
Key_Init(); //
// HAL_TIM_Base_Start_IT(&htim6);
USART_Printf(&huart1,"reset!\r\n");
ADC_SetSampleRate(&ADC1_TRIGGER,ADC_SampleRate);
HAL_Delay(2000);
HAL_ADC_Start(&hadc2);
HAL_ADCEx_MultiModeStart_DMA(&hadc1,adc_buffer,ADC_BUFFER_SIZE);
HAL_TIM_Base_Start_IT(&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)
{
USART_Printf(&huart1,"ADC Complete!\n");
ADC1_CompleteFlag = 1; //
}
}
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc)
{
if(hadc == &hadc1)
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)
{
}
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
ā2025-06-10 8:32 AM
I still don't understand
My DMA works in normal mode and only starts once after powering up, and no more after that. Just set the flag of the ADC sampling in the ADC callback function. Waiting for the ADC to complete the acquisition in the main cycle, and then printing out the data, what does this have to do with the serial port rate?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
ā2025-06-10 9:20 AM - edited ā2025-06-10 9:24 AM
@smile wrote:what does this have to do with the serial port rate?
12 bit ADC data printed in decimal with a line ending takes max 4 digits and 1 line ending character. So 5 characters.
With 1 startbit,1 stop bit, 8 bit data, you need 10 bit times for 1 byte, so 50 bit times per sample. of your UART. 50ks/s would require 2.5MBaud if data is send back to back.That's very high. You can save a little by switching to 7-bit mode, but you still would need 2.25MBaud
Sending it in binary mode would mean each sample will take 2 bytes. If you combine 2 samples you can send 2 samples in 3 bytes with 1.5 bytes per sample. That would require 750KBaud. Much more doable. Using 1MBaud would add some headroom.
In theory you could even do some type of compression. Such as sending the differences between samples and not the absolute value. And then using a variable length int to save space. In that case a sample would take a little over 1 byte on average, and 2 bytes max.
If latency is acceptable you can save samples in a buffer. Convert them and then send them in batches. I would use the DMA for transmitting.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.
