(轉)Cortex-M3 (NXP LPC1788)之SysTick系統節拍定時器


 在GPIO控制篇中的延時閃爍LED只用了簡單的for循環,為了精確的計時本篇介紹使用SysTick定時器每1ms產生中斷,從而實現精確定時的目的。要使用系統節拍定時器主要進行兩個部分的配置。1:系統時鍾控制。2系統節拍定時器的控制。

一,系統時鍾控制

        LPC1788有3個獨立的振盪器。他們是主振盪器,內部RC振盪器,RTC振盪器。復位后,LPC1788將用內部的RC振盪器運行,直到被軟件切換。這樣就能在沒有任何外部晶振的情況下運行。LPC1788的時鍾控制如圖1所示

LPCCLOCK

        在開發板上使用12M的晶振作為主振盪器,它通過鎖相環PLL0來提高頻率提供CPU。由於芯片總是從內部的RC振盪器開始工作,因此主振盪器只會應軟件的請求而啟動。實現方法是設定SCS寄存器中的OSCEN位使能。主振盪器提供一個狀態標志SCS寄存器的OSCSTAT位,這樣軟件就可以確定何時主振盪器在運行穩定。此時,軟件可以控制切換到主振盪器,使其作為時鍾源。在啟動以前,必須通過SCS的OSCRANGE位,選擇一個頻率范圍。在確定了主振盪器之后,需要進行鎖相環的配置。1,配置CLKSRCSEL選擇正確的時鍾源。2,將正確的PLL設置值寫入PLLCFG寄存器並且在PLLCON中使能PLL。3,向PLLFEED寄存器中寫入饋送序列0xAA,0x55。4,設置所需的時鍾分配器如CCLKSEL,PCLSEL,EMCCLKSEL,以及USBCLKSEL寄存器。5,查詢PLLSTAT寄存器等待PLL鎖定。

二,系統節拍定時器的控制

        LPC1788的系統節拍定時器是一個24位的定時器,當數值達到0時產生中斷。系統節拍定時器的時鍾信號可以由CPU時鍾提供(即圖1中的cclk)。想要在規定的時間間隔循環的產生中斷,必須將指定的正確時間間隔值裝入STRELOAD寄存器進行初始化。假如我們選擇cclk作為系統節拍的時鍾信號,並且根據開發板將系統時鍾設置成12MHZ,為了循環1ms產生一次中斷,我們寫入STRELOAD的值為cclk/1000 - 1 。

 

        程序的代碼如下,使LED燈每500ms閃爍。SystemInit函數在啟動文件中被調用。

 

[cpp]
  1. #define rFIO1DIR        (*(volatile unsigned*)0x20098020) 
  2. #define rFIO1MASK       (*(volatile unsigned*)0x20098030) 
  3. #define rFIO1PIN        (*(volatile unsigned*)0x20098034) 
  4. #define rFIO1SET        (*(volatile unsigned*)0x20098038) 
  5. #define rFIO1CLR        (*(volatile unsigned*)0x2009803c) 
  6.  
  7. #define rCLKSRCSEL  (*(unsigned *)(0x400FC10C))     //時鍾源選擇寄存器 
  8. #define rPLL0CON    (*(unsigned *)(0x400FC080))     //PLL0控制寄存器 
  9. #define rPLL0CFG    (*(unsigned *)(0x400FC084))     //PLL0配置寄存器 
  10. #define rPLL0STAT   (*(unsigned *)(0x400FC088))     //PLL0狀態寄存器 
  11. #define rPLL0FEED   (*(unsigned *)(0x400FC08C))     //PLL0饋送寄存器 
  12. #define rPLL1CON    (*(unsigned *)(0x400FC0A0))      
  13. #define rPLL1CFG    (*(unsigned *)(0x400FC0A4)) 
  14. #define rPLL1STAT   (*(unsigned *)(0x400FC0A8)) 
  15. #define rPLL1FEED   (*(unsigned *)(0x400FC0AC)) 
  16. #define rCCLKSEL    (*(unsigned *)(0x400FC104))     //CPU時鍾選擇寄存器 
  17. #define rUSBCLKSEL  (*(unsigned *)(0x400FC108))     //USB時鍾選擇寄存器 
  18. #define rPCLKSEL    (*(unsigned *)(0x400FC1A8))     //外設時鍾寄存器 
  19. #define rPCON       (*(unsigned *)(0x400FC0C0)) 
  20. #define rPXCONP     (*(unsigned *)(0x400FC0C4)) 
  21. #define rSCS        (*(unsigned *)(0x400FC1A0))     //系統控制和狀態寄存器 
  22. #define rCLKOUTCFG  (*(unsigned *)(0x400FC1C8)) 
  23.  
  24. #define rSTCTRL     (*(unsigned *)(0xE000E010)) 
  25. #define rSTRELOAD   (*(unsigned *)(0xE000E014)) 
  26. #define rSTCURR     (*(unsigned *)(0xE000E018)) 
  27. #define rSTALIB     (*(unsigned *)(0xE000E01C)) 
  28.  
  29. #define CCLK        120000000 
  30.  
  31. volatile unsigned long SysTickCnt; 
  32.  
  33. /*
  34. 系統時鍾初始化
  35. */ 
  36. void SystemInit() 
  37.     rSCS &= ~(0x1<<4);                //頻率12M 
  38.     rSCS |= (0x1<<5);             //使能主振盪器 
  39.     while(0 == (rSCS & (0x1<<6)));//等待主振盪器穩定 
  40.      
  41.     rCLKSRCSEL = 0x1; 
  42.      
  43.     rPLL0CFG = 0x9;                 //配置CCLK = 120M 
  44.     rPLL0CON = 0x01; 
  45.     rPLL0FEED = 0xAA; 
  46.     rPLL0FEED =0x55; 
  47.     while( 0 == (rPLL0STAT & (0x1<<10)));  
  48.      
  49.     rCCLKSEL = (0x1 | (0x1<<8)); 
  50.     rPCLKSEL = 0x2;                 //配置PCLK = 60M 
  51.      
  52.     rCLKOUTCFG = 0x0 | (0xb<<4) | (0x1<<8); 
  53.  
  54. /*
  55. 系統節拍定時器初始化
  56. */ 
  57. unsigned char SysTick_Config(unsigned int ticks) 
  58.     if(ticks > 0xFFFFFFUL) 
  59.         return 0; 
  60.     rSTRELOAD = ticks; 
  61.     rSTCURR = 0x0; 
  62.     rSTCTRL = (0x1) | (0x1<<1) | (0x1<<2); 
  63.     return 1; 
  64. /*
  65. 系統節拍定時器中斷處理函數
  66. */ 
  67. void SysTick_Handler (void
  68.     SysTickCnt++; 
  69.  
  70. int main() 
  71.     unsigned char value = 1; 
  72.  
  73.     SysTick_Config(CCLK/1000-1);            //每1ms產生一次SysTick系統異常    
  74.     rFIO1DIR |= (1<<18);              //GPIO1.18 -> OUTPUT 
  75.      
  76.     while(1) 
  77.     { 
  78.         if(SysTickCnt >= 500) 
  79.         { 
  80.             SysTickCnt = 0; 
  81.             value = !value; 
  82.         } 
  83.         if(0 == value) 
  84.         { 
  85.             rFIO1PIN &= ~(1<<18); 
  86.         } 
  87.         elseif(1 == value) 
  88.         { 
  89.             rFIO1PIN |= (1<<18); 
  90.         } 
  91.     } 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM