打印
[其他产品]

PIC定时器的使用

[复制链接]
407|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
所谓定时功能就是通过来自单片机内部的时钟脉冲作计数脉冲,使计数器计数,即每个机器周期计数器加1 ,计数值达到予置值后,定时/计数模块产生溢出。
所谓计数是指对外部事件进行计数。外部事件的发生以输入脉冲表示,因此计数功能的实质就是对外来脉冲进行计数。
定时器/ 计数器TMR0 模块的定时工作方式
  对8 位定时器TMR0 来说,不使用分频器时,定时时间的计算公式为:(28 -计数初值)×指令周期
  使用分频器时,定时时间的计算公式为:分频比×(28-计数初值) ×指令周期;分频比取值为2 、4 、8…256。

         首先强调的是TMR1可以被禁止工作,以降低能耗。要关闭定时/计数模块T M R 1只要将 T M R 1使能位 TMR1ON清0 ,“ 与” 门G1的一个引脚被低电平封锁,就使得累加计数器保持静止状态。对16位定时器TMR1 来说,如选择内部时钟源,则定时时间的计算公式为:
         分频比×(216– 计数初值)  ×指令周期。分频比取值为1 、2 、4、8 。

使用特权

评论回复
沙发
functions|  楼主 | 2019-11-8 14:04 | 只看该作者
定时器TMR2模块只有一种工作方式,即定时器工作方式.时钟信
号由内部系统时钟4分频后获取,即取自指令周期信号.
(1)用作周期可调的时基发生器:如指令周期为T,分频比为P1,周期寄存器预赋值为PR2 ,则该周期的计算式为:TTMR2=T×P1×(PR2+1)。

(2)用作延时可调的周期性定时器:如指令周期为T,预分频比为P ,周期寄存器预赋值为PR2 ,后分频比为P2,则该超时溢出周期为:TTMR2IF=T×P1×(PR2+1)×P2
(3)用作普通定时器:如指令周期为T,预分频比为P1,则定时时间为P1×(28-X)×T   (以PIC16F877A为例进行的说明)

使用特权

评论回复
板凳
functions|  楼主 | 2019-11-8 14:05 | 只看该作者
TIM0  查询法使LED一秒闪烁,未使用预分频
#include<pic.h>
#define uint unsigned int
#define uchar unsigned char
#define input  RA3
#define clk  RA5
#define cs_led  RE0
__CONFIG(0x3B31);

void init();
void delay(uint);
void write_164(uchar);
uint intnum1,intnum2;
void main()
{
       init();
       while(1)
       {
              if(T0IF==1)//判断中断溢出位是否溢出,TOIF是否溢出和总中断是否开启无关系。
              {
                     T0IF=0;//需要软件清零
                 intnum1++;
                     if(intnum1==3906)//一秒钟到了
                    {
                            intnum1=0;
                            intnum2++;
                            cs_led=0;
                            if(intnum2==1)
                            write_164(0xfd);
                            if(intnum2==2)
                            {
                                   intnum2=0;
                                   write_164(0xff);
                            }
                     }                  
              }
       }
}

void init()
{
       TRISA=0b11010111;
       TRISE=0b11111110;
       OPTION=0x08;//使用内部时钟信号,预分频器分配给WDT模块,相当于不给TM0设置预分频,
       //一个时钟周期是一秒,当不装初值时,256微秒之后溢出,因为时8位定时器。
}
void delay(uint x)
{
       uint a,b;
       for(a=x;a>0;a--)
              for(b=110;b>0;b--);
}

void write_164(uchar dt)
{
       uchar i;   
       for(i=0;i<8;i++)
       {
              clk=0;     
              if(dt&0x80)
                     input=1;
              else
                     input=0;
              dt=dt<<1;                  
              clk=1;           
       }            
}

TIM0  查询法使LED一秒闪烁,使用预分频
#include<pic.h>
#define uint unsigned int
#define uchar unsigned char
#define input  RA3
#define clk  RA5
#define cs_led  RE0
__CONFIG(0x3B31);

void init();
void delay(uint);
void write_164(uchar);
uint intnum1,intnum2;
void main()
{
       init();
       while(1)
       {
              if(T0IF==1)//判断中断溢出位是否溢出,TOIF是否溢出和总中断是否开启无关系。
              {
                          T0IF=0;//需要软件清零
                     TMR0=61;//重新给定时器装初值。
                     intnum1++;
                     if(intnum1==20)//一秒钟到了
                     {
                            intnum1=0;
                            intnum2++;
                            cs_led=0;
                            if(intnum2==1)
                            write_164(0xfd);
                            if(intnum2==2)
                            {
                                   intnum2=0;
                                   write_164(0xff);
                            }
                     }
              }
       }
}

void init()
{
       TRISA=0b11010111;
       TRISE=0b11111110;
       OPTION=0x07;//使用内部时钟信号,预分频器分配给TIM0模块,256分频。
       //一个时钟周期是一秒,当不装初值时,256微秒之后溢出,因为时8位定时器。
       TMR0=61;//256*Y=50000,=>Y=195,256-195=61,这样就是50ms溢出一次,溢出20次就是1s。
}

void delay(uint x)
{
       uint a,b;
       for(a=x;a>0;a--)
              for(b=110;b>0;b--);
}

void write_164(uchar dt)
{
       uchar i;   
       for(i=0;i<8;i++)
       {
              clk=0;     
              if(dt&0x80)
                     input=1;
              else
                     input=0;
              dt=dt<<1;      
              clk=1;           
       }            
}

TIM0  中断法使LED一秒闪烁,使用预分频
#include<pic.h>
#define uint unsigned int
#define uchar unsigned char
#define input  RA3
#define clk  RA5
#define cs_led  RE0
__CONFIG(0x3B31);

void init();
void delay(uint);
void write_164(uchar);
uint intnum1,intnum2;
void main()
{
       init();
      while(1)
       {
      if(intnum1==2)//一秒钟到了
                     {
                            intnum1=0;
                            intnum2++;
                            cs_led=0;
                            if(intnum2==1)
                            write_164(0xfd);
                            if(intnum2==2)
                            {
                                   intnum2=0;
                                   write_164(0xff);                        
                            }                  
                     }            
       }
}

void init()
{
       TRISA=0b11010111;
       TRISE=0b11111110;
       OPTION=0x07;//使用内部时钟信号,预分频器分配给TIM0模块,256分频。
       //一个时钟周期是一秒,当不装初值时,256微秒之后溢出,因为时8位定时器。
       INTCON=0xa0;//GIE=1,开总中断,T0IE=1,开启T0中断,T0IE是TMR0 溢出中断允许位。
       TMR0=61;//256*Y=50000,=>Y=195,256-195=61,这样就是50ms溢出一次,溢出20次就是1s。
}

void interrupt time0()

{
       T0IF=0;//由于只开启了TMR0中断,所以不用查询是哪个中断,能进来的肯定是TMR0溢出中断,直接将中断溢出标志位清零,
       TMR0=61;
       intnum1++;
}

void delay(uint x)
{
       uint a,b;
       for(a=x;a>0;a--)
              for(b=110;b>0;b--);
}

void write_164(uchar dt)
{
      uchar i;   
       for(i=0;i<8;i++)
       {
              clk=0;            
              if(dt&0x80)
                     input=1;
              else
                     input=0;
              dt=dt<<1;                          
              clk=1;           
       }            
}

TMR1 中断法TIM0  中断法使LED一秒闪烁,不设置预分频。
#include<pic.h>
#define uint unsigned int
#define uchar unsigned char
#define input  RA3
#define clk  RA5
#define cs_led  RE0

__CONFIG(0x3B31);



void init();
void delay(uint);
void write_164(uchar);
uint intnum1,intnum2;
void main()
{
       init();
       while(1)
       {
                if(intnum1==20)//一秒钟到了

                     {

                            intnum1=0;

                            intnum2++;

                            cs_led=0;

                            if(intnum2==1)

                            write_164(0xfd);

                            if(intnum2==2)

                            {

                                   intnum2=0;

                                   write_164(0xff);

                           

                            }                  

                     }            

       }

}

void init()

{

       TRISA=0b11010111;

       TRISE=0b11111110;



       INTCON=0xc0;//GIE=1,开总中断,开启第一外设中断

       PIE1=0x01;//开启定时器1的中断

       TMR1L=(65536-50000)%256;

       TMR1H=(65536-50000)/256;//进入一次中断,是50ms,



       T1CON=0x01;//不设置预分频,关闭定时器1晶振使能控制位,与外部时钟同步,选择内部时钟,使能定时器1,



}

void interrupt time1()

{

       TMR1IF=0;//将中断溢出标志位清零,

       TMR1L=(65536-50000)%256;

       TMR1H=(65536-50000)/256;

      

       intnum1++;

}

void delay(uint x)

{

       uint a,b;

       for(a=x;a>0;a--)

              for(b=110;b>0;b--);



}

void write_164(uchar dt)

{

       uchar i;   

       for(i=0;i<8;i++)

       {

              clk=0;     

              

              if(dt&0x80)

                     input=1;

              else

                     input=0;

              dt=dt<<1;      

                     

              clk=1;           

       }            

}

TMR1 中断法TIM0  中断法使LED400ms闪烁,设置预分频

#include<pic.h>

#define uint unsigned int

#define uchar unsigned char

#define input  RA3

#define clk  RA5

#define cs_led  RE0



__CONFIG(0x3B31);



void init();

void delay(uint);

void write_164(uchar);

uint intnum1,intnum2;

void main()

{

       init();

       while(1)

       {

      

              /*    if(intnum1==20)//一秒钟到了

                     {

                            intnum1=0;

                            intnum2++;

                            cs_led=0;

                            if(intnum2==1)

                            write_164(0xfd);

                            if(intnum2==2)

                            {

                                   intnum2=0;

                                   write_164(0xff);

                           

                            }                  

                     }*/         

       }

}

void init()

{

       TRISA=0b11010111;

       TRISE=0b11111110;



       INTCON=0xc0;//GIE=1,开总中断,开启第一外设中断

       PIE1=0x01;//开启定时器1的中断

       TMR1L=(65536-50000)%256;

       TMR1H=(65536-50000)/256;//如果不设置预分频,进入一次中断,是50ms,现在设置8倍预分频,进入一次中断是400ms。



       T1CON=0x31;//设置8倍预分频,关闭定时器1晶振使能控制位,与外部时钟同步,选择内部时钟,使能定时器1,



}

void interrupt time1()

{

       TMR1IF=0;//将中断溢出标志位清零,

       TMR1L=(65536-50000)%256;

       TMR1H=(65536-50000)/256;

      

       //intnum1++;

              intnum2++;

                            cs_led=0;

                            if(intnum2==1)

                            write_164(0xfd);

                            if(intnum2==2)

                            {

                                   intnum2=0;

                                   write_164(0xff);

                           

                            }                  



}

void delay(uint x)

{

       uint a,b;

       for(a=x;a>0;a--)

              for(b=110;b>0;b--);



}

void write_164(uchar dt)

{

       uchar i;   

       for(i=0;i<8;i++)

       {

              clk=0;     

              

              if(dt&0x80)

                     input=1;

              else

                     input=0;

              dt=dt<<1;      

                     

              clk=1;           

       }            

}

TMR2预分频 后分频      

#include<pic.h>

#define uint unsigned int

#define uchar unsigned char

#define input  RA3

#define clk  RA5

#define cs_led  RE0



__CONFIG(0x3B31);



void init();

void delay(uint);

void write_164(uchar);

uint intnum1,intnum2;

void main()

{

       init();

       while(1)

       {

      

                     if(intnum1==1000)//本来预分频1:1时是200ms到了,现在预分频是4.所以是200*4 ms到了,由于后分频1:2,所以是200*4*2 ms

                     {

                            intnum1=0;

                            intnum2++;

                            cs_led=0;

                            if(intnum2==1)

                            write_164(0xfd);

                            if(intnum2==2)

                            {

                                   intnum2=0;

                                   write_164(0xff);

                           

                            }                  

                     }     

       }

}

void init()

{

       TRISA=0b11010111;

       TRISE=0b11111110;



       INTCON=0xc0;//GIE=1,开总中断,开启第一外设中断外围功能模块中断

       PIE1=0x02;//开启定时器2的中断



       TMR2=56;

       T2CON=0x0d;//预分频1:4,使能tmr2计数允许/禁止控制位,预分频1:4后分频1:2,



}

void interrupt time1()

{

       TMR2IF=0;//将中断溢出标志位清零,

       TMR2=56;

      

       intnum1++;

                           



}

void delay(uint x)

{

       uint a,b;

       for(a=x;a>0;a--)

              for(b=110;b>0;b--);



}

void write_164(uchar dt)

{

       uchar i;   

       for(i=0;i<8;i++)

       {

              clk=0;     

              

              if(dt&0x80)

                     input=1;

              else

                     input=0;

              dt=dt<<1;      

                     

              clk=1;           

       }            

}

TMR2预分频 后分频 周期寄存器

#include<pic.h>

#define uint unsigned int

#define uchar unsigned char

#define input  RA3

#define clk  RA5

#define cs_led  RE0



__CONFIG(0x3B31);



void init();

void delay(uint);

void write_164(uchar);

uint intnum1,intnum2;

void main()

{

       init();

       while(1)

       {

      

                     if(intnum1==1000)//本来预分频1:1时是100ms到了,现在预分频是4.所以是100*4 ms到了,由于后分频1:2,所以是100*4*2 ms

                     {

                            intnum1=0;

                            intnum2++;

                            cs_led=0;

                            if(intnum2==1)

                            write_164(0xfd);

                            if(intnum2==2)

                            {

                                   intnum2=0;

                                   write_164(0xff);

                           

                            }                  

                     }     

       }

}

void init()

{

       TRISA=0b11010111;

       TRISE=0b11111110;



       INTCON=0xc0;//GIE=1,开总中断,开启第一外设中断外围功能模块中断

       PIE1=0x02;//开启定时器2的中断



       TMR2=0;

       PR2=100;//周期寄存器

       T2CON=0x0d;//预分频1:4,使能tmr2计数允许/禁止控制位,预分频1:4后分频1:2,



}

void interrupt time1()

{

       TMR2IF=0;//将中断溢出标志位清零,

       //TMR2=56;

      

       intnum1++;

                           



}

void delay(uint x)

{

       uint a,b;

       for(a=x;a>0;a--)

              for(b=110;b>0;b--);



}

void write_164(uchar dt)

{

       uchar i;   

       for(i=0;i<8;i++)

       {

              clk=0;     

              

              if(dt&0x80)

                     input=1;

              else

                     input=0;

              dt=dt<<1;      

                     

              clk=1;           

       }            

}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

39

主题

446

帖子

1

粉丝