前言:STM32 为了方便用户使用,设置了专门的PWM输入捕获模式,在这种模式下,输入捕获更加快捷,而且相比于普通的输入捕获模式,该模式的代码量更小,能够快速实现对PWM周期,占空比,频率的测量。
定时器的PWM输入模式:一路输入信号被两个IC捕获,有TIM1和TIM2可以实现。此时定时器工作于从模式下的复位模式。
复位模式:当检测到边沿触发信号时,定时器计数器的值会被重新更新,从0开始计数。根据CUBEMX 配置,遇到目标边沿发生复位,如果使用上升沿触发,遇到上升沿发生复位。这样通过上升沿与下降沿两次捕获的时间差就是脉宽。
需要注意的是:捕获值需要在寄存器值的基础上加一,因为时钟是从0开始计数。
该模式是输入捕获模式的一个特例,除下列区别外,操作与输入捕获模式相同:
● 两个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。
具体的原理如下图:
使用C8T6最小系统来实现该功能。
CUBEMX 配置如下:
使用定时器1,配置如下:
引脚:
PA0产生PWM,PA8用来输入PWM,需要使用杜邦线将两个引脚相连。
定时器一的配置:
时基单元配置:
使能定时器1的中断,用于在信号边沿产生中断;
定时器2 用来产生PWM波:
串口配置:直接使能异步模式即可;
对于RCC等配置此处不再赘述;
代码很简单,只需要使能定时器,编写中断回调函数就好;
使能定时器
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start (&htim2 ,TIM_CHANNEL_1 );
HAL_TIM_IC_Start_IT (&htim1,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT (&htim1,TIM_CHANNEL_2);
printf ("TIM Capture test !\r\n");
/* USER CODE END 2 */
打印数据,printf 的使用将在串口部分介绍。
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay (500);
printf ("Cap_val1 is :%d , Cap_val1 is : %d \r\n",Cap_val1 ,Cap_val2 );
printf ("Duty is :%0.2f%% Frequency is : %0.2f\r\n",Duty ,Frequency );
}
/* USER CODE END 3 */
回调函数
/* USER CODE BEGIN 4 */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
/*判断中断来源*/
if(htim ->Channel == HAL_TIM_ACTIVE_CHANNEL_1 )
{
/*读取寄存器的值*/
Cap_val1 = HAL_TIM_ReadCapturedValue (&htim1 ,TIM_CHANNEL_1 );
Cap_val2 = HAL_TIM_ReadCapturedValue (&htim1 ,TIM_CHANNEL_2 );
/*计算占空比,频率*/
if(Cap_val1 != 0)
{
Duty = (float )(Cap_val2+ 1)*100 / (Cap_val1 +1) ;
Frequency = 72000000 / 72 / (float )(Cap_val1 +1) ;
}
}
}
/* USER CODE END 4 */
结果展示