PIC单片机之定时器(TMR0)

什么是定时器?

  定时器顾名思义就是用来定时的。在单片机应用中常常用于各种各样的定时。比如让LED灯每隔 1S 亮一次。 这个1S 就是由定时器做到的。

 指令周期 

    指令周期就是单片机执行一个指令所花费的时间。这也是定时器定时的最小时间单位。时钟频率/4=指令频率。1/指令频率=指令周期。

  假设现在的时钟是4MHZ  ,4MHz的时钟经过4分频后变成了 1MHz 其周期为0.0000001s也就是1us,这个1us就是指令周期,这1us也就是定时器定时的最小单位。

定时器与预分频器

    假设在没有预分频器情况下。开启定时器 每隔一个指令周期定时器就加一。假设时钟是4MHz  也就是每隔 1us 定时器加一。

  如果有了预分频器假设预分频器设置成2分频,定时器就 每隔2个指令周期定时器加一。如果预分频器设置成4分频,定时器就 每隔4个指令周期定时器加一,以此类推。

定时器中断标志位

 如: TMR0 这个是8位的定时器,也就是8位的寄存器。8位的寄存器能代表的数值为0~255.也就是说定时器可以从0开始加一直加到255.到255后再加一就又变成0。此时TMR0定时器中断标志位 (TMR0IF)变成 1.(如果中断没有开启,并不执行中断程序。) 

到底从时钟频率一直到定时器中断溢出之间是什么关系呢?

下面我画了一个流程图我们用频率的方式来理解这一切。假设时钟频率是4MHz ,定时器预分频值为2,定时器初始值为0.

1。首先4MHz 的时钟 4分频后变成 1MHz的指令频率;

2。然后预分频器 2 分频后变成 0.5MHz的频率供给定时器;

3。定时器经过256分频后变成约1952Hz的频率溢出中断;



 然后我们再用周期的方式来理解这一切。

1。首先0.25us时钟周期4分频后变成 1us指令周期;

2。然后预分频器 2 分频后变成 2us周期 供给定时器;

3。定时器每隔2us加一 ,加到256次  256X2us=512us溢出中断 ;



希望上面的流程图能帮你梳理一下概念。

实例说明:

   假设时钟周期为4MHZ,每隔50MS点亮LED,每隔50MS灭掉LED。这样的程序要如何做到呢。

   这50ms如何做到.

  1,得到指令周期

    4MHz/4=1MHz  

    1/1MHz=0.0000001s=1us

  2,得到预分频

       定时器定时的最大时间要超过这50mS,所以预分频器要选择256

       预分频X256=最大的定时时间。256X256=65536us=65.536ms 大于50ms

 3,  计算定时器初始值

    (定时器最大值+1)- (定时时间/预分频)=定时器的初始值。

    255+1=256

    50000/256=195.3125

    256-195.3125=60.6875 四舍五入 定时器初始值为61.

设置相关的寄存器。

  OPTION_REG寄存器中我们一般需要设置三处。

  PS<2:0>设置用来设置预分频预分频范围从2 ~256

  PSA设置成0   讲预分频器分配给Timer0模块

  TMR0CS设置成0 内部指令周期时钟。


   

实例程序:

/*开发环境 MPLAB X IDE 型号PIC16LF1823*/

#include<pic.h>  
__CONFIG(FOSC_INTOSC&WDTE_OFF&PWRTE_ON&MCLRE_OFF&CP_ON&CPD_OFF

                                                   &BOREN_ON&CLKOUTEN_OFF&IESO_ON&FCMEN_ON);
__CONFIG(PLLEN_OFF&LVP_OFF) ;
#define LED  LATA5/*也可用 #define LED RA5,只是PIC16LF1823 输出电平的时候,直接控制LATA5执行速度更快,因为传给RA5的数据最终也是传给LATA5才执行的*/
void init_fosc(void)
{
    OSCCON= 0x68;//时钟设置为4MHz
}
void init_gpio(void)
{
    PORTA = 0;
    LATA = 0;
    ANSELA = 0;
    TRISAbits.TRISA5=0; //RA5口设置成输出 用来控制LED
}
void init_timer0(void)
{
    OPTION_REG=0x87; //预分频为256
}
int main(int argc, char** argv)
{
    init_fosc();
    init_gpio();
    init_timer0();
    TMR0IF=0;//清除TMR0中断标志位
    TMR0=61;//设置中断初始值61
    while(1)
    {
        if(TMR0IF==1)//定时时间到了吗??
        {
            LED = ~LED;//改变LED的状态
            TMR0IF=0;//清除TMR0中断标志位
            TMR0=61;//设置中断初始值61为下次50ms定时做准备

        }


    }


}


  

   

  

  


  • 11
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值