|
楼主 |
发表于 2014-5-24 16:25:35
|
显示全部楼层
*****************
TIM Time Base example
*****************
一个被 很多开发板 无视的例子,但这个例子 能学到很多 定时器 用法。
Example Description
This example shows how to configure the TIM peripheral in Output Compare Timing mode with the corresponding Interrupt requests for each channel in order to generate 4 different time bases.
信号如下:
The TIM2 CC1 register value is equal to 40961, CC1 update rate = TIM2 counter clock / CCR1_Val = 146.48 Hz, so the TIM2 Channel 1 generates an interrupt each 6.8ms
The TIM2 CC2 register is equal to 27309, CC2 update rate = TIM2 counter clock / CCR2_Val = 219.7 Hz so the TIM2 Channel 2 generates an interrupt each 4.55ms
The TIM2 CC3 register is equal to 13654, CC3 update rate = TIM2 counter clock / CCR3_Val = 439.4Hz so the TIM2 Channel 3 generates an interrupt each 2.27ms
The TIM2 CC4 register is equal to 6826, CC4 update rate = TIM2 counter clock / CCR4_Val = 878.9 Hz so the TIM2 Channel 4 generates an interrupt each 1.13ms.
就是下面图片所示的信号
- __IO uint16_t CCR1_Val = 40961;
- __IO uint16_t CCR2_Val = 27309;
- __IO uint16_t CCR3_Val = 13654;
- __IO uint16_t CCR4_Val = 6826;
复制代码
这个程序和上面的程序不同之处, 不仅 是 通过中断 调用了 TIM_SetCompare1 函数,而且调用的参数 使用了 捕获方式,
capture = TIM_GetCapture1(TIM2);
TIM_SetCompare1(TIM2, capture + CCR1_Val);
******************************************
先看一下程序,只看主干,详细要看源代码
首先,
- /* Time base configuration */
- TIM_TimeBaseStructure.TIM_Period = 65535;
- TIM_TimeBaseStructure.TIM_Prescaler = 0;
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
复制代码
然后,
- /* Output Compare Timing Mode configuration: Channel1 */
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
- TIM_OC1Init(TIM2, &TIM_OCInitStructure);
- TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);
复制代码
然后,
- /* Output Compare Timing Mode configuration: Channel2 */
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
- TIM_OC2Init(TIM2, &TIM_OCInitStructure);
- TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);
复制代码
同理 通道3,4
最后,使能 进入 大循环,
- /* TIM IT enable */
- TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
- /* TIM2 enable counter */
- TIM_Cmd(TIM2, ENABLE);
- while (1);
复制代码
上面的 内容 和 前面的练习类似,难度不大,
学习重点在于中断 函数,
- void TIM2_IRQHandler(void)
- {
- if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
- {
- TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
- /* Pin PC.06 toggling with frequency = 73.24 Hz */
- GPIO_WriteBit(GPIOC, GPIO_Pin_6, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_6)));
- capture = TIM_GetCapture1(TIM2);
- TIM_SetCompare1(TIM2, capture + CCR1_Val);
- }
- else if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)
- {
- 此处省略
- }
- else if (TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET)
- {
- 此处省略
- }
- else
- {
- TIM_ClearITPendingBit(TIM2, TIM_IT_CC4);
- 此处省略
- }
- }
复制代码
核心 是理解
capture = TIM_GetCapture1(TIM2);
TIM_SetCompare1(TIM2, capture + CCR1_Val);
查找 GetCapture 的用法
uint16_t TIM_GetCapture1 ( TIM_TypeDef * TIMx )
Gets the TIMx Input Capture 1 value.
Parameters:
TIMx,: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.
Return values:
Capture Compare 1 Register value.
返回 CRR 值,这个值比较熟悉了。
然后为什么 返回的CRR 还要 + CCR1_Val,然后作为新的 CRR 再赋值呢?
网上搜一下,
http://www.360doc.com/content/11/0917/23/7736891_149118340.shtml
这里的解释是:设置TIMx捕获比较1寄存器值然后动态修改其CCR的值 使整个程序一直进行下去。
不详细,还得继续找答案,
http://www.eefocus.com/bbs/article_244_520168.html
这个就详细点了,
设置TIM2捕获比较寄存器1 的值 ,
//将计数值加上翻转的脉冲值写入输出比较寄存器中,以保证下一个TIM事
//将TIM1_CCR1的值增加2000,使得下一个TIM事件也需要2000个脉冲,
//另一种方式是清零脉冲计数器
基本可以理解了,因为 脉冲计数器(CNT),没有清零,一致再累加,为了 每计够 CCR 次时能翻转,所以 将CCR 不断 累加。感觉没有 使用 清零脉冲计数器 的方案好。
怎样清零,找到 另一种方式是清零脉冲计数器 //TIM_SetCounter(TIM2,0x0000);
先修改一下中断函数,
- void TIM2_IRQHandler(void)
- {
- if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
- {
- TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
- /* Pin PC.06 toggling with frequency = 73.24 Hz */
- GPIO_WriteBit(GPIOC, GPIO_Pin_6, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_6)));
- TIM_SetCounter(TIM2,0x0000);
- }
- else if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)
- {
- TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
- /* Pin PC.07 toggling with frequency = 109.8 Hz */
- GPIO_WriteBit(GPIOC, GPIO_Pin_7, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_7)));
- TIM_SetCounter(TIM2,0x0000);
- }
- else if (TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET)
- {
- TIM_ClearITPendingBit(TIM2, TIM_IT_CC3);
- /* Pin PC.08 toggling with frequency = 219.7 Hz */
- GPIO_WriteBit(GPIOC, GPIO_Pin_8, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_8)));
- TIM_SetCounter(TIM2,0x0000);
- }
- else
- {
- TIM_ClearITPendingBit(TIM2, TIM_IT_CC4);
- /* Pin PC.09 toggling with frequency = 439.4 Hz */
- GPIO_WriteBit(GPIOC, GPIO_Pin_9, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_9)));
- capture = TIM_GetCapture4(TIM2);
- TIM_SetCompare4(TIM2, capture + CCR4_Val);
- }
- }
复制代码
前三个通道使用 SetCounter 函数,
只有第三个通道有输出,
如果全部都使用 SetCounter 函数,
只有第四个通道有输出,
这不是偶然的,因为 第四个通道 的CCR 值最小,其它三个通道还没来得及翻转,就因为第四个通道翻转并重新把脉冲计数器 置0 ,所以其它三个通道永远无法翻转。
多个通道,而且CCR 不一致时,不要用SetCounter 。
因为CCR最大值 是 65535,所以会溢出。capture + CCR1_Val 不停进行下去,会溢出,目前看来没影响的,感觉应该类似环形队列,CCR 和 CNT 能绕回来 再从0 又开始增加,不停循环。(CCR溢出,刚开始迷惑了好久。)
看来 CCR 溢出,会破坏定时器,是个流言!
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|