最近经常用到SysCtlDelay()函数,觉得这函数不错,可以做到精确延时。不久前,做NRF905模块的时候,有一处要精确到610us。

      TI的资料中,此函数在Sysctl.c中是这样定义的:




//定义在IAR的编译环境中
 void
 SysCtlDelay(unsigned long ulCount)
 {
     __asm("    subs    r0, #1\n"
           "    bne.n   SysCtlDelay\n"
           "    bx      lr");
 }
 #endif 
 
 
 
 #if defined(codered) || defined(gcc) || defined(sourcerygxx)  
  //定义在codered、gcc、sourcerygcc编译环境下
void __attribute__((naked)) 
 
 SysCtlDelay(unsigned long ulCount) 
 
 { 
 
     __asm("    subs    r0, #1\n" 
 
           "    bne     SysCtlDelay\n" 
 
           "    bx      lr"); 
 
 } 
 
 #endif 
 
 
 
 #if defined(rvmdk) || defined(__ARMCC_VERSION)  
 //在KEIL MDK的编译环境下
__asm void 
 
 SysCtlDelay(unsigned long ulCount) 
 
 { 
 
     subs    r0, #1; 
 
     bne     SysCtlDelay; 
 
     bx      lr; 
 
 } 
 
 #endif


  不管哪种环境下,发现用了三条汇编指令。我用的是KEIL MDK。


  subs  r0,#1;  // 使用了16位的Thumb指令,无条件更新标志位。S后缀的使用要担心,16位的Thunb指令有可能会无条件更新标志位,也有可能不会。所以,但你需要更新标志位时,一定不要忘了加上S后缀。


   bne SysCtlDelay;  //  无条件跳转指令有两条,B和BX,  BNE中的NE即NotEqual,对应于标志位Z==0;


  表示不等的时候无条件转移到SysCtlDelay处对应的地址;


   bx    lr;   //执行这条指令后,把返回地址存储到LR(R14)中;


 


 关于SysCtlDelay()延时函数:


   TI LM3S8962 默认的设置为采用主晶振6M,   所以,一个周期的时间是1/6us。


   SysCtlDelay()函数里执行了三条指令。


   1.微妙级的延时:


       SysCtlDelay(2); // 延时1us;


        SysCtlDelay(2*x); 延时x us;x=1000时,延时1ms;


        另一种写法


      #defined TheSysClock 6000000


SysCtlDelay(1*(TheSysClock/3000000)) //延时 1us


SysCtlClockGet(  )  /  3000);        //      延时1ms 


SysCtlDelay(10  *  (SysCtlClockGet(  )  /  3000));        //      延时10ms 


)=6000000 ;


    另一种种写法


        // 定义系统时钟 6M
        #define TheSysClock  6000000


       SysCtlDelay(10 * (TheSysClock / 3000)); 延时10ms


      // 定义系统时钟 8M
        #define TheSysClock  8000000


      SysCtlDelay(10 * (TheSysClock / 3000));  延时10ms


 


 




  1. /********************************************************************
  2. 程序名称:系统频率设置&精确延时
  3. 硬件环境:EKK-LM3S9B92-CD-572
  4. 软件环境:keil 4.12
  5. 创建日期:2010.11.7
  6. 修改日期:2010.11.8
  7. 作      者:牙小狼 程序说明:
  8. 1、根据LED闪烁情况可以看出频率设置的效果。
  9. 2、延时函数在低频情况下可能有一定的误差,因为库函数的调用,以及延时的
  10. 计算会消耗一定的时间。
  11. 更新说明:
  12. 1、发现无法使用MAP_SysCtlDelay(),必须改为SysCtlDelay(),否则会跑死
  13. 原因暂时不明。
  14. ********************************************************************/

  15. //----------------------HEADER FILE 头文件-------------------------//
  16. #define TARGET_IS_TEMPEST_RC1
  17. #include "../inc/hw_memmap.h"               //提供内存地址映射的支持
  18. #include "../inc/hw_types.h"                    //提供数据类型的支持
  19. #include "../driverlib/gpio.h"                    //提供GPIO的API支持
  20. #include "../driverlib/sysctl.h"                  //提供系统控制的API支持
  21. #include "../driverlib/rom.h"                    //提供ROM内API的支持
  22. #include "../driverlib/rom_map.h"            //提供MAP_这种定义的支持

  23. //--------------------MAVRO DEFINITION 宏定义----------------------//
  24. #define DELAY_US(n)          SysCtlDelay(n * (MAP_SysCtlClockGet() / 3000000))
  25. #define DELAY_MS(n)          SysCtlDelay(n * (MAP_SysCtlClockGet() / 3000))
  26. #define DELAY_S(n)            SysCtlDelay(n * (MAP_SysCtlClockGet() / 3))

  27. //-----------------FUNCTION PROTOTYPES 函数声明--------------------//
  28. void LED_blinking(unsigned long ultimes,unsigned long ulloop);

  29. /********************************************************************
  30. 函数名称:LED_blinking()
  31. 函数入口:ultimes:闪烁次数        ulloop:间隔的时钟周期
  32. 函数出口:无
  33. 函数说明:LED闪烁函数,实际效果和系统频率有关
  34. ********************************************************************/
  35. void LED_blinking(unsigned long ultimes,unsigned long ulloop)
  36. {
  37. unsigned long i,j;
  38. for(i=0x0000;i<ultimes;i++)
  39. {
  40. for(j=0x0000;j<ulloop;j++);
  41. MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 1);
  42. for(j=0x0000;j<ulloop;j++);
  43. MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 0);
  44. }
  45. }
  46. /********************************************************************
  47. 函数名称:main()
  48. 函数入口:务
  49. 函数出口:无
  50. 函数说明:系统主函数
  51. ********************************************************************/
  52. int main(void)
  53. {
  54. MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
  55. //使能PD端口
  56. MAP_GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_0);
  57. //PD0设置为输出

  58. MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | \
  59. SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
  60. //外部频率16MHZ,PLL倍频至80HMZ
  61. LED_blinking(10,500000);

  62. MAP_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC |  \
  63. SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
  64. //外部频率16MHZ,不分频
  65. LED_blinking(10,500000);

  66. MAP_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_OSC | \
  67. SYSCTL_OSC_INT);
  68. //内部晶振4分频,即4MHZ
  69. LED_blinking(10,500000);

  70. while (1)
  71. {
  72. MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 1);
  73. DELAY_MS(500);
  74. MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 0);
  75. DELAY_MS(500);
  76. //LED按照指定的时间间隔进行闪烁
  77. }
  78. }



复制代码