【STM库应用】stm32 之 TIM (详解二 脉冲宽度、周期测量)
最后更新于:2022-04-01 14:51:14
昨天已经把这个研究出来了,但是由于修改专利申请书,一直没有时间上传,今天补上!
今天主要是用TIM3进行PWM的输入模式,进行对矩形波的脉冲信号宽度以及其周期进行测量,先来看一幅图。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-21_576915bb8cee0.jpg)
**图1 TIM内部逻辑图**
我们先来看看datasheet上是怎么说的:
该模式是输入捕获模式的一个特例,除下列区别外,操作与输入捕获模式相同:
● 两个ICx信号被映射至同一个TIx输入。
● 这2个ICx信号为边沿有效,但是极性相反。
● 其中一个TIxFP信号被作为触发输入信号,而从模式控制器被配置成复位模式。
例如,你需要测量输入到TI1上的PWM信号的长度(TIMx_CCR1寄存器)和占空比(TIMx_CCR2
寄存器),具体步骤如下(取决于CK_INT的频率和预分频器的值)
● 选择TIMx_CCR1的有效输入:置TIMx_CCMR1寄存器的CC1S=01(选择TI1)。
● 选择TI1FP1的有效极性(用来捕获数据到TIMx_CCR1中和清除计数器):置CC1P=0(上升沿
有效)。
● 选择TIMx_CCR2的有效输入:置TIMx_CCMR1寄存器的CC2S=10(选择TI1)。
● 选择TI1FP2的有效极性(捕获数据到TIMx_CCR2):置CC2P=1(下降沿有效)。
● 选择有效的触发输入信号:置TIMx_SMCR寄存器中的TS=101(选择TI1FP1)。
● 配置从模式控制器为复位模式:置TIMx_SMCR中的SMS=100。
● 使能捕获:置TIMx_CCER寄存器中CC1E=1且CC2E=1。
我们从图1上可以看出只有TI1FP1和TI2FP2连到了从模式控制器,所以PWM输入模式只能使用TIMx_CH1 /TIMx_CH2信号。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-21_576915bbb1393.jpg)
**图2 IC1,IC2捕获信号图**
TI1为输入PWM波信号波形,TIMx_CNT为计数器计数值,当第一个下降沿信号到来,IC2会先进行捕获,然后到下一个上升沿到来,IC1进行捕获!在捕获的同时,IC1和IC2会吧CNT的值映射到对应的CCR1、CCR2的寄存器里面,这个值就是我们需要的计数值!
那么我们所需测量的周期就是IC1捕获的值,脉冲宽度即为IC2测量的值了!
可是,这里有个bug,不注意的人,很容易犯错!我们的CCRx寄存器是一个16bit的寄存器计数范围为0~0xffff,即0~65535,可是当测量的矩形波周期太长,脉冲宽度太宽,二我们的计数又太快,很容易出现CCRx溢出现象,所以,我们在测量低频信号时,一定要对TIM的时钟进行分频,这样我们的计数就不会那么快了,也不会产生溢出现象,当我们计数计完了,再把分频所导致的结果进行倍频就OK了。
还有个地方,可能你只按照我上面说的进行做,你会发现他总是跟实际的频率,或者周期差那么一点点!其实这是有来由的!下面看看图3:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-21_576915bbc812a.jpg)
**图3 注意点**
根据图3,我们可以看出他在开始计数的过程中会差那么三个时钟,所以我们要在数值上进行补齐!也就这么多!下面附上代码:
~~~
void inpwm_init(void)
{
TIM_ICInitTypeDef TIM_ICInitStructure;
/* TIM3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* GPIOA clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* NVIC configuration */
NVIC_Configuration();
/* Configure the GPIO ports */
GPIO_Configuration();
/* TIM3 configuration: PWM Input mode ------------------------
The external signal is connected to TIM3 CH2 pin (PA.07),
The Rising edge is used as active edge,
The TIM3 CCR2 is used to compute the frequency value
The TIM3 CCR1 is used to compute the duty cycle value
------------------------------------------------------------ */
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
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);
/* Select the TIM3 Input Trigger: TI2FP2 */
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
/* Select the slave Mode: Reset Mode */
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
/* Enable the Master/Slave Mode */
TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);
/* TIM enable counter */
TIM_Cmd(TIM3, ENABLE);
/* Enable the CC2 Interrupt Request */
TIM_ITConfig(TIM3, TIM_IT_CC2|TIM_IT_CC1, ENABLE);
}
~~~
~~~
void TIM3_IRQHandler(void)
{
if(TIM_GetFlagStatus(TIM3,TIM_FLAG_CC1) == SET)
{
DutyCycle = TIM_GetCapture1(TIM3)+3;
Frequency = 72000000 / DutyCycle;
TIM_ClearFlag(TIM3,TIM_FLAG_CC1);
}
if(TIM_GetFlagStatus(TIM3,TIM_FLAG_CC2) == SET)
{
IC2Value = TIM_GetCapture2(TIM3)+4;
TIM_ClearFlag(TIM3,TIM_FLAG_CC2);
}
}
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-21_576915bbe6a3e.jpg)
**图4 实际波形**
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-21_576915bc177f7.jpg)
**图5 测量结果**
蓝桥杯-嵌入式交流群
147520657