/** ****************************************************************************** * @file : user_mian.h * @brief : V1.00 ****************************************************************************** * @attention * ****************************************************************************** */ /* Include Include ------------------------------------------------- --------------*/ #include "stm32f10x.h" #include <stdbool.h> #include "user_gpio.h" #include "user_delay.h" #include "user_rcc_config.h" #include "user_uart.h" #include "user_timer.h" /* Typedef type------------------------------------------------- ---------------*/ /* Define definition------------------------------------------------- ---------------*/ /* Macro macro ----------------------------------------------- -----------------*/ /* Variables variable------------------------------------------------- -------------*/ //Receive up to 200 bytes at a time uint8_t USART_RX_BUF[200]; //receiving status //bit15, receive completion flag //bit14, received 0x0d //bit13~0, the number of valid bytes received uint16_t USART_RX_STA=0; //receive status flag extern u8 TIM5CH1_CAPTURE_STA; //input capture status extern u16 TIM5CH1_CAPTURE_VAL; //Enter capture value /* Constants constant------------------------------------------------- -------------*/ /* Function function------------------------------------------------- -------------*/ int main(void) { u32 temp=0; /*Configure system interrupt grouping as 2-bit preemptive 2-bit response*/ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /*Delay function initialization*/ delay_init(); /*RCC configuration*/ Rcc_config(); /*GPIO initialization*/ Gpio_Init(); /*USART1 initialization*/ Uart1_Init(9600); /*Timer 5 initialization*/ Tim5_Input_Init(0xFFFF,72-1); //Counting at a frequency of 1Mhz, the counter overflows from 0 to FFFF, and one clock cycle is 1us /*Infinite loop*/ while(1){ delay_ms(10); /*successfully captured the completion*/ if(TIM5CH1_CAPTURE_STA&0X80) { /*How many times to take overflow*/ temp=TIM5CH1_CAPTURE_STA&0X3F; /*Because every time the counter time is FFFF converted to decimal is 65535*/ temp*=65536;//sum of overflow times temp+=TIM5CH1_CAPTURE_VAL;//The sum of the last capture + overflow time = get the total high time printf("HIGH:%d ms\r\n",temp/1000);//Print the total high flat time TIM5CH1_CAPTURE_STA=0;//start next capture } } } /************************************************************** END OF FILE ****/
STM32 input capture working process
STM32 input capture working process (channel 1 as an example)
Summarize the working process in one sentence: By detecting the edge signal on TIMx_CHx, when the edge signal jumps (such as rising edge/falling edge), store the current timer value (TIMx_CNT) in the corresponding capture/compare register (TIMx_CCRx inside), to complete a capture.
input capture filter
Input capture 1 filter ICIF[3:0], this is used to set the input sampling frequency and digital filter length. Among them, fck_INT is the input frequency of the timer (TIMxCLK), generally 72Mhz, and fDTS is determined according to the setting of CKD[1:0] of TIMx_CRI. If CKD[1:0] is set to 00, then fors= fck_INT. The N value is the filter length.
Set input capture polarity
Set the capture mapping channel
If CC1S is set to 00, channel 1 is set to output. 01 is CC1 channel is configured bit input and mapped to TI1.
In general, channel 1 is mapped to IC1, and channel 2 is mapped to IC2.
Set the input capture divider
Capturing a valid signal can enable the interrupt
Brief description: The input capture of STM32, simply put, is to detect the edge signal on TIMx_CHx, and when the edge signal jumps (such as rising edge/falling edge), the current timer value (TIMx_CNT) is stored in the corresponding In the capture/compare register (TIMx_CCRx) of the channel, a capture is completed. First set the input capture to rising edge detection, and record the value of TIMx_CNT when the rising edge occurs. Then configure the capture signal as falling edge capture. When the falling edge arrives, the capture occurs and the TIMx_CNT value at this time is recorded. In this way, the difference between the two TIMx_CNT before and after is the high-level pulse width. At the same time, we know the counting frequency of TIMx, so that the accurate time of the high-level pulse width can be calculated.
Frequency calculation:
Set the capture mode to falling edge/rising edge capture. When the rising edge/falling edge is captured for the first time, an interrupt will be triggered. In the interrupt, the current count value will be recorded as Value1; the rising edge will be captured for the second time. /falling edge, trigger an interrupt again, in which we record the current count value Value2. So the time between the second capture and the first is the period of the wave. Assuming the timer's clock is set to 72MHz, then the frequency of the resulting wave should be 72MHz/(Value2 - Value1).
Detailed input capture structure
typedef struct { uint16_t TIM_Channel; //Capture channels 1-4 uint16_t TIM_ICPolarity; //capture polarity uint16_t TIM_ICSelection; //Mapping relations uint16_t TIM_ICPrescaler; //Frequency division factor uint16_t TIM_ICFilter; //filter }TIM_ICInitTypeDef;
Input capture related functions
Input capture channel initialization function
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
Channel polarity setting independent function
void TIM_OCxPofarityConfig(TIM_TypeDef* TIMx, uint16_1 TIM_OCPolarity);
Get channel capture value
uint32_t TIM GetCapture 1(TIM_ TypeDef* TIMx):
General configuration steps for input capture:
1. Initialize the timer and the clock corresponding to the IO of the channel.
2. Initialize the IO port, mode bit input:
GPIO_Init();
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // Pull down input
3. Initialize the timer ARR,PSC
TIM_TimeBaselnit();
4. Initialize the input capture channel
TIM ICInit();
5. If you want to enable capture interrupt
TIM_ITConfig();
NVIC Init();
6. Enable the timer
TIM_Cmd();
7. Write interrupt service function
TIMx_IRQHandler();
Experiment code:
Detect the high level time of the GPIOA.0 pin
/** ****************************************************************************** * @file : user_rcc_config.c * @brief : V1.00 ****************************************************************************** * @attention * ****************************************************************************** */ /* Include Include------------------------------------------------- --------------*/ #include "user_rcc_config.h" /* Typedef type------------------------------------------------- ---------------*/ /* Define definition------------------------------------------------- ---------------*/ /* Macro macro ----------------------------------------------- -----------------*/ /* Variables variable------------------------------------------------- -------------*/ /* Constants constant------------------------------------------------- -------------*/ /* Function function------------------------------------------------- -------------*/ /*! \brief Timer initialization \param[in] none \param[in] none \retval none */ void Rcc_config(void) { /*Enable GPIOA clock*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); /*Enable UART1 clock*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); /*Enable Timer 5 clock*/ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE); } /************************************************************** END OF FILE ****/
/** ****************************************************************************** * @file : user_gpio.c * @brief : V1.00 ****************************************************************************** * @attention * ****************************************************************************** */ /* Include Include------------------------------------------------- --------------*/ #include "user_gpio.h" /* Typedef type------------------------------------------------- ---------------*/ /* Define definition------------------------------------------------- ---------------*/ /* Macro macro ----------------------------------------------- -----------------*/ /* Variables variable------------------------------------------------- -------------*/ /* Constants constant------------------------------------------------- -------------*/ /* Function function------------------------------------------------- -------------*/ /*! \brief GPIO initialization function \param[in] none \param[out] none \retval none */ void Gpio_Init(void) { /*GPIO structure*/ GPIO_InitTypeDef GPIO_InitTypeDefstruct; /*UART1 Send pin configuration*/ GPIO_InitTypeDefstruct.GPIO_Mode = GPIO_Mode_AF_PP;//Push-pull multiplexed output GPIO_InitTypeDefstruct.GPIO_Pin = GPIO_Pin_9; GPIO_InitTypeDefstruct.GPIO_Speed = GPIO_Speed_10MHz; /*Write structure to GPIOA*/ GPIO_Init(GPIOA,&GPIO_InitTypeDefstruct); /*UART1 Receive pin configuration*/ GPIO_InitTypeDefstruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;//floating input GPIO_InitTypeDefstruct.GPIO_Pin = GPIO_Pin_10; GPIO_InitTypeDefstruct.GPIO_Speed = GPIO_Speed_10MHz; /*Write structure to GPIOA*/ GPIO_Init(GPIOA,&GPIO_InitTypeDefstruct); /*Initialize PA0*/ GPIO_InitTypeDefstruct.GPIO_Mode = GPIO_Mode_IPD;//pull down input GPIO_InitTypeDefstruct.GPIO_Pin = GPIO_Pin_0; /*Write structure to GPIOA*/ GPIO_Init(GPIOA,&GPIO_InitTypeDefstruct); /*Set as dropdown input*/ GPIO_ResetBits(GPIOA,GPIO_Pin_0); } /************************************************************** END OF FILE ****/
/** ****************************************************************************** * @file : user_uart.c * @brief : V1.00 ****************************************************************************** * @attention * ****************************************************************************** */ /* Include Include------------------------------------------------- --------------*/ #include "user_uart.h" /* Typedef type------------------------------------------------- ---------------*/ /* Define definition------------------------------------------------- ---------------*/ /* Macro macro ----------------------------------------------- -----------------*/ /* Variables variable------------------------------------------------- -------------*/ extern uint16_t USART_RX_STA; extern uint8_t USART_RX_BUF[200]; /* Constants constant------------------------------------------------- -------------*/ /* Function function------------------------------------------------- -------------*/ #if 1 #pragma import(__use_no_semihosting) /*Implement Printf code*/ struct __FILE { int handle; }; FILE __stdout; void _sys_exit(int x) { x = x; } //Redefine the fputc function int fputc(int ch, FILE *f) { while((USART1->SR&0X40)==0);//Send in a loop until the send is complete USART1->DR = (u8) ch; return ch; } #endif /*! \brief UART1 initialization \param[in] none \param[out] none \retval none */ void Uart1_Init(u32 bound) { /*UART structure*/ USART_InitTypeDef USART_InitTypeDefstruct; /*UART Structure configuration*/ USART_InitTypeDefstruct.USART_BaudRate = bound; //baud rate USART_InitTypeDefstruct.USART_HardwareFlowControl =USART_HardwareFlowControl_None; //no hardware streaming USART_InitTypeDefstruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//Send and receive enable USART_InitTypeDefstruct.USART_Parity = USART_Parity_No; //Do not use parity USART_InitTypeDefstruct.USART_StopBits = USART_StopBits_1; //1 stop bit USART_InitTypeDefstruct.USART_WordLength = USART_WordLength_8b; //8 data bits /*write to USART1*/ USART_Init(USART1,&USART_InitTypeDefstruct); /*Enable serial port 1*/ USART_Cmd(USART1,ENABLE); } /*! \brief UART1 interrupt service function \param[in] none \param[out] none \retval none */ void USART1_IRQHandler(void) { } /************************************************************** END OF FILE ****/
/** ****************************************************************************** * @file : user_timer.c * @brief : V1.00 ****************************************************************************** * @attention * ****************************************************************************** */ /* Include Include------------------------------------------------- --------------*/ #include "user_timer.h" /* Typedef type------------------------------------------------- ---------------*/ /* Define definition------------------------------------------------- ---------------*/ /* Macro macro ----------------------------------------------- -----------------*/ /* Variables variable------------------------------------------------- -------------*/ /* Because the captured high level does not know how long Is it possible that the timer has been exceeded or High level so get a byte to record Capture complete, capture to high level, and timer overflow times This works out how much time we captured TIM5CH1_CAPTURE_STA bit7 capture complete flag bit6 capture high flag bit5~0 Capture the number of high-level timer overflows */ u8 TIM5CH1_CAPTURE_STA=0; //input capture status u16 TIM5CH1_CAPTURE_VAL; //Enter capture value /* Constants constant------------------------------------------------- -------------*/ /* Function function------------------------------------------------- -------------*/ /*! \brief Timer initialization \param[in] loading value \param[in] Frequency division factor \retval none */ void Tim5_Input_Init(uint16_t arr, uint16_t psc) { /*Timer structure*/ TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypeDefstruct; /*Timer 5 input capture structure*/ TIM_ICInitTypeDef TIM5_ICInitStructure; /*interrupt controller structure*/ NVIC_InitTypeDef NVIC_InitStructure; /*Timer initialization configuration*/ TIM_TimeBaseInitTypeDefstruct.TIM_Period = arr; //autoload value TIM_TimeBaseInitTypeDefstruct.TIM_Prescaler = psc; //Frequency division factor TIM_TimeBaseInitTypeDefstruct.TIM_CounterMode = TIM_CounterMode_Up;//count up mode TIM_TimeBaseInitTypeDefstruct.TIM_ClockDivision = TIM_CKD_DIV1;//clock frequency division /*Write Timer 5*/ TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitTypeDefstruct); /*Initialize Timer 5 input capture parameters*/ TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 select input IC1 is mapped to TI1 TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //Mapped to TI1 TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //Rising edge capture TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//Configure the input frequency division. If there is no frequency division, there is a rising edge capture. If the frequency division is 2, it will only start capturing after 2 rising edges. TIM5_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 Configure input filter No filter, no acquisition /*Write to Timer 5 input capture channel*/ TIM_ICInit(TIM5, &TIM5_ICInitStructure); /*Interrupt group initialization*/ NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; //TIM5 interrupt NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//preemption priority 2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //Sub Priority Level 0 NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE; //Enable input capture /*write to the interrupt controller*/ NVIC_Init(&NVIC_InitStructure); /*Enable updates, allow CCC1IE to capture interrupts*/ TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE); /*enable timer*/ TIM_Cmd(TIM5,ENABLE); } /*! \brief TIM5_IRQHandler \param[in] none \param[in] none \retval none */ void TIM5_IRQHandler(void) { /*Judging whether a high level has been captured, we will start counting effectively when it is 0, otherwise exit the interrupt*/ if((TIM5CH1_CAPTURE_STA & 0x80) == 0) //not yet captured { /*Determine whether the timer is up*/ if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET) { /*High level has been captured*/ if(TIM5CH1_CAPTURE_STA&0X40) { /*The high level is too long, the number of counting times is full, and the flag is directly forced to be*/ if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F) { TIM5CH1_CAPTURE_STA|=0X80;//mark a successful capture TIM5CH1_CAPTURE_VAL=0XFFFF; } else { /*The counter update event plus 1 is used to calculate the high level time TIM5CH1_CAPTURE_STA*Timer setting + TIM5CH1_CAPTURE_VAL = high level time */ TIM5CH1_CAPTURE_STA++; } } } } /*Determine whether capture has occurred*/ if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET) { /*Judging whether the high level was captured last time, if the last time If it is a high level, then this time it has captured a low level */ if(TIM5CH1_CAPTURE_STA&0X40) //caught on a falling edge { TIM5CH1_CAPTURE_STA|=0X80; //The marker successfully captures a high level pulse width TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5); //Save the value of the capture compare register for calculating the time TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //CC1P=0 set as rising edge capture }else { /*capture high level*/ TIM5CH1_CAPTURE_STA=0; //empty TIM5CH1_CAPTURE_VAL=0; TIM_SetCounter(TIM5,0); //Set the timer count to 0 to start recording the high level time TIM5CH1_CAPTURE_STA|=0X40; //Flag captured on rising edge TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //CC1P=1 set as falling edge capture } } /*clear interrupt flag*/ TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); } /************************************************************** END OF FILE ****/
/** ****************************************************************************** * @file : user_mian.h * @brief : V1.00 ****************************************************************************** * @attention * ****************************************************************************** */ /* Include Include------------------------------------------------- --------------*/ #include "stm32f10x.h" #include <stdbool.h> #include "user_gpio.h" #include "user_delay.h" #include "user_rcc_config.h" #include "user_uart.h" #include "user_timer.h" /* Typedef type------------------------------------------------- ---------------*/ /* Define definition------------------------------------------------- ---------------*/ /* Macro macro ----------------------------------------------- -----------------*/ /* Variables variable------------------------------------------------- -------------*/ //Receive up to 200 bytes at a time uint8_t USART_RX_BUF[200]; //receiving status //bit15, receive completion flag //bit14, received 0x0d //bit13~0, the number of valid bytes received uint16_t USART_RX_STA=0; //receive status flag extern u8 TIM5CH1_CAPTURE_STA; //input capture status extern u16 TIM5CH1_CAPTURE_VAL; //Enter capture value /* Constants constant------------------------------------------------- -------------*/ /* Function function------------------------------------------------- -------------*/ int main(void) { u32 temp=0; /*Configure system interrupt grouping as 2-bit preemptive 2-bit response*/ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /*Delay function initialization*/ delay_init(); /*RCC configuration*/ Rcc_config(); /*GPIO initialization*/ Gpio_Init(); /*USART1 initialization*/ Uart1_Init(9600); /*Timer 5 initialization*/ Tim5_Input_Init(0xFFFF,72-1); //Counting at a frequency of 1Mhz, the counter overflows from 0 to FFFF, and one clock cycle is 1us /*Infinite loop*/ while(1){ delay_ms(10); /*successfully captured the completion*/ if(TIM5CH1_CAPTURE_STA&0X80) { /*How many times to take overflow*/ temp=TIM5CH1_CAPTURE_STA&0X3F; /*Because every time the counter time is FFFF converted to decimal is 65535*/ temp*=65536;//sum of overflow times temp+=TIM5CH1_CAPTURE_VAL;//The sum of the last capture + overflow time = get the total high time printf("HIGH:%d ms\r\n",temp/1000);//Print the total high flat time TIM5CH1_CAPTURE_STA=0;//start next capture } } } /************************************************************** END OF FILE ****/