a) 目的:基础PWM输入也叫捕获,以及中断配合应用。使用前一章的输出管脚PB1(19脚),直接使用跳线连接输入的PA3(13脚),配置为TIM2_CH4,进行实验。
b) 对于简单的PWM输入应用,暂时无需考虑TIM1的高级功能之区别,按照目前我的应用目标其实只需要采集高电平宽度,而不必知道周期,所以并不采用PWM输入模式,而是普通脉宽捕获模式。
c) 初始化函数定义:
void TIM_Configuration(void); //定义TIM初始化函数
d) 初始化函数调用:
TIM_Configuration(); //TIM初始化函数调用
e) 初始化函数,不同于前面模块,TIM的CAP初始化分为三部分——计时器基本初始化、通道初始化和时钟启动初始化:
void TIM_Configuration(void)//TIM2的CAP初始化函数
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//定时器初始化结构
TIM_ICInitTypeDef TIM_ICInitStructure; //通道输入初始化结构
//TIM2输出初始化
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; //周期0~FFFF
TIM_TimeBaseStructure.TIM_Prescaler = 5; //时钟分频
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分割
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);//基本初始化
//TIM2通道的捕捉初始化
TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;//通道选择
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;//下降沿
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//管脚与寄存器对应关系
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//分频器
TIM_ICInitStructure.TIM_ICFilter = 0x4; //滤波设置,经历几个周期跳变认定波形稳定0x0~0xF
TIM_ICInit(TIM2, &TIM_ICInitStructure); //初始化
TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2); //选择时钟触发源
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);//触发方式
TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable); //启动定时器的被动触发
TIM_ITConfig(TIM2, TIM_IT_CC4, ENABLE); //打开中断
TIM_Cmd(TIM2, ENABLE); //启动TIM2
}
f) RCC初始化函数中加入TIM时钟开启:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM3, ENABLE);
g) GPIO里面将输入和输出管脚模式进行设置。IN_FLOATING,50MHz。
h) 使用中断的话在NVIC里添加如下代码:
//打开TIM中断(与前一章相同)
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
i) 简单应用:
变量 = TIM_GetCapture4(TIM2);
j) 注意事项:
i. 由于我的需求只跟高电平宽度有关,所以避免了使用PWM输入模式,这样可以每个管脚捕捉一路信号。如果使用PWM模式,每一路需要占用两个寄存器,所以一个定时器只能同时使用两路PWM输入。
ii. 由于捕捉需要触发启动定时器,所以PWM输出与捕捉不容易在同一个TIM通道上实现。如果必须的话只能增加计数溢出的相关代码。
iii. 有些程序省略了捕捉通道的初始化代码,这是不对的
iv. 在基本计时器初始化代码里面注意选择适当的计数器长度,最好让波形长度不要长于一个计数周期,否则需要增加溢出代码很麻烦。一个计数周期的长度计算跟如下几个参数有关:
(1) RCC初始化代码里面的RCC_PCLKxConfig,这是TIM的基础时钟源与系统时钟的关系。
(2) TIM初始化的TIM_Period,这是计数周期的值
(3) TIM初始化的TIM_Prescaler,这是计数周期的倍频计数器,相当于调节计数周期,可以使TIM_Period尽量大,提高计数精度。
疑问:
现在有两个疑问:
1、在TIM2的捕捉输入通道初始化里面这句
TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2); //选择时钟触发源
按照硬件框图,4通道应该对应TI4FP4。可是实际使用TI1FP1,TI2FP2都行,其他均编译错误未注册。这是为什么?
2、关闭调试器和IAR程序,直接供电跑出来的结果第一个周期很正常,当输出脉宽第二次循环变小后捕捉的数值就差的远了。不知道是为什么
要测量高电平的宽度必须使用PWM输入模式,而且只能使用CH1
所谓脉冲方波长度高电平的宽度是指信号的上升沿至下降沿之间的时间,如果使用普通的捕获模式,只能知道出现上升沿的时间或出现下降沿的时间(你选择了后者),在你的程序中因为出现上升沿的时间与定时器启动的时间相吻合,所以第一次出现下降沿的时间就是高电平的宽度,而从第二次开始结果自然不准了。
使用PWM输入模式,实际上在出现上升沿的时侯,定时器捕获了这个时间至CC1,同时定时器内部有一个通过TI1_ED清零计数器的操作,所以每次出现下降沿时,计数器的内容刚好是高电平的宽度,这个数值被拷贝(捕获)至CC2中。
从定时器的结构图可以看到,只有通道1有一个到触发控制器的控制线(TI1_ED),而其它通道没有这样的控制线,所以PWM输入模式只能使用CH1和CH2,而不能使用CH3和CH4。
谢谢
谢谢,看来我的程序有问题,不过还是不大明白,回头学学再改改。
有点不明白,看驱动库手册上油如下说明:
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);//选择从模式:选中触发信号(TRGI)的上升沿重初始化计数器并触发寄存器的更新
这个不是一设置就一直生效的吗?这样每次上升沿时都初始化计算器,下降沿时获取计数器值,得到的应该一直都是高电平宽度信息啊。
还是上面这条语句在普通模式下只执行一次?