回答

收藏

STM32F4步步为营三:延时函数

#其他 #其他 3473 人阅读 | 0 人回复 | 2014-07-15

STM32F429 Discovery开发板,集成了ST_LINK2和2.4寸的TFT  LCD彩屏,可以为学习开发带来不少的方便。此外,还有64Mbits SDRAM,ST MEMS,LED,按键及USB OTG  micro-B接口。本文将介绍这款开发板的延时函数。
        在讨论延时函数之前,先说一下带有CMSIS的程序的流程。
        可以看一下startup_stm32f429_439xx.s文件里启动的代码:
        _Vectors_Size  EQU  __Vectors_End - __VectorsAREA    |.text|, CODE, READONLY; Reset handlerReset_Handler    PROCEXPORT  Reset_Handler             [WE***]IMPORT  SystemInitIMPORT  __mainLDR     R0, =SystemInitBLX     R0LDR     R0, =__mainBX      R0ENDP; Dummy Exception Handlers (infinite loops which can be modified)        可见,先调用了一个SystemInit的函数,然后才是主函数main.
        这个函数主要完成了系统时钟及各总线时钟的设置。其在system_stm32f4xx.c中定义。
        而其中的一些参数设置,又在其头文件Stm32f4xx.h中定义。
        比如:
#if !defined  (HSE_VALUE)#define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */#endif /* HSE_VALUE **** @brief In the following line adjust the External High Speed oscillator (HSE) StartupTimeout value*/#if !defined  (HSE_STARTUP_TIMEOUT)#define HSE_STARTUP_TIMEOUT    ((uint16_t)0x05000)   /*!< Time out for HSE start up */#endif /* HSE_STARTUP_TIMEOUT */#if !defined  (HSI_VALUE)#define HSI_VALUE    ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/#endif /* HSI_VALUE */        就定义了各种频率的值。而硬件方面的值又在system_stm32f4xx.c中定义。
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */#if defined  (PLL_SOURCE_HSI)#define PLL_M      16#else#define PLL_M      8#endif#define PLL_N      360/* SYSCLK = PLL_VCO / PLL_P */#define PLL_P      2/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */#define PLL_Q      7        总之,到了main函数,系统的各个时钟已经设完。
        书归正转,STM32的延进函数可分为三种:
           
  • 第一种,就是平时51那种自己延时,这种有些不准,有些参数要自己去碰。
        如:
void MyusDelay(__IO uint32_t nTime){   uint32_t i,j;for(j=0;j<nTime;j++) {for(i=0;i<45;i++) { ; }}}
           
  • 第二种是利用Systick中断去延时程序如下
        娈量声明:static __IO uint32_t TimingDelay;
        初始化:
if (SysTick_Config(SystemCoreClock / 1000)){while (1);}        以上是延时1ms的值,要延10ms则应写成:
if (SysTick_Config(SystemCoreClock / 100)){while (1);}        函数原型应写成:
void Delay(__IO uint32_t nTime){TimingDelay = nTime;while(TimingDelay != 0);}        中断函数为:
void SysTick_Handler(void){TimingDelay_Decrement();}
           
  • 第三种方法是用Systick的不中断功能。
        我们可以看下参考手册231页的寄存器值的说明如下:
        可见就三个值有用:
        CLKSOURCE:选则SysTick的时钟来源。一般选0
        TICKINT:这个值决定了是否中断。
        ENABLE:这个是使能SysTick.
        明白了上述下面就很简单了:
void delay_ms(uint32_t nus){uint32_t temp;SysTick ->LOAD = 20*1000*nus;  //test ????SysTick ->VAL = 0x00;SysTick ->CTRL = 0x01;do{temp = SysTick->CTRL;}while((temp&0x01)&&(!(temp&(1<<16))));SysTick ->VAL = 0x00;SysTick ->CTRL = 0x00;}        主程序直接调用它就行了。
        三种方法比较,我认为还是中断最准最简单最实用,要注意的只有一点,定时时间不要小于1ms因为一但程序大了会有很多中断,这样就出现了不稳定因素。强烈建议设为10ms
        以下是中断和不中断的比较:
        这个不是中断的50ms:
       
        下图是用中断的50ms:
       
关注下面的标签,发现更多相似文章
分享到:
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /2 下一条