2024-12-27 04:00 AM
Hi Friends, I have a problem using the DAC with the DMA. I have configured the DAC's DMA in normal mode and I want it to generate an interrupt at the end of data transmission to let me know that it has sent all the data to the output. The data is modified at the output through Timer 6. This is how the DAC is configured:
static void MX_DAC1_Init(void)
{
/* USER CODE BEGIN DAC1_Init 0 */
/* USER CODE END DAC1_Init 0 */
DAC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN DAC1_Init 1 */
/* USER CODE END DAC1_Init 1 */
/** DAC Initialization
*/
hdac1.Instance = DAC1;
if (HAL_DAC_Init(&hdac1) != HAL_OK)
{
Error_Handler();
}
/** DAC channel OUT1 config
*/
sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;
sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE;
sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY;
if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN DAC1_Init 2 */
/* USER CODE END DAC1_Init 2 */
}
this is how the dma is configured:
void HAL_DAC_MspInit(DAC_HandleTypeDef* hdac)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hdac->Instance==DAC1)
{
/* USER CODE BEGIN DAC1_MspInit 0 */
/* USER CODE END DAC1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_DAC1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**DAC1 GPIO Configuration
PA4 ------> DAC1_OUT1
*/
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* DAC1 DMA Init */
/* DAC_CH1 Init */
hdma_dac_ch1.Instance = DMA1_Channel3;
hdma_dac_ch1.Init.Request = DMA_REQUEST_6;
hdma_dac_ch1.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_dac_ch1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_dac_ch1.Init.MemInc = DMA_MINC_ENABLE;
hdma_dac_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_dac_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_dac_ch1.Init.Mode = DMA_NORMAL;
hdma_dac_ch1.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_dac_ch1) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hdac,DMA_Handle1,hdma_dac_ch1);
/* DAC1 interrupt Init */
HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
/* USER CODE BEGIN DAC1_MspInit 1 */
/* USER CODE END DAC1_MspInit 1 */
}
}
This is the function that handles end-of-transmission interrupts:
void DMA1_Channel3_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
//INTERRUPT DI FINE TRASMISSION DMA
if (DMA1->ISR & DMA_ISR_TCIF3)
{
HAL_DAC_Stop_DMA(&hdac1, DAC_CHANNEL_1);
DMA1->IFCR = DMA_IFCR_CTCIF3; // Reset del flag TCIF3
HAL_DMA_IRQHandler(&hdma_dac_ch1);
}
}
it all seems to work, but it signals the end-of-transmission interrupt when there are still two values of the array to be transmitted. When the array is composed of only two values, there is never an error. Please help me because I can't solve the problem.
HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, &DAC_VALUE, LUNGHEZZA, DAC_ALIGN_12B_R);
function to start data transmission.
2024-12-27 03:05 PM
> it signals the end-of-transmission interrupt when there are still two values of the array to be transmitted
Why do you think so?
Have you read the DAC chapter in RM?
JW
2024-12-27 09:10 PM
I did some tests using a defined signal to transmit on the DAC and a physical pin that goes high when an interrupt is generated. The array signal that is transmitted on the DAC is composed of 10 different points and when it transmits the eighth value I see that the physical pin goes high...so I think it is not handling the end-of-transmission interrupt correctly. If instead I create an array of only two points when it has transmitted the second point it generates an interrupt and the pin goes high, so it seems to work correctly, but only up to two points.
help me understand what you mean by RM in the DAC chapter.