# STM32 ###### tags: `Embedded` ###### date : 20210621 >致謝 Cortex Manual https://developer.arm.com/documentation/ddi0337/e/BEIEFGDB STM32中精确延时函数的实现 https://zhuanlan.zhihu.com/p/134495172 事情是這樣,學長要我幫他量AGV小車程式碼裡面一個迴圈花多少時間, 我用邏輯分析儀量,卻發現有點問題,經由這次機會才比較了解delay是怎麼實作的 ```c= //in main() function //這樣會對,分析圖會是1s GPIO_SetBits(GPIOB,GPIO_Pin_1); delay_ms(1000); GPIO_ResetBits(GPIOB,GPIO_Pin_1); //這樣卻錯了,分析圖不是2s GPIO_SetBits(GPIOB,GPIO_Pin_1); delay_ms(2000); GPIO_ResetBits(GPIOB,GPIO_Pin_1); ``` Cortex-M3 processor has three functional clock: 1. FCLK Free running processor clock, used for sampling interrupts and clocking debug blocks. FCLK ensures that interrupts can be sampled, and sleep events can be traced, while the processor is sleeping. 2. HCLK Processor clock 3. DAPCLK Debug port Advanced High-performance Bus Access Port (AHB-AP) clock. FCLK and HCLK are synchronous to each other. FCLK is a free running version of HCLK. 系統時脈SYSCLK最大頻率为72MHz,提供STM32中絕大部分部件工作的時脈來源,並且它通過AHB分頻器分頻之後送给各模組使用,其中HCLK是送给AHB總線、kernel、memory和DMA的時脈,以下被稱為外部時鐘,可以看[時鐘圖](https://zhuanlan.zhihu.com/p/134495172) ```c= /*!< System Clock Frequency (Core Clock) */ uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz; ``` ```c= void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource) { /* Check the parameters */ assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource)); if (SysTick_CLKSource == SysTick_CLKSource_HCLK) { SysTick->CTRL |= SysTick_CLKSource_HCLK; //內部時鐘72M } else { SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8; //外部時鐘 72/8=9M } } ``` ```c= void delay_init() { #if SYSTEM_SUPPORT_OS u32 reload; #endif SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); fac_us=SystemCoreClock/8000000; #if SYSTEM_SUPPORT_OS reload=SystemCoreClock/8000000; reload*=1000000/delay_ostickspersec; fac_ms=1000/delay_ostickspersec; SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; SysTick->LOAD=reload; SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; #else fac_ms=(u16)fac_us*1000; #endif } ``` ```c= void delay_ms(u16 nms) { u32 temp; SysTick->LOAD=(u32)nms*fac_ms; SysTick->VAL =0x00; SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; do{ temp=SysTick->CTRL; } //bit1 enable==1 && bit16 countflag!=0 while((temp&0x01)&&!(temp&(1<<16))); SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; SysTick->VAL =0X00; } ``` SysTick是一个24位的倒數計時器,計時到0的時候,將從LOAD暫存器中自動重裝載定時初值並繼續計數,且同時觸發中斷。只要不把它在SysTick控制及狀態寄存器中的使能位清除,就不會停。SysTick的最大使命,就是產生一个周期性的中斷。 Systick定时器的四个寄存器: 1. CTRL: Systick控制和狀態暫存器 2. LOAD: Systick重裝載 3. VAL : Systick當前值暫存器 4. CALIB: Systick校准值寄存器,不常用 SysTick->LOAD为24位寄存器,所以最大延時為: nms<=0xffffff*8*1000/SYSCLK SYSCLK单位為Hz,nms单位为ms 對72M條件下,nms<=1864,所以我根本就不能設參數2000嘛