rockyyangyang 发表于 2014-9-15 20:38:24

【转载跟我学OSKinetis】第7课-PIT定时器!

说起PIT周期中断定时器,那就是一句话,So easy!写这个模块的教程简直是太轻松了,PIT的功能就是它名字本身的字面意思,如果非要深究严谨的说的话,就是周期中断或触发定时器。我们常用的就是它的周期中断功能,其实他还可以作为周期定时触发功能,至于触发什么,当然是DMA或PDB啦!

PIT工作原理
即使你不用固件库来编程,PIT也绝对是不会让你望而却步的一个东西,打开技术文档看看它的寄存器数量,你就会惊喜的发现,这货才5个寄存器,简直是业界良心啊有木有。这绝对是新手入门级的模块,如果你能用寄存器编程来搞定这个模块,你也可以自豪的跟别人说,哥也是会写K60驱动的人啊。那么今天就破例讲讲这些寄存器是干嘛的吧!(有点凑字儿嫌疑)
PIT_MCR-PIT模块控制寄存器。别看这个寄存器是32位的,但其实他就俩位可编写,一个是FRZ位,用来控制PIT在DEBUG模式下是否工作(这位你压根就不用管);另一个是MDIS位,用来使能PIT模块时钟,要想配置PIT其他寄存器,你就必须首先使能它。
PIT_LDVALn-定时器加载值寄存器n。这个寄存器是存放计数值的,当这里的数减到0时,PIT就会中断一次或者触发一次。当然,这里说减数并不真的是这个寄存器的数值在自减,而是PIT的另一个寄存器的数值在自减,当减到0后,PIT会重新把LDVAL的值重新加载到那个自减的计数器中。
PIT_CVALn-当前定时器值寄存器n。这个就是刚刚说到的自减计数器。
PIT_TCTRLn-定时器控制寄存器。这货也是虚有其表,明明是32位的寄存器,才2位能用。TEN定时器使能位,用来使能定时器开始工作的,这里指的开始工作就是定时器值开始自减;TIE定时器中断使能位,用来使能是否产生定时中断,当使能后,PIT会在计数器减到0后产生中断。当然不管使能与否,PIT都会在计数器减到0后产生触发信号。
PIT_TFLGn-定时器标志寄存器。这货就1位可用,TIF定时中断标志。
如果你真打算拿PIT来试试手,那么请按照这个顺序来初始化:使能SIM_SCGC6寄存器的PIT时钟位->使能MCR寄存器的MDIS位,开启PIT时钟->使能中断(如果不用中断可忽略)->给LDVAL寄存器赋值(决定定时周期)->使能TCTRL的TEN开启PIT定时器。
其中你可能会关心的PIT定时器的时钟频率是多少,PIT的时钟源只有1个,就是总线时钟,你需要通过你的总线时钟和你要中断的周期来计算加载值LDVAL。

//计算公式:LDVAL=周期ns*总线频率hz

PIT例程讲解
通过了解PIT的工作原理,相信你也应该知道使用固件库编程肯定也是一件轻松的事情了。事实确实如此,打开例程“LPLD_PeriodicInterrupt”,编译并运行后,可以从串口调试助手看到PIT0和PIT1分别以2秒和1秒的周期产生中断。
首先看初始化函数pit_init()
pit0_init_struct.PIT_Pitx = PIT0;
pit0_init_struct.PIT_PeriodS = 2;   //定时周期2秒
pit0_init_struct.PIT_Isr = pit0_isr;//设置中断函数
LPLD_PIT_Init(pit0_init_struct);
pit1_init_struct.PIT_Pitx = PIT1;
pit1_init_struct.PIT_PeriodMs = 1000; //定时周期1000毫秒
pit1_init_struct.PIT_Isr = pit1_isr;//设置中断函数
LPLD_PIT_Init(pit1_init_struct);
LPLD_PIT_EnableIrq(pit0_init_struct);
LPLD_PIT_EnableIrq(pit1_init_struct);
Line 1:使用PIT0模块。PIT一共有4个通道,分别是0~3。
Line 2:配置成员变量PIT_PeriodS,使PIT0的定时周期为2秒。
Line 3:设置中断函数为pit0_isr。
Line 4:初始化pit0。
Line 7:这里配置pit1的周期为1000ms即1s,用的是PIT_PeriodMs成员变量,当热你也可以用PIT_PeriodUs,周期是微秒,这三个变量配置其一即可,也可以组合使用,周期是所有时间的相加。
Line 11:使能PIT0的中断控制器,下同。如果不使用此函数,则不会触发中断请求,只会产生触发信号。
接下来的中断函数就没什么好看的了,你可以在里面做任何事情,当然你也不用去清除任何标志位,因为底层函数已经为你做好这些事情了。

关于这几个定时器
好多人问PIT、Systick、LPTMR、PDB到底有什么不同呢,他们不都是定时器吗?干嘛非得用PIT,不用其他的呢?
其实这是一个比较尴尬的问题,如同问自行车、汽车、飞机不都是交通工具吗?都可以从甲地到乙地,干嘛非用某某呢?
好了,一开始我们就说了,PIT是最简单的定时器,用起来极其简单,如果你想周期性的产生中断,OK,用PIT就足够了。
Systick是什么呢,它是Cortex内核的定时器,也就是说不管是M3\M4,不管是ST的单片机还是飞思卡尔的单片机,这个定时器的结构和用法是一样的,它也可以产生周期中断,也可以作为精准延时函数。但是他的真正用武之地值操作系统的嘀嗒时钟,也就是为uC/OS等操作系统提供时钟节拍。一来他是内核级别的时钟,中断优先级比其他外设模块要高;二来他比较通用,可以不用改任何代码就移植到其他单片机上。
那么LPTMR、PDB呢?这两个是飞思卡尔Kinetis特有的外设模块,也可以用来做定时器,产生周期中断,但是他们也是各自有各自特殊的用途的,LPTMR可以用来做脉冲累加器,用来测量脉冲波的频率;PDB是可编程延时模块,他的主打功能是产生DAC、ADC模块的硬件触发信号,来使他们能够自主的、不需要用户软件来进行工作。

zhaotyue 发表于 2014-9-16 08:29:16

还是寄存器操作比较方便,我觉得这是“授人与鱼 不如授人与渔”的问题,寄存器操作只要掌握了,对其他单片机的开发是一样的思路
        SIM_SCGC6|=1<<23;                        //开启PIT时钟
       
        enable_irq(68);                                //允许pit0中断
       
        PIT_TCTRL0 &=~(1<<0);                //禁用定时器PIT0
        PIT_MCR    &=~(1<<1);                //使能定时器PIT0时钟
        PIT_MCR    |=1<<0;                        //调试模式下定时器停止计数
        PIT_TFLG0|=1<<0;                        //清除定时器中断标志位
       
        PIT_LDVAL0=599999;                //定时器装载值10ms(60M×0.01S-1=599999)
        PIT_TCTRL0 |=1<<1;                        //使能定时器中断请求
        PIT_TCTRL0 |=1<<0;                        //使能定时器
页: [1]
查看完整版本: 【转载跟我学OSKinetis】第7课-PIT定时器!