Skip to main content
Visitor II
February 26, 2024
Question

Need to know capability of STM32L073RZ board for generating sinusoidal 12.5 MHz burst signal.

  • February 26, 2024
  • 4 replies
  • 4987 views

Hi All ,

I want to generate the following specification of the burst signal from the STM32L073RZ board  , need to know is that possible? Or else need your valuable suggestion whether it is possible from other STM32 boards?

 Parameters

Values /Settings

Waveform

Sine

Offset

0V

Phase

0 deg

Amplitude

 2mV

Frequency

12.5MHz

Burst Cycle #

 150

Trigger

 External

Load Impedance

 50 ohm

 

 

    This topic has been closed for replies.

    4 replies

    Graduate II
    February 26, 2024

    Generaly not. But you can generate 12.5MHz squarewave and the filter out higher harmonics by low pass filter. 

     

    Visitor II
    February 26, 2024

    Are you meaning ,do I need to integrate the LPF to convert the generated Square wave to Sinusoidal? Please confirm. Also  , can the amplitude of 2mV be achieved and load impedance of 50 ohms?

    Graduate II
    February 26, 2024

    It means only that you cannot generate 12.5MHz sine using embedded (and probably also external) DAC from L073. You can use multiple ways, like find some external DDS chip/module etc. And if your frequency is fixed, then probably some kind of active/passive first/second/third order LPF can be used. Depends on quality of sine you need. Amplitude of two mV into 50Ohm (only about 40uA) is probably OK with passive filters. But i am not an expert in "filter desing" - use simulator, or filter design calculator from AD, TI etc.

    Visitor II
    February 26, 2024
    Graduate II
    February 26, 2024

    I am not sure how that "burst" should look like ... few periods, few milions of periods ? How fast it has to stop, how fast it has to start ? It is triggered by some kind of external signal, or not etc. Probably consider also use of some kind of RF switch at DDS output as gate to better control of burst. 

    Graduate
    February 26, 2024

    It would require some clarification.

    1. Is it necessary for the sine signal to start with a phase shift of 0 degrees?

    2. Is the critical value 150 pulses?

    3. What is the maximum acceptable value of the delay between the trigger pulse and the start of signal generation.

    Visitor II
    February 27, 2024

    Hi , Please find my in-line response.

     

    1. Is it necessary for the sine signal to start with a phase shift of 0 degrees?

    Yes , it is necessary for the sine signal to start with a phase of 0 deg.

    2. Is the critical value 150 pulses?

    Not critical.

    3. What is the maximum acceptable value of the delay between the trigger pulse and the start of signal generation

    Not sure about the delay between trigger pulse , will check and come back.

     

    Also , I tried to generate a 8 MHz sine wave using DAC , DMA and timer of  STM32 L073RZ board ,  the clock configuration for all the timer has been set to 32 MHz and prescalar and period have been set as "1" and samples kept as "100" , according to the formula for the signal frequency : 32 M / 1+1 = 8 MHz , but when I probe the PA4 pin in oscilloscope , I am getting only 40 KHz of sine wave . Could somebody point me , where I am wrong , below is the code generated.

     

    /* USER CODE BEGIN Header */
    /**
      ******************************************************************************
      * @file           : main.c
      * @brief          : Main program body
      ******************************************************************************
      * @attention
      *
      * Copyright (c) 2024 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 "math.h"
    uint32_t sine_val[100];
     
    #define PI 3.1415926
     
    void get_sineval ()
    {
    for (int i=0; i<100; i++)
    {
    sine_val[i] = ((sin(i*2*PI/100) + 1)*(4096/2));
    }
    }
    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
     
    /* 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 ---------------------------------------------------------*/
     DAC_HandleTypeDef hdac;
    DMA_HandleTypeDef hdma_dac_ch1;
     
    TIM_HandleTypeDef htim2;
     
    /* USER CODE BEGIN PV */
     
    /* USER CODE END PV */
     
    /* 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_TIM2_Init(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_DAC_Init();
      MX_TIM2_Init();
      /* USER CODE BEGIN 2 */
      HAL_TIM_Base_Start(&htim2);
     
      get_sineval();
     
    HAL_DAC_Start_DMA(&hdac, DAC1_CHANNEL_1, sine_val, 100, DAC_ALIGN_12B_R);
      /* USER CODE END 2 */
     
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* 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_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_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_6;
      RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_3;
      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_DIV1;
      RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
     
      if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
      {
        Error_Handler();
      }
    }
     
    /**
      * @brief DAC Initialization Function
      * @PAram None
      * @retval None
      */
    static void MX_DAC_Init(void)
    {
     
      /* USER CODE BEGIN DAC_Init 0 */
     
      /* USER CODE END DAC_Init 0 */
     
      DAC_ChannelConfTypeDef sConfig = {0};
     
      /* USER CODE BEGIN DAC_Init 1 */
     
      /* USER CODE END DAC_Init 1 */
     
      /** DAC Initialization
      */
      hdac.Instance = DAC;
      if (HAL_DAC_Init(&hdac) != HAL_OK)
      {
        Error_Handler();
      }
     
      /** DAC channel OUT1 config
      */
      sConfig.DAC_Trigger = DAC_TRIGGER_T2_TRGO;
      sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
      if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1) != HAL_OK)
      {
        Error_Handler();
      }
      /* USER CODE BEGIN DAC_Init 2 */
     
      /* USER CODE END DAC_Init 2 */
     
    }
     
    /**
      * @brief TIM2 Initialization Function
      * @PAram None
      * @retval None
      */
    static void MX_TIM2_Init(void)
    {
     
      /* USER CODE BEGIN TIM2_Init 0 */
     
      /* USER CODE END TIM2_Init 0 */
     
      TIM_ClockConfigTypeDef sClockSourceConfig = {0};
      TIM_MasterConfigTypeDef sMasterConfig = {0};
     
      /* USER CODE BEGIN TIM2_Init 1 */
     
      /* USER CODE END TIM2_Init 1 */
      htim2.Instance = TIM2;
      htim2.Init.Prescaler = 1;
      htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
      htim2.Init.Period = 1;
      htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
      htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
      if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
      {
        Error_Handler();
      }
      sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
      if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
      {
        Error_Handler();
      }
      sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
      sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
      if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
      {
        Error_Handler();
      }
      /* USER CODE BEGIN TIM2_Init 2 */
     
      /* USER CODE END TIM2_Init 2 */
     
    }
     
    /**
      * 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();
     
    }
     
    /* USER CODE BEGIN 4 */
     
    /* 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 */

     

    Visitor II
    February 27, 2024

    How do you try to get a sinusoidal signal with 12.5 MHz on your MCU/board?

    Using the MCU internal DAC?

    As I see in STM32L073xx datasheet: the DAC has a max. update rate of 1 MSps (page 114/163).

    Considering the Nyquist criteria (Shannon Theorem): you need 2xfs, so two values per period: this can generate just 500 KHz. But it would look like a tri-angular signal (not a sine wave).

    For a nice 12.5 MHz sine wave, out of a DAC, you might need (at least) 10 samples per period: so, the DAC has to support 12.5 MHz * 10 - 125 MHz as update rate.
    But 10 samples per period is still pretty bad - a huge THD (not a smooth sine wave yet).

    Or, as other have mentioned here: you generate 12.5 MHz as digital - but you have to do an external low pass filter: the cut-off frequency is somewhere at 15 MHz: your sine wave might be attenuated (check the need for the 3dB cut-off frequency and how "sharp" your filter has to be, maybe N-orders).
    With a simple 1-order RC filter, used to "smooth" the 12.5 MHz to a sine wave - you will get so many harmonics into the resulting signal (still almost a rectangle).

    Also a simple "cross-check":

    • your MCU runs with 32 MHz - the MCU core clock
    • but you want to get a 12.5 MHz sine wave (never mind if via DAC or as digital GPIO and low-pass filter afterwards)
    • 12.5 MHz is already 2.5 MCU clock cycles ONLY!
    • how can you write so fast to any peripheral (like a GPIO pin, for 12.5 MHz rectangle, or even every 2 MCU clock cycles to a DAC with a new value)?

    IMPOSSIBLE!

    Assume, you need at least 3..5 clock cycles just to do one simple C-code line as instruction. You are already "behind" the speed you need for ANY 12.5 MHz signal (even it would be a rectangle signal on a GPIO pin).

    NO WAY!

    For a sine out of a DAC, with 12.5 MHz - you had to write (at least) 10 values per period, so with 125 MHz a new value into the DAC. But this is already way above your MCU core clock.

    And even trying to toggle a GPIO pin with 12.5 MHz on an MCU which runs "just" with 32 MHz - quite impossible (and it would be a "full speed looping" - nothing else can be done).

     

    Graduate II
    February 27, 2024

    A) you have wrong clock configuration
    B) you have wrong timer configuration

    Use MCO feature and PLL instead of Timer. It will have better frequency resolution.

    Visitor II
    February 28, 2024

    Hi , Please find below the clock configuration , I have used TIM2_CH1 for generating PWM signal @ PA0 pin. All timers are configured to 32 MHz only, In my clock configuration , the MCO source is not selectable ( greyed out). And the below code is what I used for the same. Please guide me  how to get the desired frequency of PWM signal( atleast 16 MHz) . FYI, I am using STM32 L073RZ board.

     

    The value of htim2.Init.Period was changed many times and at max I have got only 580 Khz signal by setting this value as "55-1". 

     

    Dineshkumar_0-1709090151799.png

    static void MX_TIM2_Init(void)
    {

    /* USER CODE BEGIN TIM2_Init 0 */

    /* USER CODE END TIM2_Init 0 */

    TIM_ClockConfigTypeDef sClockSourceConfig = {0};
    TIM_MasterConfigTypeDef sMasterConfig = {0};
    TIM_OC_InitTypeDef sConfigOC = {0};

    /* USER CODE BEGIN TIM2_Init 1 */

    /* USER CODE END TIM2_Init 1 */
    htim2.Instance = TIM2;
    htim2.Init.Prescaler = 0;
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = 55-1;
    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
    {
    Error_Handler();
    }
    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
    if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
    {
    Error_Handler();
    }
    if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
    {
    Error_Handler();
    }
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
    {
    Error_Handler();
    }
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 35;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
    {
    Error_Handler();
    }
    /* USER CODE BEGIN TIM2_Init 2 */

    /* USER CODE END TIM2_Init 2 */
    HAL_TIM_MspPostInit(&htim2);

    }

    Graduate II
    February 28, 2024

    Search tutorials to use MCO ... for example:
    https://community.st.com/t5/missing-articles/how-can-i-output-a-clock-signal-to-the-stm32-s-mco-pin/td-p/49583
    If your timer "period" is set to 55, then its frequency will be 32MHz/55=582kHz... what is wrong with that ? :)
    Looks like you need to study the basics. Take a look on series of STM32 MOOC courses
    https://www.youtube.com/watch?v=sQCqVBuq-gA&list=PLnMKNibPkDnGtuIl5v0CvC81Am7SKpj02
    and STM32 "hands on" courses (youtube). You can also search for some books. For example "Mastering the STM32 Microcontroller by Carmine Noviello" is good one. Also you can find good tutorials on web. for example:
    https://embedded.fm/blog/embedded-wednesdays