【單片機】【PIC16F1937】之定時器

這篇文章是談談關於1937的定時器的,剛開始被晶振頻率、時鐘頻率、振盪週期、振盪頻率、指令週期、指令頻率等等的名詞繞暈了。先來解決這個問題。編程

晶振頻率是表明振盪器的頻率,說的是晶振這個器件的頻率,由於一個單片機有內部外部晶振,好比你選擇了內部晶振,那麼這個晶振的頻率就是你單片機的時鐘頻率,url

振盪頻率和晶振頻率說的是一回事。振盪週期是1/(晶振頻率),T = 1/f 嘛。指令週期這個根據單片機的不一樣會不一樣,8位的PIC單片機(PIC10/12/16/18系列)是4個時鐘週期爲一個指令週期。16位的PIC24單片機和dsPIC數字處理芯片和32位PIC32處理器是2個時鐘週期爲一個指令週期。(以上關於指令週期的內容是百度到的,內容較可靠http://zhidao.baidu.com/link?url=uEnsn0C-bb-xdDNG_qEI0HmhIpoDNVc4d2lheztGKsQMpflMcpbnlWAGdXyeMz05fJAhXardxSrQDLHEdDrCx_)spa

理清上面的內容,就開始咱們的正題。code

TIMER0blog

/*
* TIMER0是一個8位定時器/計數器,有8位預分頻器(1:2-1:256),是全部定時器中預分頻最大的(能夠這麼說吧。。)
* 可編程的內外部時鐘源,可編程的外部時鐘邊沿選擇。
* 溢出時中斷
* TMR0可用於門控Timer1(還沒試過。。)
* 休眠模式中沒法工做
* 此時選擇內部晶振8mhz,預分頻1:16,每2.04s燈狀態改變一次。TMR0從0計數到255
* 因此是255*16*1000/(Fosc(晶振頻率)/4) = 2.04
*/it

這些是我寫在單片機程序開頭的內容,大體描述了TIMER0模塊,接下來告訴大家怎麼使用它吧。(只寫關於初始化TIMER0的,CPU的初始化之類的略過)class

1.先初始化時鐘源,在OSSCON寄存器中設置SCS位來選擇內部振盪模塊,IRCF設置內部頻率百度

2.如今初始化TIMER0,仍是同樣,先選擇時鐘源,TMR0CS = 0;表示內部指令週期(注意是指令週期,fosc/4)定時器

3.選擇預分頻,PSA位來選擇需不須要預分頻,PS<2:0>來設置預分頻gc

4.時鐘都和中斷有關,因此這裏要容許有效中斷,GIE = 1;

5.而後容許TIM0IE中斷,TIM0IE = 1;

6.最後是溢出中斷標誌位,TMR0IF = 0;表示未溢出,當定時器開啓的時候TMRO就會開始計數,一個指令週期加一,從0-255.當加到255後再加一使TMR0IF = 1;計數會跳到0繼續。

7.TMR0能夠不用使能,自動計數,但由於執行時會延遲2個指令週期,因此TMR0的初值須要設置,來抵消這個延遲。

仍是上代碼吧,哈哈嘞

 1 void InitTime();
 2 void Init_fosc(); //設置內部振盪器,不過好像沒用。。
 3 
 4 unsigned int count = 0;
 5 
 6 int main(int argc, char** argv) 
 7 {
 8 InitCPU();
 9 Init_fosc();
10 InitTime();
11 TRISC = 0x00;
12 // LATC = 0x00;
13 while(1);
14 return (EXIT_SUCCESS);
15 }
16 
17 void InitTime()
18 {
19 // INTEDG = 0; //bit6 中斷邊沿選擇位,1 = 上升沿,0 = 降低沿
20 TMR0CS = 0; //bit5 Timer0時鐘源選擇位,0 = 內部指令週期時鐘(Fosc/4)
21 TMR0SE = 0; //bit4 Timer0時鐘源邊沿選擇位,1 = 在T0CKI引腳電平降低沿時遞增,0 = 上升沿時遞增
22 PSA = 0; //bit3 預分頻器分配位,1 = 不分給Timer0,0 = 預分頻器分給Timer0
23 PS0 = 1;
24 PS1 = 1;
25 PS2 = 0; //1:16
26 //PS<2:0>,預分頻器分頻比選擇位
27 GIE = 1; //容許全部有效中斷
28 PEIE = 0; //禁止全部外設中斷,有待考慮
29 TMR0IE = 1; //容許TMR0中斷 
30 TMR0IF = 0; //溢出中斷標誌位,未溢出
31 TMR0 = 1;
32 }
33 
34 void Init_fosc()
35 {
36 // OSCCON = 0x6a; 下面的設置爲設置內部振盪器頻率的
37 SCS0 = 1;
38 SCS1 = 0; //1x內部振盪器模塊
39 IRCF0 = 0;
40 IRCF1 = 1;
41 IRCF2 = 1;
42 IRCF3 = 0; //1101 = 250kHz
43 
44 }
45 
46 void interrupt ISR()
47 {
48 TMR0 = 1;
49 count++;
50 if(count ==10)
51 {
52 LATC = ~LATC;
53 count = 0;
54 }
55 TMR0IF = 0;
56 }

 

TMR0是不用使能的,其餘的時候也許不用管他,就算它在計數,沒有容許它中斷(TMR0IE位),也是沒啥用的啊,殘念ね。。

 

接下來是TIMER1模塊,TIMER1模塊的特殊的地方是帶門控,是16位的定時計數器,有專用32kHz的振盪器電路。

此次先上代碼吧,感受會更有條理些

 1 void InitTime();
 2 void Init_fosc(); //設置內部振盪器,不過好像沒用。。
 3 
 4 unsigned int count = 0;
 5 
 6 int main(int argc, char** argv) 
 7 {
 8 InitCPU();
 9 Init_fosc();
10 InitTime();
11 TRISC = 0x00;
12 // LATC = 0x00;
13 while(1);
14 return (EXIT_SUCCESS);
15 }
16 
17 void InitTime()
18 {
19 // INTEDG = 0; //bit6 中斷邊沿選擇位,1 = 上升沿,0 = 降低沿
20 TMR0CS = 0; //bit5 Timer0時鐘源選擇位,0 = 內部指令週期時鐘(Fosc/4)
21 TMR0SE = 0; //bit4 Timer0時鐘源邊沿選擇位,1 = 在T0CKI引腳電平降低沿時遞增,0 = 上升沿時遞增
22 PSA = 0; //bit3 預分頻器分配位,1 = 不分給Timer0,0 = 預分頻器分給Timer0
23 PS0 = 1;
24 PS1 = 1;
25 PS2 = 0; //1:16
26 //PS<2:0>,預分頻器分頻比選擇位
27 GIE = 1; //容許全部有效中斷
28 PEIE = 0; //禁止全部外設中斷,有待考慮
29 TMR0IE = 1; //容許TMR0中斷 
30 TMR0IF = 0; //溢出中斷標誌位,未溢出
31 TMR0 = 1;
32 }
33 
34 void Init_fosc()
35 {
36 // OSCCON = 0x6a; 下面的設置爲設置內部振盪器頻率的
37 SCS0 = 1;
38 SCS1 = 0; //1x內部振盪器模塊
39 IRCF0 = 0;
40 IRCF1 = 1;
41 IRCF2 = 1;
42 IRCF3 = 0; //1101 = 250kHz
43 
44 }
45 
46 void interrupt ISR()
47 {
48 TMR0 = 1;
49 count++;
50 if(count ==10)
51 {
52 LATC = ~LATC;
53 count = 0;
54 }
55 TMR0IF = 0;
56 }

 

再來寫下總結的步驟

1.初始時鐘源

2.在Timer1的初始中先選擇時鐘源

3.設置預分頻

4.容許中斷和溢出位清零

5.使能Timer1

雖然看起來簡單,可是Timer1的功能比Timer0多,好些本身也沒有用到過,有一個注意的地方,TMR1H和TMR1L的初值設定最好剛剛把延時拿回來就好了。使能也應該放最後,恰好須要起振時間

 

 最後最後,1937裏面最多的定時器,數量超過個人想象,居然多達,,居然擁有3個!!何等的數量啊。。。。。好了,不裝怪了,他是TIMER2/4/6葫蘆三兄弟。

/*1937共含有3個相同的Timer2模塊,分別爲Timer二、Timer四、Timer6
* 8位定時器和週期寄存器(TMRx和PRx)
* 可讀寫、預分頻(1:1:4:16:64)後分頻(1:1至1:16)
* TMRx與相應的PRx分別匹配時中斷、可選擇做爲MSSP模塊的移位時鐘(僅Timer2)
*/

看到了嗎,這裏是TMRx與相應的PRx分別匹配時中斷,不像前面兩個あほ(TIMER0與TIMER1)是溢出中斷

仍是先上代碼吧,,,這裏直接上初始化Timer2/4/6的程序了,

 

 1 void Init_Timer2() //時鐘是系統指令時鐘 Fosc/4,沿邊沿遞增計數。
 2 {
 3 T2CON = 0x0d; //設置後分頻,使能Timer2,設置預分頻
 4 TMR2 = 0;
 5 PR2 = 100; //TMR2與PR2的值越相近,進入中斷越快
 6 GIE = 1; //容許全部有效中斷,!!!!實驗無此語句可否運做
 7 PEIE = 1;
 8 TMR2IE = 1; //容許Timer2中斷
 9 TMR2IF = 0; //溢出標誌位,未溢出
10 }

 

 

TIMER2/4/6是沒法本身選擇內外部時鐘的,系統選什麼他就得選什麼,做爲對比,TIMER0和TIMER1是能夠本身選的,素晴らしい!

 

 

全部的時鐘設置總結來講,必須考慮的要素有如下幾條

    • 1.設置時鐘,系統時鐘和定時器要用的時鐘(TIMER0和TIMER1是能夠選的)
    • 2.預分頻及後分頻,全部時鐘裏TIMER0的預分頻最大(1:2-1:256),TIMER2/4/6既有預分頻又有後分頻
    • 3.TMRxIE、PEIE、GIE(容許TIMERx中斷、容許外設中斷、容許全部有效中斷),這三個的賦值。除PEIE在TIMER0中沒有也能夠運做外,其餘兩個在每一個定時器中必須有
    • 4.TMRxIF,溢出的標誌位,通常會在中斷程序裏面清零,因此在初始化裏面無關緊要。
    • 5.計數的設置TIMER0中的TMRO(0-255),TIMER1中的TMR1H和TMR1L,TIMER2/4/6中的TMRx(0-PRx),PRx(0-255)
相關文章
相關標籤/搜索