這篇文章是談談關於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是能夠本身選的,素晴らしい!
全部的時鐘設置總結來講,必須考慮的要素有如下幾條