在线时间7266 小时
UID3426478
注册时间2017-9-25
NXP金币5384
TA的每日心情 | 擦汗 昨天 15:50 |
---|
签到天数: 1874 天 连续签到: 5 天 [LV.Master]伴坛终老
超级版主
 
- 积分
- 112714
- 最后登录
- 2025-8-31
|
之前由于时间比较急,大致看了一下定时器,
链接在这里:https://www.nxpic.org.cn/module/forum/thread-616318-1-1.html
然后是以前LPC11U68的定时器:
链接在这里:https://www.nxpic.org.cn/module/forum/thread-615325-1-1.html
最近老是在外面出差,忙的基本差不多了,还带着开发板一起,也就忙里偷闲学习一下,把知识点总结一下,为自己留个笔记,也给论坛的网友提供一个参考。如果讲的不对,还请批评指正。
定时器基本原理
首先,定时器想要工作,必须要有供电,TIM0和TIM1在系统复位后是默认供电的,而TIM2/TIM3则是不供电的,这个可以通过PCONP寄存器查看和配置。
其次,定时器需要有时钟来源,这个时钟来源的源头就是内核时钟,也就是CCLK,但是这个CCLK并不一定是直接提供给Timer的,PCLKSEL0
和PCLKSEL1中可以配置相应定时器的时钟来源,其实本质上都是CCLK,但是PCLKSEL中的值不同,CCLK的分频也不同,默认情况下是00,对应的是CCLK/4,如果LPC1768的系统频率为100MHz,那么时钟的频率PCLK将会是25MHz。
此外,Timer外设获取到的这个主频,内部还可以再做一次预分频,这个可以由PR(Prescaler Register)寄存器配置,指定了PC(后面解释)的最大值。建议这个值写好了之后,没事就不要修改,并且配置这个值得时候,尽可能满足你需要的最小刻度,而又不至于太精细,例如,我的应用只会是1ms 的整数倍,那么,PR可以配置为25000(实际应该向寄存器写入25000-1,后面再解释),如果配置为25(实际应该向寄存器写入25-1),当然能够满足要求,但是没必要,后面寄存器也不一定能满足太大的时间间隙。与PR相对于的是PC,即Prescale Counter register,这个值会在每个时钟源增加1,然后达到了PR中的值以后,将会在下一个时钟源PCLK到来后(所以这也是为什么前面要减去1),TC(Timer Counter)中的值加1,而PC又从0开始。
然后才是定时器真正的Tick功能了,与之紧密相关的是CCR和TC,即Count Control Register和Timer Counter register, CCR配置定时器/计时器的工作模式,而TC就是定时器的当前值,该值受到前面PC的影响。如果TC不清零,在抵达0xffffffff后,会在PC的达到PR的值后,又会从0开始,这个行为并不会触发任何中断。
说到中断,TC并不产生中断,那么具体产生中断的机制是什么呢?LPC系列的MCU采用的是匹配中断,也就是说,当TC的值等于某个值的时候, 就会产生一个匹配(Match),这个Match会产生中断,这些由寄存器MCR和MR0-MR3完成。先说MR0-MR3,这4个就是匹配寄存器,相当于4个通道,当TC与之匹配时,就会产生中断(如果中断被使能的话)。MCR就是控制MR0-MR3匹配产生时的行为,在匹配发生时,可以不产生中断(相当于关闭中断),或者简单产生中断,或者在产生中断的时候,将TC清零;或者产生中断的时候,停止TC和PC(这样就不会周期性产生中断了);与中断相关的是寄存器是IR,IR中的bit位读到为1的时候,标识对应的中断产生了,相当于是中断的Flag,这个没啥大不了的,有意思的是,如果给对应的Bit位写1,则会清除这个中断标志,这样,清除中断标志就非常简单。
其他一些寄存器,例如控制定时器使能等的TCR,就不展开细说了。
测试及代码分析
talk is cheap,show me your code.废话少说,上代码:
- uint8_t TIM0_FLAG;
- void Tim0_Config(void)
- {
- LPC_SC->PCONP|=1UL<<1;//tim0
- LPC_SC->PCLKSEL0&=0xffffffff3;//PCLK_TIMER0= CCLK/4=25MHz
-
- TIM0_FLAG=0;
- LPC_TIM0->TCR=0x02;//reset tim0
- LPC_TIM0->CCR=0x00;//Timer Mode
- LPC_TIM0->PR=25000-1;//TC++ per 1ms
-
- LPC_TIM0->IR=0x3f;//clear all interrupt flag
- LPC_TIM0->MCR=0x19;//MR0/1 Interrupt enable,MR1 Reset TC
- LPC_TIM0->MR0=100;
- LPC_TIM0->MR1=300;
-
- LPC_TIM0->TCR=0x01;//start tim0
-
- NVIC_EnableIRQ(TIMER0_IRQn);
- }
- void TIMER0_IRQHandler(void)
- {
- if(LPC_TIM0->IR & 0x01)//MR0 Interrupt
- {
- TIM0_FLAG=1;
- LPC_TIM0->IR=0x01;//Clear Interrupt flag
- }
- if(LPC_TIM0->IR & 0x02)//MR1 Interrupt
- {
- TIM0_FLAG=0;
- LPC_TIM0->IR=0x02;
- }
- }
复制代码 这段代码的意思是……你懂的,无需解释。不过我还是啰嗦一下吧,TC在0-100(MR0)阶段,TIM0_FLAG=0,然后在MR0匹配上之后,ISR中将其置1,此后在100-300一直保持1,然后在300时(MR1)时,TC会被清零,TIM0_FLAG也会被清零。在main函数中就可以使用这个TIM0_FLAG去做一些有趣(或者无聊)的事情,例如最简单的是翻转高低电平,这样的话就会有个周期为400ms,占空比为75的PWM波。
|
|