Universal timers are used as input captures. We will use the TIM5 Channel 1 (PA0) to do the input capture, capture PA0 high-level pulse width (with the WK_UP key input), through the serial port printing high-level pulse width time
Introduction to input Capture
The input capture mode can be used to measure the pulse width or measurement frequency. STM32 timers, in addition to TIM6 and TIM7, have input capture capabilities for other timers. STM32 input capture, simply by detecting the edge signal on the TIMX_CHX, when the edge signal jumps (such as rising edge/falling edge), the current timer value (timx_cnt) stored in the corresponding channel capture/comparison register (TIMX_CCRX) inside, Complete one capture. You can also configure whether to trigger interrupt/DMA when capturing, and so on.
We use the tim5_ch1 to capture the high-level pulse width, that is, to set the input capture as the rising edge detection, record the rising edge when the tim5_cnt value. The capture signal is then configured for a falling edge capture, and when the falling edge arrives, a capture occurs, and the tim5_cnt value is recorded at this time. In this way, the difference between the front and back two tim5_cnt is the pulse width of the high level, while the counting frequency of the TIM5 is known, so that the accurate time of the high-level pulse width can be calculated.
Enter the configuration steps for the capture:
1) Turn on the TIM5 clock and the Gpioa clock and configure P A0 as the drop-down input.
To use TIM5, we must first turn on the TIM5 clock. Here we also configure P A0 as the drop-down input, because we want to capture the high-level pulse width above the tim5_ch1, and Tim5_ch1 is connected to PA0.
Rcc_apb1periphclockcmd (RCC_APB1PERIPH_TIM5, ENABLE); Enable TIM5 clock
Rcc_apb2periphclockcmd (Rcc_apb2periph_gpioa, ENABLE); Enable Gpioa clock
2) Initialize TIM5, set TIM5 ARR and PSC.
After the TIM5 clock is turned on, we will set the values of ARR and PSC two registers to set the automatic reload value and count frequency for the input capture. This is achieved through the Tim_timebaseinit function in the library function.
Click ( here) to collapse or open
- Tim_timebaseinittypedef tim_timebasestructure;
- Tim_timebasestructure.tim_period = arr; Set counter Auto Reload value
- Tim_timebasestructure.tim_prescaler =PSC; Setting the Prescaler value
- Tim_timebasestructure.tim_clockdivision = TIM_CKD_DIV1; Tdts = Tck_tim
- Tim_timebasestructure.tim_countermode = tim_countermode_up; TIM Up counting mode
- Tim_timebaseinit (TIM5, &tim_timebasestructure);
3) Set the input comparison parameter of TIM5, turn on input capture
The settings for the input comparison parameters include mapping relationships, filtering, dividing, and capturing methods. Here we need to set channel 1 as input mode, and IC1 map to TI1 (Channel 1) above, and do not use filter (increase response speed), rising edge capture. The library function initializes the input comparison parameters by using the Tim_icinit function:
void Tim_icinit (tim_typedef* timx, tim_icinittypedef* tim_icinitstruct);
Again, let's take a look at the definition of the parameter setting structure body TIM_ICINITTYPEDEF:
Click ( here) to collapse or open
- typedef struct
- {
- uint16_t Tim_channel; Set Channel
- uint16_t tim_icpolarity; Set the effective capture polarity of the input signal
- uint16_t tim_icselection; Set mapping relationships
- uint16_t Tim_icprescaler; Set input capture divide factor
- uint16_t Tim_icfilter; Setting the filter length
- } tim_icinittypedef;
The Configuration code is:
Click ( here) to collapse or open
- Tim_icinittypedef tim5_icinitstructure;
- Tim5_icinitstructure.tim_channel = Tim_channel_1; Select input IC1 map to TI1
- tim5_icinitstructure.tim_icpolarity = tim_icpolarity_rising; Rising edge Capture
- Tim5_icinitstructure.tim_icselection = Tim_icselection_directti; Map to TI1
- Tim5_icinitstructure.tim_icprescaler = TIM_ICPSC_DIV1; Configurable input divider, no crossover
- Tim5_icinitstructure.tim_icfilter = 0x00;//ic1f=0000 configuration input filter not filtered
- Tim_icinit (TIM5, &tim5_icinitstructure);
4) Enable capture and update interrupts (set TIM5 's DIER register)
Because we want to capture the pulse width of the high-level signal, so, the first capture is the rising edge, the second capture of the falling edge, must be captured after the rising edge, set the capture edge for the falling edge, and if the pulse width is longer, then the timer will overflow, the overflow must be processed, otherwise the result is not allowed. Both of these things we are doing in the interrupt, so we have to turn on capture interrupts and update interrupts.
Here we use the timer's interrupt function Tim_itconfig to enable capture and update interrupts:
Tim_itconfig (tim5,tim_it_update| tim_it_cc1,enable);//Allow update interrupts and capture interrupts
5) Set interrupt grouping, write interrupt service function
Setting up interrupt grouping is done primarily through function nvic_init (). After the grouping is complete, we also need to complete key operations such as data processing and capture setup within the interrupt function to achieve high-level pulse-width statistics. In the interrupt service function, as in the previous external interrupt and timer interrupt experiment, we have to interrupt type judgment at the beginning of the interrupt, and to clear the interrupt flag at the end of the interrupt. The functions used are the tim_getitstatus () function and the Tim_clearitpendingbit () function, respectively.
if (Tim_getitstatus (TIM5, tim_it_update)! = RESET) {}//Determines if the update is interrupted
if (Tim_getitstatus (TIM5, tim_it_cc1)! = RESET) {}//Determines whether a capture event occurs
Tim_clearitpendingbit (TIM5, tim_it_cc1| tim_it_update);//clear interrupt and capture flag bit
6) Enable timer (set TIM5 's CR1 register)
Finally, you must turn on the timer counter switch, start the TIM5 counter, and start the input capture.
Tim_cmd (tim5,enable); Enable Timer 5
Routines:
Click ( here) to collapse or open
- #include "Timer.h"
- #include "Led.h"
- #include "Usart.h"
- /**
- * Timer 5 Channel 1 input capture configuration
- */
- void Tim5_cap_init (U16 arr,u16 PSC)
- {
- Gpio_inittypedef gpio_initstructure;
- Tim_timebaseinittypedef tim_timebasestructure;
- Tim_icinittypedef tim5_icinitstructure;
- Nvic_inittypedef nvic_initstructure;
- Rcc_apb1periphclockcmd (rcc_apb1periph_tim5,enable); /* Enable TIM5 clock */
- Rcc_apb2periphclockcmd (rcc_apb2periph_gpioa,enable); /* Enable GPIOA clock */
- Gpio_initstructure.gpio_pin = gpio_pin_0; /**/
- Gpio_initstructure.gpio_mode = GPIO_MODE_IPD; /*PA0 Input */
- Gpio_init (gpioa,&gpio_initstructure);
- Gpio_resetbits (GPIOA,GPIO_PIN_0); /*PA0 drop down */
- /* Initialize Timer 5 tim5*/
- Tim_timebasestructure.tim_period = arr; /* Set counter Auto reload value */
- Tim_timebasestructure.tim_prescaler = PSC; /* Prescaler */
- Tim_timebasestructure.tim_clockdivision = TIM_CKD_DIV1; /* Set clock split: Tdts = tck_tim*/
- Tim_timebasestructure.tim_countermode = tim_countermode_up; /*tim Up counting Mode */
- Tim_timebaseinit (tim5,&tim_timebasestructure); /* Initializes the time base unit of the TIMX based on the parameters specified in Tim_timebaseinitstruct */
- /* Initialize TIM5 input capture parameters */
- Tim5_icinitstructure.tim_channel = Tim_channel_1; /*CC1S=01 Select input IC1 map to TI1 */
- tim5_icinitstructure.tim_icpolarity = tim_icpolarity_rising; /* Rising edge capture */
- Tim5_icinitstructure.tim_icselection = Tim_icselection_directti; /* Map to TI1 */
- Tim5_icinitstructure.tim_icprescaler = TIM_ICPSC_DIV1; /* Configure input divider, no crossover */
- Tim5_icinitstructure.tim_icfilter = 0; /*ic1f=0000 configuration Input Filter not filtered */
- Tim_icinit (tim5,&tim5_icinitstructure);
- /* Interrupt grouping initialization */
- Nvic_initstructure.nvic_irqchannel = TIM5_IRQN; /*TIM5 Interrupt */
- Nvic_initstructure.nvic_irqchannelpreemptionpriority = 2; /* First Priority Level 2 */
- nvic_initstructure.nvic_irqchannelsubpriority = 0; /* FROM priority Level 0 */
- Nvic_initstructure.nvic_irqchannelcmd = ENABLE; /*IRQ Channel is enabled */
- Nvic_init (&nvic_initstructure);
- Tim_itconfig (tim5,tim_it_update| tim_it_cc1,enable);/* Allow update interrupts, allow Cc1ie capture interrupt */
- Tim_cmd (tim5,enable); /* Enable timer 5*/
- }
- U8 tim5ch1_capture_sta=0; Input capture Status
- U16 Tim5ch1_capture_val; Input Capture Value
- /**
- * Timer 5 Interrupt Service Program
- */
- void Tim5_irqhandler (void)
- {
- if ((tim5ch1_capture_sta&0x80) ==0)//not successfully captured
- {
- if (Tim_getitstatus (tim5,tim_it_update)! = RESET)
- {
- if (tim5ch1_capture_sta&0x40)//has been captured to high level
- {
- if ((tim5ch1_capture_sta&0x3f) ==0x3f)//high level too long
- {
- The tim5ch1_capture_sta|=0x80;//tag was successfully captured once
- TIM5CH1_CAPTURE_VAL=0XFFFF;
- }else tim5ch1_capture_sta++;
- }
- }
- if (Tim_getitstatus (TIM5,TIM_IT_CC1)!=reset)
- {
- if (Tim5ch1_capture_sta & 0x40)
- {
- tim5ch1_capture_sta|=0x80; Mark succeeds in capturing a rising edge
- Tim5ch1_capture_val = Tim_getcounter (TIM5);
- Tim_oc1polarityconfig (tim5,tim_icpolarity_rising); Cc1p=0 set to rising edge capture
- }
- Else
- {
- tim5ch1_capture_sta=0; Empty
- tim5ch1_capture_val=0;
- Tim_setcounter (tim5,0);
- tim5ch1_capture_sta|=0x40; The tag captures the rising edge
- Tim_oc1polarityconfig (tim5,tim_icpolarity_falling); Cc1p=1 set to falling edge capture
- }
- }
- }
- Tim_clearitpendingbit (tim5,tim_it_cc1| Tim_it_update); /* Clear Interrupt flag bit */
- }
Click ( here) to collapse or open
- extern U8 Tim5ch1_capture_sta; Input capture Status
- extern U16 Tim5ch1_capture_val; Input Capture Value
- int main (void)
- {
- U32 temp=0;
- Delay_init (); Time-lapse function initialization
- Nvic_configuration (); Set Nvic Interrupt grouping 2:2-bit preemption priority, 2-bit response priority
- Uart_init (9600); Serial port initialized to 9600
- Led_init (); LED Port Initialization
- Tim5_cap_init (0xffff,72-1); Counting at a frequency of 1Mhz
- while (1)
- {
- Delay_ms (10);
- if (tim5ch1_capture_sta&0x80)//successful capture to a rising edge
- {
- temp=tim5ch1_capture_sta&0x3f;
- temp*=65536;//Overflow Time sum
- temp+=tim5ch1_capture_val;//get the total high-power room
- printf ("high:%d us\r\n", temp);//Print the total high of the usual room
- tim5ch1_capture_sta=0;//Open Next Capture
- }
- }
- }
STM32 Learning Note 11 (Universal Timer as input capture 2)