stm32之Systick(系統時鍾)


Systick的兩大作用:

  1、可以產生精確延時;

  2、可以提供給操作系統一個單獨的心跳(時鍾)節拍;

通常實現Delay(N)函數的方法為:

  for(i=0;i<x;i++)

    ;

  對於STM32系統微處理器來說,執行一條指令只有幾十ns(納秒),進入for循環,要實現N毫秒的x值非常大;而由於系統頻率的寬廣,很難計算出延時N毫秒的精確值;針對STM32微處理器,需要重新設計一個新的方法去實現該功能,以實現在程序中使用Delay(N);

  cortex的內核中包含一個SysTick時鍾,SysTick為一個24位遞減計數器;SysTick設定初值並使能后,每經過1個系統時鍾周期,計數值就減1;計數到0,SysTick計數器自動裝載初值並繼續計數,同時內部的COUNTFLAG標志會置位;觸發中斷(前提是中斷使能);

  如果外部晶振(即外接的晶振)位8Mhz,經過內部9分頻;系統時鍾則為72Mhz(cpu的時鍾);SysTick的最高頻率為9Mhz(cpu時鍾的8分頻);在這個條件下;如果設置SysTick值為9000;而SysTick是9Mhz;則能產生1ms的時間基;即SysTick產生1ms的中斷;

 

  SysTick相關的寄存器:

  CTRL:  SysTick控制和狀態寄存器;

  LOAD:  SysTick重裝載值寄存器;

  VAL:   SysTick當前寄存器;(重新寫入的時候;會把狀態寄存器的FLAG清零)

  CALIB:  SysTick校准值寄存器;

SysTick設置步驟:(使用ST的函數庫使用Systick的方法)

  1、調用SysTick_CounterCmd()失能SysTick計數器;

  2、調用SysTick_ITConfig()失能SysTick中斷;

  3、調用SysTick_CLKSourceConfig()設置SysTick時鍾源;

  4、調用SysTick_SetReload() 設置SysTick重裝載值;

  5、調用SysTick_ITConfig() 使能SysTick中斷;

  6、調用SysTick_CounterCmd()  開啟SysTick計數器;

 

/*Include---------------------------*/
#include"stm32f10x_lib.h"        //包含所有的頭文件
#include<stdio.h>

//----------------函數聲明--------------------
void Delay_MS(u16 dly);
void RCC_Configuration(void);
void GPIO_Configuration(void);
void USART3_Configuration(void);


u8 tab[] = "hello welcome to class !";

void SYSTICK_Configuration(void)
{
    SysTick_CounterCmd(SysTick_Counter_Disable);
    SysTick_ITConfig(DISABLE);
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
    SysTick_SetReload(9000*1000);
       SysTick_CounterCmd(SysTick_Counter_Enable);

    //*************打開systick時鍾,但是由於systick時鍾是默認開啟的;
    
}      


/*******************************************************************************
* Function Name  : main
* Description    : Main program.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/ 
int main(void)
{
    u8 min, sec;
    #ifdef DEBUG
    debug();
    #endif
    //------------初始化------------
    RCC_Configuration();
    GPIO_Configuration();    
    USART3_Configuration();
    SYSTICK_Configuration();      

//     id_num[0] = *((u8*)(0x1FFFF7E9));    //stm32芯片id的放置地址,96位id;12字節
     printf("hello world\n");
    //------------將數據上傳給上位機-----------
    min = 1;
    sec = 30;

    while(1)
    {
        FlagStatus Status;
        Status = SysTick_GetFlagStatus(SysTick_FLAG_COUNT);
        if(Status == RESET)
        {
            ;
        }
        else
        {
            sec++;
            if(sec == 60)
            {
                sec=0;
                min++;
            }
            printf("\t\t%d:%d", min, sec);
        }
    }
        
}

/*******************************************************************************
* Function Name  : Delay_Ms
* Description    : delay 1 ms.
* Input          : dly (ms)
* Output         : None
* Return         : None
*******************************************************************************/
void Delay_MS(u16 dly)
{
    u16 i,j;
    for(i=0;i<dly;i++)
        for(j=1000;j>0;j--);
}

/*******************************************************************************
* Function Name  : RCC_Configuration
* Description    : Configures the different system clocks.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RCC_Configuration(void)
{
    //----------使用外部RC晶振-----------
    RCC_DeInit();            //初始化為缺省值
    RCC_HSEConfig(RCC_HSE_ON);    //使能外部的高速時鍾 
    while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);    //等待外部高速時鍾使能就緒
    
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);    //Enable Prefetch Buffer
    FLASH_SetLatency(FLASH_Latency_2);        //Flash 2 wait state
    
    RCC_HCLKConfig(RCC_SYSCLK_Div1);        //HCLK = SYSCLK
    RCC_PCLK2Config(RCC_HCLK_Div1);            //PCLK2 =  HCLK
    RCC_PCLK1Config(RCC_HCLK_Div2);            //PCLK1 = HCLK/2
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);    //PLLCLK = 8MHZ * 9 =72MHZ
    RCC_PLLCmd(ENABLE);            //Enable PLLCLK

    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);    //Wait till PLLCLK is ready
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);    //Select PLL as system clock
    while(RCC_GetSYSCLKSource()!=0x08);        //Wait till PLL is used as system clock source
    
    //---------打開相應外設時鍾--------------------
    RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);    //使能APB2外設的GPIOC的時鍾
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE); //復用功能時鍾開啟             
}

/*******************************************************************************
* Function Name  : GPIO_Configuration
* Description    : 初始化GPIO外設
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
//由電路圖可知;配置PC10,PC11引腳
void GPIO_Configuration(void)
{
    //CLK:PB5  CLR:PE11 DATA:PE10
    GPIO_InitTypeDef    GPIO_InitStructure;        //聲明一個結構體變量
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;     //選擇PB.1-
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //管腳頻率為50MHZ
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     //輸出模式為 "復用推挽輸出"
    GPIO_Init(GPIOC,&GPIO_InitStructure);                 //初始化GPIOB寄存器
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 |GPIO_Pin_11 ;     //選擇PE.10 PE.11
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //管腳頻率為50MHZ
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;     //輸出模式為    "浮空輸入"
    GPIO_Init(GPIOC,&GPIO_InitStructure);                 //初始化GPIOE寄存器
    
    //開啟時鍾    必須在RCC_Configuration中設置    
    
    
    //端口重映射:PC10/PC11
    GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);    
} 

void USART3_Configuration(void)
{
    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl =    USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;

    USART_Init(USART3, &USART_InitStructure);

    USART_Cmd(USART3, ENABLE);    //開啟使能
}

/***********************************************************
 name:    fputc                                               *
 Description:重定向這個c庫printf函數,文件流--->串口USART  *
                                                           *
************************************************************/
int fputc(int ch,FILE *f)
{
    //ch發送給USART1
    USART_SendData(USART3, ch);
    //等待發送完畢
    while(USART_GetFlagStatus(USART3, USART_FLAG_TC)==RESET)
        ;
    return ch;
}

 


免責聲明!

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



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