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