STM32 滴答時鍾 SysTick 的使用 STM32F103C8T6


 

      程序完成利用STM32F103C8T6 滴答時鍾 SysTick進行定時,每隔1秒輸出腳PC13的小燈閃爍一下。

注意,小燈每隔1秒閃爍只是轉換狀態,可以理解為定時或1個脈沖時間,但並不是頻率,頻率要2個

脈沖時間2秒,所以要測頻率的話是0.5Hz,即頻率=1/2秒= 0.5Hz 。

 

1  使用中斷的方法

修改stm32f10x_it.c文件,增加下面內容:

extern void LED_PC13 ();             //外部引入函數聲明  加在文件首部

void SysTick_Handler(void)          //中斷入口
{

LED_PC13 ();                               //亮燈取反滅燈函數

}

 

下面是main.c

#include "stm32f10x.h"

//**********************************************************************************

void GPIO_CFG()                                                                   //亮燈引腳配置函數
{
GPIO_InitTypeDef GPIO_InitStructure;                                   //聲明GPIO_InitStructure結構變量
// 原版創作,引用請指明出處 https://www.cnblogs.com/beiyhs/p/12438787.html   北有寒山
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //使能AHB預分頻器到端口C的開關

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;                     //指定腳13輸出
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;       //設置為推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //設定端口最快輸出50MHz
GPIO_Init(GPIOC, &GPIO_InitStructure);                              //按以上參數設置C口

GPIO_SetBits( GPIOC, GPIO_Pin_13);                                 //置高GPIO_Pin_13,關閉LED
}

//*********************************************************************************
void LED_PC13(void)                                                             //亮燈取反滅燈函數
{
GPIO_WriteBit(GPIOC, GPIO_Pin_13,                                  //指定修改PC13腳的位
(BitAction)((1-GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13)))); //讀PC狀態后取反
}

//********************************************************************************* 

//*********************************************************************************
int main(void)
{
GPIO_CFG() ;                                           //亮燈腳PC13的設置函數

SysTick_Config(9000000);                        //重裝值設9M,定時1秒
//SysTick_Config(9000);                            //重裝值設9K,定時1毫秒
//SysTick_Config(9);                                  //重裝值設9,定時1微秒
//NVIC_SetPriority (SysTick_IRQn, 0);      //設SysTick中斷優先級最高,不會在中斷時被別的中斷打斷
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);  //配置SysTick時鍾=HCLK時鍾/8
                                                                                                      //即72M/8=9MHz 即記數9M次耗時1秒
                                                                                                      //注意要放在SysTick_Config函數之后

                                                                                                       //如果屏蔽此句,默認使用的時鍾是72M

                                                                                                      //將上面9000000 改為72000000仍可得到

                                                                                                      //1秒定時

while (1)
{ }
}

 說明:
 1.1  systick定時器的內部計數器是24位遞減的,最大重裝值0xFFFFFF,即16777215,設置時不能超此值。

 1.2  使用systick定時器,只需調用SysTick_Config(uint32_t ticks)函數即可,該函數可以自動完成重裝載

        值的裝載、時鍾源選擇、計數寄存器復位、中斷優先級的設置(默認最低)、開中斷、開始計數的工作。

        一次搞定,是不是很爽。函數是在core_cm3.h頭文件中進行定義的。
 1.3  要修改時鍾源,比如外部時鍾,可以修改SysTick_CLKSourceConfig函數內部,也可按照SysTick_Config

       中默認設置FCLK不變。

 1.4 要修改中斷優先級調用 NVIC_SetPriority函數,函數在core_cm3.h

 1.5 systick是cortex_m3的標配,不是外設。故不需要在RCC寄存器組打開他的時鍾。

 1.6 每次systick溢出后會置位計數標志位和中斷標志位,計數標志位在計數器重裝載后被清除,而中斷標志位

      也會隨着中斷服務程序的響應被清除,所以這兩個標志位都不需要手動清除。

 

2  使用延時的方法

下面是下面是main.c

//*********************************************************************************

#include "stm32f10x.h"

//************************************************

void delay_ms(unsigned int ms)  //把ms換成us,下面9000換成9,就改成了us定時函數

{
unsigned int tmp = 0;

SysTick->LOAD = ms * 9000;    //  重裝寄存器 設置 72MHz/9000=9MHz

SysTick->VAL = 0x00;               // 當前計數寄存器 清零

SysTick->CTRL = 0x01;            // 控制寄存器  使能systick,禁止中斷,時鍾頻率AHB/8
do
   {
    tmp = SysTick->CTRL;         // 讀取控制寄存器的值賦給tmp
   }

 while (!(tmp & (1<<16)));         // 就是讀取tmp的第16位的值,這一位如果為0就表示計數器的值不是0(即

                                                 // 還在計數),如果是1就表示計數器已經自減到0了,計數結束。

                                                  //假設該值為0,還在計數,套上外面的!取反為1,繼續做do的內容。

 SysTick->VAL = 0x00;             // 當前計數寄存器 清零
 
SysTick->CTRL = 0x00;          //失能systick
}

 

//*********************************************************************************
int main(void)

{

GPIO_CFG() ;                                           //亮燈腳PC13 設置   參照上面同名函數,不再貼出

while(1)

 {

  Delay_ms(1000);

  GPIO_SetBits(GPIOC,GPIO_Pin_13);
  Delay_ms(1000);
  GPIO_ResetBits(GPIOC,GPIO_Pin_13);

  }

}

//*********************************************************************************************************

說明: 上面的定時函數如果用到us級別時,誤差還是不能忽視的,尤其是10us級別誤差很大的這是因為

程序指令的執行、跳轉都是要花費時間的,也是在us級別。如果是us級精確定時輸出控制的話,可以考

慮使用PWM方式,畢竟設定一次即可,后面全是硬件自己控制。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM