SysTick是內核系統的定時器,先來看看SysTick來源在哪,下圖stm32f030cc的時鐘樹
SysTick的時鐘為HCLK的8分頻,systick = HCLK/8
先提一下標準庫的大概運作方式,標準庫有寫好自動判斷要用外部石因還是內部,外部不正常或沒接上的話會自動使用內部HSI,有掛外部的話石中的進行路線如下圖,
可以看到紅色路徑是有掛8M時會跑的路徑,重點來了!! PREDIV和PLLMUL是除多少和乘上多少,要來看看system_stm32f0xx.c,這個是標準庫剛方寫好的,建議不要去動了,官方寫的算完整了。以下是系統時鐘配置的函示
static void SetSysClock(void)這函是底下的一部份:
/*PLL configuration */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL6);
應該有看到除1和乘6吧,這個看法也可以套運在其他MCU上,標準庫都差不多的。
再來要看看STM32F0xxx Cortex-M0 programming manual M0編程手冊,要看這是因為我們是用操作內核的暫存器
手冊網址:https://www.st.com/resource/en/programming_manual/pm0215-stm32f0xxx-cortexm0-programming-manual-stmicroelectronics.pdf
先來看看程式吧:
#ifndef __SYSTICK_H
#define __SYSTICK_H
#include "stm32f0xx.h"
#define STK_CSR (*(volatile unsigned long*)0xE00E010)
#define STK_RVR (*(volatile unsigned long*)0xE00E014)
#define STK_CVR (*(volatile unsigned long*)0xE00E018)
void delay_ms(uint16_t nms);//16
void delay_us(uint16_t nus);//16
void SysTick_Init(uint8_t SYSCLK);//8
#endif /* __SYSTICK_H */
上面可以看到我有定義三個暫存器指標,這三個位置在第四章節
再來看看
#include "bsp_SysTick.h"
static uint8_t fac_us=0;
static uint16_t fac_ms=0;
void SysTick_Init(uint8_t SYSCLK)
{
SysTick->CTRL = 0xfffffffb;
fac_us=SYSCLK/8;
fac_ms=(uint16_t)fac_us*1000;
}
void delay_ms(uint16_t nms)
{
uint32_t temp;
SysTick->LOAD = (uint32_t)nms*fac_ms;
SysTick->VAL =0x00;
SysTick->CTRL =0x01;
do
{
temp = SysTick->CTRL;
}
while((temp&0x01)&&(!(temp&(1<<16))));
SysTick->CTRL = 0x00;
SysTick->VAL =0x00;
}
void delay_us(uint16_t nus)
{
uint32_t temp;
SysTick->LOAD = (uint32_t)nus*fac_us;
SysTick->VAL =0x00;
SysTick->CTRL =0x01;
do
{
temp = SysTick->CTRL;
}
while((temp&0x01)&&(!(temp&(1<<16))));
SysTick->CTRL = 0x00;
SysTick->VAL =0x00;
}
這些操作方法M0編程手冊裡的說明很清楚了,有興趣的就自己看看吧,絕對不會看不懂很好理解。
再來是看主程式要如何使用?
#include "bsp_SysTick.h"
int main(void)
{
SysTick_Init(48);//初始化
delay_ms(20);
}
初始化後就可以使用了,我打48是因為我有掛外部石因震盪8M除1在乘6倍頻就會變48M,才會輸入48,還是不知道為甚麼在往前看看,假如不外掛石因用內部的話這邊要改成8
這絕對會比用迴圈計數還準。