2009-11-08 05:38 AM
Tim1 Input Capture PPM from a RC controller
2011-05-17 04:15 AM
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 ]2011-05-17 04:15 AM
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++; } }2011-05-17 04:15 AM
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 ]2011-05-17 04:15 AM
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 ]2011-05-17 04:15 AM
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