×
单片机 > 单片机程序设计 > 详情

Cortex-M3 (NXP LPC1788)之SysTick系统节拍定时器

发布时间:2020-08-21 发布时间:
|
        在GPIO控制篇中的延时闪烁LED只用了简单的for循环,为了精确的计时本篇介绍使用SysTick定时器每1ms产生中断,从而实现精确定时的目的。要使用系统节拍定时器主要进行两个部分的配置。1:系统时钟控制。2系统节拍定时器的控制。

一,系统时钟控制

        LPC1788有3个独立的振荡器。他们是主振荡器,内部RC振荡器,RTC振荡器。复位后,LPC1788将用内部的RC振荡器运行,直到被软件切换。这样就能在没有任何外部晶振的情况下运行。LPC1788的时钟控制如图1所示

        在开发板上使用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函数在启动文件中被调用。

  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. {  
  38.     rSCS &= ~(0x1<<4);                //频率12M  
  39.     rSCS |= (0x1<<5);             //使能主振荡器  
  40.     while(0 == (rSCS & (0x1<<6)));//等待主振荡器稳定  
  41.       
  42.     rCLKSRCSEL = 0x1;  
  43.       
  44.     rPLL0CFG = 0x9;                 //配置CCLK = 120M  
  45.     rPLL0CON = 0x01;  
  46.     rPLL0FEED = 0xAA;  
  47.     rPLL0FEED =0x55;  
  48.     while( 0 == (rPLL0STAT & (0x1<<10)));   
  49.       
  50.     rCCLKSEL = (0x1 | (0x1<<8));  
  51.     rPCLKSEL = 0x2;                 //配置PCLK = 60M  
  52.       
  53.     rCLKOUTCFG = 0x0 | (0xb<<4) | (0x1<<8);  
  54. }  
  55.   
  56. /* 
  57. 系统节拍定时器初始化 
  58. */  
  59. unsigned char SysTick_Config(unsigned int ticks)  
  60. {  
  61.     if(ticks > 0xFFFFFFUL)  
  62.         return 0;  
  63.     rSTRELOAD = ticks;  
  64.     rSTCURR = 0x0;  
  65.     rSTCTRL = (0x1) | (0x1<<1) | (0x1<<2);  
  66.     return 1;  
  67. }  
  68. /* 
  69. 系统节拍定时器中断处理函数 
  70. */  
  71. void SysTick_Handler (void)  
  72. {  
  73.     SysTickCnt++;  
  74. }  
  75.   
  76. int main()  
  77. {  
  78.     unsigned char value = 1;  
  79.   
  80.     SysTick_Config(CCLK/1000-1);            //每1ms产生一次SysTick系统异常     
  81.     rFIO1DIR |= (1<<18);              //GPIO1.18 -> OUTPUT  
  82.       
  83.     while(1)  
  84.     {  
  85.         if(SysTickCnt >= 500)  
  86.         {  
  87.             SysTickCnt = 0;  
  88.             value = !value;  
  89.         }  
  90.         if(0 == value)  
  91.         {  
  92.             rFIO1PIN &= ~(1<<18);  
  93.         }  
  94.         else if(1 == value)  
  95.         {  
  96.             rFIO1PIN |= (1<<18);  
  97.         }  
  98.     }  
  99. }  

        关于SysTick的异常的优先级可以在SHPR3中进行设置,优先级等级可以从0~31。初始化默认为0,只低于固定的负数优先级的复位,硬件故障和NMI。
关键字:Cortex-M3  LPC1788  SysTick  系统节拍  定时器 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
如何为单片机选择合适的负载电容