占空比和频率的计算思路
如上图所示的一个PWM波,占空比可通过高电平所占时间和周期之间的比值计算的得出
占空比=t1/t
PWM频率计算则为:频率=定时器时钟频率 /(分频系数*周期t)
本次将使用单通道捕获上升沿和下降沿获取高电平所占时间t1和周期t。实现流程
- 在第一次捕获上升沿时将计数器清零,并将下一次捕获设置为下降沿捕获;
- 在捕获到下降沿后,将计数器里的值保存起来(这是计数器里的值就是高电平t1),并将下一次捕获设置为上升沿捕获;
- 在第二次捕获道上升沿后将计数器里的值保存起来(这时计数器里的值就是周期t)。
后续就可以通过获取到的t1和t计算出PWM波的频率和周期了。
CubeMX配置
我使用的时stm32f103c8t6的实验板,先将时钟频率调整为72MHz。
然后选择TIM2,通道1,将分频系数设置为72-1
打开中断
代码部分
生成代码后为我们在中断回调函数中添加以下内容
volatile uint32_t falltime = 0; // 下降沿捕获值
volatile uint32_t periodValue = 0; // 周期值
volatile uint8_t dutyCycle = 0; // 占空比(0-100%)
volatile uint8_t captureState = 0; //电平捕获
volatile uint8_t measurementReady = 0; // 测量完成标志
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM2){
switch (captureState){
case 0: // 捕获到上升沿
__HAL_TIM_SET_COUNTER(htim,2);//计数器设置为2,(这里按理来说应该设置为0的,但我通过调试发现设置为2准确)
captureState = 1;
// 切换为下降沿捕获
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);
break;
case 1: // 捕获到下降沿
falltime = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
captureState = 2;
// 切换为上升沿捕获
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
break;
case 2: // 第二个上升沿,计算周期
periodValue = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);//周期
captureState = 0;
measurementReady = 1; // 设置测量完成标志
break;
}
}
}
main函数
while (1)
{
if (measurementReady){
// 计算占空比
if (periodValue != 0){
dutyCycle = (falltime* 100 / periodValue) ;
frequency = 72000000 / (72*periodValue);
// 打印结果
printf("ZK %d Hz\r\n,PL%d%%\r\n",dutyCycle,frequency);
}
measurementReady = 0; // 清除标志
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
测试部分
为了方便拍视频就将结果显示到OLED显示屏上
用示波器生成不同频率,不同占空比的波形供开发板捕获