最近经常用到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
- /********************************************************************
- 程序名称:系统频率设置&精确延时
- 硬件环境:EKK-LM3S9B92-CD-572
- 软件环境:keil 4.12
- 创建日期:2010.11.7
- 修改日期:2010.11.8
- 作 者:牙小狼 程序说明:
- 1、根据LED闪烁情况可以看出频率设置的效果。
- 2、延时函数在低频情况下可能有一定的误差,因为库函数的调用,以及延时的
- 计算会消耗一定的时间。
- 更新说明:
- 1、发现无法使用MAP_SysCtlDelay(),必须改为SysCtlDelay(),否则会跑死
- 原因暂时不明。
- ********************************************************************/
- //----------------------HEADER FILE 头文件-------------------------//
- #define TARGET_IS_TEMPEST_RC1
- #include "../inc/hw_memmap.h" //提供内存地址映射的支持
- #include "../inc/hw_types.h" //提供数据类型的支持
- #include "../driverlib/gpio.h" //提供GPIO的API支持
- #include "../driverlib/sysctl.h" //提供系统控制的API支持
- #include "../driverlib/rom.h" //提供ROM内API的支持
- #include "../driverlib/rom_map.h" //提供MAP_这种定义的支持
- //--------------------MAVRO DEFINITION 宏定义----------------------//
- #define DELAY_US(n) SysCtlDelay(n * (MAP_SysCtlClockGet() / 3000000))
- #define DELAY_MS(n) SysCtlDelay(n * (MAP_SysCtlClockGet() / 3000))
- #define DELAY_S(n) SysCtlDelay(n * (MAP_SysCtlClockGet() / 3))
- //-----------------FUNCTION PROTOTYPES 函数声明--------------------//
- void LED_blinking(unsigned long ultimes,unsigned long ulloop);
- /********************************************************************
- 函数名称:LED_blinking()
- 函数入口:ultimes:闪烁次数 ulloop:间隔的时钟周期
- 函数出口:无
- 函数说明:LED闪烁函数,实际效果和系统频率有关
- ********************************************************************/
- void LED_blinking(unsigned long ultimes,unsigned long ulloop)
- {
- unsigned long i,j;
- for(i=0x0000;i<ultimes;i++)
- {
- for(j=0x0000;j<ulloop;j++);
- MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 1);
- for(j=0x0000;j<ulloop;j++);
- MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 0);
- }
- }
- /********************************************************************
- 函数名称:main()
- 函数入口:务
- 函数出口:无
- 函数说明:系统主函数
- ********************************************************************/
- int main(void)
- {
- MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
- //使能PD端口
- MAP_GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_0);
- //PD0设置为输出
- MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | \
- SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
- //外部频率16MHZ,PLL倍频至80HMZ
- LED_blinking(10,500000);
- MAP_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | \
- SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
- //外部频率16MHZ,不分频
- LED_blinking(10,500000);
- MAP_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_OSC | \
- SYSCTL_OSC_INT);
- //内部晶振4分频,即4MHZ
- LED_blinking(10,500000);
- while (1)
- {
- MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 1);
- DELAY_MS(500);
- MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 0);
- DELAY_MS(500);
- //LED按照指定的时间间隔进行闪烁
- }
- }
复制代码
|