1
\$\begingroup\$

I've got this timer (TIM4) that's in PWM mode. I'm outputting one PWM channel and i want to wait a bit, and then grab the latest ADC samples from a DMA conversion.

TIM4 -> ARR is 4096 TIM4 -> CCR1 is dynamic, but it starts around 200

I want to start at the rising edge of the TIM4 pulse, wait half the of the Pulses on-time, and then grab the latest and greatest DMA samples...Here's a snippet of what I've got going on:

Where things seems to come unglued is the line: TIM5->ARR = TIM4->CCR1/2;. What is strange, is that if I put a constant in there, like TIM5->ARR = 20;, it works fine...It doesn't fire in the middle of the on-pulse of TIM4, but it does fire at the 20/FCLK you would expect.

I read DM00236305.pdf, but I couldn't make sense of what they were talking about with Shadow registers, which is what I think my problem is. I also tried to follow what was said here, but that was also rather vauge, and I wasn't sure if it applied, since he was talking about output compares rather than auto-reload registers.

How do I adjust TIM5->ARR to track to one-half of what is in TIM4->CCR1?

void TIM5_IRQHandler(void)
{
  /* USER CODE BEGIN TIM5_IRQn 0 */

    HAL_GPIO_WritePin(GPIOA, TX_Pin, SET);
    HAL_TIM_Base_Stop(&htim5);
    while(!(DMA2->LISR & DMA_LISR_TCIF0));
    motorDummy_FOC.curr_a_sense = ADCValue[0];
    motorDummy_FOC.curr_b_sense = ADCValue[1];
    update_PWM(&motorDummy_FOC);
    HAL_GPIO_WritePin(GPIOA, TX_Pin, RESET);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
  if (htim == &htim4){
    HAL_GPIO_WritePin(GPIOA, RX_Pin, SET);
    GPIOC->ODR = 0b0000000000000110;
    //TIM4->CR1 &= ~(1<<0);
    MX_TIM5_Init();
    TIM5->ARR = (TIM4->CCR1/2);
    HAL_TIM_Base_Start_IT(&htim5);
    HAL_TIM_Base_Start(&htim5);
  }

}
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim){

  if (htim == &htim4){
    GPIOC->ODR = 0b0000000000000100;
    HAL_GPIO_WritePin(GPIOA, RX_Pin, RESET);

  }
}

void update_PWM(motorFOC *c){
  if(c->curr_b_sense < c->curr_b_commanded)
  {c->i_feedback++;}
  else if(c->curr_b_sense > c->curr_b_commanded)
  {c->i_feedback--;}
  TIM4->CCR1 = c->i_feedback;
}
\$\endgroup\$
  • \$\begingroup\$ Why not use TIM4->CCR2? \$\endgroup\$ – Jeroen3 Jan 23 '18 at 6:57
  • \$\begingroup\$ The truth is that this is prototype code for a larger system... I've got other plans for TIM4->CCR2 :) \$\endgroup\$ – testname123 Jan 23 '18 at 6:58
3
\$\begingroup\$

I think the mistake that you are doing is you are stopping the timer base clock in IRQHandler() and want to update it in PeriodElapsedCallback(), which will be executed inside the IRQHandler().

The thing you are looking for is __HAL_TIM_SET_AUTORELOAD macro.

There are individual macros defined in *_hal_tim.h files to update the ARR, CCR etc. values. The only thing you need to do is grab the CCR value dynamically and update the macro, you do not need to stop and start the timer..! The same problem is addressed here.

\$\endgroup\$
  • \$\begingroup\$ Oh, this looks like it! Can't wait to test it out tomorrow morning, thanks. I wish I could understand the syntax of the macro, but that will take a bit more digging \$\endgroup\$ – testname123 Jan 23 '18 at 7:08
  • \$\begingroup\$ Yeah! that is the main problem with HAL! It is hard to dig through the internals, there is only so far that you can go! Please explain here if you have found out how the macro is defined. Good luck! \$\endgroup\$ – charansai Jan 23 '18 at 8:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.