1. 程式人生 > >STM32_Systick學習及例程改寫

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 );
	}