之所以把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
}
|