PWM输入捕获模式是输入捕获模式的特例,自己理解如下:
- 每个定时器有四个输入捕获通道IC1、IC2、IC3、IC4。且IC1 IC2一组,IC3 IC4一组。并且可是设置管脚和寄存器的对应关系。
- 同一个TIx输入映射了两个ICx信号。
- 这两个ICx信号分别在相反的极性边沿有效。
- 两个边沿信号中的一个被选为触发信号,并且从模式控制器被设置成复位模式。
- 当触发信号来临时,被设置成触发输入信号的捕获寄存器,捕获“一个PWM周期(即连续的两个上升沿或下降沿)”,它等于包含TIM时钟周期的个数(即捕获寄存器中捕获的为TIM的计数个数n)。
- 同样另一个捕获通道捕获触发信号和下一个相反极性的边沿信号的计数个数m,即(即高电平的周期或低电平的周期)
- 由此可以计算出PWM的时钟周期和占空比了
frequency=f(TIM时钟频率)/n。
duty cycle=(高电平计数个数/n),
若m为高电平计数个数,则duty cycle=m/n
若m为低电平计数个数,则duty cycle=(n-m)/n
注:因为计数器为16位,所以一个周期最多计数65535个,所以测得的 最小频率= TIM时钟频率/65535。
二、程序设计与分析 - 程序概述:选择TIM3作为PWM输入捕获。IC2设置为上升沿,并设置为有效的触发输入信号。所以IC2的捕获寄存器捕获PWM周期,IC1的捕获寄存器捕获PWM的高电平周期。
- 之前调试的时候,想检测低频,按照上面方法进行分频处理时,怎么都不行,后来才搞明白,由于检测时要进行计数,印记预装载值TIM_Period还是要设置成0xffff,而TIM_Prescaler是进行分频用的,也就是说,如果定时器时钟为72M,则将TIM_Prescaler设置成5后,TIM的时钟为14.4M,此时可以检测的最小频率=14.4M/0xffff,也就是说最小检测频率= 14.4M/TIM_Period。
#include "stm32f10x.h"
//
void Tim3_Ch_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_TimeBaseInitTypeDef TIM_BaseInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_BaseInitStructure.TIM_Prescaler = 64;
TIM_TimeBaseInit(TIM3, &TIM_BaseInitStructure);//这里只对预分频系数设定
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);
TIM_SelectInputTrigger(TIM3, TIM_TS_TI2FP2);//选择有效的输入端 //选择IC2为始终触发源
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);//配置为PWM输入主从复位模式,每次输入端有效电平变化的时候定时器计数器就会硬件上置0
TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);//启动定时器的被动触发
TIM_Cmd(TIM3, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);
//这里选择T3C2为始终的触发源,且为上升沿触发,则T3C1经 以上设置后,变为下降沿触发(自动??)
//C3 C4为一组
}
//中断
__IO uint16_t IC2Value = 0;
__IO uint16_t DutyCycle = 0;
__IO uint32_t Frequency = 0;
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3, TIM_IT_CC2) == SET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
IC2Value = TIM_GetCapture2(TIM3);
if (IC2Value != 0){
DutyCycle = (TIM_GetCapture1(TIM3) * 100) / IC2Value;//考虑上下沿的关系
Frequency = SystemCoreClock / 64 / IC2Value ;
}else{
DutyCycle = 0;
Frequency = 0;
}
}
}