1. 程式人生 > >STM32 自定義延時函式

STM32 自定義延時函式

在stm32除錯過程中加入一個延時,有兩種方式:一種是純計數方式,另一種是使用系統計數器的方式。

現使用系統計數器產生中斷的方式實現,查閱STM32的程式設計手冊可知,STM32有一個24bit的系統計時器,並有STK_CTRL、STK_LOAD、STK_VAL、STK_CALIB暫存器供讀寫配置。






而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 <b>__Vendor_SysTickConfig</b> is set to 1, then the
           function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
           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才可以。