多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
比赛终于结束了,好几天没有更新了,今天重新开始!进入深入学习TIM! 定时器,中断这两样东西是学习一个MCU必须掌握的,也是非常有用的! STM32的TIM一般有高级定时器TIM1,(TIM8只有在互联性产品有),普通定时器TIM2,TIM3,TIM4,(TIM5,TIM6,TIM7有点设备中没有);今天就只介绍普通定时器,因为高级定时器我还不会!每一个普通定时器都有4路通道! ![](https://box.kancloud.cn/2016-06-21_576915bb129e9.jpg) 我们先看看这个逻辑图吧!我们今天先讨论讨论定时器的问题!我用红色笔标过的路线就是定时器的工作路线,时钟有内部时钟产生,到PSC哪里进行分频处理,然后CNT进行计数,上面还有一个自动重装载寄存器APP。 ![](https://box.kancloud.cn/2016-06-21_576915bb30d8f.jpg) 这个是分频器的工作原理,我们可以看,分频器设定之前分频系数为1[1],后面的[2][3][4]分频系数为2,分频系数改变后,计数周期也跟着改变了;同时预分频设置生效时,他还会产生一个中断信号,这个中断信号不要管他,一个系统时钟周期后会自动消失,跟I2C的差不多! ![](https://box.kancloud.cn/2016-06-21_576915bb4672c.jpg) 这个是计数过程,上面说过了,计数跟分频后的周期有关;当计数达到装载的数值之后,系统会产生一个三个信号,其中溢出信号和更新事件一个时钟周期后会自动消失,而这时候触发了更新中断标志位UIF,我们可以用这个UPDATE来做定时器的中断标志信号! TIM_ITConfig(TIM2, TIM_IT_UPDATE, ENABLE); 另外还有4个中断,我们知道PWM的产生把,他就跟PWM的产生有着血缘关系! ![](https://box.kancloud.cn/2016-06-21_576915bb5d086.jpg) 如果我们在OC模式选择的时候,TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;选择了Timing那么我们就可以做定时器了。 有时候我们会发现当UPdate中断信号产生时,其他四个中断信号也产生,什么原因呢?因为我们在设置tim.TIM_Period = period;时,period时间太短,就错觉的以为他们是一群产生中断信号的!来我们分析下: 假设分频因子为71,即72分频,PCLK为72M,我们设置的周期为1000;那么我们产生定时器的Upddate信号频率为1000Hz,周期为1ms,假设我们这里设置的CCR1 = 100;CCR2 = 500;CCR3 = 600;CCR4 = 900; 那么update信号产生后0.1ms产生CCR1的中断信号,0.5ms后产生CCR2的中断信号,0.6ms后产生CCR3的中断信号,这些中断标志位是: ~~~ #define TIM_FLAG_Update                    ((uint16_t)0x0001) #define TIM_FLAG_CC1                       ((uint16_t)0x0002) #define TIM_FLAG_CC2                       ((uint16_t)0x0004) #define TIM_FLAG_CC3                       ((uint16_t)0x0008) #define TIM_FLAG_CC4                       ((uint16_t)0x0010) #define TIM_FLAG_COM                       ((uint16_t)0x0020) #define TIM_FLAG_Trigger                   ((uint16_t)0x0040) #define TIM_FLAG_Break                     ((uint16_t)0x0080) #define TIM_FLAG_CC1OF                     ((uint16_t)0x0200) #define TIM_FLAG_CC2OF                     ((uint16_t)0x0400) #define TIM_FLAG_CC3OF                     ((uint16_t)0x0800) #define TIM_FLAG_CC4OF                     ((uint16_t)0x1000) ~~~ [OF为溢出]后面做研究! 对于这些CCR1在定时方面的应用我还没有想出什么好的点子,但是他确实存在,如果想验证的话,我们可以把周期设置长一点,比如设置为1s,然后通过设置CCR的值,来看看效果,呵呵,不过这是不容易实现的,因为CCRx 最大为0xffff = 65535跟72M比比,还能说什么?好吧,谁有什么好办法,可以跟我说下! ~~~ void tim_init(u32 period,u32 psc) { TIM_TimeBaseInitTypeDef tim; TIM_OCInitTypeDef TIM_OCInitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); tim.TIM_Period = period; tim.TIM_Prescaler = psc; tim.TIM_ClockDivision = 0; tim.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &tim); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_Pulse = 1*period/4; TIM_OC2Init(TIM2, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable); TIM_OCInitStructure.TIM_Pulse = 2*period/4; TIM_OC3Init(TIM2, &TIM_OCInitStructure); TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable); TIM_OCInitStructure.TIM_Pulse = 3*period/4; TIM_OC4Init(TIM2, &TIM_OCInitStructure); TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Disable); TIM_ITConfig(TIM2, TIM_IT_CC2|TIM_IT_CC3|TIM_IT_CC4, ENABLE); TIM_Cmd(TIM2,ENABLE); /* Enable the TIM2 global Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } ~~~ ~~~ void TIM2_IRQHandler(void) { static u32 cc2 = 0,cc3 = 0,cc4 = 0,cc5 = 0; static u8 flag2 = 0,flag3 = 0,flag4 = 0,flag5 = 0; u32 capture; if(TIM_GetFlagStatus(TIM2,TIM_FLAG_CC2) == SET) { cc2 ++; if(cc2 > 1000) { flag2 = ~flag2; if(flag2) led_on(4); else led_off(4); cc2 = 0; } TIM_ClearFlag(TIM2,TIM_FLAG_CC2); capture = TIM_GetCapture2(TIM2); TIM_SetCompare2(TIM2, capture + 255); } if(TIM_GetFlagStatus(TIM2,TIM_FLAG_CC3) == SET) { cc3 ++; if(cc3 > 1000) { flag3 = ~flag3; if(flag3) led_on(5); else led_off(5); cc3 = 0; } TIM_ClearFlag(TIM2,TIM_FLAG_CC3); capture = TIM_GetCapture3(TIM2); TIM_SetCompare3(TIM2, capture + 500); } if(TIM_GetFlagStatus(TIM2,TIM_FLAG_CC4) == SET) { cc4 ++; if(cc4 > 1000) { flag4 = ~flag4; if(flag4) led_on(6); else led_off(6); cc4 = 0; } TIM_ClearFlag(TIM2,TIM_FLAG_CC4); capture = TIM_GetCapture4(TIM2); TIM_SetCompare4(TIM2, capture + 725); } if(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update) == SET) { cc5 ++; if(cc5 > 1000) { flag5 = ~flag5; if(flag5) led_on(7); else led_off(7); cc5 = 0; } TIM_ClearFlag(TIM2,TIM_FLAG_Update); } } ~~~ 蓝桥杯-嵌入式交流群 147520657