ARM Cortex-M3內核中有一個Systick定時器,它是一個24位(0~(2^24-1))的倒計數定時器,當計數到0時,它就會從Load寄存器中自動重裝定時初值,只要不把CTRL寄存器中的ENABLE清0,它就永不停。
時鍾源可以是內部時鍾FCLK或外部時鍾STCLK
配置系統定時器步驟:
①選擇時鍾源
②設定重載數(reload)
③開啟中斷
④啟動滴答定時器
在core_cm3.h中有關於系統定時器的配置:
__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 */ }
可以通過系統定時器產生的時基用於延時功能的設置:
時基:1/72M 裝值:SystemCoreClock /X X: 1000000 //10^(-6)----1us X: 100000 //10^(-5)----10us X: 1000 //10^(-3)----1ms u32 TimingDelay; void Systick_Init(void) { //判斷是否大於72000000 if(SysTick_Config(SystemCoreClock /100000)) // 10us while(1); SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk ;//禁止定時器中斷 } //1ms void Delay_ms(__IO u32 time) { TimingDelay =time*100; //1ms SysTick->CTRL |=SysTick_CTRL_ENABLE_Msk; while(TimingDelay !=0); SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk; } //1us void Delay_us(__IO u32 time) { TimingDelay =time; SysTick->CTRL |=SysTick_CTRL_ENABLE_Msk; while(TimingDelay !=0); SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk; } //中斷服務函數 void SysTick_Handler(void) { if(TimingDelay!=RESET) TimingDelay--; }
不帶中斷的延時:
//不帶中斷進行精確延時 //全局變量 static u8 fac_us;//us級基數 --0~255 static u16 fac_ms;//ms級基數 --0~65536 //延時函數初始化 void Delay_init(void) { SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//9MHz //SysTick->CTRL &= 0xfffffffb;--misc.c-199選擇HCLK/8作為systick時鍾 fac_us =SystemCoreClock/8000000;//9 fac_ms =(u16)fac_us*1000; } //us void Dealy_us(u32 nus)//nus--2^24/9 { u32 time; SysTick->CTRL = 0x00; //關閉SysTick定時器 SysTick->LOAD =nus*fac_us;//加載時間 SysTick->VAL =0x00; //清空計數器 //SysTick->CTRL |=0x01;//開定時器 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;//使能定時器 do { time =SysTick->CTRL; }while(time&0x01 && !(time&(1<<16)));//等待時間到達 SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;//失能定時器 SysTick->VAL =0x00;//清空計數器 } //ms void Dealy_us(u16 nms)//nms<=2^24/9000=1864 { u32 time; SysTick->CTRL = 0x00; //關閉SysTick定時器 SysTick->LOAD =(u32)nms*fac_ms;//加載時間 SysTick->VAL =0x00; //清空計數器 //SysTick->CTRL |=0x01;//開定時器 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;//使能定時器 do { time =SysTick->CTRL; }while(time&0x01 && !(time&(1<<16)));//等待時間到達 SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;//失能定時器 //SysTick->CTRL = 0x00; //關閉SysTick定時器 SysTick->VAL =0x00;//清空計數器 }