pwm 输入捕获
2016 年 08 月 13 日 09:51:03 gtkknd 阅读数:5767 更多
个人分类: 32 timer
PWM 输入是输入捕获的一个特殊应用,输入捕获就是当连接到定时器
的引脚上产生电平变化时对应的捕获装置会立即将当前计数值复制到
另一个寄存器中。你可以开启捕获中断然后在中断处理函数中读出保存
的计数值。
与输入捕获不同的是 PWM 输入模式会将同一个输入信号(TI1 或 TI2)
连接到两个捕获装置(IC1 和 IC2)。这两个捕获装置一个捕获上升沿
一个捕获下降沿。TI1FP1、TI2FP2 它们中的一个被选择为触发输入且
从模式控制器被配置为复位模式。
PWM 输入捕获原理和时序图:
1) 当第一次上升沿到达时 IC1 捕获 TIMx_CCR1 的值为当前计数值
4,IC2 不会捕获 TIMx_CCR2 保持不变,计数器复位从 0 开始计数。
2) 第一个下降沿到达时 IC2 捕获 TIMx_CCR2 的值为 2 表示脉冲宽度。
当上升再次到达时 TIMx_CCR1 的值就表示脉冲周期了(注意:第一次
上升沿捕获的是个随机值)。
2) 原理也讲过了,那么下面就是实战了
一、操作步骤:
①将我的源码从论坛里面下载下来
②用杜邦线将 PB7 和 PC6 连接起来
③将编译完成的 hex 文件下载到开发板
④打开串口调试助手波特率选 9600
⑤按下开发板的复位键,OK 那么你就能看到串口的打印信息。
⑥用杜邦线依次将 PB7 和 PC7、PB7 和 PC8、PB7 和 PC9 连接起来,
看串口打印不同占空比和相同周期的信息。
二、主程序讲解:
①TIM3_PWM_Init(1000-1,72-1);
//1KHz 的周期
这个计算相信大部分人应该没有问题原子哥也做过详细的讲解那么我
在重复一遍
CPU 主频是 72MHZ 这里将 72MHZ 主频 72 分频,那么就为 1MHZ,
所以计数器每加 1 那么就是代表增加 1US,我这里设置的是 999,因为
0-999 正好是 1000us,所以我设置的周期是 1000us 也就是 1KHZ
②TIM_SetCompare1(TIM3,200);
这个函数式设置 PWM 通道的占空比,因为周期是 1000us 所以我这里
设置的是 20%的占空比,这个计算我就算教小白吧 占空比 =
200/1000 我这里设置的是通道 1 也就是 PC6 的占空比。下面三个我就
不讲了。
③TIM4_PWMINPUT_INIT(0xffff,72-1);
这个函数是 PWM 输入模式初始化,这个我设置的最大计数是 0xffff,
因为是 16 位的计数器当然最大也只能这么大了,后面的参数是设置捕
捉频率的,我这里还设置为 1MHz,这样为了好看实验现象。
④While(1){}
主程序那三个打印语句我就不讲了,这个都不会,那么你就该补补了。
三、四路 PWM 程序讲解:
①void TIM3_PWM_Init(u16 arr,u16 psc)
这个函数我不讲很多因为原子哥已经将的很清楚了,我就将几个注意的
地方和大家说一下,
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); 这个函
数式定时器的全映射,将
TIM3 定时器的引脚映射到了 PC6 C7 C8 C9 上了。
四、PWM 输入捕捉程序讲解:
①void TIM4_PWMINPUT_INIT(u16 arr,u16 psc)
这个函数我在源码里面已经注释的很清楚了,有几个点需要大家注意
②TIM_SelectInputTrigger(TIM4, TIM_TS_TI2FP2);
这个是选择有效的输入端 ,我这里 TIM_TS_TI2FP2 选择的 PB7,注
意:只有 TI1FP1 和 TI2FP2 连到了从模式控制器,所以 PWM 输入模
式只能使用 TIMx_CH1 /TIMx_CH2 信号。
③TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);
这个是配置为 PWM 输入主从复位模式,就是每次输入端有效电平变化
的时候定时器计数器就会硬件上置 0
中断函数讲解
至于 TIM4 的中断函数很简单我就不多讲什么了,主要就是将捕捉到的
周期和占空比记录下来。
注意:我提醒大家一下,我现在这个捕捉的周期的范围是 1-65535us,
如果你要捕捉的周期超出这个怎么办,我给大家一点建议①将捕获精度
降低,也就是讲捕获频率降下来②这个就是用原子哥那种溢出计数的方
法,但是这个有意思的是主从复位模式,每次复位也会产生更新中断,
那么如果不加设置的话,可能这种方法是行不通的。但是我已经解决了,
看手册介绍,解决的。哈哈,大家有兴趣的话,可以去试着解决,自己
做的饭才是最香的。实在是想用第二种方法,但是又解决不了的,就可
以回复,但是我想着还是自己解决的好。
说了这么多,有的人可能会提出疑问?那你给我们讲这些理论,你自己
到底实现了没有?俗话说的好,有图有真相,没图说啥?那么好的上真
相,不过是有误差的,但是我认为这个误差在接受范围内。
---------------------------------------------------源码
-------------------------------------------------------------------------------
PWM。c
#include "pwm.h"
/*功能名称IM3_PWM_Init(u16 arr,u16 psc)
描述 TIM3 产生四路 PWM
*/
void TIM3_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDefGPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC |
RCC_APB2Periph_AFIO, ENABLE);
时钟使能
//使能 GPIO 外设和 AFIO 复用功能模块
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); //Timer3 全映射
GPIOC-> 6,7,8,9
//用于 TIM3 的
CH2 输出的 PWM 通过该 LED 显示
//设置该引脚为复用输出功能,输出 TIM3 CH1 CH2 CH3 CH4 的 PWM 脉冲波
形
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 |
GPIO_Pin_9; //初始化 GPIO
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;
//复用推挽输出
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period= arr; //设置在下一个更新事件装入活
动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler=psc; //设置用来作为 TIMx 时钟频
率除数的预分频值 不分频
TIM_TimeBaseStructure.TIM_ClockDivision= 0; //设置时钟分割:TDTS =
Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode=
TIM_CounterMode_Up;
//TIM 向上计数模式
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); //根据
TIM_TimeBaseInitStruct 中指定的参数初始化 TIMx 的时间基数单位
TIM_OCInitStructure.TIM_OCMode= TIM_OCMode_PWM1; //选择定时器
模式:TIM 脉冲宽度调制模式 1
TIM_OCInitStructure.TIM_OutputState= TIM_OutputState_Enable; //比较输
出使能
TIM_OCInitStructure.TIM_Pulse= 0; //设置待装入捕获比较寄存器的脉冲值
TIM_OCInitStructure.TIM_OCPolarity= TIM_OCPolarity_High; //输出极
性:TIM 输出比较极性高
TIM_OC1Init(TIM3,&TIM_OCInitStructure);
//根据 TIM_OCInitStruct 中指
定的参数初始化外设 TIMx
TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);
//使能 TIMx 在
CCR1 上的预装载寄存器
TIM_OC2Init(TIM3,&TIM_OCInitStructure);
//根据 TIM_OCInitStruct 中指
定的参数初始化外设 TIMx
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
//使能 TIMx 在
CCR2 上的预装载寄存器
TIM_OC3Init(TIM3,&TIM_OCInitStructure);
//根据 TIM_OCInitStruct 中指
定的参数初始化外设 TIMx
TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable);
//使能 TIMx 在
CCR3 上的预装载寄存器
TIM_OC4Init(TIM3,&TIM_OCInitStructure);
//根据 TIM_OCInitStruct 中指
定的参数初始化外设 TIMx
TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);
//使能 TIMx 在
CCR4 上的预装载寄存器
TIM_ARRPreloadConfig(TIM3,ENABLE); //使能 TIMx 在 ARR 上的预装载寄
存器