計(jì)框架)
SysTick 是 Cortex-M 內(nèi)核提供的24 位向下計(jì)數(shù)定時(shí)器。配置好計(jì)數(shù)周期后硬件周期性請(qǐng)求中斷CPU 進(jìn)入SysTick_Handler()我們?cè)谄渲袑?shí)現(xiàn)軟件計(jì)時(shí)。1. 設(shè)計(jì)思路先確定中斷周期再累計(jì)次數(shù)以“LED 每隔 1 秒翻轉(zhuǎn)一次”為例SysTick 每 1 ms 中斷一次 ↓ 軟件計(jì)數(shù)加 1 ↓ 主程序發(fā)現(xiàn)經(jīng)過 1000 ms ↓ 翻轉(zhuǎn) LED這樣中斷只負(fù)責(zé)提供時(shí)間基準(zhǔn)主程序負(fù)責(zé)具體任務(wù)。2. 如何計(jì)算中斷周期選擇 HCLK 作為 SysTick 時(shí)鐘時(shí)ticks HCLK頻率 × 期望周期秒 LOAD ticks - 1 中斷周期 (LOAD 1) / HCLK頻率假設(shè) HCLK 為 168 MHz需要每 1 ms 中斷一次ticks 168,000,000 × 0.001 168000 LOAD 167999使用庫函數(shù)SysTick_Config(SystemCoreClock / 1000U);常用配置配置參數(shù)中斷周期SystemCoreClock / 10001 msSystemCoreClock / 10000010 μsSystemCoreClock / 10000001 μs前提是SystemCoreClock與實(shí)際 HCLK 一致不能整除時(shí)存在取整誤差。3. 初始化配置了什么SysTick_Config(ticks)主要完成以下操作SysTick-LOAD ticks - 1U; // 設(shè)置計(jì)數(shù)周期 SysTick-VAL 0U; // 清除當(dāng)前計(jì)數(shù)值 // 設(shè)置中斷優(yōu)先級(jí) NVIC_SetPriority(SysTick_IRQn, 15U); // 選擇時(shí)鐘、允許中斷、啟動(dòng)計(jì)數(shù)器 SysTick-CTRL SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;CTRL的低三位分別控制位設(shè)置為 1 的作用CLKSOURCE第 2 位選擇 HCLKTICKINT第 1 位允許計(jì)數(shù)到 0 時(shí)請(qǐng)求中斷ENABLE第 0 位啟動(dòng)計(jì)數(shù)器選擇 HCLK 不會(huì)改變 HCLK 的頻率系統(tǒng)時(shí)鐘需要提前配置。4. 推薦框架中斷計(jì)時(shí)主循環(huán)處理任務(wù)下面以 STM32F407 為例。假設(shè)工程已經(jīng)提供時(shí)鐘配置、LED 初始化和翻轉(zhuǎn)函數(shù)并由本示例獨(dú)立使用 SysTick。#include stm32f4xx.h static volatile uint32_t system_ms 0; // 初始化每 1 ms 請(qǐng)求一次中斷 void SysTick_Init(void) { if (SysTick_Config(SystemCoreClock / 1000U) ! 0U) { while (1) { // 配置參數(shù)超出范圍 } } } // 中斷只更新時(shí)間 void SysTick_Handler(void) { system_ms; } int main(void) { SystemClock_Config(); LED_GPIO_Config(); SysTick_Init(); uint32_t last_ms system_ms; while (1) { uint32_t now system_ms; if ((uint32_t)(now - last_ms) 1000U) { last_ms now; LED_Toggle(); // 使用工程實(shí)際的 LED 翻轉(zhuǎn)函數(shù) } // 這里可以繼續(xù)處理其他任務(wù) } }這個(gè)框架沒有空循環(huán)等待延時(shí)主程序可以繼續(xù)執(zhí)行其他任務(wù)。LED 每秒翻轉(zhuǎn)一次完整亮滅周期約為 2 秒。5. 必須記住的重點(diǎn)硬件計(jì)數(shù)和軟件計(jì)數(shù)不同LOAD決定一次中斷隔多久system_ms累計(jì)中斷次數(shù)。LOAD ticks - 1計(jì)算周期時(shí)使用LOAD 1。共享計(jì)時(shí)變量使用volatile保證主程序讀取中斷更新后的值。中斷函數(shù)保持簡(jiǎn)短更新時(shí)間或置標(biāo)志具體任務(wù)放在主循環(huán)。不要在中斷里等待 SysTick 延時(shí)如果 SysTick 無法搶占當(dāng)前中斷可能一直等待。周期按需求選擇LED 等毫秒級(jí)任務(wù)使用 1 ms 節(jié)拍即可過于頻繁的中斷會(huì)增加 CPU 開銷。24 位限制ticks最大為22?168 MHz 下最大單次周期約 99.86 ms更長(zhǎng)時(shí)間用軟件累計(jì)。HAL 工程注意已有 SysTick通常已經(jīng)用于 1 ms 系統(tǒng)節(jié)拍應(yīng)在現(xiàn)有框架中擴(kuò)展并保留HAL_IncTick()等必要處理。