0

This is my code for DAC using DMA. I want to generate a triangular wave of frequency 8kHz with DAC operating at update rate of 1MSPS. I am using CUBEMX and system work bench.I am using timer trigger for DAC. I am working on stm32L476 discovery board. I am not getting any wave when I try to set the update rate to 1MSPS. When I set update rate to 500ksps, I get triangular wave which has uneven slope. Can anyone tell me what should I do to resolve this and what should I do to get my code running as desired?

#include "main.h"
#include "stm32l4xx_hal.h"
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private variables -------------------------------------------------------
--*/
DAC_HandleTypeDef hdac1;
DMA_HandleTypeDef hdma_dac_ch2;

TIM_HandleTypeDef htim2;

/* USER CODE BEGIN PV */
/* Private variables -------------------------------------------------------
--*/

/* 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_DAC1_Init(void);
static void MX_TIM2_Init(void);

/* USER CODE BEGIN PFP */
/* Private function prototypes ---------------------------------------------
--*/
const uint16_t val[] = {65,130,195,260,325,390,455,520,
    585,650,715,780,846,911,976,1041,
    1106,1171,1236,1301,1366,1431,1496,1561,
    1626,1691,1756,1821,1886,1951,2016,2081,
    2146,2211,2276,2341,2406,2472,2537,2602,
    2667,2732,2797,2862,2927,2992,3057,3122,
    3187,3252,3317,3382,3447,3512,3577,3642,
    3707,3772,3837,3902,3967,4032,4065,4032,
    3967,3902,3837,3772,3707,3642,3577,3512,
    3447,3382,3317,3252,3187,3122,3057,2992,
    2927,2862,2797,2732,2667,2602,2537,2472,
    2406,2341,2276,2211,2146,2081,2016,1951,
    1886,1821,1756,1691,1626,1561,1496,1431,
    1366,1301,1236,1171,1106,1041,976,911,
    846,780,715,650,585,520,455,390,
    325,260,195,130,65,0};
/* USER CODE BEGIN 0 */
/* USER CODE END PFP */

/* USER CODE BEGIN 0 */
/* USER CODE END PFP */

/* USER CODE BEGIN 0 */
/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

int main(void)
    {

  /* USER CODE BEGIN 1 */
    int n=sizeof(val);
    int l=n/sizeof(val[0]);
    /* 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_DAC1_Init();
  MX_TIM2_Init();

   /* USER CODE BEGIN 2 */
   HAL_TIM_Base_Start(&htim2);
   //HAL_DAC_Start(&hdac1, DAC_CHANNEL_2);
   HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_2, (uint32_t*)val, l,                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 */

 }

 /** System Clock Configuration
 */
 void SystemClock_Config(void)
 {

   RCC_OscInitTypeDef RCC_OscInitStruct;
   RCC_ClkInitTypeDef RCC_ClkInitStruct;

     /**Initializes the CPU, AHB and APB busses clocks 
     */
   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
   RCC_OscInitStruct.MSIState = RCC_MSI_ON;
   RCC_OscInitStruct.MSICalibrationValue = 0;
   RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
   RCC_OscInitStruct.PLL.PLLM = 1;
   RCC_OscInitStruct.PLL.PLLN = 40;
   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
   RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
   {
     _Error_Handler(__FILE__, __LINE__);
   }

     /**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_DIV1;
   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV4;

   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
   {
     _Error_Handler(__FILE__, __LINE__);
   }

     /**Configure the main internal regulator output voltage 
     */
   if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) !=      HAL_OK)
   {
     _Error_Handler(__FILE__, __LINE__);
   }

     /**Configure the Systick interrupt time 
     */
   HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

     /**Configure the Systick 
     */
   HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

   /* SysTick_IRQn interrupt configuration */
   HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
 }

 /* DAC1 init function */
 static void MX_DAC1_Init(void)
 {

   DAC_ChannelConfTypeDef sConfig;

     /**DAC Initialization 
     */
   hdac1.Instance = DAC1;
   if (HAL_DAC_Init(&hdac1) != HAL_OK)
   {
     _Error_Handler(__FILE__, __LINE__);
   }

     /**DAC channel OUT2 config 
     */
   sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;
   sConfig.DAC_Trigger = DAC_TRIGGER_T2_TRGO;
   sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
   sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_ENABLE;
   sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY;
   if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_2) != HAL_OK)
   {
     _Error_Handler(__FILE__, __LINE__);
   }

 }

 /* TIM2 init function */
 static void MX_TIM2_Init(void)
 {

   TIM_ClockConfigTypeDef sClockSourceConfig;
   TIM_MasterConfigTypeDef sMasterConfig;

   htim2.Instance = TIM2;
   htim2.Init.Prescaler = 19;
   htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
   htim2.Init.Period = 1;
   htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
   if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
   {
     _Error_Handler(__FILE__, __LINE__);
   }

   sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
   if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
   {
     _Error_Handler(__FILE__, __LINE__);
   }

   sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
   if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) !=      HAL_OK)
   {
     _Error_Handler(__FILE__, __LINE__);
   }

 }

 /** 
   * Enable DMA controller clock
        */
 static void MX_DMA_Init(void) 
 {
   /* DMA controller clock enable */
   __HAL_RCC_DMA1_CLK_ENABLE();

        /* DMA interrupt init */
   /* DMA1_Channel4_IRQn interrupt configuration */
        HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 0);
   HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);

 }

 /** Configure pins as 
         * Analog 
              * Input 
              * Output
         * EVENT_OUT
         * EXTI
 */
 static void MX_GPIO_Init(void)
 {

   GPIO_InitTypeDef GPIO_InitStruct;

   /* GPIO Ports Clock Enable */
        __HAL_RCC_GPIOA_CLK_ENABLE();

   /*Configure GPIO pin : PA4 */
   GPIO_InitStruct.Pin = GPIO_PIN_4;
   GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
   GPIO_InitStruct.Pull = GPIO_NOPULL;
   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

 }

 /* USER CODE BEGIN 4 */

 /* USER CODE END 4 */

 /**
        * @brief  This function is executed in case of error occurrence.
   * @param  None
   * @retval None
   */
      void _Error_Handler(char * file, int line)
 {
   /* USER CODE BEGIN Error_Handler_Debug */
   /* User can add his own implementation to report the HAL error return      state */
   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
user8398475
  • 61
  • 2
  • 7
  • Using "easy to use" HAL is always complicated and time consuming without the guarantee to be successful. – 0___________ Oct 24 '17 at 11:08
  • Can you please have a look at my code and tell me if there is anything wrong? Because I am learning to HAL. So I need to find where the problem is. – user8398475 Oct 26 '17 at 04:24

2 Answers2

0

It is the version for the STM32 with DMA channels and one DAC with two channels. Easy to ammend for your micro

void StartDAC(DAC_TypeDef *dac, int DACchannel, uint16_t Nsamples, uint16_t *samples, uint16_t psc, uint16_t arr)
{

    DMA_Channel_TypeDef *DMA_Channel = !DACchannel ? DMA2_Channel3 : DMA2_Channel4;
    TIM_TypeDef *tim = !DACchannel ? TIM6 : TIM7;

    DMA_Channel->CCR = 0;
    if (!DACchannel)
    {
        dac->CR &= ~(DAC_CR_DMAUDRIE1 | DAC_CR_DMAEN1);
        dac->CR |= (DAC_CR_DMAUDRIE1 | DAC_CR_DMAEN1);
    }
    else
    {
        dac->CR &= ~(DAC_CR_DMAUDRIE2 | DAC_CR_DMAEN2);
        dac->CR |= (DAC_CR_DMAUDRIE2 | DAC_CR_DMAEN2);
    }
    DMA_Channel->CNDTR = Nsamples;
    DMA_Channel->CMAR = (uint32_t)samples;
    DMA_Channel->CPAR = !(DACchannel) ? (uint32_t)&DAC->DHR12R1 : (uint32_t)&DAC->DHR12R2;
    DMA_Channel->CCR |= DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 | DMA_CCR_MINC | DMA_CCR_CIRC | DMA_CCR_EN | DMA_CCR_TEIE | DMA_CCR_DIR;
    tim->DIER = TIM_DIER_UDE;// | TIM_DIER_UIE;
    tim->CR2 |= TIM_CR2_MMS_1;
    tim->PSC = psc;
    tim->ARR = arr;
    /* tim clock frequency / ((psc + 1) * (arr + 1) * nsamples)  == frequency of the  generated signal    - do the calculations yourself*/
    tim->CR1 |= TIM_CR1_CEN;
}
0___________
  • 60,014
  • 4
  • 34
  • 74
0

Well I just figured out where the problem is. DAC speed is limited when it is connected to other peripherals along with the external output pin. To use DAC at higher speeds, the DAC should be connected only to external pin. At least that is what I found. Previously, I had selected the option to connect the DAC to external pin and on chip peripherals. So I couldn't use DAC at high speed. But then I selected the option to external pin only(DAC connected to external pin only), it solved the problem and DAC works just fine. Also make sure there are no resistor capacitor circuits in series with this DAC output pin, else the output wave may get disturbed.

user8398475
  • 61
  • 2
  • 7