cancel
Showing results for 
Search instead for 
Did you mean: 

High frequency DAC signal generation

JFric
Associate II

Hi, i am working on signal wave generation on the STM32L053 Discovery kit. I'd like to see the maximum frequency of signal generation (a sinus with 100 samples using DMA).

But the problem is : i cannot reach over ~20kHz, which is not even in the ultrasound domain.

The configuration of the peripherals must be wrong so, and I am using CubeMX to generate Low Layer code.

The system clock is PLLCLK at 32MHz (the maximum for AHB and APB1), and the DAC is triggered on the Timer6 trigger output.

I don't really understand the source of the problem. May someone can help me ? Thanks a lot !0690X000008AH1fQAG.jpg

Here is the code i used :

PS : the picture shows a problem i have when i change the SYSCLK frequency from under 4MHz to 8, 16 or 32 MHz. The sinus wave observed is at the right frequency but there are some timelaps where the potential is 0.

#include "main.h"
 
DAC_HandleTypeDef hdac;
DMA_HandleTypeDef hdma_dac_ch1;
 
TIM_HandleTypeDef htim6;
 
const uint8_t sinusValue100[100] = {144,	152,	160,	168,	175,	182,	190,	197,	203,	210,
                                    216,	221,	227,	232,	236,	240,	244,	247,	250,	252,
                                    254,	255,	255,	255,	255,	255,	254,	252,	250,	247,
                                    244,	240,	236,	232,	227,	221,	216,	210,	203,	197,	
                                    190,	182,	175,	168,	160,	152,	144,	136,	128,	120,	
                                    112,	104,	96,	88,	81,	74,	66,	59,	53,	46,	
                                    40,	35,	29,	24,	20,	16,	12,	9,	6,	4,	
                                    2,	1,	0,	0,	0,	1,	2,	4,	6,	9,	
                                    12,	16,	20,	24,	29,	35,	40,	46,	53,	59,	
                                      66,	74,	81,	88,	96,	104,	112,	120,	128, 144};
 
const uint8_t signalResolution = 100;
const uint16_t outputFrequency = 5000;
const uint32_t CNT_FREQ = 32000000/4;
 
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_DAC_Init(void);
static void MX_TIM6_Init(void);
 
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_DAC_Init();
  MX_TIM6_Init();
 
  /* Infinite loop */
  while (1)
  {
 
  }
}
 
/**
  * @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_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /**Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_4;
  RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /**Initializes the CPU, AHB and APB busses 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_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}
 
/**
  * @brief DAC Initialization Function
  * @param None
  * @retval None
  */
static void MX_DAC_Init(void)
{
 
  DAC_ChannelConfTypeDef sConfig = {0};
 
  /**DAC Initialization 
  */
  hdac.Instance = DAC;
  if (HAL_DAC_Init(&hdac) != HAL_OK)
  {
    Error_Handler();
  }
  /**DAC channel OUT1 config 
  */
  sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;
  if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
 
  if (HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)sinusValue100, 100, DAC_ALIGN_8B_R) != HAL_OK)
  {
    Error_Handler();
  }
  
 
 
}
 
/**
  * @brief TIM6 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM6_Init(void)
{
 
  TIM_MasterConfigTypeDef sMasterConfig = {0};
 
  htim6.Instance = TIM6;
  htim6.Init.Prescaler = 0;
  htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim6.Init.Period =  0xF;//CNT_FREQ/(signalResolution*outputFrequency);
  htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
 
  HAL_TIM_Base_Start(&htim6);
 
}
 
/** 
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void) 
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();
 
  /* DMA interrupt init */
  /* DMA1_Channel2_3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
 
}
 
/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
 
}
 
/**
  * @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 */
 
  /* USER CODE END Error_Handler_Debug */
}

6 REPLIES 6

Hello!

"'d like to see the maximum frequency of signal generation (a sinus with 100 samples using DMA). "

According to DS (DocID025844 Rev 8), for max vcc the max Conversion Time gives 1,14 Msps, so with 100 samples per cycle, max theoretical freq will be about 11 KHz.

JFric
Associate II

Hi,

1.14 Msps is the maximum frequency for the ADC, the DAC is around 1Msps. Does it mean that for a sinus with 100 samples (the minimum for a correct waveform signal) it's impossible to reach over 10kHz?

I think it is really low.

But yet, i don't even manage to have a good sinus at 10kHz, i always have the problem mentionned on the picture.

Thanks !

JFric
Associate II

Update :

After some tests, i manage to have some signal (with only 10 samples) at around 40kHz.

But when i want to change the HCLK to 8MHz, i have the issues mentionned on the topic.

More, i try to play with the Tim6.Period to fix the signal frequency. I cannot fix it under 0x8, or i'll have a constant signal.

> 1.14 Msps is the maximum frequency for the ADC, the DAC is around 1Msps. Does it mean that for a sinus with 100 samples (the minimum for a correct waveform signal) it's impossible to reach over 10kHz?

As noted several times here, the settling time of the DAC output is in the range of several microseconds, resulting in a much lower effective bandwidth.

rclar.6
Associate III

I have a similar issue with the STM32G474. I have the DMA on a circular buffer to DAC3 outputting to OPAMP3. This allows a 15 M sample theoretical max (66nS). I have it set to 150nS and it works well for 2kHz and 4kHz at 1.6V pk to pk. I see the full 1.6V pk to pk on the oscilloscope. When I take the frequency up to around 50kHz I notice the amplitude attenuating. When the signal is at 200 kHz (with 1.6V pk to pk signals in the DAC output buffer) the signal attenuates to around 0.4V pk to pk. I have tried the fast slew rate option but this makes no practical difference.

S.Ma
Principal

Check in the DS the max slew rate vs the waveform, then the sample output rate x nb of samples vs desired sine frequency. Check analog buffer is enabled. If not clamp by slewrates, nb of samples per period need to be shrunk.