cancel
Showing results for 
Search instead for 
Did you mean: 

Timer 15 not working

angcheebeng
Associate II
Posted on April 30, 2014 at 04:58

Hi,

I am trying to remap and use TIM15 for my project and faced some problems. Using TIM2 was ok. Below are some of my codes related to using TIM15. When I run, first thing I noticed was that the IRQ Handler was not called. By the way, I am using STM32F100RB value-line series.

#define AXIS_A_PULSE_TIMER_IRQ_HANDLER void TIM1_BRK_TIM15_IRQHandler(void) //void TIM2_IRQHandler(void)

/*----------------------------------------------------------------------------

 * Definition of peripherals used

 *---------------------------------------------------------------------------*/

#define AXIS_A_TIM_FREQ 24000000

#define AXIS_A_PULSE_PIN GPIO_Pin_14 //GPIO_Pin_0

#define AXIS_A_PULSE_GPIO_PORT GPIOB //GPIOA

#define AXIS_A_PULSE_GPIO_CLK RCC_APB2Periph_GPIOB //RCC_APB2Periph_GPIOA

#define AXIS_A_PULSE_TIM_CLK RCC_APB2Periph_TIM15 //RCC_APB1Periph_TIM2

#define AXIS_A_PULSE_TIM_IRQ TIM1_BRK_TIM15_IRQn //TIM2_IRQn

#define AXIS_A_PULSE_TIM TIM15 //TIM2

-----------------------------------------------------------------------------------------------void Stm32f100rbPulseGeneratorAxis1::configure() 

{

  configureRcc();

  configureNvic();

  configureGpio();

  configureTimer(65535);

}

/**

 * @brief Generate pulse output.

 * @param pulses - Number of pulses to be generated.

 * @param freq - Frequency of the PWM

 * @retval None.

 */

void Stm32f100rbPulseGeneratorAxis1::output(const uint8_t pulses, uint32_t freq) 

{

  /* -----------------------------------------------------------------------

  Pulse for Axis A is generated via TIM2 Channel 1:

  The TIM2CLK frequency is set to SystemCoreClock (Hz), to get TIM2 counter

  clock at 24 MHz the Prescaler is computed as following:

   - Prescaler = (TIM2CLK / TIM2 counter clock) - 1

  SystemCoreClock is set to 72 MHz for Low-density, Medium-density, High-density

  and Connectivity line devices and to 24 MHz for Low-Density Value line and

  Medium-Density Value line devices

  

  The TIM2 is running at 36 KHz: TIM2 Frequency = TIM2 counter clock/(ARR + 1)

                                                = 24 MHz / 666 = 36 KHz

  TIM2 Channel1 update rate = TIM2 counter clock / CCR_Val

  ----------------------------------------------------------------------- */

  TIM_OCInitTypeDef  TIM_OCInitStructure;

  static bool done = false;

  

  if(!done)

  {

  // Given frequency, compute ARR+1 value.

  uint16_t arr = 65535;

  

  // Compute the CCR value.

  uint16_t CCR_Val = (uint16_t)(AXIS_A_TIM_FREQ / freq);

  

  // Setup the time base.

  configureTimer(arr);

  

  /* Output Compare Toggle Mode configuration: Channel 1 */

  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;

  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

  TIM_OCInitStructure.TIM_Pulse = CCR_Val;

  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

  

  TIM_OC1Init(AXIS_A_PULSE_TIM, &TIM_OCInitStructure);

  

  TIM_OC1PreloadConfig(AXIS_A_PULSE_TIM, TIM_OCPreload_Disable);

  

  //TIM_ARRPreloadConfig(AXIS_A_PULSE_TIM, ENABLE);

  

  /* TIM2 enable counter */

  TIM_Cmd(AXIS_A_PULSE_TIM, ENABLE);

  

  done = true;

  }

}

/**

 * @brief Configures the clock of the peripherals used.

 * @param None.

 * @retval None.

 */

void Stm32f100rbPulseGeneratorAxis1::configureRcc() 

{

  /* Enable the clock for pulse */

  RCC_APB1PeriphClockCmd(AXIS_A_PULSE_TIM_CLK, ENABLE);

  

  /* Enable GPIO used by pulse */

  RCC_APB2PeriphClockCmd(AXIS_A_PULSE_GPIO_CLK | RCC_APB2Periph_AFIO, ENABLE);

}

/**

 * @brief Configures the NVIC used.

 * @param None.

 * @retval None.

 */

void Stm32f100rbPulseGeneratorAxis1::configureNvic() 

{

  NVIC_InitTypeDef NVIC_InitStructure;

  

  /* Enable the pulse timer interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = AXIS_A_PULSE_TIM_IRQ;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}

/**

 * @brief Configures the GPIO used.

 * @param None.

 * @retval None.

 */

void Stm32f100rbPulseGeneratorAxis1::configureGpio() 

{

  GPIO_InitTypeDef GPIO_InitStructure;

  

  /* Configure the pulse pin for Axis A */

  GPIO_InitStructure.GPIO_Pin = AXIS_A_PULSE_PIN;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  

  GPIO_Init(AXIS_A_PULSE_GPIO_PORT, &GPIO_InitStructure);

  

  GPIO_PinRemapConfig(GPIO_Remap_TIM15, ENABLE);

}

/**

 * @brief Configures the timer used.

 * @param arr - The Auto-Reload Register value for time base configuration.

 * @retval None.

 */

void Stm32f100rbPulseGeneratorAxis1::configureTimer(uint16_t arr) 

{

  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

  uint16_t PrescalerValue = 0;

  

  /* Compute the prescaler value */

  PrescalerValue = (uint16_t) (SystemCoreClock / AXIS_A_TIM_FREQ) - 1;

  

  /* Time base configuration */

  TIM_TimeBaseStructure.TIM_Period = arr; //65535;

  TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;

  TIM_TimeBaseStructure.TIM_ClockDivision = 0;

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  

  TIM_TimeBaseInit(AXIS_A_PULSE_TIM, &TIM_TimeBaseStructure);

  

  /* TIM IT enable */

  TIM_ITConfig(AXIS_A_PULSE_TIM, TIM_IT_CC1, ENABLE);

}

/**

  * @brief  ISR Axis A pulse timer.

  * @param  None

  * @retval None

  */

AXIS_A_PULSE_TIMER_IRQ_HANDLER

{

uint16_t capture = 0;

if (TIM_GetITStatus(AXIS_A_PULSE_TIM, TIM_IT_CC1) != RESET)

{

TIM_ClearITPendingBit(AXIS_A_PULSE_TIM, TIM_IT_CC1);

capture = TIM_GetCapture1(AXIS_A_PULSE_TIM);

TIM_SetCompare1(AXIS_A_PULSE_TIM, capture + 666 );

}

}

Thanks in advance. I really running out of idea where went wrong.

CB
5 REPLIES 5
Posted on April 30, 2014 at 05:23

  /* Enable the clock for pulse */

  RCC_APB1PeriphClockCmd(AXIS_A_PULSE_TIM_CLK, ENABLE);

Wouldn't that need to be APB2?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
angcheebeng
Associate II
Posted on April 30, 2014 at 07:47

Thanks, Clive. Indeed. Should be APB2. I had totally overlooked it. Now its ISR is called, but there still no output at pin 14 of port B. Would it be my remapping gone wrong, or is there something special about TIM15, which from datasheet comes with complementary output. 

angcheebeng
Associate II
Posted on May 02, 2014 at 09:31

I got it work! This time I use TIM1. For some unknown reasons I am still investigating, TIM15 still got no waveform in its output.

To get TIM1 working, I needed to add the following configurations:

  TIM_BDTRInitTypeDef TIM_BDTRInitStructure;

  /* Automatic Output enable, Break, dead time and lock configuration*/

  TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;

  TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;

  TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;

  TIM_BDTRInitStructure.TIM_DeadTime = 0;

  TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;

  TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;

  TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;

  

  TIM_BDTRConfig(AXIS_A_PULSE_TIM, &TIM_BDTRInitStructure);

  /* Main Output Enable */

  TIM_CtrlPWMOutputs(AXIS_A_PULSE_TIM, ENABLE);

dubrov
Associate
Posted on July 08, 2014 at 18:18

I think, you might be hitting bug in the standard peripheral library. I noticed thatGPIO_PinRemapConfig(GPIO_Remap_TIM15, ENABLE) doesn't actually change theMAPR2 register (according to datasheet, TIM15 is remapped by setting bit 0 in MAPR2).

So, I tried setting bit manually:

AFIO->MAPR2 |= AFIO_MAPR2_TIM15_REMAP;

and it worked! I looked into the GPIO_PinRemapConfig implementation and found dubious line:

tmpreg |= (tmp << ((GPIO_Remap >> 0x15)*0x10));

I don't know what it is for (shift right by 21 bit and then shift by 16 bits times it? what?). You can see that for GPIO_Remap_TIM15 (which is 0x80000001), it would shift tmp by 16384 bits, which doesn't make any sense to me. I use STM32VLDISCOVERY board with standard peripheral library version 3.5.0.
dubrov
Associate
Posted on July 08, 2014 at 18:33

I believe the line in question should be changed to something like:

tmpreg |= (tmp << (((GPIO_Remap&DBGAFR_LOCATION_MASK) >> 0x15)*0x10)); // take one bit only (0x00200000)!

or:

if (GPIO_Remap&DBGAFR_LOCATION_MASK)

{

    tmpreg |= tmp << 0x10; // shift to high 16 bits

}

else

{

    tmpreg |= tmp; // don't shift

}