STM32_Systick學習及例程改寫
涉及的參考來自:野火的《【野火®】零死角玩轉STM32—F103霸道》、野火例程
1.systick進中斷不用清標誌的,這個好奇怪,難道是因為它是核心外設?
2.第二個不同之處是它的優先順序的奇怪,其優先順序沒有主和子優先順序之說,並且STM32只保留了其高4bit有效,也就是其優先順序可設範圍為0~15;
直接呼叫NVIC_SetPriority實現
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */
但是雖然它沒有主和子優先順序之說,但是碰到其他外設時,怎麼比較?還是按照優先順序分組的配置來比較,也就是按照優先順序分組的比例來拆分,進行比較。
3. 不管開不開其中斷,其計數器值一旦遞減為0,計數標誌就置1,有中斷進中斷,無中斷也沒啥事,繼續過載計數。
4.systick優先順序設的時候是和那個NVIC的優先順序分組沒關係,不受NVIC怎麼分組的影響,而且systick不分主和子優先順序的。但是比較的時候是按NVIC的分組值比的,比的時候將其值按分組值進行拆分再比。
5.計數-1的問題,可以這麼理解,比如你設定n,那麼它進一次中斷時n,接下來就是,n-1,n-2,……,0,實際運行了n+1,所以要-1.這樣理解就行了。為啥不用遞增理解?因為這個計數器是遞減計數器,雖然可以用遞增來理解但它沒有說明它內部是+1操作的,所以我覺得如果舉遞增的理解方式會有誤導,雖然道理一樣。
6.野火例程的改寫
針對其第二個在程式中檢測計數器標誌的延時,我是看它還是開中斷,而且每次都要重新配置,我就閒累,於是改寫成不開中斷,配置一次,之後只是開計數器關計數器。
RCC_ClocksTypeDef RccClocks; uint32_t SystemClockFrequency = 0, u32Cnt = 0; RCC_GetClocksFreq(&RccClocks); SystemClockFrequency = RccClocks.HCLK_Frequency; u32Cnt = SystemClockFrequency/1000; if ((u32Cnt - 1) > SysTick_LOAD_RELOAD_Msk) /* Reload value impossible */ { /* Capture error */ while (1); } else { SysTick->LOAD = u32Cnt - 1; /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ SysTick->VAL = 0; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk; SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk); /* Disable SysTick IRQ and SysTick Timer */ } u16 i; for(;;) { LED1( ON ); // 配置 counter 計數器的值 SysTick->VAL = 0; SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; /* Enable SysTick Timer,But diable SysTick IRQ*/ for(i=0;i<1000;i++) { // 當計數器的值減小到0的時候,CRTL暫存器的位16會置1 // 當置1時,讀取該位會清0 while( !((SysTick->CTRL)&(1<<16)) ); } // 關閉SysTick定時器 SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk; // SysTick_Delay_Ms( 1000 ); LED1( OFF ); LED2( ON ); // 配置 counter 計數器的值 SysTick->VAL = 0; SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; /* Enable SysTick Timer,But diable SysTick IRQ*/ for(i=0;i<1000;i++) { // 當計數器的值減小到0的時候,CRTL暫存器的位16會置1 // 當置1時,讀取該位會清0 while( !((SysTick->CTRL)&(1<<16)) ); } // 關閉SysTick定時器 // 配置 counter 計數器的值 SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk; // SysTick_Delay_Ms( 1000 ); LED2( OFF ); LED3( ON ); // 配置 counter 計數器的值 SysTick->VAL = 0; SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; /* Enable SysTick Timer,But diable SysTick IRQ*/ for(i=0;i<1000;i++) { // 當計數器的值減小到0的時候,CRTL暫存器的位16會置1 // 當置1時,讀取該位會清0 while( !((SysTick->CTRL)&(1<<16)) ); } // 關閉SysTick定時器 SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk; // SysTick_Delay_Ms( 1000 ); LED3( OFF ); }