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