cancel
Showing results for 
Search instead for 
Did you mean: 

Cannot get Cube DAC/TIM/DMA Signal Generation example working

Lars Beiderbecke
Senior III

I've adapted the DAC signal generation example from the HAL samples to my project, but I cannot get any signal from DAC2.

Using CubeMX, I configured TIM6 and DMA1 like this:

/* Includes ------------------------------------------------------------------*/
#include "dac.h"
 
/* USER CODE BEGIN 0 */
 
/* USER CODE END 0 */
 
DAC_HandleTypeDef hdac;
DMA_HandleTypeDef hdma_dac2;
 
/* DAC init function */
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 OUT2 config 
  */
  sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
  if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
 
}
 
void HAL_DAC_MspInit(DAC_HandleTypeDef* dacHandle)
{
 
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(dacHandle->Instance==DAC)
  {
  /* USER CODE BEGIN DAC_MspInit 0 */
 
  /* USER CODE END DAC_MspInit 0 */
    /* DAC clock enable */
    __HAL_RCC_DAC_CLK_ENABLE();
  
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**DAC GPIO Configuration    
    PA5     ------> DAC_OUT2 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
    /* DAC DMA Init */
    /* DAC2 Init */
    hdma_dac2.Instance = DMA1_Stream6;
    hdma_dac2.Init.Channel = DMA_CHANNEL_7;
    hdma_dac2.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_dac2.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_dac2.Init.MemInc = DMA_MINC_ENABLE;
    hdma_dac2.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_dac2.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_dac2.Init.Mode = DMA_CIRCULAR;
    hdma_dac2.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_dac2.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_dac2) != HAL_OK)
    {
      Error_Handler();
    }
 
    __HAL_LINKDMA(dacHandle,DMA_Handle2,hdma_dac2);
 
    /* DAC interrupt Init */
    HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
  /* USER CODE BEGIN DAC_MspInit 1 */
 
  /* USER CODE END DAC_MspInit 1 */
  }
}
 
void HAL_DAC_MspDeInit(DAC_HandleTypeDef* dacHandle)
{
 
  if(dacHandle->Instance==DAC)
  {
  /* USER CODE BEGIN DAC_MspDeInit 0 */
 
  /* USER CODE END DAC_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_DAC_CLK_DISABLE();
  
    /**DAC GPIO Configuration    
    PA5     ------> DAC_OUT2 
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5);
 
    /* DAC DMA DeInit */
    HAL_DMA_DeInit(dacHandle->DMA_Handle2);
 
    /* DAC interrupt Deinit */
  /* USER CODE BEGIN DAC:TIM6_DAC_IRQn disable */
    /**
    * Uncomment the line below to disable the "TIM6_DAC_IRQn" interrupt
    * Be aware, disabling shared interrupt may affect other IPs
    */
    /* HAL_NVIC_DisableIRQ(TIM6_DAC_IRQn); */
  /* USER CODE END DAC:TIM6_DAC_IRQn disable */
 
  /* USER CODE BEGIN DAC_MspDeInit 1 */
 
  /* USER CODE END DAC_MspDeInit 1 */
  }
} 
 
/* USER CODE BEGIN 1 */
 
/* USER CODE END 1 */
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

and

void MX_TIM6_Init(void)
{
  TIM_MasterConfigTypeDef sMasterConfig = {0};
 
  htim6.Instance = TIM6;
  htim6.Init.Prescaler = 44898;
  htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim6.Init.Period = 21;
  htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
 
}
 
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
 
  if(tim_baseHandle->Instance==TIM2)
  {
  /* USER CODE BEGIN TIM2_MspInit 0 */
 
  /* USER CODE END TIM2_MspInit 0 */
    /* TIM2 clock enable */
    __HAL_RCC_TIM2_CLK_ENABLE();
  /* USER CODE BEGIN TIM2_MspInit 1 */
 
  /* USER CODE END TIM2_MspInit 1 */
  }
  else if(tim_baseHandle->Instance==TIM6)
  {
  /* USER CODE BEGIN TIM6_MspInit 0 */
 
  /* USER CODE END TIM6_MspInit 0 */
    /* TIM6 clock enable */
    __HAL_RCC_TIM6_CLK_ENABLE();
 
    /* TIM6 interrupt Init */
    HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
  /* USER CODE BEGIN TIM6_MspInit 1 */
 
  /* USER CODE END TIM6_MspInit 1 */
  }
}

TIM6 is configured to convert from 95 MHz peripheral bus clock to about 44.1 kHz. (I guess that's still pretty fast for only 6 values, but decreasing the frequency further didn't help.)

Then, I start signal generation:

const uint8_t aEscalator8bit[6] = {0x0, 0x33, 0x66, 0x99, 0xCC, 0xFF};
 
HAL_TIM_Base_Start(&htim6);  // not sure if needed
if (HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_2, (uint32_t *)aEscalator8bit, 6, 
         DAC_ALIGN_8B_R) != HAL_OK)
    return error(1);

No error is returned. After this, I only get low-voltage noise on PA5, although I do hear a single click (and see a small spike unlike the desired signal) at the beginning.

The example has an interrupt handler DACx_DMA_IRQHandler(), which is not generated by Cube. Despite from that, I see no differences in code.

There might be lots of higher priority interrupts during signal generation, but I would assume to see at least something on the scope. Which part did I miss?

1 ACCEPTED SOLUTION

Accepted Solutions
Lars Beiderbecke
Senior III

I think I got it now ... In above code,

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

is wrong, but this should have been UPDATE all along.

I guess I always had one of the many puzzle pieces wrong, but now everything works together.

View solution in original post

2 REPLIES 2
S.Ma
Principal

For debugging do use a timer output pin and wire it to the dac trigger input pin so you can check both stages.

Lars Beiderbecke
Senior III

I think I got it now ... In above code,

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

is wrong, but this should have been UPDATE all along.

I guess I always had one of the many puzzle pieces wrong, but now everything works together.