Skip to main content
Visitor II
August 3, 2021
Solved

Direct Input Capture Interrupt too slow - STM32 L476RG

  • August 3, 2021
  • 4 replies
  • 3339 views

I'm trying to align an input 15 kHz signal with a 20% duty cycle with an output 15 kHz signal with a 50% duty cycle. To do this I'm hooking up the input signal to a direct capture interrupt and Timer 1 Channel 4 and using the HAL_TIM_IC_CaptureCallback function to begin my PWM timer. In doing this I notice a significant delay of 6ms as shown in the picture below. I need the delay to be on the order of 1-2µs not 6ms. Is this possible using the STM32 L476RG operating at 80 MHz? Otherwise, what are some common solutions to meeting these kinds of timing requirements?

Here is my ISR for reference:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
	if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4) {
		if (num_pulses == 0) {
			HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, state);
			HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
			++num_pulses;
		}
		else if (num_pulses == 50) {
			if (state = 0) {
				state = 1;
			}
			else {
				state = 0;
			}
			num_pulses = 0;
		}
		else {
			++num_pulses;
		}
	}
}

Here is the delay on the logic analyzer:

0693W00000D1PsqQAF.png 

Thank you!

    This topic has been closed for replies.
    Best answer by TDK

    There has to be something else going on. The IRQ delay isn't 6ms even with HAL overhead.

    Are you sure the timer IC is ready at the time you start the other PWM signal?

    Another way to do this would be to trigger the TIM2_CH1 to start when the other signal goes high. Look at the trigger slave mode for how to do this. You will still have some small fixed delay which you could eliminate by adjusting the starting CNT value.

    4 replies

    TDKAnswer
    Super User
    August 3, 2021

    There has to be something else going on. The IRQ delay isn't 6ms even with HAL overhead.

    Are you sure the timer IC is ready at the time you start the other PWM signal?

    Another way to do this would be to trigger the TIM2_CH1 to start when the other signal goes high. Look at the trigger slave mode for how to do this. You will still have some small fixed delay which you could eliminate by adjusting the starting CNT value.

    LBouz.1Author
    Visitor II
    August 3, 2021

    How can I make sure the timer IC is ready? The only line of code I have outside of the default and ISR is HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_4) which I call in the main function before the loop. Here are my timer 1 settings:

    0693W00000D1QRWQA3.png0693W00000D1QSKQA3.png 

    The trigger slave mode seems like a solution but the only problem is I also have to set a GPIO pin high/low at the same time so I believe I need an ISR.

    Super User
    August 3, 2021

    > How can I make sure the timer IC is ready?

    Call HAL_TIM_IC_Start_IT before you start the PWM.

    You can set a pin high using another channel of the timer using trigger slave mode.

    Graduate II
    August 3, 2021

    Maybe your num_pulses isnt initialised to 0 , when for example 1 ...

    Super User
    August 3, 2021

    > Using the slave mode path, what type of Trigger Output (TRGO) should be used for an input capture timer? The only options are output capture ones.

    Use "Compare Pulse" (0b11 in TIMx_CR2.MMS). It's incredibly badly named, but it sets TRGO to output a pulse whenever CC1IF is set, whether it's because of Input Capture or Output Compare. Only CH1 can be used for this purpose.

    But you don't need to do that. As TDK said above, set up the timer for the PWM output but don't enable it in TIMx_CR1.CEN and connect the input signal to a channel which can trigger the Slave-mode controller set to Trigger mode (again, only CH1 and CH2 can be used). Set a third channel to Output Compare, Active on Match, and that will serve you as the pin which you want to set when the edge is detected.

    JW

    LBouz.1Author
    Visitor II
    August 3, 2021

    I'm confused what you mean by "set up the timer for the PWM output but don't enable it in TIMx_CR1.CEN"? Also, how can I connect the input signal to a trigger without using the Compare Pulse?

    Super User
    August 3, 2021

    > I'm confused what you mean by "set up the timer for the PWM output

    Set TIMx_ARR to the period you desire (including TIMx_PSC if needed, keeping in mind that PSC is uncondionally preloaded). Set the chosen output channel's TIMx_CCRx according to required duty, in respective TIMx_CCMRx leave CCxS at its default 0b00 for Output Compare and set OCxM to 0b110 or 0b111 depending on which PWM mode you've chosen. Finally, enable given channel by setting its respective TIMx_CCER.CCxE bit and if this is one of the Advanced Timers (TIM1, TIM8 and others which have complementary outputs), set TIMx_BDTR.MOE.

    You probably usually solve all this by some clicking in CubeMX, I don't use that, as not everything can be clicked.

    > but don't enable it in TIMx_CR1.CEN"

    Well, literally that, leave TIMx_CR1.CEN cleared. It's then the Slave-mode controller in Trigger mode, which will set it, when the trigger arrives.

    > Also, how can I connect the input signal to a trigger without using the Compare Pulse?

    "Compare Pulse" is a mode how to output an input channel (namely CH1) onto TRGO, which is an output of given TIMx module towards *other* TIMy module. You don't need to trigger an *other* TIMy module - you can if you wish to do so, but it's unnecessary.

    To trigger TIMx's Slave mode controller, set the chosen channel (CH1 or CH2) to Input Capture mode by setting the respective TIMx_CCMRx.CCxS to 0b01 (or 0b10 if you wish to trigger "the other" channel, but leave that for later if things will be more clear). There's no need to actually enable the capture in TIMx_CCER, if you don't want to perform the capture, but you can do so if you want. You can select the desired edge using TIMx_CCER.CCxP/CCxNP (note that these bits don't form a continguous bitfield). You can also set a digital filter on the channel in TIMx_CCMRx.ICxF. Now in TIMx_SMCR.TS select input to the Slave-mode Controller, 0b101 if you use CH1 or 0b110 if you use CH2; and then in TIMx_SMS select the Trigger mode.

    All above assumes you have properly set the TIMx_CHx pins in GPIO, i.e. set then to AF in GPIO_MODER and selected proper AF number in GPIO_AFR[]. Again, you probably click in CubeMX.

    JW