/******************************************************************************* * COPYRIGHT (C) 2021 CMS Technologies Ltd. * * * ******************************************************************************** * FileName : tim_demo.c * * Author : * * Version : 1.0 * * Date : 2021.08.13 * * Description : * * Function List : * ********************************************************************************/ #include "RTE_TIM40.h" #include "cgc.h" #include "common.h" #include "BAT32A279.h" #include "gpio.h" #include "tim.h" #include "string.h" #include "isr.h" typedef struct { uint32_t u32Period[RTE_TIM40_PERIOD_FILTER_SUM]; uint32_t u32Freq; uint8_t u8PeriodCnt; uint8_t u8PeriodBufCnt; uint32_t u32CHClock; }TIM40CapObj_st_t; volatile TIM40CapObj_st_t g_stTIM40CapObj[RTE_TIM40_CH_SUM]; void RTE_TIM4_Capture_Init(uint8_t u8CapChannel); uint32_t RTE_Frequency_Get(uint8_t u8ch); void tim40_channel0_interrupt(void ); void tim40_channel1_interrupt(void ); void tim40_channel2_interrupt(void ); void tim40_channel3_interrupt(void ); void RTE_Calc_Freq(uint8_t u8ch); void RTE_CAPTURE_KL30_Init(void) { memset((void*)g_stTIM40CapObj,0,sizeof(g_stTIM40CapObj)); RTE_TIM4_Capture_Init(RTE_VSPEED_CAP_CH); RTE_TIM4_Capture_Init(RTE_ENGINE_CAP_CH); } void RTE_CAPTURE_Wakeup_Init(void) { memset((void*)g_stTIM40CapObj,0,sizeof(g_stTIM40CapObj)); RTE_TIM4_Capture_Init(RTE_VSPEED_CAP_CH); RTE_TIM4_Capture_Init(RTE_ENGINE_CAP_CH); } void RTE_CAPTURE_Sleep_Init(void) { TIM_Cmd(TM40,RTE_TIM40_CH0,DISABLE); TIM_Cmd(TM40,RTE_TIM40_CH1,DISABLE); TIM_Cmd(TM40,RTE_TIM40_CH2,DISABLE); TIM_Cmd(TM40,RTE_TIM40_CH3,DISABLE); CGC_PER0PeriphClockCmd(CGC_PER0Periph_TIM40,DISABLE); } uint32_t RTE_VSPEED_Freq_Get(void) { return RTE_Frequency_Get(RTE_VSPEED_CAP_CH); } uint32_t RTE_ENGINE_Freq_Get(void) { return RTE_Frequency_Get(RTE_ENGINE_CAP_CH); } const uint32_t TIM4_Clock[16U] = { 64000000UL, 32000000UL, 16000000UL, 8000000UL, 4000000UL, 2000000UL, 1000000UL, 500000UL, 250000UL, 125000UL, 62500UL, 31250UL, 15625UL, 7812UL, 3906UL, 1953UL, }; void RTE_TIM4_Capture_Init(uint8_t u8CapChannel) { TIM_InitTypeDef TIM_InitStructure; GPIO_InitTypeDef GPIO_InitStruct; uint8_t u8IndexCh; u8IndexCh = 1 << u8CapChannel; switch (u8IndexCh) { case TIM_Channel_0: GPIO_PinAFConfig(GPIO_PORT0, GPIO_Pin_0, GPIO_P00, GROUP_AF_ODEFAULT); //P00 used as TI00 input GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStruct.GPIO_Ctrl = GPIO_Control_DIG; GPIO_Init(GPIO_PORT0, &GPIO_InitStruct); TIM_InitStructure.TIM_Channel = TIM_Channel_0; TIM_InitStructure.TIM_ClkDivision = TIM_CLK0_Div128; //specify the operation clk of tim TIM_InitStructure.TIM_Trigger = TIM_Trigger_IputEdge; //IputEdge is used to start trigger and capture trigger TIM_InitStructure.TIM_Pulse_Edge = TIM_Pulse_Rising; // Measure the high or low level pulse width of P00/TI00 /TIM_Pulse_Both/TIM_Pulse_Rising TIM_InitStructure.TIM_Mode = TIM_Mode_PluseInterval; // pulse interval measure: use capture function TIM_InitStructure.TIM_StartInt = TIM_StartInt_Disable; TIM_InitStructure.TIM4_Input = TIM4_CH0_Input_TI00; // specify the input of TI g_stTIM40CapObj[u8CapChannel].u32CHClock = TIM4_Clock[TIM_InitStructure.TIM_ClkDivision]; TIM_Init(TM40,&TIM_InitStructure); ISR_Register(TM00_IRQn, tim40_channel0_interrupt); break; case TIM_Channel_1: GPIO_PinAFConfig(GPIO_PORT1, GPIO_Pin_6, GPIO_P16, GROUP_AF_ODEFAULT); //P16 used as TI01 input转速GPIO GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStruct.GPIO_Ctrl = GPIO_Control_DIG; GPIO_Init(GPIO_PORT0, &GPIO_InitStruct); TIM_InitStructure.TIM_Channel = TIM_Channel_1; TIM_InitStructure.TIM_ClkDivision = TIM_CLK0_Div128; //specify the operation clk of tim TIM_InitStructure.TIM_Trigger = TIM_Trigger_IputEdge; //IputEdge is used to start trigger and capture trigger TIM_InitStructure.TIM_Pulse_Edge = TIM_Pulse_Both; // Measure the high or low level pulse width of P00/TI00 /TIM_Pulse_Both/TIM_Pulse_Rising TIM_InitStructure.TIM_Mode = TIM_Mode_PluseInterval; // pulse interval measure: use capture function TIM_InitStructure.TIM_StartInt = TIM_StartInt_Disable; TIM_InitStructure.TIM4_Input = TIM4_CH1_Input_TI01; // specify the input of TI TIM_Init(TM40,&TIM_InitStructure); g_stTIM40CapObj[u8CapChannel].u32CHClock = TIM4_Clock[TIM_InitStructure.TIM_ClkDivision]; ISR_Register(TM01_IRQn, tim40_channel1_interrupt); break; case TIM_Channel_2: GPIO_PinAFConfig(GPIO_PORT1, GPIO_Pin_7, GPIO_P17, GROUP_AF_ODEFAULT); //P17 used as TI02 input车速 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStruct.GPIO_Ctrl = GPIO_Control_DIG; GPIO_Init(GPIO_PORT0, &GPIO_InitStruct); TIM_InitStructure.TIM_Channel = TIM_Channel_2; TIM_InitStructure.TIM_ClkDivision = TIM_CLK0_Div128; //specify the operation clk of tim TIM_InitStructure.TIM_Trigger = TIM_Trigger_IputEdge; //IputEdge is used to start trigger and capture trigger TIM_InitStructure.TIM_Pulse_Edge = TIM_Pulse_Both; // Measure the high or low level pulse width of P00/TI00 /TIM_Pulse_Both/TIM_Pulse_Rising TIM_InitStructure.TIM_Mode = TIM_Mode_PluseInterval; // pulse interval measure: use capture function TIM_InitStructure.TIM_StartInt = TIM_StartInt_Disable; TIM_InitStructure.TIM4_Input = TIM4_CH0_Input_TI00; // specify the input of TI g_stTIM40CapObj[u8CapChannel].u32CHClock = TIM4_Clock[TIM_InitStructure.TIM_ClkDivision]; TIM_Init(TM40,&TIM_InitStructure); ISR_Register(TM02_IRQn, tim40_channel2_interrupt); break; case TIM_Channel_3: GPIO_PinAFConfig(GPIO_PORT3, GPIO_Pin_1, GPIO_P31, GROUP_AF_ODEFAULT); //P31 used as TI03 input GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStruct.GPIO_Ctrl = GPIO_Control_DIG; GPIO_Init(GPIO_PORT0, &GPIO_InitStruct); TIM_InitStructure.TIM_Channel = TIM_Channel_3; TIM_InitStructure.TIM_ClkDivision = TIM_CLK0_Div32; //specify the operation clk of tim TIM_InitStructure.TIM_Trigger = TIM_Trigger_IputEdge; //IputEdge is used to start trigger and capture trigger TIM_InitStructure.TIM_Pulse_Edge = TIM_Pulse_Rising; // Measure the high or low level pulse width of P00/TI00 /TIM_Pulse_Both/TIM_Pulse_Rising TIM_InitStructure.TIM_Mode = TIM_Mode_PluseInterval; // pulse interval measure: use capture function TIM_InitStructure.TIM_StartInt = TIM_StartInt_Disable; TIM_InitStructure.TIM4_Input = TIM4_CH0_Input_TI00; // specify the input of TI g_stTIM40CapObj[u8CapChannel].u32CHClock = TIM4_Clock[TIM_InitStructure.TIM_ClkDivision]; TIM_Init(TM40,&TIM_InitStructure); ISR_Register(TM03_IRQn, tim40_channel3_interrupt); break; default: break; } TIM_Start(TM40,u8CapChannel); } uint32_t RTE_Frequency_Get(uint8_t u8ch) { /* unit : 0.1HZ */ return g_stTIM40CapObj[u8ch].u32Freq; } void RTE_Calc_Freq(uint8_t u8ch) { uint32_t u32Temp = 0U; uint8_t i = 0U; uint16_t u16TDR; uint16_t u16TSR; uint8_t u8RollingCh = 0; switch (u8ch) { case RTE_TIM40_CH0: u16TDR = TM40->TDR[0U]; u16TSR = TM40->TSR[0U]; break; case RTE_TIM40_CH1: u16TDR = TM40->TDR[1U]; u16TSR = TM40->TSR[1U]; u8RollingCh = 0U; break; case RTE_TIM40_CH2: u16TDR = TM40->TDR[2U]; u16TSR = TM40->TSR[2U]; break; case RTE_TIM40_CH3: u16TDR = TM40->TDR[3U]; u16TSR = TM40->TSR[3U]; break; default: u16TDR = TM40->TDR[0U]; u16TSR = TM40->TSR[0U]; break; } if (1U == (u16TSR & _0001_TM4_OVERFLOW_OCCURS)) { g_stTIM40CapObj[u8ch].u32Period[g_stTIM40CapObj[u8ch].u8PeriodBufCnt] = (uint32_t)(u16TDR + 1UL) + 0x10000UL; } else { g_stTIM40CapObj[u8ch].u32Period[g_stTIM40CapObj[u8ch].u8PeriodBufCnt] = (uint32_t)(u16TDR + 1UL); // Fre_In_Channel_Capture_ISR_Reset_Count(FRE_ENGINE,g_stTIM40CapObj[u8ch].u32Period[g_stTIM40CapObj[u8ch].u8PeriodBufCnt]); } g_stTIM40CapObj[u8ch].u8PeriodBufCnt++; if (g_stTIM40CapObj[u8ch].u8PeriodBufCnt >= RTE_TIM40_PERIOD_FILTER_SUM) { g_stTIM40CapObj[u8ch].u8PeriodBufCnt = 0U; } if (g_stTIM40CapObj[u8ch].u8PeriodCnt < RTE_TIM40_PERIOD_FILTER_SUM) { g_stTIM40CapObj[u8ch].u8PeriodCnt++; } for( i = 0U;i < g_stTIM40CapObj[u8ch].u8PeriodCnt;i++) { u32Temp += g_stTIM40CapObj[u8ch].u32Period[i]; } u32Temp = u32Temp / g_stTIM40CapObj[u8ch].u8PeriodCnt; g_stTIM40CapObj[u8ch].u32Freq = (g_stTIM40CapObj[u8ch].u32CHClock * 10U) / u32Temp; } /*********************************************************************************************************************** * Function Name: tim40_channel0_interrupt * @brief TIM4 Channel interrupt service routine * @param msg * @return None ***********************************************************************************************************************/ void tim40_channel0_interrupt(void) { INTC_ClearPendingIRQ(TM00_IRQn); // clear INTTM00 interrupt flag RTE_Calc_Freq(RTE_TIM40_CH0); } /*********************************************************************************************************************** * Function Name: tim40_channel1_interrupt * @brief TIM4 Channel interrupt service routine * @param msg * @return None ***********************************************************************************************************************/ void tim40_channel1_interrupt(void) { INTC_ClearPendingIRQ(TM01_IRQn); // clear INTTM01 interrupt flag RTE_Calc_Freq(RTE_TIM40_CH1); } /*********************************************************************************************************************** * Function Name: tim40_channel2_interrupt * @brief TIM4 Channel interrupt service routine * @param msg * @return None ***********************************************************************************************************************/ void tim40_channel2_interrupt(void) { INTC_ClearPendingIRQ(TM02_IRQn); // clear INTTM02 interrupt flag RTE_Calc_Freq(RTE_TIM40_CH2); } /*********************************************************************************************************************** * Function Name: tim40_channel3_interrupt * @brief TIM4 Channel interrupt service routine * @param msg * @return None ***********************************************************************************************************************/ void tim40_channel3_interrupt(void) { INTC_ClearPendingIRQ(TM03_IRQn); // clear INTTM03 interrupt flag RTE_Calc_Freq(RTE_TIM40_CH3); }