cancel
Showing results for 
Search instead for 
Did you mean: 

Tim1 Input Capture PPM from a RC controller

niklascooke1
Associate II
Posted on November 08, 2009 at 14:38

Tim1 Input Capture PPM from a RC controller

5 REPLIES 5
niklascooke1
Associate II
Posted on May 17, 2011 at 13:15

Hi!

Im wondering if anyone have done this on the Cortex M3 controller.

TIM1 Input capture of a PPM signal from a RC controller?

Any ideas?

the pulse look like this. --|__|---|_|---|___|---

I want to mesure from the falling edge.

How to get the timevalue for the gaps and the time inbetween?

Regards Niklas

[ This message was edited by: niklascooke on 24-06-2009 01:54 ]

kounst
Associate II
Posted on May 17, 2011 at 13:15

Hi Niklas,

maybe this program helps you. I think it does just what you want using Timer2.

Regards,

kounst

void TIM2_Configuration(void)

{

TIM_ICInitTypeDef TIM_ICInitStructure;

//TIM_ICInitStructure.TIM_ICMode = TIM_ICMode_ICAP;

TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;

TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;

TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

TIM_ICInitStructure.TIM_ICFilter = 0x0;

TIM_ICInit(TIM2, &TIM_ICInitStructure);

TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);

TIM_InternalClockConfig(TIM2);

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

TIM_TimeBaseStructure.TIM_Period = 0xFFFF;

TIM_TimeBaseStructure.TIM_Prescaler = 17; // fCK_PSC / (17 + 1) 1ms = 4000

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM2, & TIM_TimeBaseStructure);

/* TIM enable counter */

TIM_Cmd(TIM2, ENABLE);

/* Enable the CC2 Interrupt Request */

TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);

}

void RCC_Configuration(void)

{

/* RCC system reset(for debug purpose) */

RCC_DeInit();

/* Enable HSE */

RCC_HSEConfig(RCC_HSE_ON);

/* Wait till HSE is ready */

HSEStartUpStatus = RCC_WaitForHSEStartUp();

if(HSEStartUpStatus == SUCCESS)

{

/* Enable Prefetch Buffer */

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

/* Flash 2 wait state */

FLASH_SetLatency(FLASH_Latency_2);

/* HCLK = SYSCLK */

RCC_HCLKConfig(RCC_SYSCLK_Div1);

/* PCLK2 = HCLK */

RCC_PCLK2Config(RCC_HCLK_Div1);

/* PCLK1 = HCLK/2 */

RCC_PCLK1Config(RCC_HCLK_Div2);

/* PLLCLK = 12MHz * 6 = 72 MHz */

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_6);

/* Enable PLL */

RCC_PLLCmd(ENABLE);

/* Wait till PLL is ready */

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)

{

}

/* Select PLL as system clock source */

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

/* Wait till PLL is used as system clock source */

while(RCC_GetSYSCLKSource() != 0x08)

{

}

}

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

}

void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

#ifdef VECT_TAB_RAM

/* Set the Vector Table base location at 0x20000000 */

NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);

#else /* VECT_TAB_FLASH */

/* Set the Vector Table base location at 0x08000000 */

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

#endif

/* Enable the TIM2 global Interrupt */

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

/*******************************************************************************

* Function Name : TIM2_IRQHandler

* Description : This function handles TIM2 global interrupt request.

* Input : None

* Output : None

* Return : None

*******************************************************************************/

void TIM2_IRQHandler(void)

{

if(TIM_GetITStatus(TIM2, TIM_IT_CC2) == SET)

{

/* Clear TIM2 Capture compare interrupt pending bit */

TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);

//TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

TIM_ClearFlag(TIM2, TIM_FLAG_CC2);

GPIO_ResetBits(GPIOA, GPIO_Pin_0);

// /* Get the Input Capture value */

IC2Value = TIM_GetCapture2(TIM2);

vu16 length = IC2Value - lastIC2Value;

if(length > 20000)

channel = 0;

switch(channel)

{

case 1:

pulswidth.pw1 = length;

break;

case 2:

pulswidth.pw2 = length;

break;

case 3:

pulswidth.pw3 = length;

break;

case 4:

pulswidth.pw4 = length;

break;

case 5:

pulswidth.pw5 = length;

break;

case 6:

pulswidth.pw6 = length;

break;

case 7:

pulswidth.pw7 = length;

break;

// case 8:

// pulswidth.pw8 = length;

// break;

// case 9:

// pulswidth.pw9 = length;

// break;

default:

channel = 0;

break;

}

lastIC2Value = IC2Value;

if(channel == 6) GPIO_SetBits(GPIOA, GPIO_Pin_0); else GPIO_ResetBits(GPIOA, GPIO_Pin_0);

channel++;

}

}

thorsten2
Associate II
Posted on May 17, 2011 at 13:15

Hi Niklas,

have you the PPM decode running with Timer1?

I tried it, but it does not work :-?

I like to use PA8 with Timer 1.

I have changed:

/* Enable the TIM1 global Interrupt */

NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQChannel;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

void TIM1_IRQHandler(void)

{

if(TIM1_GetITStatus(TIM1_IT_CC2) == SET)

{

/* Clear TIM1 Capture compare interrupt pending bit */

TIM1_ClearITPendingBit(TIM1_IT_CC2);

//TIM_ClearITPendingBit(TIM1, TIM_IT_Update);

TIM1_ClearFlag(TIM1_FLAG_CC2);

GPIO_ResetBits(GPIOA, GPIO_Pin_8);

// /* Get the Input Capture value */

IC2Value = TIM1_GetCapture2();

....

/* Timer for PPM decode */

TIM1_ICInitTypeDef TIM1_ICInitStructure;

//TIM_ICInitStructure.TIM_ICMode = TIM_ICMode_ICAP;

TIM1_ICInitStructure.TIM1_Channel = TIM1_Channel_1; //Pin: PA8

TIM1_ICInitStructure.TIM1_ICPolarity = TIM1_ICPolarity_Falling;

TIM1_ICInitStructure.TIM1_ICSelection = TIM1_ICSelection_DirectTI;

TIM1_ICInitStructure.TIM1_ICPrescaler = TIM1_ICPSC_DIV1;

TIM1_ICInitStructure.TIM1_ICFilter = 0x0;

TIM1_ICInit(&TIM1_ICInitStructure);

TIM1_SelectInputTrigger(TIM1_TS_TI2FP2);

TIM1_InternalClockConfig();

TIM1_TimeBaseInitTypeDef TIM1_TimeBaseStructure;

TIM1_TimeBaseStructure.TIM1_Period = 0xFFFF;

TIM1_TimeBaseStructure.TIM1_Prescaler = 17; // fCK_PSC / (17 + 1) 1ms = 4000

TIM1_TimeBaseStructure.TIM1_ClockDivision = TIM1_CKD_DIV1;

TIM1_TimeBaseStructure.TIM1_CounterMode = TIM1_CounterMode_Up;

TIM1_TimeBaseInit(& TIM1_TimeBaseStructure);

/* TIM enable counter */

TIM1_Cmd(ENABLE);

/* Enable the CC2 Interrupt Request */

TIM1_ITConfig(TIM_IT_CC2, ENABLE);

/* Enable for PPM decode ---------*/

/* TIM1 clock enable */

RCC_APB1PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

/* GPIOA clock enable */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

Many thanks for yout help!

Best Regards,

Thorsten

[ This message was edited by: thorsten.raab on 08-11-2009 13:00 ]

thorsten2
Associate II
Posted on May 17, 2011 at 13:15

I found 2 mistake:

/* TIM1 clock enable */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

/* [0xAC] TIM1 Capture/Compare Interrupt */

void TIM1_CC_IRQHandler(void)

the interrupt works - but the length is always 0

Regards,

Thorsten

[ This message was edited by: thorsten.raab on 08-11-2009 12:51 ]

thorsten2
Associate II
Posted on May 17, 2011 at 13:15

Hi,

ok, now it works :D

I have to use TIM1_IT_CC1

Here the complete codeparts:

/* Enable for PPM decode -------------------------------------------*/

/* TIM1 clock enable */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

/* GPIOA clock enable */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

/* Timer for PPM decode ---------------------------------------------------*/

TIM1_ICInitTypeDef TIM1_ICInitStructure;

//TIM_ICInitStructure.TIM_ICMode = TIM_ICMode_ICAP;

TIM1_ICInitStructure.TIM1_Channel = TIM1_Channel_1; //Pin: PA8

TIM1_ICInitStructure.TIM1_ICPolarity = TIM1_ICPolarity_Falling;

TIM1_ICInitStructure.TIM1_ICSelection = TIM1_ICSelection_DirectTI;

TIM1_ICInitStructure.TIM1_ICPrescaler = TIM1_ICPSC_DIV1;

TIM1_ICInitStructure.TIM1_ICFilter = 0x0;

TIM1_ICInit(&TIM1_ICInitStructure);

TIM1_SelectInputTrigger(TIM1_TS_TI2FP2);

TIM1_InternalClockConfig();

TIM1_TimeBaseInitTypeDef TIM1_TimeBaseStructure;

TIM1_TimeBaseStructure.TIM1_Period = 0xFFFF;

TIM1_TimeBaseStructure.TIM1_Prescaler = 17; // fCK_PSC / (17 + 1) 1ms = 4000

TIM1_TimeBaseStructure.TIM1_ClockDivision = TIM1_CKD_DIV1;

TIM1_TimeBaseStructure.TIM1_CounterMode = TIM1_CounterMode_Up;

TIM1_TimeBaseInit(& TIM1_TimeBaseStructure);

/* TIM enable counter */

TIM1_Cmd(ENABLE);

/* Enable the CC1 Interrupt Request */

TIM1_ITConfig(TIM_IT_CC1, ENABLE);

/* Configure PA8 for PPM Dekode -----------------------------------------*/

/* TIM1 channel 1 pin (PA.08) configuration */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);

/* Enable the TIM1 global Interrupt ------------------------------*/

NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQChannel;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

/* [0xAC] TIM1 Capture/Compare Interrupt --------------------*/

void TIM1_CC_IRQHandler(void)

{

if(TIM1_GetITStatus(TIM1_IT_CC1) == SET)

{

/* Clear TIM1 Capture compare interrupt pending bit */

TIM1_ClearITPendingBit(TIM1_IT_CC1);

//TIM_ClearITPendingBit(TIM1, TIM_IT_Update);

TIM1_ClearFlag(TIM1_FLAG_CC1);

GPIO_ResetBits(GPIOA, GPIO_Pin_8);

// /* Get the Input Capture value */

IC2Value = TIM1_GetCapture1();

//vu16 length = IC2Value - lastIC2Value;

vu16 length = IC2Value - lastIC2Value;

...

...

lastIC2Value = IC2Value;

if(channel == 6) GPIO_SetBits(GPIOA, GPIO_Pin_8); else GPIO_ResetBits(GPIOA, GPIO_Pin_8);

channel++;

...

Regards,

Thorsten