STM32测量外部输入信号的频率的方法有很多:
- 采用内部定时器输入捕获功能。
- 采用普通的IO口设置外部中断+定时器的当时测量PWM信号的频率。
这两种方式比较推荐使用第一种,比较使用内部的资源可以节省CPU资源的利用,
当然当内部资源不够使用的时候,或者是说,硬件电路设计的时候没有连接相应的应引脚只能使用第二种方式了。
本次由于硬件电路设计的不足,导致需要测量PWM输入信号的引脚没有接到相应的通道上,对此使用了第二种方式:
注意:这里定时器中断的优先级要高于外部中断的优先级
思路如下:
- 设置PWM输入信号的引脚为外部中断的方式,并且触发方式为GPIO_MODE_IT_RISING_FALLING 上升,下降沿均可触发。
- 其次使能一个定时器TIM4,定时中断时间看自己需要测量频率来设置。(本次设置为2us –> 最大可测量的频率为50KHz)
- 外部中断中,上升沿到来,清空计数器TIM4->CNT=0,置一个上升沿的标志位为1,代表计算PWM时间的开始tim4_PWM_cnt++。
- 下降沿到来,置一个下降沿的标志为1.
- 下一次上升沿到来,判断上一次是否为下降沿的标志,如果是,则代表PWM一个周期的时间已经到达。读取时间。PWM_Cycle = timer4_PWM_cnt*2. 并且把计数变量清零tim4_PWM_cnt = 0
- 接着下一次下降沿到来,判断上一次是否为上升沿的标志,如果是,则代表一个周期高电平结束,读取时间,即为脉宽 PWM_Duty = timer4_PWM_cnt*2。
具体c语言实现代码如下:
if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_11) != RESET)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11);
if(PWM_EN()==1)
{
TIM4->CNT=0;
if((PWM_FLAG_DOWM==1)&&(PWM_FLAG_UP==2))
{
PWM_Cycle = timer4_PWM_cnt*2;
timer4_PWM_cnt=0;
}
PWM_FLAG_CNT = 1;
PWM_FLAG_UP = 1;
PWM_FLAG_DOWM = 2;
}
else
{
if((PWM_FLAG_DOWM==2)&&(PWM_FLAG_UP == 1))
{
PWM_Duty = timer4_PWM_cnt*2;
}
PWM_FLAG_DOWM=1;
PWM_FLAG_UP=2;
}
void TIM4_Init(u16 arr,u16 psc)
{
TIM4_Handler.Instance=TIM4;
TIM4_Handler.Init.Prescaler=psc;
TIM4_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;
TIM4_Handler.Init.Period=arr;
TIM4_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&TIM4_Handler);
HAL_TIM_Base_Start_IT(&TIM4_Handler);
}
void TIM4_IRQHandler(void)
{
HAL_TIM_IRQHandler(&TIM4_Handler);
if(PWM_FLAG_CNT == 1)
{
timer4_PWM_cnt++;
}
}