cancel
Showing results for 
Search instead for 
Did you mean: 

NUCLEO-H723ZG DAC differential signal

TOsso.1
Associate III

Hi,
I’m working with the NUCLEO-H723ZG board and would like to know if it’s possible to use its two DAC outputs to generate a differential signal.

Thank you very much

11 REPLIES 11

Hi
But this is example for 1 channel no?
with 1 channel I have project that work.

Right, one channel. But you are free to activate second channel (copy-paste allowed).

Of course, DMA has to be WORD, since data for 2 DAC transported at ones. 

HAL_DACEx_DualStart_DMA() serves only one purpose, off-load DMA, and its needs only when DAC updates rate exceeds max bandwidth. My tests on stm32G474re - dacs 15 msps - show that DMA failed above ~14 msps.

I replaced  HAL_DACEx_DualStart_DMA() in my projects for my own version, but don't remember why. Could be arduino nuances, since I'm using arduino IDE.

Here is essential DAC part of the code:

void init_dacs(void)
{
  generator();

  __HAL_RCC_DMAMUX1_CLK_ENABLE();

  __HAL_RCC_DAC3_CLK_ENABLE();
  __HAL_RCC_DMA1_CLK_ENABLE();  
  __HAL_RCC_DAC4_CLK_ENABLE();
  __HAL_RCC_DMA2_CLK_ENABLE();


  Serial.print(F("\n\tdma_config3..."));
  delay(100); 
  DMA_Config3(&hdac3);
  Serial.print(F("\tdone."));  

  Serial.print(F("\n\tdma_config4..."));
  delay(100); 
  DMA_Config4(&hdac4);
  Serial.print(F("\tdone."));

  Serial.print(F("\n\tdac_config3..."));
  delay(100);      
  DAC_Config3();
  Serial.print(F("\tdone."));

  Serial.print(F("\n\tdac_config4..."));
  delay(100);      
  DAC_Config4();
  Serial.print(F("\tdone."));
  Serial.print(F("\n"));
}

void DMA_Config3(DAC_HandleTypeDef *hdac)
{
  static DMA_HandleTypeDef  hdma_dac3;

  hdma_dac3.Instance                  = DMA1_Channel1;
  hdma_dac3.Init.Request              = DMA_REQUEST_DAC3_CHANNEL1;
  hdma_dac3.Init.Direction            = DMA_MEMORY_TO_PERIPH;
  hdma_dac3.Init.PeriphInc            = DMA_PINC_DISABLE;
  hdma_dac3.Init.MemInc               = DMA_MINC_ENABLE;
  hdma_dac3.Init.PeriphDataAlignment  = DMA_PDATAALIGN_WORD;
  hdma_dac3.Init.MemDataAlignment     = DMA_MDATAALIGN_WORD;
  hdma_dac3.Init.Mode                 = DMA_CIRCULAR;
  hdma_dac3.Init.Priority             = DMA_PRIORITY_VERY_HIGH;

  HAL_DMA_Init(&hdma_dac3);

  __HAL_LINKDMA(hdac, DMA_Handle1, hdma_dac3);

//  HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0);
  //HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
}

void DMA_Config4(DAC_HandleTypeDef *hdac)
{
  static DMA_HandleTypeDef  hdma_dac4;

  hdma_dac4.Instance                  = DMA2_Channel1;
  hdma_dac4.Init.Request              = DMA_REQUEST_DAC4_CHANNEL1;
  hdma_dac4.Init.Direction            = DMA_MEMORY_TO_PERIPH;
  hdma_dac4.Init.PeriphInc            = DMA_PINC_DISABLE;
  hdma_dac4.Init.MemInc               = DMA_MINC_ENABLE;
  hdma_dac4.Init.PeriphDataAlignment  = DMA_PDATAALIGN_WORD;
  hdma_dac4.Init.MemDataAlignment     = DMA_MDATAALIGN_WORD;
  hdma_dac4.Init.Mode                 = DMA_CIRCULAR;
  hdma_dac4.Init.Priority             = DMA_PRIORITY_VERY_HIGH;

  HAL_DMA_Init(&hdma_dac4);

  __HAL_LINKDMA(hdac, DMA_Handle1, hdma_dac4);

//  HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0);
  //HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
}

HAL_StatusTypeDef dual_DAC_Start_DMA(DAC_HandleTypeDef* hdac, uint32_t* pData, uint32_t Length, uint32_t Alignment)
{
  uint32_t tmpreg = 0U;
      
  __HAL_LOCK(hdac);  
  hdac->State = HAL_DAC_STATE_BUSY;

//    hdac->DMA_Handle1->XferCpltCallback = DAC_DMAConvCpltCh1;
//    hdac->DMA_Handle1->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh1;
//    hdac->DMA_Handle1->XferErrorCallback = DAC_DMAErrorCh1;

    switch(Alignment)
    {
      case DAC_ALIGN_12B_R:
        tmpreg = (uint32_t)&hdac->Instance->DHR12RD;// DAC_DHR8RD
        break;
      case DAC_ALIGN_12B_L:
        tmpreg = (uint32_t)&hdac->Instance->DHR12LD;
        break;
      case DAC_ALIGN_8B_R:
        tmpreg = (uint32_t)&hdac->Instance->DHR8RD;
        break;
      default:
        break;
    }

    hdac->Instance->CR |= DAC_CR_DMAEN1;
    __HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR1);
    
    HAL_DMA_Start_IT(hdac->DMA_Handle1, (uint32_t)pData, tmpreg, Length);
  
  __HAL_DAC_ENABLE(hdac, DAC_CHANNEL_1);  
  __HAL_DAC_ENABLE(hdac, DAC_CHANNEL_2); 
   
  __HAL_UNLOCK(hdac);
  
  return HAL_OK;
}

void DAC_Config3(void)
{
  DAC_ChannelConfTypeDef sConfig = {0};
  
  if (HAL_DAC_Init(&hdac3) != HAL_OK) {
    Error_Handler();
    }

  sConfig.DAC_HighFrequency           = DAC_HIGH_FREQUENCY_INTERFACE_MODE_ABOVE_80MHZ;
  sConfig.DAC_DMADoubleDataMode       = DISABLE;
  sConfig.DAC_SignedFormat            = DISABLE;
  sConfig.DAC_SampleAndHold           = DAC_SAMPLEANDHOLD_DISABLE;
  sConfig.DAC_Trigger                 = DAC_TRIGGER_T2_TRGO;
  sConfig.DAC_Trigger2                = DAC_TRIGGER_NONE;
  sConfig.DAC_OutputBuffer            = DAC_OUTPUTBUFFER_DISABLE;
  sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_ENABLE;
  sConfig.DAC_UserTrimming            = DAC_TRIMMING_FACTORY;
  if (HAL_DAC_ConfigChannel(&hdac3, &sConfig, DAC_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
//  sConfig.DAC_Trigger                 = DAC_TRIGGER_T2_TRGO;
  if (HAL_DAC_ConfigChannel(&hdac3, &sConfig, DAC_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }

  
/*  
  if (HAL_DAC_Start_DMA(&hdac3, DAC_CHANNEL_1,
                            (uint32_t *)buff,
                            (BUF_SIZE / 2),
                            DAC_ALIGN_12B_R
                           ) != HAL_OK)
   {
     Error_Handler();
   }
*/
/*
  if (HAL_DACEx_DualStart_DMA(&hdac3, DAC_CHANNEL_1, 
                              (uint32_t *) buff3, 
                              (BUF_SIZE / 4), 
                              DAC_ALIGN_12B_R) != HAL_OK)
  {
    Error_Handler();
  }
*/
//  if (dual_DAC_Start_DMA(&hdac3, (uint32_t *)buff3, (BUF_SIZE / 4), DAC_ALIGN_12B_R) != HAL_OK)
  if (dual_DAC_Start_DMA(&hdac3, (uint32_t *)buff3, BUF_SIZE, DAC_ALIGN_12B_R) != HAL_OK)
  {
    Error_Handler();
  }
}

void DAC_Config4(void)
{
  DAC_ChannelConfTypeDef sConfig = {0};
  
  if (HAL_DAC_Init(&hdac4) != HAL_OK) {
    Error_Handler();
    }

  sConfig.DAC_HighFrequency           = DAC_HIGH_FREQUENCY_INTERFACE_MODE_ABOVE_80MHZ;
  sConfig.DAC_DMADoubleDataMode       = DISABLE;
  sConfig.DAC_SignedFormat            = DISABLE;
  sConfig.DAC_SampleAndHold           = DAC_SAMPLEANDHOLD_DISABLE;
//  sConfig.DAC_Trigger                 = DAC_TRIGGER_T2_TRGO;

  sConfig.DAC_Trigger                 = DAC_TRIGGER_T3_TRGO;
  sConfig.DAC_Trigger2                = DAC_TRIGGER_NONE;
  sConfig.DAC_OutputBuffer            = DAC_OUTPUTBUFFER_DISABLE;
  sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_ENABLE;
  sConfig.DAC_UserTrimming            = DAC_TRIMMING_FACTORY;
  if (HAL_DAC_ConfigChannel(&hdac4, &sConfig, DAC_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
//  sConfig.DAC_Trigger                 = DAC_TRIGGER_T8_TRGO;
  if (HAL_DAC_ConfigChannel(&hdac4, &sConfig, DAC_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
//  if (dual_DAC_Start_DMA(&hdac4, (uint32_t *)buff4, (BUF_SIZE / 4), DAC_ALIGN_12B_R) != HAL_OK)
  if (dual_DAC_Start_DMA(&hdac4, (uint32_t *)buff4, BUF_SIZE, DAC_ALIGN_12B_R) != HAL_OK)
  {
    Error_Handler();
  }
}