SysCtlDelay()函数解析

来源:互联网 发布:康德 二律背反 知乎 编辑:程序博客网 时间:2024/06/03 13:43
最近经常用到SysCtlDelay()函数,觉得这函数不错,可以做到精确延时。不久前,做NRF905模块的时候,有一处要精确到610us。
      TI的资料中,此函数在Sysctl.c中是这样定义的:
 
     #if defined(ewarm) || defined(DOXYGEN)   //定义在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
    2.毫秒级的延时:
        SysCtlDelay(SysCtlClockGet( 3000);    //   延时1ms 
        SysCtlDelay(10 (SysCtlClockGet( 3000));    //   延时10ms 
         SysCtlClockGet( )=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. 作      者:牙小狼 QQ:398968891  Email:xiaolang.ya@gmail.com
  8. 版      本:R1.2
  9. 程序说明:
  10. 1、根据LED闪烁情况可以看出频率设置的效果。
  11. 2、延时函数在低频情况下可能有一定的误差,因为库函数的调用,以及延时的
  12. 计算会消耗一定的时间。
  13. 更新说明:
  14. 1、发现无法使用MAP_SysCtlDelay(),必须改为SysCtlDelay(),否则会跑死
  15. 原因暂时不明。
  16. ********************************************************************/

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

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

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

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

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

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

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

  72. while (1)
  73. {
  74. MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 1);
  75. DELAY_MS(500);
  76. MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 0);
  77. DELAY_MS(500);
  78. //LED按照指定的时间间隔进行闪烁
  79. }
  80. }
复制代码
原创粉丝点击