找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2441|回复: 2
打印 上一主题 下一主题
收起左侧

基于pic16f1947的所有定时器 timer0/timer1/timer2/timer4/timer6驱动程序

[复制链接]
跳转到指定楼层
楼主
ID:511543 发表于 2020-12-25 11:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
之所以把pic16f1947单片机的所有定时器发给大家,也是因为我在开发之前也找过这方面的资源,但是很少,所以只能去研究寄存器,最终都搭建成功,分享给大家,避免少走弯路。本人已经毫无保留分享给大家了。谢谢。

单片机源程序如下:
///////////////////// 头文件///////////////////////
#ifndef     __TIMER_H
#define    __TIMER_H

#include   "datatype.h"
#include   "pic.h"                        //PIC16F IC寄存器定义文件

//#define   TIMER0        //如果不使用TIMER0,请用//注释掉
#ifdef  TIMER0
extern  uint16_t   timer0_count  ;
void Timer0_Init(void);//定时器0初始化
#endif

//#define   TIMER1        //如果不使用TIMER1,请用//注释掉
#ifdef  TIMER1
extern  uint16_t   timer1_count  ;
void Timer1_Init(void);//定时器1初始化
#endif

#define   TIMER2        //如果不使用TIMER2,请用//注释掉
#ifdef  TIMER2
extern  uint16_t   timer2_count  ;
void Timer2_Init(void);//定时器2初始化
#endif

//#define   TIMER4        //如果不使用TIMER4,请用//注释掉
#ifdef  TIMER4
extern  uint16_t   timer4_count  ;
void Timer4_Init(void);//定时器2初始化
#endif

//#define   TIMER6        //如果不使用TIMER6,请用//注释掉
#ifdef  TIMER6
extern  uint16_t   timer6_count  ;
void Timer6_Init(void);//定时器2初始化
#endif

#endif


//////////////////////// 对应的.c 文件 ////////////////////////////////////
#include   "timer.h"

#ifdef  TIMER0
uint16_t   timer0_count = 0 ;
/*
*@brief                timer0初始化
*@prama        None
*@retval        Value
      预分频器分频
    PS2   PS1   PS0
     0        0      0     --2分频
     0        0      1     --4分频
     0        1      0     --8分频
     0        1      1     --16分频
     1        0      0     --32分频
     1        0      1     --64分频
     1        1      0     --128分频
     1        1      1     --256分频
     timer0 定时计算:
    如果FOSC = 16,内部指令周期时钟 CLK =(FOSC /4)=4MHz,  1/CLK =0.25us
    如果FOSC = 64,内部指令周期时钟 CLK =(FOSC /4)=16MHz, 1/CLK =0.0625us
    需要定时间=255*预分频器分频数*(1/CLK) us
    即是:        63.75us*                   15.9375us*
                      FOSC = 16               FOSC = 64  
      2分频 ---    127.5us                   31.875us        
      4分频 ---       255us                   63.75us
      8分频 ---       510us                   127.5us
     16分频 ---    1020us                    255us
     32分频 ---    2040us                    510us
     64分频 ---    4080us                    1020us   
   128分频 ---    8160us                    2040us
   256分频 ---  16320us                    4080us
   */
void Timer0_Init(void)
{
         //这里选择2.04ms 周期
        TMR0CS=0;         //1-T0CKI 引脚上信号的跳变,0 = 内部指令周期时钟(FOSC /4)
        TMR0SE=0;  //1 = 在 T0CKI 引脚电平发生由高到低的跳变时递增,0 = 在 T0CKI 引脚电平发生由低到高的跳变时递增
        //预分频128
        if( SYSTEMCLK == 64 ) //64M-128分频
        {
                PS2=1;                                
                PS1=1;
                PS0=0;
        }
        else//16M-32分频
        {
              PS2=1;                                
                PS1=0;
                PS0=0;
        }
               
        PSA=0;                                //1 = 不将预分频器分配给 Timer0 模块,0 = 将预分频器分配给 Timer0 模块
        TMR0IF=0;                        //清除timer0中断标志位
        TMR0IE=1;                        //开启timer0中断
        PEIE=1;                                //开启外设中断
        GIE=1;                                //开启全局中断
}
#endif



#ifdef   TIMER1
uint16_t   timer1_count = 0 ;
/*
*@brief                timer1始化
*@prama        None
*@retval        Value
      时钟源选择
   TMR1CS1      TMR1CS0       T1OSCEN
      0                   1                      x          ---系统时钟 (FOSC )
      0                   0                      x          ---指令时钟 (FOSC /4)
      1                   1                      x          ---电容触摸传感振荡器
      1                   0                      0         ---T1CKI 引脚上的外部时钟
      1                   0                      1         ---T1OSI/T1OSO 引脚上的振荡器电路
      时钟分频因子                                         使能选择
      T1CKPS1     T1CKPS0                          TMR1ON           TMR1GE
          1               1      --8分频                      0                         0            --关闭
          1               0      --4分频                      0                         1            --关闭
          0               1      --2分频                      1                         0            --时钟开启
          0               0      --1分频                      1                         1            --使能计数

     定时计算:
    如果FOSC = 16,内部指令周期时钟 CLK =(FOSC /4)=4MHz,  1/CLK =0.25us
    如果FOSC = 64,内部指令周期时钟 CLK =(FOSC /4)=16MHz, 1/CLK =0.0625us
    需要定时间=(count)*预分频器分频数*(1/CLK) us  1ms时,count=500,10ms时,cout=5000
    重转载值 = 65535-count
    下面是定时1ms.
*/
void Timer1_Init(void)
{
        //时钟源选择:指令时钟 (FOSC /4)
        TMR1CS1 = 0 ;
        TMR1CS0 = 0 ;        
       T1OSCEN =0 ;                        //禁止Timer1振荡器电路

       //TIMER1 :时钟开启
        TMR1ON = 1 ;               
        TMR1GE  = 0 ;        
        
        //分频因子:8分频        
        T1CKPS1=1;
        T1CKPS0=1;        

       //重装载值
       if( SYSTEMCLK == 64 ) //64M
       {
                TMR1H=0xF8;                        //0xF830
                TMR1L=0x30;
        }
        else
        {
                TMR1H=0xFE;                        //0xFE07
                TMR1L=0x0C;
        }
        
        TMR1IF=0;                        //清除TMR1计数溢出标志位清零
        TMR1IE=1;                        //使能TMR1中断
        PEIE=1;                                //开启外设中断
        GIE=1;                                //开启全局中断
}

#endif


#ifdef   TIMER2
uint16_t   timer2_count = 0 ;
/*
*@brief                timer1始化
*@prama        None
*@retval        Value
T2CON:bit6~bit3                         bit1~bit0
                        1111 = 1:16 后分频比      11 = 预分频值为 64
                        1110 = 1:15 后分频比      10 = 预分频值为 16
                        1101 = 1:14 后分频比      01 = 预分频值为 4
                        1100 = 1:13 后分频比      00 = 预分频值为 1
                        1011 = 1:12 后分频比
                        1010 = 1:11 后分频比
                        1001 = 1:10 后分频比
                        1000 = 1:9 后分频比
                        0111 = 1:8 后分频比
                        0110 = 1:7 后分频比
                        0101 = 1:6 后分频比
                        0100 = 1:5 后分频比
                        0011 = 1:4 后分频比
                        0010 = 1:3 后分频比
                        0001 = 1:2 后分频比
                        0000 = 1:1 后分频比
    定时计算:
    如果FOSC = 16,内部指令周期时钟 CLK =(FOSC /4)=4MHz,  1/CLK =0.25us
    如果FOSC = 64,内部指令周期时钟 CLK =(FOSC /4)=16MHz, 1/CLK =0.0625us
    需要定时间=(count)*预分频*后分频*(1/CLK) us   100*4*10*0.25 =1ms   100*16*10*0.0625=1ms
*/
void Timer2_Init(void)
{
        
        if( SYSTEMCLK == 64 ) //64M
        {
                      T2CON=0b01001010;        //预分频4,后分频10
               PR2=100;
          }
          else
          {
                     T2CON=0b01001001;        //预分频4,后分频10
               PR2=100;
          }

        TMR2ON=1;             //使能TMR2定时器,开始计数        bit2
        TMR2IF=0;       //清空定时器2中断标志位
        TMR2IE=1;       //开启定时器2中断
        PEIE=1;            //开启外设中断
        GIE=1;             //开启总中断
}
#endif

#ifdef   TIMER4
uint16_t   timer4_count = 0 ;
/*
*@brief                timer1始化
*@prama        None
*@retval        Value
T2CON:bit6~bit3                         bit1~bit0
                        1111 = 1:16 后分频比      11 = 预分频值为 64
                        1110 = 1:15 后分频比      10 = 预分频值为 16
                        1101 = 1:14 后分频比      01 = 预分频值为 4
                        1100 = 1:13 后分频比      00 = 预分频值为 1
                        1011 = 1:12 后分频比
                        1010 = 1:11 后分频比
                        1001 = 1:10 后分频比
                        1000 = 1:9 后分频比
                        0111 = 1:8 后分频比
                        0110 = 1:7 后分频比
                        0101 = 1:6 后分频比
                        0100 = 1:5 后分频比
                        0011 = 1:4 后分频比
                        0010 = 1:3 后分频比
                        0001 = 1:2 后分频比
                        0000 = 1:1 后分频比
    定时计算:
    如果FOSC = 16,内部指令周期时钟 CLK =(FOSC /4)=4MHz,  1/CLK =0.25us
    如果FOSC = 64,内部指令周期时钟 CLK =(FOSC /4)=16MHz, 1/CLK =0.0625us
    需要定时间=(count)*预分频*后分频*(1/CLK) us   100*4*10*0.25 =1ms   100*16*10*0.0625=1ms
*/
void Timer4_Init(void)
{
        
        if( SYSTEMCLK == 64 ) //64M
        {
                      T4CON=0b01001010;        //预分频4,后分频10
               PR4=100;
          }
          else
          {
                     T4CON=0b01001001;        //预分频4,后分频10
               PR4=100;
          }

        TMR4ON=1;             //使能TMR2定时器,开始计数        bit2
        TMR4IF=0;       //清空定时器2中断标志位
        TMR4IE=1;       //开启定时器2中断
        PEIE=1;            //开启外设中断
        GIE=1;             //开启总中断
}
#endif


#ifdef   TIMER6
uint16_t   timer6_count = 0 ;
/*
*@brief                timer1始化
*@prama        None
*@retval        Value
T2CON:bit6~bit3                         bit1~bit0
                        1111 = 1:16 后分频比      11 = 预分频值为 64
                        1110 = 1:15 后分频比      10 = 预分频值为 16
                        1101 = 1:14 后分频比      01 = 预分频值为 4
                        1100 = 1:13 后分频比      00 = 预分频值为 1
                        1011 = 1:12 后分频比
                        1010 = 1:11 后分频比
                        1001 = 1:10 后分频比
                        1000 = 1:9 后分频比
                        0111 = 1:8 后分频比
                        0110 = 1:7 后分频比
                        0101 = 1:6 后分频比
                        0100 = 1:5 后分频比
                        0011 = 1:4 后分频比
                        0010 = 1:3 后分频比
                        0001 = 1:2 后分频比
                        0000 = 1:1 后分频比
    定时计算:
    如果FOSC = 16,内部指令周期时钟 CLK =(FOSC /4)=4MHz,  1/CLK =0.25us
    如果FOSC = 64,内部指令周期时钟 CLK =(FOSC /4)=16MHz, 1/CLK =0.0625us
    需要定时间=(count)*预分频*后分频*(1/CLK) us   100*4*10*0.25 =1ms   100*16*10*0.0625=1ms
*/
void Timer6_Init(void)
{
        
        if( SYSTEMCLK == 64 ) //64M
        {
                      T6CON=0b01001010;        //预分频4,后分频10
               PR6=100;
          }
          else
          {
                     T6CON=0b01001001;        //预分频4,后分频10
               PR6=100;
          }

        TMR6ON=1;             //使能TMR2定时器,开始计数        bit2
        TMR6IF=0;       //清空定时器2中断标志位
        TMR6IE=1;       //开启定时器2中断
        PEIE=1;            //开启外设中断
        GIE=1;             //开启总中断
}
#endif


//测试文件/////////////////////////////
//#define    PLLx4TO64M        //PLL*4 倍频设置时钟为64M,不需要倍频为64M//注释掉即可,这时为16M

#ifdef      PLLx4TO64M
#define   SYSTEMCLK    64
#else
#define   SYSTEMCLK    16
#endif


#ifdef   PLLx4TO64M
__CONFIG( FOSC_HS  & WDTE_OFF & BOREN_OFF );        //配置字一,选择外部振荡器,关闭看门狗,关闭低电压复位
__CONFIG( VCAPEN_ON & LVP_OFF& PLLEN_ON );        //配置字二,使能RF0引脚稳压电容,关闭低电压编程,打开时钟4倍频
#else
__CONFIG( FOSC_HS  & WDTE_OFF & BOREN_OFF );        //配置字一,选择外部振荡器,关闭看门狗,关闭低电压复位
__CONFIG( VCAPEN_ON & LVP_OFF& PLLEN_OFF );        //配置字二,使能RF0引脚稳压电容,关闭低电压编程,关闭时钟4倍频
#endif

void main(void)
{

        //Timer0_Init();                   //定时器0初始化
        //Timer1_Init();                   //定时器1初始化
        //Timer2_Init();                   //定时器2初始化
        //Timer4_Init();                   //定时器4初始化
        //Timer6_Init();                   //定时器4初始化
        while(1)
      {

   ;}
}

中断处理函数
void interrupt  ISR(void)        
{

            //定时器0中断测试
        #ifdef TIMER0
        {
             if(  TMR0IE && TMR0IF )
             {
                      TMR0IF=0;
                      timer0_count ++;
                      if(timer0_count%300==0)        //2.04ms*300=612ms到
                    {
                                LED^=1;                              //LED1状态取反
                      }
              }
        }
        #endif      
        
        //定时器1中断测试
        #ifdef TIMER1
        {
                if(TMR1IE&&TMR1IF)
                {
                        TMR1IF=0;
                        TMR1ON=0;
                        //重装载值
                       if( SYSTEMCLK == 64 ) //64M
                       {
                                 TMR1H=0xF8;                        //0xF830
                               TMR1L=0x30;
                        }
                        else
                        {
                                TMR1H=0xFE;                        //0xFE07
                                TMR1L=0x0C;
                        }
                        TMR1ON=1;
                        
                        timer1_count++;
                        if(timer1_count%1000==0)                //500ms到
                        {
                         printf("1\r\n");
                                LED^=1;                        //LED1状态取反
                        }
                }
        }
        #endif        
        
        //定时器2中断测试
        #ifdef TIMER2
        {
                  if(TMR2IE&&TMR2IF)
                 {
                        TMR2IF=0;        
                        timer2_count++;
                        if(timer2_count%200==0)                //50ms到
                        {
                                 printf("1\r\n");
                                        LED^=1;                        //LED1状态取反
                        }
                 }
        }
        #endif
        
        //定时器4中断测试
        #ifdef TIMER4
        {
                  if(TMR4IE&&TMR4IF)
                 {
                        TMR4IF=0;        
                        timer4_count++;
                        if(timer4_count%1000==0)                //500ms到
                        {
                                 printf("1\r\n");
                                        LED^=1;                        //LED1状态取反
                        }
                 }
        }
        #endif
        
        //定时器6中断测试
        #ifdef TIMER6
        {
                  if(TMR6IE&&TMR6IF)
                 {
                        TMR6IF=0;        
                        timer6_count++;
                        if(timer6_count%1000==0)                //500ms到
                        {
                                 printf("1\r\n");
                                        LED^=1;                        //LED1状态取反
                        }
                 }
        }
        #endif
}


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:759020 发表于 2021-1-20 16:54 | 只看该作者
很受用,谢谢
回复

使用道具 举报

板凳
ID:385637 发表于 2021-3-26 14:10 | 只看该作者
很实用的好资料
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表