SysCtlDelay()函数解析

最近经常用到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. }
复制代码
/********************************************************************************************************** *.c文件功能说明: * ADC0序列0通道0中断处理函数 ADC0Sequence0Handler * ADC0初始化 ADC0_Init * ADC0采集函数 ADC0_GetValue * 使用引脚: * E3 **********************************************************************************************************/ #include "all_head.h" #include "adc_user.h" /*ADC0均值滤波结构体*/ FFP_TypeDef FFP_ADC0SS0_0; /*ADC0卡尔曼滤波结构体*/ KFP_TypeDef KFP_ADC0SS0_0; /** *函 数 名: ADC0Sequence0Handler *功能说明: ADC0中断处理函数,产生中断进入一次此函数,用于获取各个通道的数值 *参 数: 无 *返 回 值: 无 **/ void ADC0Sequence0Handler(void) { /*清除ADC0中断标志*/ ADCIntClear(ADC0_BASE,0); /*获取采集结果*/ ADCSequenceDataGet(ADC0_BASE, 0, &ADC0_0_Value); /*均值滤波+卡尔曼滤波*/ ADC0_0_Value = Average(&FFP_ADC0SS0_0,ADC0_0_Value,2); ADC0_0_Value = Kalman(&KFP_ADC0SS0_0,ADC0_0_Value); } /** *函 数 名: ADC0_Init *功能说明: ADC0初始化函数 *参 数: 无 *返 回 值: 无 **/ unsigned int ADC0_0_Value; void ADC0_Init(void) { /*初始化ADC0/PE3*/ SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3); /*配置ADC采集序列0,开启通道0中断*/ ADCSequenceConfigure(ADC0_BASE,0,ADC_TRIGGER_PROCESSOR, 0); ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0 |ADC_CTL_END | ADC_CTL_IE ); /*使能ADC采集序列*/ ADCSequenceEnable(ADC0_BASE, 0); /*使能ADC序列0中断*/ IntEnable(INT_ADC0SS0); /*中断函数注册*/ ADCIntRegister(ADC0_BASE,0,ADC0Sequence0Handler); /*中断优先级2*/ IntPrioritySet(INT_ADC0SS0,USER_INT2); /*清除ADC0中断标志*/ ADCIntClear(ADC0_BASE,0); /*使能ADC0中断*/ ADCIntEnable(ADC0_BASE,0); /*ADC0数据卡尔曼滤波初始化*/ Kalman_INIT(&KFP_ADC0SS0_0,50,5,250); } /** *函 数 名: ADC0_GetValue *功能说明: ADC0采集函数 *参 数: 无 *返 回 值: 无 **/ void ADC0_GetValue(void) { /*触发采集*/ ADCProcessorTrigger(ADC0_BASE, 0); }
最新发布
07-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值