2025-11-20 3:43 AM - last edited on 2025-11-20 3:55 AM by Andrew Neil
Post edited by ST moderator to be inline with the community rules for the code sharing. In next time please use </> button to paste your code. Please read this post: How to insert source code.
Hallo,
I am trying to measure the frequency of rectangular signals. the borad I am using is stm32f411-disco
I used the timer 2 channel 1 for input capture. at every capture the timer value will be sent to memery by uing DMA. The DMA seems working, because I printed the captured value periodically. the DMA-Buffer is two, and it is working in a circular mode.
I try to do some calculation in the interruption-function: "void HAL_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma)" like this:
void HAL_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma)
{
if (hdma->Instance == DMA1_Stream5) // MCU-abhängig!
{
uint32_t first = IC_Values[0];
uint32_t second = IC_Values[1];
if (second >= first)
diff = second - first;
else
diff = (0xFFFFFFFF - first + second);
/* Timer läuft mit 1 MHz → 1 µs pro Tick */
Frequency = 1e6f / diff;
}
}
But this interruption is not triggered.
so my question is, shouldn't this function be triggered after the DMA transfer complete?
complete script please see the attachment:
Solved! Go to Solution.
2025-11-21 6:21 AM
HAL only calls HAL_TIM_IC_CaptureCallback, not HAL_DMA_XferCpltCallback, at the end of this transfer. That is the intended behavior.
You can hijack the DMA1_Stream5_IRQHandler handler if you want to process the TC flag.
2025-11-20 5:47 AM
When HAL_TIM_IC_Start_DMA completes, the HAL_TIM_IC_CaptureCallback callback is called.
2025-11-20 6:41 AM
Hello @xtxftzld
Set a breakpoint in the DMA IRQ handler function to verify that the DMA interrupt handler is being triggered and also check the DMA status registers to see if the transfer complete flag is set as expected.
2025-11-21 12:07 AM
Hi,
the regular input capture call back: "HAL_TIM_IC_CaptureCallback" is working well. Normally I am also doing like this. But I read in the internet, that after the completion of DMA transfer there is also a callback, which I want to test:
void HAL_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma)But it turned out not working, although the DMA is working properly (the variables are really overwritten).
2025-11-21 12:54 AM
Hello Saket,
thanks for your answer,
I checked first as you said, the DMA_Stream5_IRQHandler by toggling the LED:
void DMA1_Stream5_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Stream5_IRQn 0 */
//HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_15);
/* USER CODE END DMA1_Stream5_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_tim2_ch1);
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_15);
/* USER CODE BEGIN DMA1_Stream5_IRQn 1 */
/* USER CODE END DMA1_Stream5_IRQn 1 */
}I gave a rectangular signal of 1 Hz on the PD15, and this IRQHandler is triggerd, since I see the LED blinking with also about 1 Hz.
Secondly I checked the DMA status registers with:
void CheckDMA1_Stream5_Status(void)
{
uint32_t status = DMA1->HISR;
//printf("DMA1->HISR = 0x%08lX\n", status);
snprintf(usb_buffer, sizeof(usb_buffer),"DMA1->HISR = 0x%08lX\n", status);
CDC_Transmit_FS((uint8_t*)usb_buffer, strlen(usb_buffer));
if (status & DMA_HISR_TCIF5){
snprintf(usb_buffer, sizeof(usb_buffer),"TCIF5 = Transfer Complete\n");
CDC_Transmit_FS((uint8_t*)usb_buffer, strlen(usb_buffer));
}
if (status & DMA_HISR_HTIF5){
snprintf(usb_buffer, sizeof(usb_buffer),"HTIF5 = Half Transfer\n");
CDC_Transmit_FS((uint8_t*)usb_buffer, strlen(usb_buffer));
}
if (status & DMA_HISR_TEIF5){
snprintf(usb_buffer, sizeof(usb_buffer),"TEIF5 = Transfer Error\n");
CDC_Transmit_FS((uint8_t*)usb_buffer, strlen(usb_buffer));
}
if (status & DMA_HISR_DMEIF5){
snprintf(usb_buffer, sizeof(usb_buffer),"DMEIF5 = Direct Mode Error\n");
CDC_Transmit_FS((uint8_t*)usb_buffer, strlen(usb_buffer));
}
if (status & DMA_HISR_FEIF5){
snprintf(usb_buffer, sizeof(usb_buffer),"FEIF5 = FIFO Error\n");
CDC_Transmit_FS((uint8_t*)usb_buffer, strlen(usb_buffer));
}
}Hier I just got the message in my serial monitor: "DMA1->HISR = 0x00000000"
It seems DMA-Status is not changed at all, although the DMA_Stream5_IRQHandler is triggered.
2025-11-21 1:10 AM
Hello @xtxftzld
Could you try with the config below please:
// DMA handle declaration
DMA_HandleTypeDef DmaHandle;
static void TransferComplete(DMA_HandleTypeDef *DmaHandle);
int main(void) {
// Register the transfer complete callback
HAL_DMA_RegisterCallback(&DmaHandle, HAL_DMA_XFER_CPLT_CB_ID, TransferComplete);
while (1) {
// Main loop code
// You can check for transfer completion or handle other tasks
}
}
// Callback function for transfer complete
static void TransferComplete(DMA_HandleTypeDef *DmaHandle)
{
/* Transfer correct */
}
2025-11-21 1:24 AM
Hi,
I just put your script manually (without touching the CubeMX) in my main.c with a LED-Toggleing in "TransferComplete":
static void TransferComplete(DMA_HandleTypeDef *DmaHandle)
{
/* Transfer correct */
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
}I finish the declartion and registered the function as you did. I uploaded the program, the function you offered is not triggered.
I checked the Variables IC_Values[0], where I stored the DMA values. The DMA is running in circular mode.
2025-11-21 1:44 AM
Hello @xtxftzld
Could you please check which flag triggers the DMA interrupt? You can set a breakpoint at HAL_DMA_IRQHandler() and step through the code to identify the specific flag.
2025-11-21 2:14 AM
Hi,
in debugging modus, it arrives "/* Transfer complete callback */", which means the transfer complete call back should be triggered, right? but after this point, the program dose not go back to main.c:
after this the program runs into:
then it comes back to my breakpont I set:
and so on.
the programm never enter the main.c again, strange.
2025-11-21 2:21 AM
Could you please share your code ?