STM32 自定义延时函数

在stm32调试过程中加入一个延时,有两种方式:一种是纯计数方式,另一种是使用系统计数器的方式。

现使用系统计数器产生中断的方式实现,查阅STM32的编程手册可知,STM32有一个24bit的系统计时器,并有STK_CTRL、STK_LOAD、STK_VAL、STK_CALIB寄存器供读写配置。

STM32 自定义延时函数_第1张图片

STM32 自定义延时函数_第2张图片

STM32 自定义延时函数_第3张图片





而CORTEX_M3有提供了一些函数可以供我们调用来控制这几个寄存器。

在编写延时函数时需要的库函数:

/**
  \brief   System Tick Configuration
  \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
           Counter is in free running mode to generate periodic interrupts.
  \param [in]  ticks  Number of ticks between two interrupts.
  \return          0  Function succeeded.
  \return          1  Function failed.
  \note    When the variable __Vendor_SysTickConfig is set to 1, then the
           function SysTick_Config is not included. In this case, the file device.h
           must contain a vendor-specific implementation of this function.
 */
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
  {
    return (1UL);                                                   /* Reload value impossible */
  }

  SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
  return (0UL);                                                     /* Function successful */
}
它将延时计数写入LOAD寄存器,设置时钟源为AHB并启动计数器。


如果我们使用的系统时钟为72MHz,那么如果ticks的值设置为72,000,000,则完成一个计数周期为1s,那么如果ticks值为72,000则计数周期为1ms,ticks值为72则计数周期为1us。

在计数器运行的过程中,每次计数都会产生一个系统中断,如果我们在中断中进行计数,就可以得到一个“准确”的延时了。

源码如下:

volatile unsigned long time_delay; // 延时时间,注意定义为全局变量,并且要在中断中做自减

/*********************************************************************************************
函 数 名: delay_ms
实现功能: 延时一定的毫秒数 
输入参数: volatile unsigned long nms:		延时的毫秒数
		  
输出参数: 无;
返 回 值: 0 	发送成功, 
          其他  发送失败;
说    明: 无;
*********************************************************************************************/
void delay_ms(volatile unsigned long nms)
{
	//设置计数器  若失败则返回1
	if (SysTick_Config(SYS_FREQ/1000))
	{
		while (1)
		{
			printf("delay_ms init error\n");
		}
	  
	}
	time_delay=nms;//读取定时时间
	while(time_delay);
	SysTick->CTRL=0x00; //关闭计数器
    SysTick->VAL =0X00; //清空计数器
}
/*********************************************************************************************
函 数 名: delay_us
实现功能: 延时一定的微秒数 
输入参数: volatile unsigned long nus:		延时的微秒数
		  
输出参数: 无;
返 回 值: 0 	发送成功, 
          其他  发送失败;
说    明: 无;
*********************************************************************************************/
void delay_us(volatile unsigned long nus)
{
	//设置计数器  若失败则返回1
	 if (SysTick_Config(SYS_FREQ/1000000))
	 {
		 while (1)
	 	{
			printf("delay_us init error\n");
	 	}
	 }
	 time_delay=nus;//读取定时时间
	 while(time_delay);
	 SysTick->CTRL=0x00; //关闭计数器
	 SysTick->VAL =0X00; //清空计数器
} 

extern __IO unsigned long time_delay; // 延时时间,注意定义为全局变量,并且要在中断中做自减
void SysTick_Handler(void)
{
	if(time_delay > 0)
	{
		time_delay--;
	}
}

需要注意的是,SysTick_Config()函数的使用需要调用core_cm3.h,而单独包含 core_cm3.h则会产生error:#20:identifier"IRQn_Type"isundefined 错误,这是因为数据类型RQn_Type是在stm32f10x.h中声明的,而core_cm3.h并没有进行包含,所以我们应用程序需要在包含core_cm3.h之前包含stm32f10x.h才可以。





你可能感兴趣的:(STM32,时钟)