STM32采用普通的IO口来测量PWM的频率
2018-07-01 来源:eefocus
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;//这里清空TIM4计数。重新开始计数
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; //通用定时器4
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);//使能定时器4和定时器4更新中断:TIM_IT_UPDATE
}
void TIM4_IRQHandler(void)
{
HAL_TIM_IRQHandler(&TIM4_Handler);
if(PWM_FLAG_CNT == 1)//PWM上升沿到来标志
{
timer4_PWM_cnt++;
}
}