STM32F4步步为营三:延时函数

作者: ddllxxrr
上传时间为: 2014-07-15 07:09 PM

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 - __Vectors
AREA    |.text|, CODE, READONLY
; Reset handler
Reset_Handler    PROC
EXPORT  Reset_Handler             [WEAK]
IMPORT  SystemInit
IMPORT  __main
LDR     R0, =SystemInit
BLX     R0
LDR     R0, =__main
BX      R0
ENDP
; 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) Startup
Timeout 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

下图是用中断的50ms:

中断的50ms

全部评论 ()

创建讨论帖子

登录 后参与评论
系统提示