STM32 Timer PWM mode input capture
The timers in the Stm32, in addition to the TIM6 and TIM7, have input capture capabilities for other timers. This mode is usually used in the calculation of the input signal frequency frequency, the duty ratio duty, the high and low pulse width, has the very wide use.
STM32 input capture, simply means 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 deposit (TIMX_CCRX) inside, Complete one capture. You can also configure whether to trigger interrupt/DMA when capturing, and so on.
PWM Mode Capture method: Use Tim3_ch1 as PWM output, TIM2_CH2 capture the above PWM signal, and measure the frequency and duty-free ratio. Set PWM frequency to 1KHz, duty ratio 50%.
Specific steps:
1. To achieve PWM input capture, the TIM2 occupies 2 channels. The level change of the 2nd channel is detected by the first channel and the second channel PIN, where the first channel is set to slave mode (how to quickly distinguish the master-slave mode, the rule is as follows: If the second channel is set as the PWM input capture, then the remaining first channel is the slave, and vice versa).
2. Assuming that the input PWM starts at a low level, when the first rising edge arrives, the channel detects the rising edge at the same time. The slave is set to reset mode, so the TIM2 count value is reset to 0, and no interrupt request is generated at this time.
3. The next incoming level is the falling edge, at which time the capture event occurs in Channel 1, and the count value is stored in the CCR1 of Channel 1.
4. Then the second rising edge arrives, at which time the capture event occurs in Channel 2, and the count value at this time is deposited in the CCR2 of Channel 2. The reset mode now resets the TIM2 count to 0, waiting for the second falling edge to arrive.
5. Once the capture process is complete, the PWM frequency F=72m/ccr2; Duty cycle: duty= (CCR1/CCR2) x100%
Note:
PWM input mode, use two channels (typically with timx_ch1 or TIMX_CH2), only one channel is assigned a gpio clock, and the other is used internally. After assigning a gpio clock to one channel, you need to set another to slave and reset mode. (for example, use Ch2,ch1 to set the slave mode). When an input signal (TI1 or TI2) comes in temporarily, the main channel captures the rising edge and the slave captures the falling edge.
In the CH2 channel:
TI2FP1 and TI2FP2 all come from the same signal TI2 edge detection, the same signal, the same tix input mapped two icx signals.
The TI2FP1 and TI2FP2 can be triggered by a corresponding control register of the ICX (IC1 or IC2) connected to it, respectively, to the rising or falling edge, which is valid on the opposite polarity edge, respectively, for the two icx signals. If the TI2FP2 is set to a rising edge, the TI2FP1 is set to a falling edge, which is the opposite polarity.
ch1,3,4 the same.
Specific procedures:
Include "Pbdata.h"
void rcc_configuration (void);
void gpio_configuration (void);
void nvic_configuration (void);
void tim2_configuration (void);
void tim3_configuration (void);
void usart_configuration (void);
int FPUTC (int ch,file *f)
{
Usart_senddata (USART1, (U8) ch);
while (Usart_getflagstatus (USART1,USART_FLAG_TXE) ==reset);
return ch;
}
int main (void)
{
Rcc_configuration (); Configuring the Clock
Gpio_configuration ();//io Port configuration
Tim3_configuration ();
Tim2_configuration ();
Nvic_configuration ();
Usart_configuration ();
while (1)
{
if (flag==1)
{
flag=0;
printf ("The Duty is%d/r/n", duty);
printf ("The frequency is%.2fkhz/r/n", freq);
}
}
}
void Rcc_configuration (void)
{
Systeminit ();
Rcc_apb2periphclockcmd (rcc_apb2periph_gpioa| rcc_apb2periph_usart1,enable);
Rcc_apb1periphclockcmd (rcc_apb1periph_tim2| rcc_apb1periph_tim3,enable);
Rcc_apb2periphclockcmd (rcc_apb2periph_afio,enable);
}
void Gpio_configuration (void)
{
Gpio_inittypedef gpio_initstructure;
Led
Gpio_initstructure.gpio_pin=gpio_pin_9;//tx
Gpio_initstructure.gpio_speed=gpio_speed_50mhz;
GPIO_INITSTRUCTURE.GPIO_MODE=GPIO_MODE_AF_PP;
Gpio_init (gpioa,&gpio_initstructure);
Gpio_initstructure.gpio_pin=gpio_pin_10;//rx
gpio_initstructure.gpio_mode=gpio_mode_in_floating;
Gpio_init (gpioa,&gpio_initstructure);
Gpio_initstructure.gpio_pin=gpio_pin_6;//pwm,tim3_ch1
Gpio_initstructure.gpio_speed=gpio_speed_50mhz;
GPIO_INITSTRUCTURE.GPIO_MODE=GPIO_MODE_AF_PP;
Gpio_init (gpioa,&gpio_initstructure);
Gpio_initstructure.gpio_pin=gpio_pin_1;//tim2_ch2
gpio_initstructure.gpio_mode=gpio_mode_in_floating;
Gpio_init (gpioa,&gpio_initstructure);
}
void Tim2_configuration (void)
{
Tim_timebaseinittypedef tim_timebasestruct;
Tim_icinittypedef tim_icinitstructure;
tim_icinitstructure.tim_channel=tim_channel_2;//Select TIM2_CH2, select Input IC2 map to TI2
tim_icinitstructure.tim_ icpolarity=tim_icpolarity_rising;//Rising edge capture
tim_icinitstructure.tim_icselection=tim_icselection_directti;// Map to TI2 on
tim_icinitstructure.tim_icprescaler=tim_icpsc_div1;//to perform a capture each time an edge is detected on the capture input
tim_ icinitstructure.tim_icfilter=0;//filter setting, through a few periodic jump to determine the waveform stability. (Sampling high, only the continuous acquisition of n levels is high level is considered valid, otherwise less than n is considered invalid, n take 0x0-0xf)
Tim_pwmiconfig (tim2,&tim_icinitstructure);// The above is the input capture configuration
Tim_selectinputtrigger (TIM2,TIM_TS_TI2FP2);//Select the filtered TI2FP2 input as the trigger source, triggering the reset of the following program
Tim_selectslavemode (tim2,tim_slavemode_reset)///From the mode controller is set to reset mode-the selected trigger signal rising edge reinitialize counter and produces an update signal (rising edge one to, tim2->cnt is cleared, each rising edge comes, CNT will be cleared 0)
Tim_selectmasterslavemode (tim2,tim_masterslavemode_enable);//start timer passive trigger
Tim_itconfig (tim2,tim_ it_cc2,enable);//capture Interrupt Open
Tim_clearflag (TIM2,TIM_IT_CC2);//clear Flag bit
Tim_cmd (tim2,enable);//Enable Timer 2
}
void Tim3_configuration (void)
{
Tim_timebaseinittypedef tim_timebasestruct;
Tim_ocinittypedef tim_ocinitstructure;
tim_timebasestruct.tim_period=72000;//Count Initial value
tim_timebasestruct.tim_prescaler=0;//divide factor
tim_timebasestruct.tim_clockdivision=0;//Clock Segmentation
tim_timebasestruct.tim_countermode=tim_countermode_up;//Up counting mode
Tim_timebaseinit (tim3,&tim_timebasestruct);
Tim3_ch1 as PWM output
TIM_OCINITSTRUCTURE.TIM_OCMODE=TIM_OCMODE_PWM1;
tim_ocinitstructure.tim_outputstate=tim_outputstate_enable;
tim_ocinitstructure.tim_pulse=36000;
Tim_ocinitstructure.tim_ocpolarity=tim_ocpolarity_high;
Tim_oc1init (tim3,&tim_ocinitstructure);
Tim_oc1preloadconfig (tim3,tim_ocpreload_enable);
Tim_arrpreloadconfig (tim3,enable);
Tim_cmd (tim3,enable);
}
void Nvic_configuration (void)
{
Nvic_inittypedef nvic_initstructure;
Nvic_prioritygroupconfig (nvic_prioritygroup_1);
Nvic_initstructure.nvic_irqchannel = TIM2_IRQN;
nvic_initstructure.nvic_irqchannelpreemptionpriority = 0;
nvic_initstructure.nvic_irqchannelsubpriority = 1;
Nvic_initstructure.nvic_irqchannelcmd = ENABLE;
Nvic_init (&nvic_initstructure);
}
void Usart_configuration (void)
{
Usart_inittypedef usart_initstructure;
usart_initstructure.usart_baudrate=115200;
usart_initstructure.usart_wordlength=usart_wordlength_8b;
Usart_initstructure.usart_stopbits=usart_stopbits_1;
Usart_initstructure.usart_parity=usart_parity_no;
Usart_initstructure.usart_hardwareflowcontrol=usart_hardwareflowcontrol_none;
Usart_initstructure.usart_mode=usart_mode_rx| Usart_mode_tx;
Usart_init (usart1,&usart_initstructure);
Usart_cmd (usart1,enable);
Usart_clearflag (USART1,USART_FLAG_TC);
}
Interrupt Program
void Tim2_irqhandler (void)
{
if (Tim_getitstatus (TIM2,TIM_IT_CC2) ==bit_set)
{
float ic2value=0;
float dutycycle=0;
float frequency=0;
float pulse=0;
Ic2value=tim_getcapture2 (TIM2);//Get the value of CCR2
Pulse=tim_getcapture1 (TIM2);//Get the value of CCR1
Dutycycle=pulse/ic2value;
Frequency=72000000/ic2value;
Duty= (U32) (dutycycle*100);
Freq= (frequency/1000);
flag=1;
Tim_clearitpendingbit (TIM2,TIM_IT_CC2);
}
}
Duty and freq are defined global variables
extern u32 duty;
extern U16 Freq;
U32 duty=0;
U16 Freq=0;
is available through the debug program. The frequency and duty ratio are all right. The frequency setting is not too high, because the printf function takes more time, the time interval of two captures may cause printf to be unable to send the data in time, causing the data to be refreshed. Change method, using: Usart_senddata (), function hair number.
Other applications:
1. Measure high time: A, the CCR1 in the above is a high-level time, B, when using a channel CH1, the trigger Edge is selected as the rising edge, resulting in a capture interrupt, read the contents of the CCR1, and then change the trigger along the falling edge, the falling edge of the arrival of the capture, Read the contents of the CCR1 again and subtract two times from the high-level time.
2. Measure the number of pulses: A, turn on the timer 1 capture interrupt, capture the signal edge (rising or falling edge) into the interrupt, count++ count, and then turn on the Timer 2 update interrupt, timing a certain time into the update interrupt, read the count value, this is the number of pulses. b, open the external interrupt, configure along the trigger interrupt, count++ count, and then turn on Timer x update interrupt, timing a certain time into the update interrupt, read the count value, this is the number of pulses.
3. Calculate the frequency of the signal, you can select the CH1 or CH2 of the timer (the two frequencies cannot be computed at the same time, otherwise the calculated frequency is the signal frequency represented by the post-initialized channel. Of course, it is also possible to switch channels after each frequency, to take the data through DMA, and use the PWM input capture mode to trigger with the rising edge. The CH3 and CH4 channels are not, as shown in Figure 2, only the 4 signals indicated by the red line are connected to the slave mode controller. Therefore, for 3 and 4 channels, the value of the counter cannot be reset when it receives the rising edge of the signal.