大家好,歡迎來到 DSP28335 的核心精講系列。我們已經掌握了如何通過外部中斷來響應“外部事件”,但系統內部同樣需要一個精準的節拍器來處理“內部周期性任務”。單純依靠?DELAY_US()?這樣的軟件延時,不僅精度差,而且會在延時期間霸占整個CPU,導致系統無法響應其他任何事情,這是專業開發中無法接受的。
今天,我們將學習嵌入式系統的“心臟”——CPU 定時器 (CPU Timer),并利用它來產生精確的定時器中斷。掌握它,你就能創建一個非阻塞的、可以同時執行多個任務的、真正意義上的多任務雛形系統。
一、硬件原理:一個會自動重裝的“數字沙漏”
F28335 內置了三個 32 位的 CPU 定時器 (Timer0, Timer1, Timer2)。要理解它們如何工作,我們首先要看懂其內部的硬件邏輯。
[圖1: CPU 定時器硬件邏輯圖]
這個看似復雜的圖,其核心工作原理就像一個可以精確計時的“數字沙漏”:
時鐘源 (Clock Source):?定時器的動力來自系統時鐘?SYSCLKOUT。這就是“沙漏”中“沙子”下落的速度基準。
預分頻器 (Prescaler):
PSCH:PSC?(16位) 是一個預分-頻計數器。
TDDHR:TDDR?(16位) 是一個定時器分頻器。
它們組合起來,可以對輸入的?SYSCLKOUT?進行分頻。例如,如果?SYSCLKOUT?是 150MHz,我們可以設置一個 N 分頻,讓最終進入主計數器的時鐘頻率變為?150MHz / N。這允許我們實現更長時間的定時。
計數器 (Counter):?TIMH:TIM?是一個 32 位的遞減計數器。這是“沙漏”的上半部分。它在每個分頻后的時鐘脈沖到來時,數值減一。
周期寄存器 (Period Register):?PRDH:PRD?是一個 32 位的周期寄存器。這是“沙漏”的下半部分,用來設定總的“沙子”量。
工作流程:
啟動:?當我們啟動定時器時,PRD?的值被加載到?TIM?計數器中。
遞減:?TIM?寄存器開始以分頻后的時鐘速度向下計數。
中斷:?當?TIM?減到?0?時,它會產生一個中斷信號 (INT) 給 PIE 模塊。
重載:?與此同時,TIM?會自動將?PRD?的值重新加載進來,然后開始新一輪的遞減計數。
這個“遞減->歸零->中斷->重載”的過程周而復始,就為我們提供了一個穩定、精確的周期性中斷信號,成為了系統的“心跳”。
二、控制樞紐:關鍵寄存器解析
要指揮定時器工作,我們必須學會操作它的控制寄存器。
[圖2 & 圖3: Timer0/1/2 寄存器地址映射]
每個定時器都有一組獨立的寄存器。其中,最重要的就是控制寄存器 (TCR - Timer Control Register)。
[圖4 & 圖5: TCR 寄存器位功能描述]
讓我們來認識一下TCR中最重要的幾個“開關”:
bit 15 (TIF): 中斷標志位 (Timer Interrupt Flag)
當計數器減到 0 時,硬件會自動將該位置 1。
我們必須在中斷服務函數中手動向該位寫 1?來清除它,否則中斷會不停地產生。
bit 14 (TIE): 中斷使能位 (Timer Interrupt Enable)
只有將該位置 1,當計數器減到 0 時,才會向 PIE 發出中斷請求。
bit 5 (TRB): 重載控制位 (Timer Reload Bit)
必須將該位置 1。當它為 1 時,每當定時器啟動或計數器歸零時,PRD?的值都會被重新加載到?TIM。這是實現周期性定時的關鍵。
bit 4 (TSS): 啟動/停止位 (Timer Start/Stop)
寫 1 停止?定時器。
寫 0 啟動?或?重新啟動?定時器。
三、軟件配置:五步點燃“心跳引擎”
TI 官方在?DSP2833x_CpuTimers.c?文件中為我們提供了一系列標準函數,極大地簡化了定時器的配置。結合這些庫函數,我們的配置流程非常清晰。
Step 1: 使能定時器外設時鐘
任何外設工作的前提都是有時鐘。
EALLOW;
SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1; // 開啟 Timer 0 的時鐘
EDIS;
Step 2: 初始化定時器參數 (使用庫函數)
TI 提供了一個強大的函數?ConfigCpuTimer(),它能自動根據我們設定的 CPU 頻率和想要的定時周期(微秒),計算出正確的?PRD?周期值并寫入寄存器。
// 使用示例:
// 假設 Freq=150 (MHz), Period=500000 (us)
ConfigCpuTimer(&CpuTimer0, Freq, Period);```
?Step 3: 關聯中斷向量與 ISR
//在 PIE 中斷向量表中,將 TINT0 (定時器0中斷) 指向我們自己的中斷服務函數 `TIM0_IRQn`。
EALLOW;
PieVectTable.TINT0 = &TIM0_IRQn;
EDIS;```
Step 4: 開啟中斷通路并啟動定時器
// PIE 級:TINT0 屬于第1組第7個中斷
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
// CPU 級
IER |= M_INT1;
// 全局
EINT;
// 啟動定時器!
CpuTimer0Regs.TCR.bit.TSS = 0;
Step 5: 編寫中斷服務函數 (ISR)
這是中斷發生時執行的代碼。記得在函數末尾進行中斷應答。
interrupt void TIM0_IRQn(void)
{// ... 用戶功能代碼 ...// PIE 中斷應答PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
四、代碼實戰:雙燈齊“閃”,各司其職
下面的代碼將實現:
D2 指示燈:由 Timer0 中斷精確控制,每 500ms 翻轉一次。
D1 指示燈:在主函數?while(1)?循環中閃爍,證明 CPU 在沒有中斷時并未閑置。
time.h
#ifndef TIME_H_
#define TIME_H_#include "DSP2833x_Device.h" // DSP2833x 頭文件
#include "DSP2833x_Examples.h" // DSP2833x 例子相關頭文件// 聲明初始化函數和中斷服務函數
void TIM0_Init(float Freq, float Period);
interrupt void TIM0_IRQn(void);#endif /* TIME_H_ */
time.c
#include "time.h"
#include "leds.h"void TIM0_Init(float Freq, float Period)
{// Step 1: 使能時鐘EALLOW;SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1;EDIS;// Step 3: 關聯中斷向量EALLOW;PieVectTable.TINT0 = &TIM0_IRQn;EDIS;// 手動進行一些基礎配置CpuTimer0.RegsAddr = &CpuTimer0Regs;CpuTimer0Regs.PRD.all = 0xFFFFFFFF; // 先設為最大值CpuTimer0Regs.TCR.bit.TSS = 1; // 確保停止CpuTimer0Regs.TCR.bit.TRB = 1; // 使能重載CpuTimer0.InterruptCount = 0;// Step 2: 使用庫函數計算并配置周期ConfigCpuTimer(&CpuTimer0, Freq, Period);// Step 4: 開啟中斷通路并啟動定時器IER |= M_INT1;PieCtrlRegs.PIEIER1.bit.INTx7 = 1;CpuTimer0Regs.TCR.bit.TSS = 0; // 啟動!EINT;ERTM;
}// Step 5: 編寫 ISR
interrupt void TIM0_IRQn(void)
{EALLOW;LED2_TOGGLE; // 精確的周期性任務PieCtrlRegs.PIEACK.bit.ACK1 = 1; // 中斷應答EDIS;
}
main.c
#include "leds.h"
#include "time.h"void main()
{int i=0;InitSysCtrl();InitPieCtrl();IER = 0x0000;IFR = 0x0000;InitPieVectTable();LED_Init();// 初始化定時器0,CPU頻率150MHz,定時周期500000us (0.5s)TIM0_Init(150, 500000);while(1){i++;if(i%2000==0){LED1_TOGGLE; // 主循環任務}DELAY_US(100);}
}
現象: 程序運行后,你會看到 D2 指示燈以非常精準的 1Hz 頻率在閃爍,而 D1 指示燈則以 `while` 循環的速度在閃爍。D2 的閃爍完全不受主循環中 `DELAY_US` 的影響,反之亦然。這完美地展示了前臺任務(中斷)和后臺任務(主循環)并行工作的場景。
### 總結
CPU 定時器中斷是嵌入式開發從“入門”走向“專業”的分水嶺。通過本次學習,你已經掌握了:
1. ?定時器的**硬件工作原理**:基于遞減計數器和周期寄存器實現周期性中斷。
2. ?**關鍵寄存器 TCR** 的配置方法,尤其是啟動、停止和重載位。
3. ?利用 TI 庫函數進行**標準化配置的完整流程**。
4. ?如何編寫中斷服務函數來執行**精確的周期性任務**。
定時器是操作系統的“時鐘節拍”、PWM生成的“基準”、任務調度的“指揮官”。精通了它,你就擁有了構建復雜、實時、高效嵌入式系統的核心能力。